diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000000..55a3c159e043 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +# top-most EditorConfig file +# See http://editorconfig.org/ +root = true + +[*] +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = false diff --git a/CHANGES b/CHANGES index 276969ac1077..fbde4fa1b01b 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,291 @@ +Version 1.10.0 +(?? ??? 2018, from /branches/1.10.x) +http://svn.apache.org/repos/asf/subversion/tags/1.10.0 + +See the 1.10 release notes for a more verbose overview of the changes since +the 1.9 release: https://subversion.apache.org/docs/release-notes/1.10.html + + User-visible changes: + - Major new features: + * Better interactive conflict resolution for tree conflicts (r1687489 et al) + * Wilcards and improved performance in path-based authorization (r1776832) + * New experimental 'svn shelve' command (issue #3625) + - Minor new features and improvements: + * svnbench: Show time taken & bytes transferred (r1703383, r1710586) + * New 'svnadmin dump' options to include/exclude paths (r1811992 et al) + * New '--normalize-props' option for 'svnadmin dump' (r1807836 et al) + * New 'svnadmin 'load-revprops', 'dump-revprops' subcommands (r1694191, -225) + * New '--no-flush-to-disk' option for 'svnadmin load' (r1736357, -7357) + * New '--file' option for several svnadmin subcommands (r1738021) + * New '--max-request-size', '--max-response-size' options for svnserve (r1714330, -333) + * New '-rN' option for 'svnadmin lstxns' (r1703699) + * New '--search' option for fast 'svn ls' searches (r1767186 et al) + * Add '--search' option support to 'svnbench null-list' (r1767202) + * New '-M' option for 'svnlook tree' (r1708222) + * New '--skip-unchanged' option for 'svnsync copy-revprops' (r1692655) + * 'svn log --search' now ignores case and diacriticals (r1731300, r1735614) + * Improved performance of server-side log processing (r1732768, r1731656) + * diff3: Reduce processing time and memory usage (r1731659) + * ra_serf: Adjustments for serf versions with HTTP/2 support (r1716400) + * ra_serf: Send svndiff1 deltas during commit (r1704317, r1704613, r1791290) + * ra_serf: Stream svndiff deltas w/o creating temporary files (r1803143 et al) + * ra_serf: Don't necessarily request full MERGE reponses (r1806017 et al) + * 'svn patch': Parse binary diffs in git-style patches (r1703925) + * 'svnadmin info' now reports latest revision in the repository (r1697953) + * ra_svn: Various performance-related tweaks (r1694490) + * Optimize svndiff parser (r1685063) + * 'svn status' without -v: Stop showing uninteresting deletions (r1664533) + * Save a few cycles in svn_stringbuf_set() (r1759177) + * windows: Use the Unicode Windows API (r1756193) + * windows: Distinguish out-of-memory error from abort() (r1724784, -809) + * windows: Explicitly release file locks (r1702089) + * windows: Correctly check result from LoadLibrary() call (r1755983) + * Remove Windows-specific slowdown during pristine cleanup (r1701641) + * FSFS: Optionally cache node properties without full-text cache (r1723715) + * FSFS: Open transaction's proto revision in write-only mode (r1759135) + * FSFS: Avoid checksum calculations if logical addressing is used (r1756377) + * FSFS: Do not read very long change lists in block read mode (r1746012) + * FSFS: Avoid double DAG lookup (r1711582) + * FSFS: Avoid double cache lookups (r1681974, r1710370) + * FSFS: Increase default revprop pack size from 4k to 16k (r1709799) + * FSFS: Speed up revprop access (r1707986 et al) + * FSFS: Disable representation sharing for directories (r1706619) + * FSFS: Speed up transaction processing for large directories (r1706617) + * FSFS: Tune format 7 pack ordering heuristics (r1706615) + * FSFS: Reduce I/O overhead during history traversal (r1703237) + * FSFS: Use native Windows API to guarantee data is flushed (r1701053) + * FSFS: Warn if a possible rep-cache SHA1 collision is detected (r1674673) + * FSFS: Optimize revprop cache filling strategy under high load (r1795324) + * FSFS: New "verify-before-commit" fsfs.conf option (r1795351) + * FSFS: New format 8 with various performance improvements (r1801940 et al) + * FSFS/FSX: Chunked read support for changed paths lists (r1746026, -4987) + * FSFS/FSX: Improvements to cache implementation (r1694489) + * FSX: Add checksums to packed revprop manifests and files (r1713132, -9717) + * FSX: Significantly reduce size of packed revprop manifest data (r1713109) + * FSX: Improved on-disk representation of property lists (r1717427) + * FSX: New in-repository representation of directories (r1712967) + * FSX: Make 'svnadmin recover' discard all transactions (r1712937) + * FSX: Reduce number of fsync operations (r1711354 et al) + * mod_dav_svn: Improve performance and memory usage of PROPFIND (r1721732) + * mod_dav_svn: Show process-id on Windows in /svn-status page (r1718567) + * mod_dav_svn: Advertise svndiff1 support to clients (r1704891, r1791285) + * mod_dav_svn: Remove disk I/O to TMPDIR during first commit (r1716240) + * svnsync: Fix assertion failure with up-to-date repositories (r1727140) + * ra_serf: Parallel requests for text and property changes (r1716575) + * svnserve: Remove disk I/O to TMPDIR during first commit (r1716240) + * Triple performance of URI escaping (r1710099, -103) + * 'svn blame': Optimize a bit on the server side (r1711666) + * 'svn cleanup': Add --vacuum-pristines option (r1802787 et al) + * 'svn diff --git': Show diffs of symlinks like git and hg (r1706372) + * 'svn patch': Capable of handling git-like symlink changes (r1706446) + * 'svn patch': Improve detection of additions and deletions (r1706623) + * 'svn patch': Handle zero-byte files vs deleted files (r1705856) + * 'svn diff --git': Produce 'rename from/to' headers (r1706855) + * 'svn diff --git': Produce proper mode headers (r1706041) + * 'svn lock', 'svn unlock': Take the -q option (r1796288) + * 'svn help': improved wording and consistency (r1802989 et al) + * 'svn': Add a new '--accept recommended' option. (r1805623) + * 'svn': --non-interactive uses recommended tree conflict resolution (r1805620) + * Evaluate 'old mode' and 'new mode' lines from git-syle diffs (r1705391) + * svnrdump, svndumpfilter: Enable buffered stdin (r1703074) + * ra_serf: Receive svndiff1 and gzip compressed deltas (r1791282, -3, -4) + * svnadmin: 'lock', 'unlock', 'rmlocks': Take the -q option (r1796406) + * New svndiff2 binary delta format using lz4 compression (r1801938, et al) + * gpg-agent: Support gpg ≥2.1.13 and unset GPG_AGENT_INFO (r1795087) + * Add 'http-compression=auto' client config option as default (r1803899 et al) + * Speed up processing of mergeinfo (r1802470 et al) + * Check for invalid 'xt' fields in x509 certs (r1809290) + * New '--password-from-stdin' option for 'svn' (r1819093) + - Client-side bugfixes: + * svnbench: Honour the '--with-no-revprops' option (r1709593) + * ra_serf: Fix segfault when running over HTTP v1 (r1766089) + * ra_serf: Keep small svndiffs in memory during commit (r1724455) + * ra_serf: Improve error messages related to lock operations (r1716450) + * ra_serf: Work around a bug in serf bucket handling (r1714806) + * ra_serf: Fix lock token handling for file-path commits (r1815799 et al) + * Raise a malfunction instead of segfaulting with corrupt wc.db (r1749887) + * Fix check for unversioned obstructions blocking file externals (r1735932) + * 'svn patch' bugfixes: + + Fix behaviour if a reject file can't be created (r1725948) + + Describe adds and removes in reject file headers (r1707034) + + Detect recorded moves that are already applied (r1706893) + + Detect already applied patches in edge cases (r1706687) + + Fix handling of missing trailing context (issue #4609) + + Fix interaction of moves and property changes (r1706875) + + Fix output for reordered hunks (issue #4533) + + Prevent from overwriting existing reject files (r1706600) + + Improve handling of added properties (r1706598) + + Improve handling of rejected file deletions (r1706221) + + Fix --dry-run with replaced files (r1706217) + + Fix applying prop changes which should conflict (r1705733) + + Fix duplicate notifications when adding directories (r1704883) + + Fix duplicate notifications when patching svn:executable prop (r1706078) + + Fix notifications when adding/removing properties (r1705698) + + Make handle already applied property patches (r1705692) + + Change some notifications to 'U' instead of 'G' (r1706693) + + Don't create file if git-style patch indicates modification (r1706005) + + Parse any properties following svn:mergeinfo (r1706825) + + Fix potential unbounded memory usage in parser (r1705979) + + Fix problems with --git diffs applied in reverse (r1704854, -88) + + Fix removal of EOL if final patch context line has no EOL (#4315) + * 'svn diff --git': Fix file permission modes to match git and hg (r1695384) + * 'svn diff --git': added/deleted filenames are never /dev/null (issue #4689) + * Fix a problem with relocating some externals (r1723385) + * Fix 'svn diff URL@REV WC' wrongly looks up URL@HEAD (issue #4597) + * Fix 'svn diff --no-diff-added' shows properties as added (issue #4596) + * Properly raise text merge conflicts with file externals (r1680245) + * Fix 'svn diff' with local directories marked incomplete (r1674413 et al) + * ra_svn/ra_serf: Make negative log limits work as documented (r1665530) + * ra_svn: Eliminate unnecessary URL reparenting (r1779611, r1779611) + * ra_svn: Use svndiff2 deltas when supported on both ends (r1803269 et al) + * Handle invalid revision numbers consistently across RA layers (r1665328) + * Handle commits to revs > HEAD consistently across RA layers (r1664698) + * Eliminate one client/server roundtrip from checkouts of HEAD (r1779620) + * Expose some error messages generated by github's SVN server (r1707164) + * 'svnfsfs stats': Show average lengths of delta chains (r1705739) + * svnmucc: Fix crash during application teardown (r1795727) + * Fix assertion when exporting a working copy containing relative externals + (r1802316) + - Server-side bugfixes: + * Fix checksum validation error due to data eviction from cache (r1781694) + * FSFS pack: Use unbuffered file streams in a couple of places (r1759405) + * FSFS: Reduce excessive amount of read and seek syscalls (r1758979, -9399) + * FSFS: Reduce memory footprint of cached directories (r1725179) + * FSFS: Add various checks for integer overflows (r1714372, -32, -34) + * FSFS: Detect a very unlikely case of item index corruption (r1716973) + * FSFS: Make handling of revprop size information more resilient (r1716784) + * FSFS: Don't re-parse a directory which just got committed (r1706679) + * FSFS: Handle some known quirks in committed node revisions (r1673875) + * FSFS format 7: Verify item types more thoroughly (r1796160) + * FSFS: Fix false positive "Not a directory" error involving file moved and + replaced by dir (issue #4677) + * FSFS: Fix crash accessing revprops with --memory-cache-size=0 (r1795164) + * FSFS: Fix issue #4623 for FSFS. (r1813794 et al) + * mod_dav_svn: Omit Cache-Control HTTP header for HEAD URLs (issue #4514) + * mod_dav_svn: Reduced memory consumption for DAV merge responses (r1727790) + * mod_dav_svn: Don't set a Last-Modified header in GET responses (r1724790) + * mod_dav_svn: Actually use FSFS transaction directory cache (r1723720) + * mod_dav_svn: Do not insert newlines in base64 encoded responses (r1712223) + * Fix insertion of very large items into the membuffer cache (r1717337, -8) + * Fix capacity check of the membuffer cache's prefix pool (r1714356) + * Prevent paths containing newlines from being committed (r1662585) + * Fix for properties: Null updates break last-changed-revision (issue #4700) + * 'svnfsfs stats': Fix false positive checksum errors reading old revisions + (r1785904) + * 'svnfsfs stats': Fix support for pre-v4 FSFS repositories. (r1816966) + * svnadmin, svnfsfs: Detect invalid arguments to -M (r1787023, r1787045) + * svnlook, svnserve: Detect invalid arguments to -M (r1787023, r1787045) + * svnadmin: Output locked paths in canonical form (r1796420) + * svnadmin: Output locked paths correctly encoded (r1797122) + * svn: propdel, propset: Transcode property names on output (r1797186) + * svnserve: Make use-sasl=true a fatal error in SASL-less builds. (r1803188) + - Client-side and server-side bugfixes: + * Fix integer overflow check with >= 1G mergeinfo ranges per path (r1714380) + * Fix integer overflow checks on WoW64 platforms (r1714372) + * Fix bug with canonicalizing Window-specific drive-relative URL (r1692262) + * In file:// URLs, allow '\' directly after Windows drive letter (r1692259) + * Fix segfault with recursive configuration value definitions (issue #4543) + * FSFS: Improve error messages when DAG lookup fails (r1795120) + * Transcode command-line arguments to UTF-8 (r1797190, r1797362, et al) + * Fix segfault on x509 certificate with empty name (r1798157) + * Fix segfault with invalid URLs in svn:externals (r1803471) + * Windows: Failure to write files might remain undetected (r1806014) + - Other tool improvements and bugfixes: + * New svn-mergeinfo-normalizer tool (r1695992 et al) + * Allow configuring mailer.py to use SMTP SSL (r1777846) + * svnmucc can now delete directories with deleted children (issue #4666) + * svn-vendor.py: Minor enhancements, mostly in treating symlinks (r1732669) + * bash_completion: Better URL completion (r1701494) + * bash_completion: Complete arguments to 'svn info --show-item' (r1698276) + * fsfs-stats: New 1.8-compatible wrapper for 'svnfsfs stats' (r1802032) + * Drop support for upgrading working copies created with Subversion 1.7 + (r1807584 et al) + + Developer-visible changes: + - General: + * windows: Removed support for building with Visual Studio 6.0 (r1703419) + * Fix .py scripts throughout the source tree for Python 3 (r1741723 et al) + * Support memcached on Windows with APR-util 1.3 or later (r1674626 et al) + * Don't require GNU-specific sed(1) extensions during the build (r1693159) + * get-deps.sh: download Googlemock and Googletest from GitHub (r1746303) + * windows: Add autodetection for 'zlibstat.lib' (r1783704) + * windows: Compile libsvn_fs_* as DLLs (r1696758, -83) + * windows: Allow building against OpenSSL 1.1.0 (r1814724 et al) + * OS X: Silence compile-time deprecation warnings with SASL (r1739649) + * OS X: Silence ranlib warnings about disabled WIN32 code (r1809792) + * 'make check GLOBAL_SCHEDULER=1' will run many tests in parallel (r1716399) + * unix: New '--enable-apache-whitelist' configure script option (r1732294) + * OS X: Support 'configure --enable-runtime-module-search' (r1677273) + * tests: Allow tests to be run over HTTP/2 (r1710707) + * tests: httpd compile-time and run-time version may differ (r1808955 et al) + * tests: Add pre-cooked repos for all FSFS versions. (r1816402 et al) + * tests: Add FSFS_DIR_DELTIFICATION option. (r1813897) + * Add basic tests for svn_xml_parser_t API (r1765214) + * Unbreak the test suite on Python 3 (r1743034, -81, et al) + * Make the test suite work when checked out of a git repository (r1771118) + * Allow Apache HTTPD with mod_deflate in testsuite on Windows (r1758776) + * Support modern utilities for finding free TCP ports for tests (r1684649) + * The C test scheduler is more efficient in SMP environments (r1775555) + * The C tests convert paths from/to UTF-8 more efficiently (r1775642) + * Add INSTALL instructions for building with OpenSSL 1.1.0 (r1778313) + * Improved INSTALL instructions for Windows (r1703470, -2, -3, -4, et al) + * Updated INSTALL instructions (r1691712) + * windows: Support Visual Studio 2017 (r1786653, r1786669) + * gnome-keyring: Support libsecret in preference to libgnome-keyring + (r1798004) + * kwallet: Support KDE 5 in preference to KDE 4 (r1798731) + * kwallet: Fix KDE5 support with clang 3.8 (r1802536 et al) + * kwallet: Add --with-kwallet=INCDIR:LIBDIR build option (r1802646) + * Rename cxxhl bindings 'make tests' to avoid confusion with 'make test' + (r1800849) + * 'make check': Allow testing with FSFS compression (r1801936) + * svnserveautocheck.sh: Support out-of-tree builds when running a single + test file (r1802081) + * Distribution artifacts now prepared with swig 3.0.10 (r1802135) + * SQLite: Use https:// links to download amalgamation sources (r1817043) + * Create reproducible tarballs (r1804618 et al) + * Disable static builds of the apache and auth provider modules (r1802612) + * utf8proc: Update to version 2.1.0 (r1809090 et al) + * utf8proc: Build against the system library by default (r1803210 et al) + - API changes: + * New svn_client_conflict_* API functions for the new conflict resolver. + * New svn_repos_fs_get_mergeinfo2() with streamy access (r1780810 et al) + * New streamy svn_repos_get_logs5() API function (r1730389, -1163) + * New streamy svn_fs_paths_changed3() API function (r1727822, r1745055) + * New svn_client_list4() API function (r1767186) + * New svn_ra_list() API function (r1767190) + * New svn_repos_list() API function (r1765088) + * New svn_stream_contents_checksum() API function (r1755486, -6651) + * New svn_io_file_get_offset() API function (r1719269) + * New svn_base64_encode2 API function (r1711517) + * New svn_fs_create2() API function (r1710631) + * New svn_string_from_stream2() API function (r1710065) + * New svn_io_write_atomic2() API function (r1703142) + * New svn_stream_for_stdin2() API function (r1702983) + * New svn_io_file_rename2() API function (r1701017) + * New svn_error_quick_wrapf() API function (r1662668) + * New svn_repos_path_change_t type (r1802114) + * New svn_repos_log_entry_t type (r1802114) + * New svn_cstring_join2() API (r1806041) + * New svn_txdelta_to_svndiff_stream() API (r1803140 et al) + * svn_repos_parse_dumpstream3() now accepts NULL pointers (r1700180) + * Return resettable streams from svn_stream_checksummed2(). (r1804807) + * Fix svnserveautocheck&davautocheck when time is only a built-in (r1665652) + - Bindings: + * Configure the swig bindings only if swig has been enabled (r1751167) + * Error if 'configure --with-swig' is used and swig is not found (r1700844) + * Perl: Fix build with libraries in non-standard LD_LIBRARY_PATH (r1781588) + * JavaHL can now get revision properties along with log messages (r1780819) + * JavaHL: Allow access to constructors of a couple JavaHL classes (r1739704) + * JavaHL: Correct some JNIEntry method names (r1706738) + * Allow swig bindings scripts to configure the FSFS cache (r1709922) + * Disable some swig wrappers that aren't working (r1700966) + * JavaHL: Make StringArray nullable (r1785429) + * JavaHL: Add missing exception checks (r1801108) + * Ruby: Fix handling of NULL MD5 digests (r1811786) + * Ruby: Detect versions up to 2.4 (r1806570) + + Version 1.9.7 (10 Aug 2017, from /branches/1.9.x) http://svn.apache.org/repos/asf/subversion/tags/1.9.7 @@ -994,6 +1282,51 @@ http://svn.apache.org/repos/asf/subversion/tags/1.9.0 * javahl: allow compiling with a C++11 compiler (r1684412) +Version 1.8.19 +(10 Aug 2017, from /branches/1.8.x) +http://svn.apache.org/repos/asf/subversion/tags/1.8.19 + + User-visible changes: + - Client-side bugfixes: + * Fix arbitrary code execution vulnerability CVE-2017-9800 + See + for details. + + - Server-side bugfixes: + (none) + + - Bindings bugfixes: + (none) + + Developer-visible changes: + - General: + (none) + + - API changes: + (none) + + +Version 1.8.18 +(10 Jul 2017, from /branches/1.8.x) +http://svn.apache.org/repos/asf/subversion/tags/1.8.18 + + User-visible changes: + - Server-side bugfixes: + * fsfs: never attempt to share directory representations (r1785053) + * fsfs: make consistency independent of hash algorithms (r1785737 et al) + This change makes Subversion resilient to collision attacks, including + SHA-1 collision attacks such as . See also our + documentation at and + . + + - Client-side and server-side bugfixes: + * work around an APR bug related to file truncation (r1759116) + + Developer-visible changes: + - General: + * update serf download URI in build scripts (r1700130 et al) + + Version 1.8.17 (29 Nov 2016, from /branches/1.8.x) http://svn.apache.org/repos/asf/subversion/tags/1.8.17 @@ -2666,7 +2999,7 @@ the 1.6 release: http://subversion.apache.org/docs/release-notes/1.7.html * fixed: ra_serf doesn't support http-auth-types config (issue #3435) * fixed: merge sets incorrect mergeinfo on skipped paths (issue #3440) * fixed: ra_serf inconsistent handling of cached authn creds (issue #3450) - * fixed: ra_serf sefault with using NTLM or Negotiate auth (r876910) + * fixed: ra_serf segfault with using NTLM or Negotiate auth (r876910) * fixed: excluded subtrees are not detected by svnversion (issue #3461) * fixed: submitting a changelist while obstructed item exists (issue #3484) * fixed: crash when changing an external's URL (issue #3530) diff --git a/COMMITTERS b/COMMITTERS index 8665dba45aa4..22bf2714faa0 100644 --- a/COMMITTERS +++ b/COMMITTERS @@ -19,7 +19,7 @@ Blanket commit access: fitz Brian W. Fitzpatrick daniel Daniel Stenberg cmpilato C. Michael Pilato - philip Philip Martin + philip Philip Martin jerenkrantz Justin Erenkrantz rooneg Garrett Rooney blair Blair Zajac @@ -27,14 +27,13 @@ Blanket commit access: dlr Daniel Rall mbk Mark Benedetto King jaa Jani Averbach - julianfoad Julian Foad + julianfoad Julian Foad jszakmeister John Szakmeister ehu Erik Hülsmann breser Ben Reser maxb Max Bowsher dberlin Daniel Berlin danderson David Anderson - ivan Ivan Zhakov djames David James pburba Paul Burba glasser David Glasser @@ -48,17 +47,20 @@ Blanket commit access: kou Kouhei Sutou danielsh Daniel Shahaf peters Peter Samuelson - rhuijben Bert Huijben + rhuijben Bert Huijben stylesen Senthil Kumaran S steveking Stefan Küng - neels Neels J. Hofmeyr + neels Neels J. Hofmeyr jwhitlock Jeremy Whitlock sbutler Stephen Butler dannas Daniel Näslund - stefan2 Stefan Fuhrmann + stefan2 Stefan Fuhrmann jcorvel Johan Corveleyn trent Trent Nelson kotkov Evgeny Kotkov + astieger Andreas Stieger + jamessan James McCoy + luke1410 Stefan Hett [[END ACTIVE FULL COMMITTERS. LEAVE THIS LINE HERE; SCRIPTS LOOK FOR IT.]] @@ -76,6 +78,7 @@ Full committers who have asked to be listed as dormant: malcolm Malcolm Rowe naked Nuutti Kotivuori ringstrom Tobias Ringström + ivan Ivan Zhakov Partial committers who have asked to be listed as dormant: @@ -100,6 +103,7 @@ Commit access for specific areas: rschupp Roderich Schupp (Swig bindings) stilor Alexey Neyman (Python bindings, svn-vendor.py) + troycurtisjr Troy Curtis, Jr (Swig bindings) Packages: @@ -164,14 +168,14 @@ Commit access for specific areas: humbedooh Daniel Gruno (svnpubsub) prabhugs Prabhu Gnana Sundar (verify-keep-going) schabi Markus Schaber (testsuite) - gbg Gabriela Gibson (gtest) + gbg Gabriela Gibson (gtest) + lyalyakin Pavel Lyalyakin (site) Translation of message files: niqueco Nicolás Lichtmaier (po: es) luebbe Lübbe Onken (po: de) jensseidel Jens Seidel (po: de) - astieger Andreas Stieger (po: de) oyvindmo Øyvind Møll (po: nb) sunny256 Øyvind A. Holm (po: nb) jzgoda Jaroslaw Zgoda (po: pl) @@ -188,8 +192,7 @@ Commit access for specific areas: lark Wang Jian (po: zh_CN) [EMAIL IS BOUNCING] giorgio_valoti Giorgio Valoti (po: it) - nebiac Federico Nebiacolombo (po: it) [EMAIL - IS BOUNCING] + nebiac Federico Nebiacolombo (po: it) fabien Fabien Coelho (po: fr) marcelg Marcel Gosselin (po: fr) mattiase Mattias Engdegård (po: sv) diff --git a/INSTALL b/INSTALL index 3ff16702aea5..dcbf67c37aaa 100644 --- a/INSTALL +++ b/INSTALL @@ -3,7 +3,7 @@ A Quick Guide ====================================== -$LastChangedDate: 2015-12-12 04:00:43 +0000 (Sat, 12 Dec 2015) $ +$LastChangedDate: 2017-12-25 04:00:08 +0000 (Mon, 25 Dec 2017) $ Contents: @@ -22,7 +22,7 @@ Contents: E. Building the Latest Source under Windows III. BUILDING A SUBVERSION SERVER - A. Setting Up Apache + A. Setting Up Apache Httpd B. Making and Installing the Subversion Server C. Configuring Apache for Subversion D. Running and Testing @@ -55,7 +55,7 @@ I. INTRODUCTION 'installers' for both Windows and OS X. Visit this page for package links: - http://subversion.apache.org/packages.html + https://subversion.apache.org/packages.html For those of you who still wish to build from source, Subversion follows the Unix convention of "./configure && make", but it has @@ -96,9 +96,9 @@ I. INTRODUCTION These diff streams are used everywhere -- over the network, in the repository, and in the client's working copy. - * libserf (OPTIONAL for client) + * Apache Serf (OPTIONAL for client) - The Serf library allows the Subversion client to send HTTP + The Apache Serf library allows the Subversion client to send HTTP requests. This is necessary if you want your client to access a repository served by the Apache HTTP server. There is an alternate 'svnserve' server as well, though, and clients @@ -110,10 +110,16 @@ I. INTRODUCTION * OpenSSL (OPTIONAL for client and server) OpenSSL enables your client to access SSL-encrypted https:// - URLs (using libserf) in addition to unencrypted http:// URLs. + URLs (using Apache Serf) in addition to unencrypted http:// URLs. To use SSL with Subversion's WebDAV server, Apache needs to be compiled with OpenSSL as well. + * Netwide Assembler (OPTIONAL for client and server) + + The Netwide Assembler (NASM) is used to build the (optionally) + assembler modules of OpenSSL. As of OpenSSL 1.1.0 NASM is the + only supported assembler. + * Berkeley DB (OPTIONAL for client and server) There are two different repository 'back-end' @@ -185,7 +191,7 @@ I. INTRODUCTION Subversion's own configure script may need to be told where to find them, if they were not installed in standard system locations. - Note: there are optional dependencies (such as openssl, swig, and httpd) + Note: there are optional dependencies (such as OpenSSL, swig, and httpd) which get-deps.sh does not download. Note: Because previous builds of Subversion may have installed older @@ -202,7 +208,7 @@ I. INTRODUCTION If you do not have a pre-installed APR and APR-util, you will need to get these yourself: - http://apr.apache.org/download.cgi + https://apr.apache.org/download.cgi On Unix systems, if you already have the APR libraries compiled and do not wish to regenerate them from source code, then Subversion needs to @@ -271,11 +277,11 @@ I. INTRODUCTION newer. The autogen.sh script knows about that. - 5. Serf library 1.3.4 or newer (OPTIONAL) + 5. Apache Serf library 1.3.4 or newer (OPTIONAL) If you want your client to be able to speak to an Apache server (via a http:// or https:// URL), you must link against - serf. Though optional, we strongly recommend this. + Apache Serf. Though optional, we strongly recommend this. In order to use ra_serf, you must install serf, and run Subversion's ./configure with the argument --with-serf. If serf is installed in a @@ -285,31 +291,31 @@ I. INTRODUCTION instead. - Serf can be obtained via your system's package distribution + Apache Serf can be obtained via your system's package distribution system or directly from http://code.google.com/p/serf/. - For more information on serf and Subversion's ra_serf, see the file - subversion/libsvn_ra_serf/README. + For more information on Apache Serf and Subversion's ra_serf, see the + file subversion/libsvn_ra_serf/README. 6. OpenSSL (OPTIONAL) - ### needs some updates. I think serf automagically handles + ### needs some updates. I think Apache Serf automagically handles ### finding OpenSSL, but we may need more docco here. and w.r.t ### zlib. - The Serf library has support for SSL encryption by relying on the + The Apache Serf library has support for SSL encryption by relying on the OpenSSL library. - a. Using OpenSSL on the client through Serf + a. Using OpenSSL on the client through Apache Serf - On Unix systems, to build Serf with OpenSSL, you need OpenSSL + On Unix systems, to build Apache Serf with OpenSSL, you need OpenSSL installed on your system, and you must add "--with-ssl" as a "./configure" parameter. If your OpenSSL installation is hard - for Serf to find, you may need to use "--with-libs=/path/to/lib" - in addition. In particular, on Red Hat (but not Fedora Core) it - is necessary to specify "--with-libs=/usr/kerberos" for OpenSSL - to be found. You can also specify a path to the zlib library - using "--with-libs". + for Apache Serf to find, you may need to use + "--with-libs=/path/to/lib" in addition. In particular, on Red Hat + (but not Fedora Core) it is necessary to specify + "--with-libs=/usr/kerberos" for OpenSSL to be found. You can also + specify a path to the zlib library using "--with-libs". Under Windows, you can specify the paths to these libraries by passing the options --with-zlib and --with-openssl to gen-make.py. @@ -334,7 +340,7 @@ I. INTRODUCTION including instructions for building and packaging on both Unix systems and Windows, at: - http://www.openssl.org/ + https://www.openssl.org/ 7. Berkeley DB 4.X (OPTIONAL) @@ -358,7 +364,7 @@ I. INTRODUCTION You'll need Berkeley DB installed on your system. You can get it from: - http://www.oracle.com/technology/software/products/berkeley-db/index.html + http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/overview/index.html If you have Berkeley DB installed in a place not searched by default for includes and libraries, add something like this: @@ -393,7 +399,7 @@ I. INTRODUCTION 9. Apache Web Server 2.2.X or newer (OPTIONAL) - (http://httpd.apache.org/download.cgi) + (https://httpd.apache.org/download.cgi) The Apache httpd server is one of two methods to make your Subversion repository available over a network - the other is a custom server @@ -404,7 +410,7 @@ I. INTRODUCTION is done: See section III for details. - 10. Python 2.7 or newer (http://www.python.org/) (OPTIONAL) + 10. Python 2.7 or newer (https://www.python.org/) (OPTIONAL) If you want to run "make check" or build from the latest source under Unix/Windows as described in section II.B, II.E and III.D, @@ -424,7 +430,7 @@ I. INTRODUCTION 12. SQLite (REQUIRED) - Subversion requires SQLite version 3.7.12 or above. You can meet this + Subversion requires SQLite version 3.8.2 or above. You can meet this dependency several ways: * Use an SQLite amalgamation file. * Specify an SQLite installation to use. @@ -435,7 +441,7 @@ I. INTRODUCTION --with-sqlite configure option. This file also ships with the Subversion dependencies distribution, or you can download it from SQLite: - http://www.sqlite.org/download.html + https://www.sqlite.org/download.html 13. pkg-config (Unix only, OPTIONAL) @@ -521,6 +527,19 @@ I. INTRODUCTION $ ./get-dep.sh gmock + 22. LZ4 (OPTIONAL) + + Subversion uses LZ4 compression libary version r129 or above. Configure + will attempt to locate the system library by default using pkg-config + and known paths. + + If it is installed in a non-standard location, then use: + + --with-lz4=/path/to/liblz4 + + If configure should use the version bundled with the sources, use: + --with-lz4=internal + D. Documentation The primary documentation for Subversion is the free book @@ -542,7 +561,7 @@ II. INSTALLATION Download the most recent distribution tarball from: - http://subversion.apache.org/download/ + https://subversion.apache.org/download/ Unpack it, and use the standard GNU procedure to compile: @@ -674,27 +693,21 @@ II. INSTALLATION D. Installing from a Zip or Installer File under Windows - -------------------------------------------------------- + ----------------------------------------------------- Of all the ways of getting a Subversion client, this is the - easiest. Download a Zip (*.zip) or self-extracting installer - (*-setup.exe) file from: + easiest. Download a Zip or self-extracting installer via: - http://subversion.apache.org/packages#windows + https://subversion.apache.org/packages.html#windows - For a Zip file, run your unzipping utility (WinZIP, ZipGenius, - UltimateZIP, FreeZIP, whatever) and extract the DLLs and EXEs to - a directory of your choice. Included in the download is the SVN - client, the SVNADMIN administration tool, and the SVNLOOK - reporting tool. + For a Zip file extract the DLLs and EXEs to a directory of your + choice. Included in the download are among other tools the SVN + client, the SVNADMIN administration tool and the SVNLOOK reporting + tool. - Note that if you need support for non-English locales you'll have - to set the APR_ICONV_PATH environment variable to the path of the - iconv directory in the folder that contains the Subversion install. - - You may also want to add the bin directory in the Subversion folder - to your PATH environment variable so as to not have to use the full - path when running Subversion commands. + You may want to add the bin directory in the Subversion folder to your + PATH environment variable so as to not have to use the full path when + running Subversion commands. To test the installation, open a DOS box (run either "cmd" or "command" from the Start menu's "Run..." menu option), change to @@ -713,58 +726,41 @@ II. INSTALLATION E.1 Prerequisites - * Visual Studio 6 and service pack. It can be built with later versions - of Visual Studio (Visual Studio.NET 2005-2015, Visual C++ Express - 2005-2010, Visual Studio Express 2012-2013 and Visual Studio Community - 2013-2015) but these instructions assume VS6. - * A recent Windows SDK. (Not needed with Visual Studio 2005 and later) - If you are using Visual Studio 6, you need the latest SDK which - is compatible with VC6, which is the one from February 2003. - You can get it from MSDN: - https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/e1147034-9b0b-4494-a5bc-6dfebb6b7eb1/download-and-install-microsoft-platform-sdk-febuary-2003-last-version-with-vc6-support?forum=windowssdk - * Python 2.7 or higher, downloaded from http://www.python.org/ which is + * Microsoft Visual Studio. Any recent (2005+) version containing the + Visual C++ component will work (E.g. Professional, Express, Community + Edition). Make sure you enable C++ support during setup. + * Python 2.7 or higher, downloaded from https://www.python.org/ which is used to generate the project files. Note that Python 3.x is not supported (yet). - * Perl 5.8 or higher from http://www.activestate.com/ - * Awk (from http://www.cs.princeton.edu/~bwk/btl.mirror/awk95.exe) is - needed to compile Apache or APR. Note that this is the actual awk - program, not an installer - just rename it to awk.exe and it is - ready to use. + * Perl 5.8 or higher from https://www.perl.org/get.html + * Awk (from https://www.cs.princeton.edu/~bwk/btl.mirror/awk95.exe) is + needed to compile Apache. Note that this is the actual awk program, + not an installer - just rename it to awk.exe and it is ready to use. * Apache apr, apr-util, and optionally apr-iconv libraries, version - 1.3 or later. Included in both the Subversion dependencies ZIP file - and the Apache 2 source zip. If you are building from a Subversion + 1.3 or later (1.2 for apr-iconv). If you are building from a Subversion checkout and have not downloaded Apache 2, then get these 3 libraries - from http://www.apache.org/dist/apr/. - * SQLite 3.7.12 or higher from http://www.sqlite.org/download.html - * ZLib 1.2 or higher is required and is included in the Subversion - dependencies zip file or can be obtained from http://www.zlib.net/ - * Either a Subversion client binary from http://subversion.apache.org/ to - do the initial checkout of the Subversion source or the zip file - source distribution. See the section "Bootstrapping from a Zip or - Installer File under Windows" above for more. - * A means of unpacking the files, e.g., WinZIP or similar. + from https://www.apache.org/dist/apr/. + * SQLite 3.8.2 or higher from https://www.sqlite.org/download.html + (3.8.11.1 or higher recommended) + * ZLib 1.2 or higher is required and can be obtained from + http://www.zlib.net/ + * Either a Subversion client binary from + https://subversion.apache.org/packages.html to do the initial checkout + of the Subversion source or the zip file source distribution. Additional Options - * [Optional] Apache 2 source, downloaded from - http://httpd.apache.org/download.cgi, these instructions assume + * [Optional] Apache Httpd 2 source, downloaded from + https://httpd.apache.org/download.cgi, these instructions assume version 2.0.58. This is only needed for building the Subversion server Apache modules. ### FIXME Apache 2.2 or greater required. - * [Optional] Apache 2 msi install file, also from - http://httpd.apache.org/download.cgi (required for running the - tests). Only needed for testing the server dso modules and if - you are using Visual Studio 6. - Note that if you are not using Visual Studio 6 (and you want to - run and test the server modules) then you must rebuild Apache - from source -- do not use the stock MSI since mixing C runtime - libraries is not supported. - * [Optional] Berkeley DB for backend support of the server - components -- versions 4.3.27 and 4.4.20 are available from - http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=688 - as db-4.3.27-win32.zip and db-4.4.20-win32.zip. + * [Optional] Berkeley DB for backend support of the server components + are available from + http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index-082944.html + (Version 4.4.20 or in specific cases some higher version recommended) For more information see Section I.C.7. - * [Optional] Openssl 0.9.7f or higher can be obtained from - http://www.openssl.org/source/openssl-0.9.7f.tar.gz + * [Optional] Openssl can be obtained from https://www.openssl.org/source/ + * [Optional] NASM can be obtained from http://www.nasm.us/ * [Optional] A modified version of GNU libintl, called svn-win32-libintl.zip, can be used for displaying localized messages. Available at: @@ -774,14 +770,11 @@ II. INSTALLATION binaries from http://gnuwin32.sourceforge.net/. You'll need the binaries (gettext-0.14.1-bin.zip) and dependencies (gettext-0.14.1-dep.zip). - * [Optional] An assembler, e.g., MASM32 from http://www.masm32.com/ - or nasm which is available from - http://www.nasm.us/pub/nasm/releasebuilds/?C=M;O=D E.2 Notes - The Serf library supports secure connections with OpenSSL and - on-the-wire compression with zlib. If you want to use the + The Apache Serf library supports secure connections with OpenSSL + and on-the-wire compression with zlib. If you want to use the secure connections feature, you should pass the option "--with-openssl" to the gen-make.py script. See Section I.C.6 for more details. @@ -802,35 +795,20 @@ II. INSTALLATION installer to register environment variables or run VCVARS32.BAT before building anything. If you are using a newer Visual Studio, use the 'Visual Studio 20xx Command Prompt' on the Start menu. - * Install and register a recent Windows Core SDK if you are using - Visual Studio 6. This is a quote from the Microsoft February 2003 - SDK documentation: - - "To register the SDK bin, include, and library directories with - Microsoft Visual Studio® version 6.0 and Visual Studio .NET, - click Start, point to All Programs, point to Microsoft Platform - SDK February 2003, point to Visual Studio Registration, and then - click Register PSDK Directories with Visual Studio. This - registration process places the SDK bin, include, and library - directories at the beginning of the search paths, which ensures - that the latest headers and libraries are used when building - applications in the IDE. Note that for Visual Studio 6.0 - integration to succeed, Visual Studio 6.0 must run at least once - before you select Register PSDK Directories with Visual - Studio. Also note that when this option is run, the IDEs should - not be running." - * Install Python and add it to your path * Install Perl (it should add itself to the path) + ### Subversion doesn't need perl. Only some dependencies need it + (OpenSSL and some apr scripts) * Copy AWK (awk95.exe) to awk.exe (e.g. SVN\awk\awk.exe) and add the directory containing it (e.g. SVN\awk) to the path. - * [Optional] Install Apache 2 using the msi file if you are going to test - the server dso modules and are using Visual Studio 6. You must build - and install it from source if you are not using Visual Studio 6 and - want to build and/or test the server modules. + ### Subversion doesn't need awk. Only some dependencies need it + (some apr scripts) + * [Optional] Install NASM and add it to your path + ### Subversion doesn't need NASM. Only some dependencies need it + optionally (OpenSSL) * [Optional] If you checked out Subversion from the repository and want to build Subversion with http/https access support then install the - serf sources into SVN\src-trunk\serf. + Apache Serf sources into SVN\src-trunk\serf. * [Optional] If you want BDB backend support, extract the Berkeley DB files into SVN\src-trunk\db4-win32. It's a good idea to add SVN\src-trunk\db4-win32\bin to your PATH, so that Subversion can find @@ -846,6 +824,7 @@ II. INSTALLATION SVN\src-trunk\db4-win32\include, and all the import libraries to SVN\src-trunk\db4-win32\lib. Again, the DLLs should be somewhere in your path. + ### Just use --with-serf instead of the hardcoded path * [Optional] If you want to build the server modules, extract Apache source into SVN\httpd-2.x.x. @@ -858,22 +837,22 @@ II. INSTALLATION - Extract the apr, apr-util and apr-iconv directories from the srclib folder in the Apache httpd source into SVN\apr, SVN\apr-util, and SVN\apr-iconv respectively. + ### Just use --with-apr, etc. instead of the hardcoded paths * Extract the ZLib sources into SVN\zlib if you are not using the zlib included in the dependencies zip file. - * [Optional] If you want secure connection (https) client support, or if - you are building with enabled support for serf extract openssl into - SVN\openssl-x.x.x + ### Just use --with-zlib instead of the hardcoded path + * [Optional] If you want secure connection (https) client support extract + OpenSSL into SVN\openssl + ### And pass the path to both serf and gen-make.py * [Optional] If you want localized message support, extract svn-win32-libintl.zip into SVN\svn-win32-libintl and extract gettext-x.x.x-bin.zip and gettext-x.x.x-dep.zip into SVN\gettext-x.x.x-bin. - Add SVN\gettext-x.x.x-bin\bin to your path. - * [Optional] Extract MASM32 (only the ML.EXE and ML.ERR files) into - SVN\asm (or extract nasm into SVN\asm) and put it in your path. - * Download the SQLite amalgemation from - http://www.sqlite.org/download.html - and extract it into SVN\sqlite-amalgemation. - See I.C.12 for alternatives to using the amalgemation package. + Add SVN\gettext-x.x.x-bin\bin to your path. + * Download the SQLite amalgamation from + https://www.sqlite.org/download.html + and extract it into SVN\sqlite-amalgamation. + See I.C.12 for alternatives to using the amalgamation package. E.4 Building the Binaries @@ -890,7 +869,7 @@ II. INSTALLATION C:>set VER=trunk C:>set DIR=trunk C:>set BUILD_ROOT=C:\SVN - C:>set PYTHONDIR=C:\Python22 + C:>set PYTHONDIR=C:\Python27 C:>set AWKDIR=C:\SVN\Awk C:>set ASMDIR=C:\SVN\asm C:>set SDKINC="C:\Program Files\Microsoft SDK\include" @@ -901,9 +880,9 @@ II. INSTALLATION C:>set INCLUDE=%SDKINC%;%INCLUDE% C:>set LIB=%SDKLIB%;%LIB% - OpenSSL + OpenSSL < 1.1.0 - C:>cd openssl-0.9.7f + C:>cd openssl C:>perl Configure VC-WIN32 [*] C:>call ms\do_masm C:>nmake -f ms\ntdll.mak @@ -913,11 +892,23 @@ II. INSTALLATION *Note: Use "call ms\do_nasm" if you have nasm instead of MASM, or "call ms\do_ms" if you don't have an assembler. + Also if you are using OpenSSL >= 1.0.0 masm is no longer + supported. You will have to use do_nasm or do_ms in this case. + + OpenSSL >= 1.1.0 + + C:>cd openssl + C:>perl Configure VC-WIN32 + C:>nmake + C:>nmake test + C:>cd .. Apache 2 This step is only required for building the server dso modules. + ### FIXME Apache 2.2 or greater required. Old build instructions for VC6. + C:>set APACHEDIR=C:\Program Files\Apache Group\Apache2 C:>msdev httpd-2.0.58\apache.dsw /MAKE "BuildBin - Win32 Release" @@ -946,11 +937,11 @@ II. INSTALLATION Note that you'd make sure to define ZLIB_WINAPI in the ZLib config header and move the lib-file into the zlib root-directory. - Serf + Apache Serf - ### Section about serf might be required/useful to add. - ### scons is required too and serf needs to be configured prior to be - ### able to build Subversion using: + ### Section about Apache Serf might be required/useful to add. + ### scons is required too and Apache Serf needs to be configured prior to + ### be able to build Subversion using: ### scons APR=[PATH_TO_APR] APU=[PATH_TO_APU] OPENSSL=[PATH_TO_OPENSSL] ### ZLIB=[PATH_TO_ZLIB] PREFIX=[PATH_TO_SERF_DEST] ### scons check @@ -967,28 +958,16 @@ II. INSTALLATION the APR libraries; the options are --with-apr, --with-apr-util and --with-apr-iconv. * If you would like a debug build substitute Debug for Release in - the msdev/msbuild commands. + the msbuild command. * There have been rumors that Subversion on Win32 can be built using the latest cygwin, you probably don't want the zip file source distribution though. ymmv. - * The /USEENV switch to msdev makes it take notice of the INCLUDE and - LIB environment variables, it also makes it ignore its own lib and - include settings so you need to have the Windows SDK lib and include - directories in the LIB and INCLUDE environment variables. Do *not* - use this switch when starting up the msdev Visual environment. If you - wish to build in the Visual environment the SDK lib and include - directories must be in the Tools/Options/Directories settings (if you - followed the 'Register the SDK with Visual Studio 6' instructions - above this has been done for you). - * If you are using Visual Studio later than VC6 change -t dsw into - -t vcproj and add the --vsnet-version=20xx option on the gen-make.py - command. - In this case you will also have to distribute the C runtime dll with - the binaries. Also, since Apache/APR do not provide .vcproj files, - you will need to convert the Apache/APR .dsp files to .vcproj files - with Visual Studio before building -- just open the Apache .dsw file - and answer 'Yes To All' when the conversion dialog pops up, or you - can open the individual .dsp files and convert them one at a time. + * You will also have to distribute the C runtime dll with the binaries. + Also, since Apache/APR do not provide .vcproj files, you will need to + convert the Apache/APR .dsp files to .vcproj files with Visual Studio + before building -- just open the Apache .dsw file and answer 'Yes To + All' when the conversion dialog pops up, or you can open the individual + .dsp files and convert them one at a time. The Apache/APR projects required by Subversion are: apr-util\libaprutil.dsp, apr\libapr.dsp, apr-iconv\libapriconv.dsp, apr-util\xml\expat\lib\xml.dsp, @@ -1003,24 +982,13 @@ II. INSTALLATION gen-make.py will already have been run. If the source is from the zip file, Apache 2 has not been built so gen-make.py must be run: - C:>python gen-make.py -t dsp --with-berkeley-db=db4-win32 - --with-openssl=..\openssl-0.9.7f --with-zlib=..\zlib + C:>python gen-make.py --vsnet-version=20xx --with-berkeley-db=db4-win32 + --with-openssl=..\openssl --with-zlib=..\zlib --with-libintl=..\svn-win32-libintl Then build subversion: - C:>msdev subversion_msvc.dsw /USEENV /MAKE "__ALL_TESTS__ - Win32 Release" - C:>cd .. - - Or, with Visual C++.NET 2005 or C++ Express 2005: - - C:>devenv subversion_vcnet.sln /build "Release" /project "__ALL_TESTS__" - C:>cd .. - - Or, with Visual C++.NET 2008+, C++ Express 2008+, Studio Express 2012+ or - Studio Community 2013+: - - C:>msbuild subversion_vcnet.sln /t:__ALL_TESTS__ /p:Configuration=Release + C:>msbuild subversion_vcnet.sln /t:__MORE__ /p:Configuration=Release C:>cd .. The binaries have now been built. @@ -1111,10 +1079,10 @@ III. BUILDING A SUBVERSION SERVER svnserve instead, jump right to section E for a quick explanation. - A. Setting Up Apache - ----------------- + A. Setting Up Apache Httpd + ----------------------- - 1. Obtaining and Installing Apache 2 + 1. Obtaining and Installing Apache Httpd 2 Subversion tries to compile against the latest released version of Apache httpd 2.2+. The easiest thing for you to do is download @@ -1123,7 +1091,7 @@ III. BUILDING A SUBVERSION SERVER If you have questions about the Apache httpd 2.2 build, please consult the httpd install documentation: - http://httpd.apache.org/docs-2.2/install.html + https://httpd.apache.org/docs-2.2/install.html At the top of the httpd tree: @@ -1206,8 +1174,8 @@ III. BUILDING A SUBVERSION SERVER Section II.E explains how to build the server on Windows. - C. Configuring Apache for Subversion - --------------------------------- + C. Configuring Apache Httpd for Subversion + --------------------------------------- The following section is an abbreviated version of the information in the Subversion Book @@ -1221,7 +1189,7 @@ III. BUILDING A SUBVERSION SERVER /usr/local/apache2/conf/httpd.conf to reflect your setup. At a minimum you should look at the User, Group and ServerName directives. Full details on setting up apache can be found at: - http://httpd.apache.org/docs-2.2/ + https://httpd.apache.org/docs-2.2/ First, your httpd.conf needs to load the mod_dav_svn module. If you pass --enable-mod-activation to Subversion's configure, @@ -1279,7 +1247,7 @@ III. BUILDING A SUBVERSION SERVER These are only a few simple examples. For a complete tutorial on Apache access control, please consider taking a look at the tutorials found under "Security" on the following page: - http://httpd.apache.org/docs-2.0/misc/tutorials.html + https://httpd.apache.org/docs-2.0/misc/tutorials.html In order for 'svn cp' to work (which is actually implemented as a DAV COPY command), mod_dav needs to be able to determine the @@ -1302,7 +1270,7 @@ III. BUILDING A SUBVERSION SERVER NOTE: If you are unfamiliar with an Apache directive, or not exactly sure about what it does, don't hesitate to look it up in the - documentation: http://httpd.apache.org/docs-2.2/mod/directives.html. + documentation: https://httpd.apache.org/docs-2.2/mod/directives.html. NOTE: Make sure that the user 'nobody' (or whatever UID the httpd process runs as) has permission to read and write the @@ -1333,7 +1301,7 @@ III. BUILDING A SUBVERSION SERVER To run the regression test suite for networked Subversion, see the instructions in subversion/tests/cmdline/README. For advice about tracing problems, see "Debugging the server" in - http://subversion.apache.org/docs/community-guide/. + https://subversion.apache.org/docs/community-guide/. E. Alternative: 'svnserve' and ra_svn @@ -1376,11 +1344,11 @@ IV. PLATFORM-SPECIFIC ISSUES between parent and child processes. The httpd Apache group explains this a lot better: - http://www.apache.org/dist/httpd/binaries/win32/#xpbug + https://www.apache.org/dist/httpd/binaries/win32/#xpbug And there's an item about this in the Subversion FAQ: - http://subversion.apache.org/faq.html#windows-xp-server + https://subversion.apache.org/faq.html#windows-xp-server The only known workaround for now is to update to Windows XP SP1 (or higher). diff --git a/LICENSE b/LICENSE index 8b1b7abcf6d3..5e9188ca232e 100644 --- a/LICENSE +++ b/LICENSE @@ -366,3 +366,60 @@ subversion/libsvn_subr/x509.h * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +For the (modified) 'linenoise' library in tools/dev/svnmover/linenoise + + Copyright (c) 2010-2014, Salvatore Sanfilippo + Copyright (c) 2010-2013, Pieter Noordhuis + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +For the (modified) LZ4 library files in subversion/libsvn_subr/lz4 + + LZ4 Library + Copyright (c) 2011-2016, Yann Collet + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Makefile.in b/Makefile.in index e63a09c6a6b7..f4c6e61b9397 100644 --- a/Makefile.in +++ b/Makefile.in @@ -54,6 +54,8 @@ SVN_SERF_LIBS = @SVN_SERF_LIBS@ SVN_SQLITE_LIBS = @SVN_SQLITE_LIBS@ SVN_XML_LIBS = @SVN_XML_LIBS@ SVN_ZLIB_LIBS = @SVN_ZLIB_LIBS@ +SVN_LZ4_LIBS = @SVN_LZ4_LIBS@ +SVN_UTF8PROC_LIBS = @SVN_UTF8PROC_LIBS@ LIBS = @LIBS@ @@ -130,14 +132,16 @@ INCLUDES = -I$(top_srcdir)/subversion/include -I$(top_builddir)/subversion \ @SVN_DB_INCLUDES@ @SVN_GNOME_KEYRING_INCLUDES@ \ @SVN_KWALLET_INCLUDES@ @SVN_MAGIC_INCLUDES@ \ @SVN_SASL_INCLUDES@ @SVN_SERF_INCLUDES@ @SVN_SQLITE_INCLUDES@ \ - @SVN_XML_INCLUDES@ @SVN_ZLIB_INCLUDES@ + @SVN_XML_INCLUDES@ @SVN_ZLIB_INCLUDES@ @SVN_LZ4_INCLUDES@ \ + @SVN_UTF8PROC_INCLUDES@ APACHE_INCLUDES = @APACHE_INCLUDES@ APACHE_LIBEXECDIR = $(DESTDIR)@APACHE_LIBEXECDIR@ APACHE_LDFLAGS = @APACHE_LDFLAGS@ -SVN_USE_GMOCK = @SVN_USE_GMOCK@ -GMOCK_INCLUDES = -I@GMOCK_SRCDIR@ +SVN_USE_GOOGLEMOCK = @SVN_USE_GOOGLEMOCK@ +GOOGLEMOCK_INCLUDES = -I@GOOGLEMOCK_SRCDIR@/googlemock/include -I@GOOGLEMOCK_SRCDIR@/googletest/include +GOOGLEMOCK_LIB_INCLUDES = -I@GOOGLEMOCK_SRCDIR@/googlemock -I@GOOGLEMOCK_SRCDIR@/googletest $(GOOGLEMOCK_INCLUDES) SWIG = @SWIG@ SWIG_PY_INCLUDES = @SWIG_PY_INCLUDES@ -I$(SWIG_SRC_DIR)/python/libsvn_swig_py @@ -186,7 +190,10 @@ CXXMAINTAINERFLAGS = @CXXMAINTAINERFLAGS@ CPPFLAGS = @CPPFLAGS@ $(EXTRA_CPPFLAGS) LDFLAGS = @LDFLAGS@ $(EXTRA_LDFLAGS) SWIG_LDFLAGS = @SWIG_LDFLAGS@ $(EXTRA_SWIG_LDFLAGS) -SWIG_CPPFLAGS = @SWIG_CPPFLAGS@ $(EXTRA_CPPFLAGS) +SWIG_FEATURES = @SWIG_FEATURES@ +SWIG_PY_FEATURES = @SWIG_PY_FEATURES@ +SWIG_PL_FEATURES = @SWIG_PL_FEATURES@ +SWIG_RB_FEATURES = @SWIG_RB_FEATURES@ COMPILE = $(CC) $(CMODEFLAGS) $(CPPFLAGS) $(CMAINTAINERFLAGS) $(CFLAGS) $(INCLUDES) COMPILE_NOWARN = $(CC) $(CMODEFLAGS) $(CPPFLAGS) $(CNOWARNFLAGS) $(CFLAGS) $(INCLUDES) @@ -199,7 +206,9 @@ LT_COMPILE_CXX_NOWARN = $(LIBTOOL) $(LTCXXFLAGS) --mode=compile $(COMPILE_CXX_NO LT_EXECUTE = $(LIBTOOL) $(LTFLAGS) --mode=execute `for f in $(abs_builddir)/subversion/*/*.la; do echo -dlopen $$f; done` # special compilation for files destined for mod_dav_svn -COMPILE_APACHE_MOD = $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) $(CMODEFLAGS) $(CPPFLAGS) $(CFLAGS) $(CMAINTAINERFLAGS) $(LT_CFLAGS) $(APACHE_INCLUDES) $(INCLUDES) -o $@ -c +COMPILE_APACHE_MOD = $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) $(CMODEFLAGS) $(CPPFLAGS) $(CFLAGS) $(CMAINTAINERFLAGS) $(LT_CFLAGS) $(APACHE_INCLUDES) $(INCLUDES) -o $@ -c -shared +COMPILE_SHARED_ONLY_LIB = $(LT_COMPILE) -o $@ -c -shared +COMPILE_SHARED_ONLY_CXX_LIB = $(LT_COMPILE_CXX) -o $@ -c -shared # special compilation for files destined for libsvn_swig_* (e.g. swigutil_*.c) COMPILE_SWIG_PY = $(LIBTOOL) $(LTFLAGS) --mode=compile $(SWIG_PY_COMPILE) $(CPPFLAGS) $(LT_CFLAGS) -DSWIGPYTHON $(SWIG_PY_INCLUDES) $(INCLUDES) -o $@ -c @@ -252,8 +261,8 @@ TEST_SHLIB_VAR_SWIG_RB=\ # special compilation for files destined for cxxhl COMPILE_CXXHL_CXX = $(LT_COMPILE_CXX) $(CXXHL_INCLUDES) -o $@ -c -COMPILE_GMOCK_CXX = $(LT_COMPILE_CXX_NOWARN) $(GMOCK_INCLUDES) -o $@ -c -COMPILE_CXXHL_GMOCK_CXX = $(LT_COMPILE_CXX) $(CXXHL_INCLUDES) $(GMOCK_INCLUDES) -o $@ -c +COMPILE_GOOGLEMOCK_CXX = $(LT_COMPILE_CXX_NOWARN) $(GOOGLEMOCK_LIB_INCLUDES) -o $@ -c +COMPILE_CXXHL_GOOGLEMOCK_CXX = $(LT_COMPILE_CXX) $(CXXHL_INCLUDES) $(GOOGLEMOCK_INCLUDES) -o $@ -c LINK = $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LT_LDFLAGS) $(CFLAGS) $(LDFLAGS) -rpath $(libdir) LINK_LIB = $(LINK) $(LT_SO_VERSION) @@ -261,11 +270,9 @@ LINK_CXX = $(LIBTOOL) $(LTCXXFLAGS) --mode=link $(CXX) $(LT_LDFLAGS) $(CXXFLAGS) LINK_CXX_LIB = $(LINK_CXX) $(LT_SO_VERSION) # special link rule for mod_dav_svn -LINK_APACHE_MOD = $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LT_LDFLAGS) $(CFLAGS) $(LDFLAGS) -rpath $(APACHE_LIBEXECDIR) -avoid-version -module $(APACHE_LDFLAGS) +LINK_APACHE_MOD = $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LT_LDFLAGS) $(CFLAGS) $(LDFLAGS) -rpath $(APACHE_LIBEXECDIR) -avoid-version -module $(APACHE_LDFLAGS) -shared # Special LDFLAGS for some libraries -libsvn_auth_gnome_keyring_LDFLAGS = @libsvn_auth_gnome_keyring_LDFLAGS@ -libsvn_auth_kwallet_LDFLAGS = @libsvn_auth_kwallet_LDFLAGS@ libsvn_client_LDFLAGS = @libsvn_client_LDFLAGS@ libsvn_delta_LDFLAGS = @libsvn_delta_LDFLAGS@ libsvn_diff_LDFLAGS = @libsvn_diff_LDFLAGS@ @@ -280,6 +287,10 @@ libsvn_ra_svn_LDFLAGS = @libsvn_ra_svn_LDFLAGS@ libsvn_repos_LDFLAGS = @libsvn_repos_LDFLAGS@ libsvn_subr_LDFLAGS = @libsvn_subr_LDFLAGS@ libsvn_wc_LDFLAGS = @libsvn_wc_LDFLAGS@ +shared_only_LDFLAGS = @shared_only_LDFLAGS@ + +LINK_SHARED_ONLY_LIB = $(LINK_LIB) $(shared_only_LDFLAGS) -shared +LINK_SHARED_ONLY_CXX_LIB = $(LINK_CXX_LIB) $(shared_only_LDFLAGS) -shared # Compilation of SWIG-generated C source code COMPILE_PY_WRAPPER = $(LIBTOOL) $(LTFLAGS) --mode=compile $(SWIG_PY_COMPILE) $(LT_CFLAGS) $(CPPFLAGS) $(SWIG_PY_INCLUDES) -prefer-pic -c -o $@ @@ -371,6 +382,7 @@ INSTALL_EXTRA_SWIG_RB=\ APXS = @APXS@ HTTPD_VERSION = @HTTPD_VERSION@ +HTTPD_WHITELIST = @HTTPD_WHITELIST@ PYTHON = @PYTHON@ PERL = @PERL@ @@ -498,17 +510,17 @@ clean-javahl: check-tigris-javahl: javahl-compat @FIX_JAVAHL_LIB@ $(TEST_SHLIB_VAR_JAVAHL) \ - $(JAVA) -Xcheck:jni "-Dtest.rootdir=$(javahl_test_rootdir)" "-Dtest.srcdir=$(javahl_test_srcdir)" "-Dtest.rooturl=$(BASE_URL)" "-Dtest.fstype=$(FS_TYPE)" "-Djava.library.path=@JAVAHL_OBJDIR@:$(libdir)" -classpath "$(javahl_compat_tests_PATH):$(javahl_tests_CLASSPATH)" "-Dtest.tests=$(JAVAHL_TESTS)" org.tigris.subversion.javahl.RunTests + $(JAVA) -Xcheck:jni "-Dtest.rootdir=$(javahl_test_rootdir)" "-Dtest.srcdir=$(javahl_test_srcdir)" "-Dtest.rooturl=$(BASE_URL)" "-Dtest.fstype=$(FS_TYPE)" "-Djava.library.path=@JAVAHL_OBJDIR@:$(libdir)" -classpath "$(javahl_compat_tests_PATH):$(javahl_tests_CLASSPATH)" "-Dtest.cleanup=$(JAVAHL_CLEANUP)" "-Dtest.tests=$(JAVAHL_TESTS)" org.tigris.subversion.javahl.RunTests check-apache-javahl: javahl @FIX_JAVAHL_LIB@ $(TEST_SHLIB_VAR_JAVAHL) \ - $(JAVA) -Xcheck:jni "-Dtest.rootdir=$(javahl_test_rootdir)" "-Dtest.srcdir=$(javahl_test_srcdir)" "-Dtest.rooturl=$(BASE_URL)" "-Dtest.fstype=$(FS_TYPE)" "-Djava.library.path=@JAVAHL_OBJDIR@:$(libdir)" -classpath "$(javahl_tests_PATH):$(javahl_tests_CLASSPATH)" "-Dtest.tests=$(JAVAHL_TESTS)" org.apache.subversion.javahl.RunTests + $(JAVA) -Xcheck:jni "-Dtest.rootdir=$(javahl_test_rootdir)" "-Dtest.srcdir=$(javahl_test_srcdir)" "-Dtest.rooturl=$(BASE_URL)" "-Dtest.fstype=$(FS_TYPE)" "-Djava.library.path=@JAVAHL_OBJDIR@:$(libdir)" -classpath "$(javahl_tests_PATH):$(javahl_tests_CLASSPATH)" "-Dtest.cleanup=$(JAVAHL_CLEANUP)" "-Dtest.tests=$(JAVAHL_TESTS)" org.apache.subversion.javahl.RunTests check-deprecated-authn-javahl: javahl @FIX_JAVAHL_LIB@ $(TEST_SHLIB_VAR_JAVAHL) \ - $(JAVA) -Xcheck:jni "-Dtest.rootdir=$(javahl_test_rootdir)" "-Dtest.srcdir=$(javahl_test_srcdir)" "-Dtest.rooturl=$(BASE_URL)" "-Dtest.fstype=$(FS_TYPE)" "-Djava.library.path=@JAVAHL_OBJDIR@:$(libdir)" -classpath "$(javahl_tests_PATH):$(javahl_tests_CLASSPATH)" "-Dtest.tests=$(JAVAHL_TESTS)" "-Dtest.authn.deprecated=true" org.apache.subversion.javahl.RunTests + $(JAVA) -Xcheck:jni "-Dtest.rootdir=$(javahl_test_rootdir)" "-Dtest.srcdir=$(javahl_test_srcdir)" "-Dtest.rooturl=$(BASE_URL)" "-Dtest.fstype=$(FS_TYPE)" "-Djava.library.path=@JAVAHL_OBJDIR@:$(libdir)" -classpath "$(javahl_tests_PATH):$(javahl_tests_CLASSPATH)" "-Dtest.cleanup=$(JAVAHL_CLEANUP)" "-Dtest.tests=$(JAVAHL_TESTS)" "-Dtest.authn.deprecated=true" org.apache.subversion.javahl.RunTests check-javahl: check-apache-javahl @@ -540,6 +552,9 @@ check: bin @TRANSFORM_LIBTOOL_SCRIPTS@ $(TEST_DEPS) @BDB_TEST_DEPS@ if test "$(HTTPD_VERSION)" != ""; then \ flags="--httpd-version $(HTTPD_VERSION) $$flags"; \ fi; \ + if test "$(HTTPD_WHITELIST)" != ""; then \ + flags="--httpd-whitelist $(HTTPD_WHITELIST) $$flags"; \ + fi; \ if test "$(SERVER_MINOR_VERSION)" != ""; then \ flags="--server-minor-version $(SERVER_MINOR_VERSION) $$flags"; \ fi; \ @@ -555,6 +570,9 @@ check: bin @TRANSFORM_LIBTOOL_SCRIPTS@ $(TEST_DEPS) @BDB_TEST_DEPS@ if test "$(PARALLEL)" != ""; then \ flags="--parallel $(PARALLEL) $$flags"; \ fi; \ + if test "$(GLOBAL_SCHEDULER)" != ""; then \ + flags="--global-scheduler $$flags"; \ + fi; \ if test "$(LOG_TO_STDOUT)" != ""; then \ flags="--log-to-stdout $$flags"; \ fi; \ @@ -577,6 +595,15 @@ check: bin @TRANSFORM_LIBTOOL_SCRIPTS@ $(TEST_DEPS) @BDB_TEST_DEPS@ if test "$(MEMCACHED_SERVER)" != ""; then \ flags="--memcached-server $(MEMCACHED_SERVER) $$flags"; \ fi; \ + if test "$(FSFS_COMPRESSION)" != ""; then \ + flags="--fsfs-compression $(FSFS_COMPRESSION) $$flags"; \ + fi; \ + if test "$(FSFS_DIR_DELTIFICATION)" != ""; then \ + flags="--fsfs-dir-deltification $(FSFS_DIR_DELTIFICATION) $$flags";\ + fi; \ + if test "$(SVN_BIN_DIR)" != ""; then \ + flags="--bin $(SVN_BIN_DIR) $$flags"; \ + fi; \ LD_LIBRARY_PATH='$(auth_plugin_dirs):$(LD_LIBRARY_PATH)' \ $(PYTHON) $(top_srcdir)/build/run_tests.py \ --config-file $(top_srcdir)/subversion/tests/tests.conf \ @@ -656,6 +683,7 @@ check-clean: gcov-clean rm -rf subversion/tests/libsvn_fs/test-repo-* \ subversion/tests/libsvn_fs_base/test-repo-* \ subversion/tests/libsvn_fs_fs/test-repo-* \ + subversion/tests/libsvn_fs_x/test-repo-* \ subversion/tests/libsvn_ra_local/test-repo-* \ subversion/tests/libsvn_repos/test-repo-* \ subversion/tests/libsvn_subr/z \ @@ -835,7 +863,7 @@ extraclean-swig-headers: clean-swig-headers $(SWIG_PL_DIR)/native/Makefile.PL: $(SWIG_SRC_DIR)/perl/native/Makefile.PL.in ./config.status subversion/bindings/swig/perl/native/Makefile.PL -$(SWIG_PL_DIR)/native/Makefile: $(SWIG_PL_DIR)/native/Makefile.PL +$(SWIG_PL_DIR)/native/Makefile: libsvn_swig_perl $(SWIG_PL_DIR)/native/Makefile.PL cd $(SWIG_PL_DIR)/native; $(PERL) Makefile.PL PREFIX=$(prefix) # There is a "readlink -f" command on some systems for the same purpose, @@ -844,11 +872,13 @@ $(SWIG_PL_DIR)/native/Makefile: $(SWIG_PL_DIR)/native/Makefile.PL READLINK_PY=$(PYTHON) -c 'import sys,os; print(os.path.realpath(sys.argv[1]))' READLINK_PL=$(PERL) -e 'use Cwd; print Cwd::realpath(shift)' -swig-pl_DEPS = autogen-swig-pl libsvn_swig_perl \ - $(SWIG_PL_DIR)/native/Makefile -swig-pl: $(swig-pl_DEPS) +swig-pl: autogen-swig-pl $(SWIG_PL_DIR)/native/Makefile if test "`$(READLINK_PL) $(SWIG_PL_DIR)`" != "`$(READLINK_PL) $(SWIG_PL_SRC_DIR)`"; then \ - ln -sf $(SWIG_PL_SRC_DIR)/native/*.c $(SWIG_PL_DIR)/native; \ + for f in $(SWIG_PL_SRC_DIR)/native/*.c ; do \ + if [ -e "$$f" ] ; then \ + ln -sf "$$f" $(SWIG_PL_DIR)/native; \ + fi; \ + done; \ fi cd $(SWIG_PL_DIR)/native; $(MAKE) OPTIMIZE="" OTHERLDFLAGS="$(SWIG_LDFLAGS)" @@ -983,4 +1013,11 @@ INSTALL_EXTRA_TOOLS=\ if test "$(DESTDIR)$(bindir)" != "$(DESTDIR)$(toolsdir)"; then \ ln -sf $(bindir)/svnmucc$(EXEEXT) $(DESTDIR)$(toolsdir)/svnmucc$(EXEEXT); \ ln -sf $(bindir)/svnbench$(EXEEXT) $(DESTDIR)$(toolsdir)/svn-bench$(EXEEXT); \ - fi + fi; \ + printf '\043\041/bin/sh\n%s\n' \ + 'exec $(bindir)/svnfsfs stats $${2:+"-M"} $${2:+"$$2"} "$$1"' \ + > $(DESTDIR)$(toolsdir)/fsfs-stats$(EXEEXT) && \ + chmod +x $(DESTDIR)$(toolsdir)/fsfs-stats$(EXEEXT) +# \043\041 is a "#!". It's written this way because gmake and bmake disagree on +# how to include a literal '#' in a command, and because '!' is special to some +# shells. diff --git a/NOTICE b/NOTICE index 811686dcb359..59e6419187a8 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,5 @@ Apache Subversion -Copyright 2017 The Apache Software Foundation +Copyright 2018 The Apache Software Foundation This product includes software developed by many people, and distributed under Contributor License Agreements to The Apache Software Foundation @@ -26,3 +26,6 @@ under a permissive license, see LICENSE. This software contains code derived from TropicSSL under a BSD 3-Clause license, see LICENSE. + +This product includes code derived from the software developed by Yann Collet +under a BSD 2-Clause license, see LICENSE. diff --git a/README b/README index 2350ceec3f40..4b7559f9c68d 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ Subversion, a version control system. ===================================== -$LastChangedDate: 2016-05-31 16:08:20 +0000 (Tue, 31 May 2016) $ +$LastChangedDate: 2016-05-31 14:07:51 +0000 (Tue, 31 May 2016) $ Contents: diff --git a/aclocal.m4 b/aclocal.m4 index d92e4a23350b..0bf9a1d93ee4 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -44,7 +44,10 @@ sinclude(build/ac-macros/serf.m4) sinclude(build/ac-macros/sqlite.m4) sinclude(build/ac-macros/swig.m4) sinclude(build/ac-macros/zlib.m4) +sinclude(build/ac-macros/lz4.m4) sinclude(build/ac-macros/kwallet.m4) +sinclude(build/ac-macros/libsecret.m4) +sinclude(build/ac-macros/utf8proc.m4) sinclude(build/ac-macros/macosx.m4) # Include the libtool macros diff --git a/build-outputs.mk b/build-outputs.mk index e82762f59aa4..7948a51df4de 100644 --- a/build-outputs.mk +++ b/build-outputs.mk @@ -23,21 +23,21 @@ RA_SERF_LINK = ../../subversion/libsvn_ra_serf/libsvn_ra_serf-1.la ../../subvers RA_SVN_DEPS = subversion/libsvn_ra_svn/libsvn_ra_svn-1.la subversion/libsvn_delta/libsvn_delta-1.la subversion/libsvn_subr/libsvn_subr-1.la RA_SVN_LINK = ../../subversion/libsvn_ra_svn/libsvn_ra_svn-1.la ../../subversion/libsvn_delta/libsvn_delta-1.la ../../subversion/libsvn_subr/libsvn_subr-1.la -BUILD_DIRS = subversion/tests/cmdline subversion/tests/libsvn_subr subversion/tests/libsvn_fs_base subversion/tests/libsvn_client subversion/tests/libsvn_wc subversion/bindings/cxxhl subversion/bindings/cxxhl/tests tools/diff subversion/tests/libsvn_diff subversion/tests/libsvn_repos subversion/tests/libsvn_fs_fs subversion/tests/libsvn_fs subversion/tests/libsvn_fs_x tools/dev subversion/bindings/javahl/src/org/apache/subversion/javahl/callback subversion/bindings/javahl/classes subversion/bindings/javahl/include subversion/bindings/javahl/src/org/tigris/subversion/javahl subversion/bindings/javahl/tests/org/tigris/subversion/javahl subversion/bindings/javahl/src/org/apache/subversion/javahl subversion/bindings/javahl/src/org/apache/subversion/javahl/remote subversion/bindings/javahl/src/org/apache/subversion/javahl/types subversion/bindings/javahl/src/org/apache/subversion/javahl/util subversion/bindings/javahl/tests/org/apache/subversion/javahl gmock-fused subversion/libsvn_auth_gnome_keyring subversion/libsvn_auth_kwallet subversion/libsvn_client subversion/libsvn_delta subversion/libsvn_diff subversion/libsvn_fs subversion/libsvn_fs_base subversion/libsvn_fs_base/bdb subversion/libsvn_fs_base/util subversion/libsvn_fs_fs subversion/libsvn_fs_util subversion/libsvn_fs_x subversion/libsvn_ra subversion/libsvn_ra_local subversion/libsvn_ra_serf subversion/libsvn_ra_svn subversion/libsvn_repos subversion/libsvn_subr subversion/bindings/swig/perl/libsvn_swig_perl subversion/bindings/swig/python/libsvn_swig_py subversion/bindings/swig/ruby/libsvn_swig_ruby subversion/tests subversion/libsvn_wc subversion/bindings/cxxhl/src subversion/bindings/cxxhl/src/aprwrap subversion/bindings/javahl/native subversion/bindings/javahl/native/jniwrapper subversion/po subversion/mod_authz_svn subversion/mod_dav_svn subversion/mod_dav_svn/reports subversion/mod_dav_svn/posts tools/server-side/mod_dontdothat subversion/tests/libsvn_ra_local subversion/tests/libsvn_ra subversion/tests/libsvn_delta subversion/svn tools/server-side tools/dev/wc-ng subversion/svnadmin subversion/svnbench subversion/svndumpfilter subversion/svnfsfs subversion/svnlook subversion/svnmucc tools/dev/svnraisetreeconflict subversion/svnrdump subversion/svnserve subversion/svnsync subversion/svnversion subversion/bindings/swig subversion/tests/libsvn_wc/../../libsvn_subr subversion/bindings/swig/python subversion/bindings/swig/perl subversion/bindings/swig/ruby subversion/bindings/swig/proxy +BUILD_DIRS = subversion/tests/afl subversion/tests/cmdline subversion/tests/libsvn_subr subversion/tests/libsvn_repos subversion/tests/libsvn_fs_base subversion/tests/libsvn_client subversion/tests/libsvn_wc subversion/tests/libsvn_client/../libsvn_wc subversion/bindings/cxxhl subversion/bindings/cxxhl/tests tools/diff subversion/tests/libsvn_diff subversion/tests/libsvn_fs_fs subversion/tests/libsvn_fs subversion/tests/libsvn_fs_x tools/dev subversion/bindings/javahl/src/org/apache/subversion/javahl/callback subversion/bindings/javahl/classes subversion/bindings/javahl/include subversion/bindings/javahl/src/org/tigris/subversion/javahl subversion/bindings/javahl/tests/org/tigris/subversion/javahl subversion/bindings/javahl/src/org/apache/subversion/javahl subversion/bindings/javahl/src/org/apache/subversion/javahl/remote subversion/bindings/javahl/src/org/apache/subversion/javahl/types subversion/bindings/javahl/src/org/apache/subversion/javahl/util subversion/bindings/javahl/tests/org/apache/subversion/javahl googlemock googlemock/googletest/src googlemock/googlemock/src subversion/libsvn_auth_gnome_keyring subversion/libsvn_auth_kwallet subversion/libsvn_client subversion/libsvn_delta subversion/libsvn_diff subversion/libsvn_fs subversion/libsvn_fs_base subversion/libsvn_fs_base/bdb subversion/libsvn_fs_base/util subversion/libsvn_fs_fs subversion/libsvn_fs_util subversion/libsvn_fs_x subversion/libsvn_ra subversion/libsvn_ra_local subversion/libsvn_ra_serf subversion/libsvn_ra_svn subversion/libsvn_repos subversion/libsvn_subr subversion/libsvn_subr/lz4 subversion/bindings/swig/perl/libsvn_swig_perl subversion/bindings/swig/python/libsvn_swig_py subversion/bindings/swig/ruby/libsvn_swig_ruby subversion/tests subversion/libsvn_wc subversion/bindings/cxxhl/src subversion/bindings/cxxhl/src/aprwrap subversion/bindings/javahl/native subversion/bindings/javahl/native/jniwrapper subversion/po subversion/mod_authz_svn subversion/mod_dav_svn subversion/mod_dav_svn/reports subversion/mod_dav_svn/posts tools/server-side/mod_dontdothat subversion/tests/libsvn_ra_local subversion/tests/libsvn_ra subversion/tests/libsvn_delta subversion/svn tools/client-side/svn-mergeinfo-normalizer tools/server-side tools/dev/wc-ng subversion/svnadmin subversion/svnbench tools/client-side/svnconflict subversion/svndumpfilter subversion/svnfsfs subversion/svnlook tools/dev/svnmover subversion/svnmucc tools/dev/svnraisetreeconflict subversion/svnrdump subversion/svnserve subversion/svnsync subversion/svnversion subversion/bindings/swig subversion/tests/libsvn_wc/../../libsvn_subr subversion/bindings/swig/python subversion/bindings/swig/perl subversion/bindings/swig/ruby subversion/bindings/swig/proxy BDB_TEST_DEPS = subversion/tests/libsvn_fs_base/changes-test$(EXEEXT) subversion/tests/libsvn_fs_base/fs-base-test$(EXEEXT) subversion/tests/libsvn_fs_base/strings-reps-test$(EXEEXT) BDB_TEST_PROGRAMS = subversion/tests/libsvn_fs_base/changes-test$(EXEEXT) subversion/tests/libsvn_fs_base/fs-base-test$(EXEEXT) subversion/tests/libsvn_fs_base/strings-reps-test$(EXEEXT) -TEST_DEPS = subversion/tests/cmdline/atomic-ra-revprop-change$(EXEEXT) subversion/tests/libsvn_subr/auth-test$(EXEEXT) subversion/tests/libsvn_subr/bit-array-test$(EXEEXT) subversion/tests/libsvn_subr/cache-test$(EXEEXT) subversion/tests/libsvn_subr/checksum-test$(EXEEXT) subversion/tests/libsvn_client/client-test$(EXEEXT) subversion/tests/libsvn_subr/compat-test$(EXEEXT) subversion/tests/libsvn_subr/config-test$(EXEEXT) subversion/tests/libsvn_wc/conflict-data-test$(EXEEXT) subversion/tests/libsvn_subr/crypto-test$(EXEEXT) subversion/tests/libsvn_wc/db-test$(EXEEXT) subversion/tests/libsvn_diff/diff-diff3-test$(EXEEXT) subversion/tests/libsvn_subr/dirent_uri-test$(EXEEXT) subversion/tests/libsvn_repos/dump-load-test$(EXEEXT) subversion/tests/libsvn_wc/entries-compat-test$(EXEEXT) subversion/tests/cmdline/entries-dump$(EXEEXT) subversion/tests/libsvn_subr/error-code-test$(EXEEXT) subversion/tests/libsvn_subr/error-test$(EXEEXT) subversion/tests/libsvn_fs_fs/fs-fs-pack-test$(EXEEXT) subversion/tests/libsvn_fs_fs/fs-fs-private-test$(EXEEXT) subversion/tests/libsvn_fs/fs-test$(EXEEXT) subversion/tests/libsvn_fs_x/fs-x-pack-test$(EXEEXT) subversion/tests/libsvn_subr/hashdump-test$(EXEEXT) subversion/tests/libsvn_subr/io-test$(EXEEXT) subversion/tests/cmdline/lock-helper$(EXEEXT) subversion/tests/libsvn_fs/locks-test$(EXEEXT) subversion/tests/libsvn_subr/mergeinfo-test$(EXEEXT) subversion/tests/libsvn_client/mtcc-test$(EXEEXT) subversion/tests/libsvn_wc/op-depth-test$(EXEEXT) subversion/tests/libsvn_subr/opt-test$(EXEEXT) subversion/tests/libsvn_subr/packed-data-test$(EXEEXT) subversion/tests/libsvn_diff/parse-diff-test$(EXEEXT) subversion/tests/libsvn_subr/path-test$(EXEEXT) subversion/tests/libsvn_subr/prefix-string-test$(EXEEXT) subversion/tests/libsvn_subr/priority-queue-test$(EXEEXT) subversion/tests/libsvn_wc/pristine-store-test$(EXEEXT) subversion/tests/libsvn_ra_local/ra-local-test$(EXEEXT) subversion/tests/libsvn_ra/ra-test$(EXEEXT) subversion/tests/libsvn_delta/random-test$(EXEEXT) subversion/tests/libsvn_repos/repos-test$(EXEEXT) subversion/tests/libsvn_subr/revision-test$(EXEEXT) subversion/tests/libsvn_subr/root-pools-test$(EXEEXT) subversion/tests/libsvn_subr/skel-test$(EXEEXT) subversion/tests/libsvn_subr/spillbuf-test$(EXEEXT) subversion/tests/libsvn_subr/sqlite-test$(EXEEXT) subversion/tests/libsvn_subr/stream-test$(EXEEXT) subversion/tests/libsvn_fs_x/string-table-test$(EXEEXT) subversion/tests/libsvn_subr/string-test$(EXEEXT) subversion/tests/libsvn_subr/subst_translate-test$(EXEEXT) tools/dev/wc-ng/svn-wc-db-tester$(EXEEXT) tools/server-side/svnauthz$(EXEEXT) tools/server-side/svnauthz-validate$(EXEEXT) subversion/tests/libsvn_delta/svndiff-test$(EXEEXT) subversion/tests/libsvn_subr/time-test$(EXEEXT) subversion/tests/libsvn_subr/translate-test$(EXEEXT) subversion/tests/libsvn_subr/utf-test$(EXEEXT) subversion/tests/libsvn_delta/vdelta-test$(EXEEXT) subversion/tests/libsvn_wc/wc-incomplete-tester$(EXEEXT) subversion/tests/libsvn_wc/wc-lock-tester$(EXEEXT) subversion/tests/libsvn_wc/wc-queries-test$(EXEEXT) subversion/tests/libsvn_wc/wc-test$(EXEEXT) subversion/tests/libsvn_delta/window-test$(EXEEXT) subversion/tests/libsvn_subr/x509-test$(EXEEXT) subversion/tests/cmdline/authz_tests.py subversion/tests/cmdline/autoprop_tests.py subversion/tests/cmdline/basic_tests.py subversion/tests/cmdline/blame_tests.py subversion/tests/cmdline/cat_tests.py subversion/tests/cmdline/changelist_tests.py subversion/tests/cmdline/checkout_tests.py subversion/tests/cmdline/commit_tests.py subversion/tests/cmdline/copy_tests.py subversion/tests/cmdline/depth_tests.py subversion/tests/cmdline/diff_tests.py subversion/tests/cmdline/entries_tests.py subversion/tests/cmdline/export_tests.py subversion/tests/cmdline/externals_tests.py subversion/tests/cmdline/getopt_tests.py subversion/tests/cmdline/history_tests.py subversion/tests/cmdline/import_tests.py subversion/tests/cmdline/info_tests.py subversion/tests/cmdline/input_validation_tests.py subversion/tests/cmdline/iprop_authz_tests.py subversion/tests/cmdline/iprop_tests.py subversion/tests/cmdline/lock_tests.py subversion/tests/cmdline/log_tests.py subversion/tests/cmdline/merge_authz_tests.py subversion/tests/cmdline/merge_automatic_tests.py subversion/tests/cmdline/merge_reintegrate_tests.py subversion/tests/cmdline/merge_tests.py subversion/tests/cmdline/merge_tree_conflict_tests.py subversion/tests/cmdline/mergeinfo_tests.py subversion/tests/cmdline/mod_authz_svn_tests.py subversion/tests/cmdline/move_tests.py subversion/tests/cmdline/patch_tests.py subversion/tests/cmdline/prop_tests.py subversion/tests/cmdline/redirect_tests.py subversion/tests/cmdline/relocate_tests.py subversion/tests/cmdline/resolve_tests.py subversion/tests/cmdline/revert_tests.py subversion/tests/cmdline/schedule_tests.py subversion/tests/cmdline/special_tests.py subversion/tests/cmdline/stat_tests.py subversion/tests/cmdline/svnadmin_tests.py subversion/tests/cmdline/svnauthz_tests.py subversion/tests/cmdline/svndumpfilter_tests.py subversion/tests/cmdline/svnfsfs_tests.py subversion/tests/cmdline/svnlook_tests.py subversion/tests/cmdline/svnmucc_tests.py subversion/tests/cmdline/svnrdump_tests.py subversion/tests/cmdline/svnsync_authz_tests.py subversion/tests/cmdline/svnsync_tests.py subversion/tests/cmdline/svnversion_tests.py subversion/tests/cmdline/switch_tests.py subversion/tests/cmdline/trans_tests.py subversion/tests/cmdline/tree_conflict_tests.py subversion/tests/cmdline/update_tests.py subversion/tests/cmdline/upgrade_tests.py subversion/tests/cmdline/wc_tests.py +TEST_DEPS = subversion/tests/afl/afl-x509$(EXEEXT) subversion/tests/cmdline/atomic-ra-revprop-change$(EXEEXT) subversion/tests/libsvn_subr/auth-test$(EXEEXT) subversion/tests/libsvn_repos/authz-test$(EXEEXT) subversion/tests/libsvn_subr/bit-array-test$(EXEEXT) subversion/tests/libsvn_subr/cache-test$(EXEEXT) subversion/tests/libsvn_subr/checksum-test$(EXEEXT) subversion/tests/libsvn_client/client-test$(EXEEXT) subversion/tests/libsvn_subr/compat-test$(EXEEXT) subversion/tests/libsvn_subr/compress-test$(EXEEXT) subversion/tests/libsvn_subr/config-test$(EXEEXT) subversion/tests/libsvn_wc/conflict-data-test$(EXEEXT) subversion/tests/libsvn_client/conflicts-test$(EXEEXT) subversion/tests/libsvn_subr/crypto-test$(EXEEXT) subversion/tests/libsvn_wc/db-test$(EXEEXT) subversion/tests/libsvn_diff/diff-diff3-test$(EXEEXT) subversion/tests/libsvn_subr/dirent_uri-test$(EXEEXT) subversion/tests/libsvn_repos/dump-load-test$(EXEEXT) subversion/tests/libsvn_wc/entries-compat-test$(EXEEXT) subversion/tests/cmdline/entries-dump$(EXEEXT) subversion/tests/libsvn_subr/error-code-test$(EXEEXT) subversion/tests/libsvn_subr/error-test$(EXEEXT) subversion/tests/libsvn_fs_fs/fs-fs-pack-test$(EXEEXT) subversion/tests/libsvn_fs_fs/fs-fs-private-test$(EXEEXT) subversion/tests/libsvn_fs/fs-sequential-test$(EXEEXT) subversion/tests/libsvn_fs/fs-test$(EXEEXT) subversion/tests/libsvn_fs_x/fs-x-pack-test$(EXEEXT) subversion/tests/libsvn_subr/hashdump-test$(EXEEXT) subversion/tests/libsvn_subr/io-test$(EXEEXT) subversion/tests/cmdline/lock-helper$(EXEEXT) subversion/tests/libsvn_fs/locks-test$(EXEEXT) subversion/tests/libsvn_subr/mergeinfo-test$(EXEEXT) subversion/tests/libsvn_client/mtcc-test$(EXEEXT) subversion/tests/libsvn_wc/op-depth-test$(EXEEXT) subversion/tests/libsvn_subr/opt-test$(EXEEXT) subversion/tests/libsvn_subr/packed-data-test$(EXEEXT) subversion/tests/libsvn_diff/parse-diff-test$(EXEEXT) subversion/tests/libsvn_subr/path-test$(EXEEXT) subversion/tests/libsvn_subr/prefix-string-test$(EXEEXT) subversion/tests/libsvn_subr/priority-queue-test$(EXEEXT) subversion/tests/libsvn_wc/pristine-store-test$(EXEEXT) subversion/tests/libsvn_ra_local/ra-local-test$(EXEEXT) subversion/tests/libsvn_ra/ra-test$(EXEEXT) subversion/tests/libsvn_delta/random-test$(EXEEXT) subversion/tests/libsvn_repos/repos-test$(EXEEXT) subversion/tests/libsvn_subr/revision-test$(EXEEXT) subversion/tests/libsvn_subr/root-pools-test$(EXEEXT) subversion/tests/libsvn_subr/skel-test$(EXEEXT) subversion/tests/libsvn_subr/spillbuf-test$(EXEEXT) subversion/tests/libsvn_subr/sqlite-test$(EXEEXT) subversion/tests/libsvn_subr/stream-test$(EXEEXT) subversion/tests/libsvn_fs_x/string-table-test$(EXEEXT) subversion/tests/libsvn_subr/string-test$(EXEEXT) subversion/tests/libsvn_subr/subst_translate-test$(EXEEXT) tools/dev/wc-ng/svn-wc-db-tester$(EXEEXT) tools/server-side/svnauthz$(EXEEXT) tools/server-side/svnauthz-validate$(EXEEXT) subversion/tests/libsvn_delta/svndiff-stream-test$(EXEEXT) subversion/tests/libsvn_delta/svndiff-test$(EXEEXT) subversion/tests/libsvn_subr/time-test$(EXEEXT) subversion/tests/libsvn_subr/translate-test$(EXEEXT) subversion/tests/libsvn_subr/utf-test$(EXEEXT) subversion/tests/libsvn_delta/vdelta-test$(EXEEXT) subversion/tests/libsvn_wc/wc-incomplete-tester$(EXEEXT) subversion/tests/libsvn_wc/wc-lock-tester$(EXEEXT) subversion/tests/libsvn_wc/wc-queries-test$(EXEEXT) subversion/tests/libsvn_wc/wc-test$(EXEEXT) subversion/tests/libsvn_delta/window-test$(EXEEXT) subversion/tests/libsvn_subr/x509-test$(EXEEXT) subversion/tests/libsvn_subr/xml-test$(EXEEXT) subversion/tests/cmdline/authz_tests.py subversion/tests/cmdline/autoprop_tests.py subversion/tests/cmdline/basic_tests.py subversion/tests/cmdline/blame_tests.py subversion/tests/cmdline/cat_tests.py subversion/tests/cmdline/changelist_tests.py subversion/tests/cmdline/checkout_tests.py subversion/tests/cmdline/commit_tests.py subversion/tests/cmdline/copy_tests.py subversion/tests/cmdline/depth_tests.py subversion/tests/cmdline/diff_tests.py subversion/tests/cmdline/entries_tests.py subversion/tests/cmdline/export_tests.py subversion/tests/cmdline/externals_tests.py subversion/tests/cmdline/getopt_tests.py subversion/tests/cmdline/history_tests.py subversion/tests/cmdline/import_tests.py subversion/tests/cmdline/info_tests.py subversion/tests/cmdline/input_validation_tests.py subversion/tests/cmdline/iprop_authz_tests.py subversion/tests/cmdline/iprop_tests.py subversion/tests/cmdline/lock_tests.py subversion/tests/cmdline/log_tests.py subversion/tests/cmdline/merge_authz_tests.py subversion/tests/cmdline/merge_automatic_tests.py subversion/tests/cmdline/merge_reintegrate_tests.py subversion/tests/cmdline/merge_tests.py subversion/tests/cmdline/merge_tree_conflict_tests.py subversion/tests/cmdline/mergeinfo_tests.py subversion/tests/cmdline/mod_authz_svn_tests.py subversion/tests/cmdline/mod_dav_svn_tests.py subversion/tests/cmdline/move_tests.py subversion/tests/cmdline/patch_tests.py subversion/tests/cmdline/prop_tests.py subversion/tests/cmdline/redirect_tests.py subversion/tests/cmdline/relocate_tests.py subversion/tests/cmdline/resolve_tests.py subversion/tests/cmdline/revert_tests.py subversion/tests/cmdline/schedule_tests.py subversion/tests/cmdline/shelve_tests.py subversion/tests/cmdline/special_tests.py subversion/tests/cmdline/stat_tests.py subversion/tests/cmdline/svnadmin_tests.py subversion/tests/cmdline/svnauthz_tests.py subversion/tests/cmdline/svndumpfilter_tests.py subversion/tests/cmdline/svnfsfs_tests.py subversion/tests/cmdline/svnlook_tests.py subversion/tests/cmdline/svnmover_tests.py subversion/tests/cmdline/svnmucc_tests.py subversion/tests/cmdline/svnrdump_tests.py subversion/tests/cmdline/svnsync_authz_tests.py subversion/tests/cmdline/svnsync_tests.py subversion/tests/cmdline/svnversion_tests.py subversion/tests/cmdline/switch_tests.py subversion/tests/cmdline/trans_tests.py subversion/tests/cmdline/tree_conflict_tests.py subversion/tests/cmdline/update_tests.py subversion/tests/cmdline/upgrade_tests.py subversion/tests/cmdline/wc_tests.py -TEST_PROGRAMS = subversion/tests/libsvn_subr/auth-test$(EXEEXT) subversion/tests/libsvn_subr/bit-array-test$(EXEEXT) subversion/tests/libsvn_subr/cache-test$(EXEEXT) subversion/tests/libsvn_subr/checksum-test$(EXEEXT) subversion/tests/libsvn_client/client-test$(EXEEXT) subversion/tests/libsvn_subr/compat-test$(EXEEXT) subversion/tests/libsvn_subr/config-test$(EXEEXT) subversion/tests/libsvn_wc/conflict-data-test$(EXEEXT) subversion/tests/libsvn_subr/crypto-test$(EXEEXT) subversion/tests/libsvn_wc/db-test$(EXEEXT) subversion/tests/libsvn_diff/diff-diff3-test$(EXEEXT) subversion/tests/libsvn_subr/dirent_uri-test$(EXEEXT) subversion/tests/libsvn_repos/dump-load-test$(EXEEXT) subversion/tests/libsvn_wc/entries-compat-test$(EXEEXT) subversion/tests/libsvn_subr/error-code-test$(EXEEXT) subversion/tests/libsvn_subr/error-test$(EXEEXT) subversion/tests/libsvn_fs_fs/fs-fs-pack-test$(EXEEXT) subversion/tests/libsvn_fs_fs/fs-fs-private-test$(EXEEXT) subversion/tests/libsvn_fs/fs-test$(EXEEXT) subversion/tests/libsvn_fs_x/fs-x-pack-test$(EXEEXT) subversion/tests/libsvn_subr/hashdump-test$(EXEEXT) subversion/tests/libsvn_subr/io-test$(EXEEXT) subversion/tests/libsvn_fs/locks-test$(EXEEXT) subversion/tests/libsvn_subr/mergeinfo-test$(EXEEXT) subversion/tests/libsvn_client/mtcc-test$(EXEEXT) subversion/tests/libsvn_wc/op-depth-test$(EXEEXT) subversion/tests/libsvn_subr/opt-test$(EXEEXT) subversion/tests/libsvn_subr/packed-data-test$(EXEEXT) subversion/tests/libsvn_diff/parse-diff-test$(EXEEXT) subversion/tests/libsvn_subr/path-test$(EXEEXT) subversion/tests/libsvn_subr/prefix-string-test$(EXEEXT) subversion/tests/libsvn_subr/priority-queue-test$(EXEEXT) subversion/tests/libsvn_wc/pristine-store-test$(EXEEXT) subversion/tests/libsvn_ra_local/ra-local-test$(EXEEXT) subversion/tests/libsvn_ra/ra-test$(EXEEXT) subversion/tests/libsvn_delta/random-test$(EXEEXT) subversion/tests/libsvn_repos/repos-test$(EXEEXT) subversion/tests/libsvn_subr/revision-test$(EXEEXT) subversion/tests/libsvn_subr/root-pools-test$(EXEEXT) subversion/tests/libsvn_subr/skel-test$(EXEEXT) subversion/tests/libsvn_subr/spillbuf-test$(EXEEXT) subversion/tests/libsvn_subr/sqlite-test$(EXEEXT) subversion/tests/libsvn_subr/stream-test$(EXEEXT) subversion/tests/libsvn_fs_x/string-table-test$(EXEEXT) subversion/tests/libsvn_subr/string-test$(EXEEXT) subversion/tests/libsvn_subr/subst_translate-test$(EXEEXT) subversion/tests/libsvn_subr/time-test$(EXEEXT) subversion/tests/libsvn_subr/translate-test$(EXEEXT) subversion/tests/libsvn_subr/utf-test$(EXEEXT) subversion/tests/libsvn_wc/wc-queries-test$(EXEEXT) subversion/tests/libsvn_wc/wc-test$(EXEEXT) subversion/tests/libsvn_delta/window-test$(EXEEXT) subversion/tests/libsvn_subr/x509-test$(EXEEXT) subversion/tests/cmdline/authz_tests.py subversion/tests/cmdline/autoprop_tests.py subversion/tests/cmdline/basic_tests.py subversion/tests/cmdline/blame_tests.py subversion/tests/cmdline/cat_tests.py subversion/tests/cmdline/changelist_tests.py subversion/tests/cmdline/checkout_tests.py subversion/tests/cmdline/commit_tests.py subversion/tests/cmdline/copy_tests.py subversion/tests/cmdline/depth_tests.py subversion/tests/cmdline/diff_tests.py subversion/tests/cmdline/entries_tests.py subversion/tests/cmdline/export_tests.py subversion/tests/cmdline/externals_tests.py subversion/tests/cmdline/getopt_tests.py subversion/tests/cmdline/history_tests.py subversion/tests/cmdline/import_tests.py subversion/tests/cmdline/info_tests.py subversion/tests/cmdline/input_validation_tests.py subversion/tests/cmdline/iprop_authz_tests.py subversion/tests/cmdline/iprop_tests.py subversion/tests/cmdline/lock_tests.py subversion/tests/cmdline/log_tests.py subversion/tests/cmdline/merge_authz_tests.py subversion/tests/cmdline/merge_automatic_tests.py subversion/tests/cmdline/merge_reintegrate_tests.py subversion/tests/cmdline/merge_tests.py subversion/tests/cmdline/merge_tree_conflict_tests.py subversion/tests/cmdline/mergeinfo_tests.py subversion/tests/cmdline/mod_authz_svn_tests.py subversion/tests/cmdline/move_tests.py subversion/tests/cmdline/patch_tests.py subversion/tests/cmdline/prop_tests.py subversion/tests/cmdline/redirect_tests.py subversion/tests/cmdline/relocate_tests.py subversion/tests/cmdline/resolve_tests.py subversion/tests/cmdline/revert_tests.py subversion/tests/cmdline/schedule_tests.py subversion/tests/cmdline/special_tests.py subversion/tests/cmdline/stat_tests.py subversion/tests/cmdline/svnadmin_tests.py subversion/tests/cmdline/svnauthz_tests.py subversion/tests/cmdline/svndumpfilter_tests.py subversion/tests/cmdline/svnfsfs_tests.py subversion/tests/cmdline/svnlook_tests.py subversion/tests/cmdline/svnmucc_tests.py subversion/tests/cmdline/svnrdump_tests.py subversion/tests/cmdline/svnsync_authz_tests.py subversion/tests/cmdline/svnsync_tests.py subversion/tests/cmdline/svnversion_tests.py subversion/tests/cmdline/switch_tests.py subversion/tests/cmdline/trans_tests.py subversion/tests/cmdline/tree_conflict_tests.py subversion/tests/cmdline/update_tests.py subversion/tests/cmdline/upgrade_tests.py subversion/tests/cmdline/wc_tests.py +TEST_PROGRAMS = subversion/tests/libsvn_subr/auth-test$(EXEEXT) subversion/tests/libsvn_repos/authz-test$(EXEEXT) subversion/tests/libsvn_subr/bit-array-test$(EXEEXT) subversion/tests/libsvn_subr/cache-test$(EXEEXT) subversion/tests/libsvn_subr/checksum-test$(EXEEXT) subversion/tests/libsvn_client/client-test$(EXEEXT) subversion/tests/libsvn_subr/compat-test$(EXEEXT) subversion/tests/libsvn_subr/compress-test$(EXEEXT) subversion/tests/libsvn_subr/config-test$(EXEEXT) subversion/tests/libsvn_wc/conflict-data-test$(EXEEXT) subversion/tests/libsvn_client/conflicts-test$(EXEEXT) subversion/tests/libsvn_subr/crypto-test$(EXEEXT) subversion/tests/libsvn_wc/db-test$(EXEEXT) subversion/tests/libsvn_diff/diff-diff3-test$(EXEEXT) subversion/tests/libsvn_subr/dirent_uri-test$(EXEEXT) subversion/tests/libsvn_repos/dump-load-test$(EXEEXT) subversion/tests/libsvn_wc/entries-compat-test$(EXEEXT) subversion/tests/libsvn_subr/error-code-test$(EXEEXT) subversion/tests/libsvn_subr/error-test$(EXEEXT) subversion/tests/libsvn_fs_fs/fs-fs-pack-test$(EXEEXT) subversion/tests/libsvn_fs_fs/fs-fs-private-test$(EXEEXT) subversion/tests/libsvn_fs/fs-sequential-test$(EXEEXT) subversion/tests/libsvn_fs/fs-test$(EXEEXT) subversion/tests/libsvn_fs_x/fs-x-pack-test$(EXEEXT) subversion/tests/libsvn_subr/hashdump-test$(EXEEXT) subversion/tests/libsvn_subr/io-test$(EXEEXT) subversion/tests/libsvn_fs/locks-test$(EXEEXT) subversion/tests/libsvn_subr/mergeinfo-test$(EXEEXT) subversion/tests/libsvn_client/mtcc-test$(EXEEXT) subversion/tests/libsvn_wc/op-depth-test$(EXEEXT) subversion/tests/libsvn_subr/opt-test$(EXEEXT) subversion/tests/libsvn_subr/packed-data-test$(EXEEXT) subversion/tests/libsvn_diff/parse-diff-test$(EXEEXT) subversion/tests/libsvn_subr/path-test$(EXEEXT) subversion/tests/libsvn_subr/prefix-string-test$(EXEEXT) subversion/tests/libsvn_subr/priority-queue-test$(EXEEXT) subversion/tests/libsvn_wc/pristine-store-test$(EXEEXT) subversion/tests/libsvn_ra_local/ra-local-test$(EXEEXT) subversion/tests/libsvn_ra/ra-test$(EXEEXT) subversion/tests/libsvn_delta/random-test$(EXEEXT) subversion/tests/libsvn_repos/repos-test$(EXEEXT) subversion/tests/libsvn_subr/revision-test$(EXEEXT) subversion/tests/libsvn_subr/root-pools-test$(EXEEXT) subversion/tests/libsvn_subr/skel-test$(EXEEXT) subversion/tests/libsvn_subr/spillbuf-test$(EXEEXT) subversion/tests/libsvn_subr/sqlite-test$(EXEEXT) subversion/tests/libsvn_subr/stream-test$(EXEEXT) subversion/tests/libsvn_fs_x/string-table-test$(EXEEXT) subversion/tests/libsvn_subr/string-test$(EXEEXT) subversion/tests/libsvn_subr/subst_translate-test$(EXEEXT) subversion/tests/libsvn_delta/svndiff-stream-test$(EXEEXT) subversion/tests/libsvn_subr/time-test$(EXEEXT) subversion/tests/libsvn_subr/translate-test$(EXEEXT) subversion/tests/libsvn_subr/utf-test$(EXEEXT) subversion/tests/libsvn_wc/wc-queries-test$(EXEEXT) subversion/tests/libsvn_wc/wc-test$(EXEEXT) subversion/tests/libsvn_delta/window-test$(EXEEXT) subversion/tests/libsvn_subr/x509-test$(EXEEXT) subversion/tests/libsvn_subr/xml-test$(EXEEXT) subversion/tests/cmdline/authz_tests.py subversion/tests/cmdline/autoprop_tests.py subversion/tests/cmdline/basic_tests.py subversion/tests/cmdline/blame_tests.py subversion/tests/cmdline/cat_tests.py subversion/tests/cmdline/changelist_tests.py subversion/tests/cmdline/checkout_tests.py subversion/tests/cmdline/commit_tests.py subversion/tests/cmdline/copy_tests.py subversion/tests/cmdline/depth_tests.py subversion/tests/cmdline/diff_tests.py subversion/tests/cmdline/entries_tests.py subversion/tests/cmdline/export_tests.py subversion/tests/cmdline/externals_tests.py subversion/tests/cmdline/getopt_tests.py subversion/tests/cmdline/history_tests.py subversion/tests/cmdline/import_tests.py subversion/tests/cmdline/info_tests.py subversion/tests/cmdline/input_validation_tests.py subversion/tests/cmdline/iprop_authz_tests.py subversion/tests/cmdline/iprop_tests.py subversion/tests/cmdline/lock_tests.py subversion/tests/cmdline/log_tests.py subversion/tests/cmdline/merge_authz_tests.py subversion/tests/cmdline/merge_automatic_tests.py subversion/tests/cmdline/merge_reintegrate_tests.py subversion/tests/cmdline/merge_tests.py subversion/tests/cmdline/merge_tree_conflict_tests.py subversion/tests/cmdline/mergeinfo_tests.py subversion/tests/cmdline/mod_authz_svn_tests.py subversion/tests/cmdline/mod_dav_svn_tests.py subversion/tests/cmdline/move_tests.py subversion/tests/cmdline/patch_tests.py subversion/tests/cmdline/prop_tests.py subversion/tests/cmdline/redirect_tests.py subversion/tests/cmdline/relocate_tests.py subversion/tests/cmdline/resolve_tests.py subversion/tests/cmdline/revert_tests.py subversion/tests/cmdline/schedule_tests.py subversion/tests/cmdline/shelve_tests.py subversion/tests/cmdline/special_tests.py subversion/tests/cmdline/stat_tests.py subversion/tests/cmdline/svnadmin_tests.py subversion/tests/cmdline/svnauthz_tests.py subversion/tests/cmdline/svndumpfilter_tests.py subversion/tests/cmdline/svnfsfs_tests.py subversion/tests/cmdline/svnlook_tests.py subversion/tests/cmdline/svnmover_tests.py subversion/tests/cmdline/svnmucc_tests.py subversion/tests/cmdline/svnrdump_tests.py subversion/tests/cmdline/svnsync_authz_tests.py subversion/tests/cmdline/svnsync_tests.py subversion/tests/cmdline/svnversion_tests.py subversion/tests/cmdline/switch_tests.py subversion/tests/cmdline/trans_tests.py subversion/tests/cmdline/tree_conflict_tests.py subversion/tests/cmdline/update_tests.py subversion/tests/cmdline/upgrade_tests.py subversion/tests/cmdline/wc_tests.py -check-deps test-deps: subversion/tests/cmdline/atomic-ra-revprop-change$(EXEEXT) subversion/tests/cmdline/entries-dump$(EXEEXT) subversion/tests/cmdline/lock-helper$(EXEEXT) tools/dev/wc-ng/svn-wc-db-tester$(EXEEXT) tools/server-side/svnauthz$(EXEEXT) tools/server-side/svnauthz-validate$(EXEEXT) subversion/tests/libsvn_delta/svndiff-test$(EXEEXT) subversion/tests/libsvn_delta/vdelta-test$(EXEEXT) subversion/tests/libsvn_wc/wc-incomplete-tester$(EXEEXT) subversion/tests/libsvn_wc/wc-lock-tester$(EXEEXT) +check-deps test-deps: subversion/tests/afl/afl-x509$(EXEEXT) subversion/tests/cmdline/atomic-ra-revprop-change$(EXEEXT) subversion/tests/cmdline/entries-dump$(EXEEXT) subversion/tests/cmdline/lock-helper$(EXEEXT) tools/dev/wc-ng/svn-wc-db-tester$(EXEEXT) tools/server-side/svnauthz$(EXEEXT) tools/server-side/svnauthz-validate$(EXEEXT) subversion/tests/libsvn_delta/svndiff-test$(EXEEXT) subversion/tests/libsvn_delta/vdelta-test$(EXEEXT) subversion/tests/libsvn_wc/wc-incomplete-tester$(EXEEXT) subversion/tests/libsvn_wc/wc-lock-tester$(EXEEXT) MANPAGES = subversion/svn/svn.1 subversion/svnadmin/svnadmin.1 subversion/svndumpfilter/svndumpfilter.1 subversion/svnlook/svnlook.1 subversion/svnmucc/svnmucc.1 subversion/svnrdump/svnrdump.1 subversion/svnserve/svnserve.8 subversion/svnserve/svnserve.conf.5 subversion/svnsync/svnsync.1 subversion/svnversion/svnversion.1 -CLEAN_FILES = subversion/bindings/cxxhl/cxxhl-tests$(EXEEXT) subversion/svn/svn$(EXEEXT) subversion/svnadmin/svnadmin$(EXEEXT) subversion/svnbench/svnbench$(EXEEXT) subversion/svndumpfilter/svndumpfilter$(EXEEXT) subversion/svnfsfs/svnfsfs$(EXEEXT) subversion/svnlook/svnlook$(EXEEXT) subversion/svnmucc/svnmucc$(EXEEXT) subversion/svnrdump/svnrdump$(EXEEXT) subversion/svnserve/svnserve$(EXEEXT) subversion/svnsync/svnsync$(EXEEXT) subversion/svnversion/svnversion$(EXEEXT) subversion/tests/cmdline/atomic-ra-revprop-change$(EXEEXT) subversion/tests/cmdline/authz_tests.pyc subversion/tests/cmdline/autoprop_tests.pyc subversion/tests/cmdline/basic_tests.pyc subversion/tests/cmdline/blame_tests.pyc subversion/tests/cmdline/cat_tests.pyc subversion/tests/cmdline/changelist_tests.pyc subversion/tests/cmdline/checkout_tests.pyc subversion/tests/cmdline/commit_tests.pyc subversion/tests/cmdline/copy_tests.pyc subversion/tests/cmdline/depth_tests.pyc subversion/tests/cmdline/diff_tests.pyc subversion/tests/cmdline/entries-dump$(EXEEXT) subversion/tests/cmdline/entries_tests.pyc subversion/tests/cmdline/export_tests.pyc subversion/tests/cmdline/externals_tests.pyc subversion/tests/cmdline/getopt_tests.pyc subversion/tests/cmdline/history_tests.pyc subversion/tests/cmdline/import_tests.pyc subversion/tests/cmdline/info_tests.pyc subversion/tests/cmdline/input_validation_tests.pyc subversion/tests/cmdline/iprop_authz_tests.pyc subversion/tests/cmdline/iprop_tests.pyc subversion/tests/cmdline/lock-helper$(EXEEXT) subversion/tests/cmdline/lock_tests.pyc subversion/tests/cmdline/log_tests.pyc subversion/tests/cmdline/merge_authz_tests.pyc subversion/tests/cmdline/merge_automatic_tests.pyc subversion/tests/cmdline/merge_reintegrate_tests.pyc subversion/tests/cmdline/merge_tests.pyc subversion/tests/cmdline/merge_tree_conflict_tests.pyc subversion/tests/cmdline/mergeinfo_tests.pyc subversion/tests/cmdline/mod_authz_svn_tests.pyc subversion/tests/cmdline/move_tests.pyc subversion/tests/cmdline/patch_tests.pyc subversion/tests/cmdline/prop_tests.pyc subversion/tests/cmdline/redirect_tests.pyc subversion/tests/cmdline/relocate_tests.pyc subversion/tests/cmdline/resolve_tests.pyc subversion/tests/cmdline/revert_tests.pyc subversion/tests/cmdline/schedule_tests.pyc subversion/tests/cmdline/special_tests.pyc subversion/tests/cmdline/stat_tests.pyc subversion/tests/cmdline/svnadmin_tests.pyc subversion/tests/cmdline/svnauthz_tests.pyc subversion/tests/cmdline/svndumpfilter_tests.pyc subversion/tests/cmdline/svnfsfs_tests.pyc subversion/tests/cmdline/svnlook_tests.pyc subversion/tests/cmdline/svnmucc_tests.pyc subversion/tests/cmdline/svnrdump_tests.pyc subversion/tests/cmdline/svnsync_authz_tests.pyc subversion/tests/cmdline/svnsync_tests.pyc subversion/tests/cmdline/svnversion_tests.pyc subversion/tests/cmdline/switch_tests.pyc subversion/tests/cmdline/trans_tests.pyc subversion/tests/cmdline/tree_conflict_tests.pyc subversion/tests/cmdline/update_tests.pyc subversion/tests/cmdline/upgrade_tests.pyc subversion/tests/cmdline/wc_tests.pyc subversion/tests/libsvn_client/client-test$(EXEEXT) subversion/tests/libsvn_client/mtcc-test$(EXEEXT) subversion/tests/libsvn_delta/random-test$(EXEEXT) subversion/tests/libsvn_delta/svndiff-test$(EXEEXT) subversion/tests/libsvn_delta/vdelta-test$(EXEEXT) subversion/tests/libsvn_delta/window-test$(EXEEXT) subversion/tests/libsvn_diff/diff-diff3-test$(EXEEXT) subversion/tests/libsvn_diff/parse-diff-test$(EXEEXT) subversion/tests/libsvn_fs/fs-test$(EXEEXT) subversion/tests/libsvn_fs/locks-test$(EXEEXT) subversion/tests/libsvn_fs_base/changes-test$(EXEEXT) subversion/tests/libsvn_fs_base/fs-base-test$(EXEEXT) subversion/tests/libsvn_fs_base/strings-reps-test$(EXEEXT) subversion/tests/libsvn_fs_fs/fs-fs-fuzzy-test$(EXEEXT) subversion/tests/libsvn_fs_fs/fs-fs-pack-test$(EXEEXT) subversion/tests/libsvn_fs_fs/fs-fs-private-test$(EXEEXT) subversion/tests/libsvn_fs_x/fs-x-pack-test$(EXEEXT) subversion/tests/libsvn_fs_x/string-table-test$(EXEEXT) subversion/tests/libsvn_ra/ra-test$(EXEEXT) subversion/tests/libsvn_ra_local/ra-local-test$(EXEEXT) subversion/tests/libsvn_repos/dump-load-test$(EXEEXT) subversion/tests/libsvn_repos/repos-test$(EXEEXT) subversion/tests/libsvn_subr/auth-test$(EXEEXT) subversion/tests/libsvn_subr/bit-array-test$(EXEEXT) subversion/tests/libsvn_subr/cache-test$(EXEEXT) subversion/tests/libsvn_subr/checksum-test$(EXEEXT) subversion/tests/libsvn_subr/compat-test$(EXEEXT) subversion/tests/libsvn_subr/config-test$(EXEEXT) subversion/tests/libsvn_subr/crypto-test$(EXEEXT) subversion/tests/libsvn_subr/dirent_uri-test$(EXEEXT) subversion/tests/libsvn_subr/error-code-test$(EXEEXT) subversion/tests/libsvn_subr/error-test$(EXEEXT) subversion/tests/libsvn_subr/hashdump-test$(EXEEXT) subversion/tests/libsvn_subr/io-test$(EXEEXT) subversion/tests/libsvn_subr/mergeinfo-test$(EXEEXT) subversion/tests/libsvn_subr/opt-test$(EXEEXT) subversion/tests/libsvn_subr/packed-data-test$(EXEEXT) subversion/tests/libsvn_subr/path-test$(EXEEXT) subversion/tests/libsvn_subr/prefix-string-test$(EXEEXT) subversion/tests/libsvn_subr/priority-queue-test$(EXEEXT) subversion/tests/libsvn_subr/revision-test$(EXEEXT) subversion/tests/libsvn_subr/root-pools-test$(EXEEXT) subversion/tests/libsvn_subr/skel-test$(EXEEXT) subversion/tests/libsvn_subr/spillbuf-test$(EXEEXT) subversion/tests/libsvn_subr/sqlite-test$(EXEEXT) subversion/tests/libsvn_subr/stream-test$(EXEEXT) subversion/tests/libsvn_subr/string-test$(EXEEXT) subversion/tests/libsvn_subr/subst_translate-test$(EXEEXT) subversion/tests/libsvn_subr/time-test$(EXEEXT) subversion/tests/libsvn_subr/translate-test$(EXEEXT) subversion/tests/libsvn_subr/utf-test$(EXEEXT) subversion/tests/libsvn_subr/x509-test$(EXEEXT) subversion/tests/libsvn_wc/conflict-data-test$(EXEEXT) subversion/tests/libsvn_wc/db-test$(EXEEXT) subversion/tests/libsvn_wc/entries-compat-test$(EXEEXT) subversion/tests/libsvn_wc/op-depth-test$(EXEEXT) subversion/tests/libsvn_wc/pristine-store-test$(EXEEXT) subversion/tests/libsvn_wc/wc-incomplete-tester$(EXEEXT) subversion/tests/libsvn_wc/wc-lock-tester$(EXEEXT) subversion/tests/libsvn_wc/wc-queries-test$(EXEEXT) subversion/tests/libsvn_wc/wc-test$(EXEEXT) tools/dev/fsfs-access-map$(EXEEXT) tools/dev/svnraisetreeconflict/svnraisetreeconflict$(EXEEXT) tools/dev/wc-ng/svn-wc-db-tester$(EXEEXT) tools/dev/x509-parser$(EXEEXT) tools/diff/diff$(EXEEXT) tools/diff/diff3$(EXEEXT) tools/diff/diff4$(EXEEXT) tools/server-side/svn-populate-node-origins-index$(EXEEXT) tools/server-side/svnauthz$(EXEEXT) tools/server-side/svnauthz-validate$(EXEEXT) +CLEAN_FILES = subversion/bindings/cxxhl/cxxhl-tests$(EXEEXT) subversion/svn/svn$(EXEEXT) subversion/svnadmin/svnadmin$(EXEEXT) subversion/svnbench/svnbench$(EXEEXT) subversion/svndumpfilter/svndumpfilter$(EXEEXT) subversion/svnfsfs/svnfsfs$(EXEEXT) subversion/svnlook/svnlook$(EXEEXT) subversion/svnmucc/svnmucc$(EXEEXT) subversion/svnrdump/svnrdump$(EXEEXT) subversion/svnserve/svnserve$(EXEEXT) subversion/svnsync/svnsync$(EXEEXT) subversion/svnversion/svnversion$(EXEEXT) subversion/tests/afl/afl-x509$(EXEEXT) subversion/tests/cmdline/atomic-ra-revprop-change$(EXEEXT) subversion/tests/cmdline/authz_tests.pyc subversion/tests/cmdline/autoprop_tests.pyc subversion/tests/cmdline/basic_tests.pyc subversion/tests/cmdline/blame_tests.pyc subversion/tests/cmdline/cat_tests.pyc subversion/tests/cmdline/changelist_tests.pyc subversion/tests/cmdline/checkout_tests.pyc subversion/tests/cmdline/commit_tests.pyc subversion/tests/cmdline/copy_tests.pyc subversion/tests/cmdline/depth_tests.pyc subversion/tests/cmdline/diff_tests.pyc subversion/tests/cmdline/entries-dump$(EXEEXT) subversion/tests/cmdline/entries_tests.pyc subversion/tests/cmdline/export_tests.pyc subversion/tests/cmdline/externals_tests.pyc subversion/tests/cmdline/getopt_tests.pyc subversion/tests/cmdline/history_tests.pyc subversion/tests/cmdline/import_tests.pyc subversion/tests/cmdline/info_tests.pyc subversion/tests/cmdline/input_validation_tests.pyc subversion/tests/cmdline/iprop_authz_tests.pyc subversion/tests/cmdline/iprop_tests.pyc subversion/tests/cmdline/lock-helper$(EXEEXT) subversion/tests/cmdline/lock_tests.pyc subversion/tests/cmdline/log_tests.pyc subversion/tests/cmdline/merge_authz_tests.pyc subversion/tests/cmdline/merge_automatic_tests.pyc subversion/tests/cmdline/merge_reintegrate_tests.pyc subversion/tests/cmdline/merge_tests.pyc subversion/tests/cmdline/merge_tree_conflict_tests.pyc subversion/tests/cmdline/mergeinfo_tests.pyc subversion/tests/cmdline/mod_authz_svn_tests.pyc subversion/tests/cmdline/mod_dav_svn_tests.pyc subversion/tests/cmdline/move_tests.pyc subversion/tests/cmdline/patch_tests.pyc subversion/tests/cmdline/prop_tests.pyc subversion/tests/cmdline/redirect_tests.pyc subversion/tests/cmdline/relocate_tests.pyc subversion/tests/cmdline/resolve_tests.pyc subversion/tests/cmdline/revert_tests.pyc subversion/tests/cmdline/schedule_tests.pyc subversion/tests/cmdline/shelve_tests.pyc subversion/tests/cmdline/special_tests.pyc subversion/tests/cmdline/stat_tests.pyc subversion/tests/cmdline/svnadmin_tests.pyc subversion/tests/cmdline/svnauthz_tests.pyc subversion/tests/cmdline/svndumpfilter_tests.pyc subversion/tests/cmdline/svnfsfs_tests.pyc subversion/tests/cmdline/svnlook_tests.pyc subversion/tests/cmdline/svnmover_tests.pyc subversion/tests/cmdline/svnmucc_tests.pyc subversion/tests/cmdline/svnrdump_tests.pyc subversion/tests/cmdline/svnsync_authz_tests.pyc subversion/tests/cmdline/svnsync_tests.pyc subversion/tests/cmdline/svnversion_tests.pyc subversion/tests/cmdline/switch_tests.pyc subversion/tests/cmdline/trans_tests.pyc subversion/tests/cmdline/tree_conflict_tests.pyc subversion/tests/cmdline/update_tests.pyc subversion/tests/cmdline/upgrade_tests.pyc subversion/tests/cmdline/wc_tests.pyc subversion/tests/libsvn_client/client-test$(EXEEXT) subversion/tests/libsvn_client/conflicts-test$(EXEEXT) subversion/tests/libsvn_client/mtcc-test$(EXEEXT) subversion/tests/libsvn_delta/random-test$(EXEEXT) subversion/tests/libsvn_delta/svndiff-stream-test$(EXEEXT) subversion/tests/libsvn_delta/svndiff-test$(EXEEXT) subversion/tests/libsvn_delta/vdelta-test$(EXEEXT) subversion/tests/libsvn_delta/window-test$(EXEEXT) subversion/tests/libsvn_diff/diff-diff3-test$(EXEEXT) subversion/tests/libsvn_diff/parse-diff-test$(EXEEXT) subversion/tests/libsvn_fs/fs-sequential-test$(EXEEXT) subversion/tests/libsvn_fs/fs-test$(EXEEXT) subversion/tests/libsvn_fs/locks-test$(EXEEXT) subversion/tests/libsvn_fs_base/changes-test$(EXEEXT) subversion/tests/libsvn_fs_base/fs-base-test$(EXEEXT) subversion/tests/libsvn_fs_base/strings-reps-test$(EXEEXT) subversion/tests/libsvn_fs_fs/fs-fs-fuzzy-test$(EXEEXT) subversion/tests/libsvn_fs_fs/fs-fs-pack-test$(EXEEXT) subversion/tests/libsvn_fs_fs/fs-fs-private-test$(EXEEXT) subversion/tests/libsvn_fs_x/fs-x-pack-test$(EXEEXT) subversion/tests/libsvn_fs_x/string-table-test$(EXEEXT) subversion/tests/libsvn_ra/ra-test$(EXEEXT) subversion/tests/libsvn_ra_local/ra-local-test$(EXEEXT) subversion/tests/libsvn_repos/authz-test$(EXEEXT) subversion/tests/libsvn_repos/dump-load-test$(EXEEXT) subversion/tests/libsvn_repos/repos-test$(EXEEXT) subversion/tests/libsvn_subr/auth-test$(EXEEXT) subversion/tests/libsvn_subr/bit-array-test$(EXEEXT) subversion/tests/libsvn_subr/cache-test$(EXEEXT) subversion/tests/libsvn_subr/checksum-test$(EXEEXT) subversion/tests/libsvn_subr/compat-test$(EXEEXT) subversion/tests/libsvn_subr/compress-test$(EXEEXT) subversion/tests/libsvn_subr/config-test$(EXEEXT) subversion/tests/libsvn_subr/crypto-test$(EXEEXT) subversion/tests/libsvn_subr/dirent_uri-test$(EXEEXT) subversion/tests/libsvn_subr/error-code-test$(EXEEXT) subversion/tests/libsvn_subr/error-test$(EXEEXT) subversion/tests/libsvn_subr/hashdump-test$(EXEEXT) subversion/tests/libsvn_subr/io-test$(EXEEXT) subversion/tests/libsvn_subr/mergeinfo-test$(EXEEXT) subversion/tests/libsvn_subr/opt-test$(EXEEXT) subversion/tests/libsvn_subr/packed-data-test$(EXEEXT) subversion/tests/libsvn_subr/path-test$(EXEEXT) subversion/tests/libsvn_subr/prefix-string-test$(EXEEXT) subversion/tests/libsvn_subr/priority-queue-test$(EXEEXT) subversion/tests/libsvn_subr/revision-test$(EXEEXT) subversion/tests/libsvn_subr/root-pools-test$(EXEEXT) subversion/tests/libsvn_subr/skel-test$(EXEEXT) subversion/tests/libsvn_subr/spillbuf-test$(EXEEXT) subversion/tests/libsvn_subr/sqlite-test$(EXEEXT) subversion/tests/libsvn_subr/stream-test$(EXEEXT) subversion/tests/libsvn_subr/string-test$(EXEEXT) subversion/tests/libsvn_subr/subst_translate-test$(EXEEXT) subversion/tests/libsvn_subr/time-test$(EXEEXT) subversion/tests/libsvn_subr/translate-test$(EXEEXT) subversion/tests/libsvn_subr/utf-test$(EXEEXT) subversion/tests/libsvn_subr/x509-test$(EXEEXT) subversion/tests/libsvn_subr/xml-test$(EXEEXT) subversion/tests/libsvn_wc/conflict-data-test$(EXEEXT) subversion/tests/libsvn_wc/db-test$(EXEEXT) subversion/tests/libsvn_wc/entries-compat-test$(EXEEXT) subversion/tests/libsvn_wc/op-depth-test$(EXEEXT) subversion/tests/libsvn_wc/pristine-store-test$(EXEEXT) subversion/tests/libsvn_wc/wc-incomplete-tester$(EXEEXT) subversion/tests/libsvn_wc/wc-lock-tester$(EXEEXT) subversion/tests/libsvn_wc/wc-queries-test$(EXEEXT) subversion/tests/libsvn_wc/wc-test$(EXEEXT) tools/client-side/svn-mergeinfo-normalizer/svn-mergeinfo-normalizer$(EXEEXT) tools/client-side/svnconflict/svnconflict$(EXEEXT) tools/dev/fsfs-access-map$(EXEEXT) tools/dev/svnmover/svnmover$(EXEEXT) tools/dev/svnraisetreeconflict/svnraisetreeconflict$(EXEEXT) tools/dev/wc-ng/svn-wc-db-tester$(EXEEXT) tools/dev/x509-parser$(EXEEXT) tools/diff/diff$(EXEEXT) tools/diff/diff3$(EXEEXT) tools/diff/diff4$(EXEEXT) tools/server-side/svn-populate-node-origins-index$(EXEEXT) tools/server-side/svnauthz$(EXEEXT) tools/server-side/svnauthz-validate$(EXEEXT) EXTRACLEAN_FILES = subversion/libsvn_fs_fs/rep-cache-db.h subversion/libsvn_fs_x/rep-cache-db.h subversion/libsvn_subr/internal_statements.h subversion/libsvn_wc/wc-queries.h subversion/tests/libsvn_wc/wc-test-queries.h \ $(abs_builddir)/subversion/libsvn_subr/errorcode.inc \ $(abs_builddir)/subversion/libsvn_subr/config_keys.inc \ @@ -93,6 +93,12 @@ autogen-swig: autogen-swig-rb # Section 5: Individual target build rules ######################################## +afl_x509_PATH = subversion/tests/afl +afl_x509_DEPS = subversion/tests/afl/afl-x509.lo subversion/libsvn_subr/libsvn_subr-1.la +afl_x509_OBJECTS = afl-x509.lo +subversion/tests/afl/afl-x509$(EXEEXT): $(afl_x509_DEPS) + cd subversion/tests/afl && $(LINK) $(afl_x509_LDFLAGS) -o afl-x509$(EXEEXT) $(afl_x509_OBJECTS) ../../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APR_LIBS) $(LIBS) + atomic_ra_revprop_change_PATH = subversion/tests/cmdline atomic_ra_revprop_change_DEPS = subversion/tests/cmdline/atomic-ra-revprop-change.lo subversion/libsvn_ra/libsvn_ra-1.la subversion/libsvn_subr/libsvn_subr-1.la atomic_ra_revprop_change_OBJECTS = atomic-ra-revprop-change.lo @@ -105,6 +111,12 @@ auth_test_OBJECTS = auth-test.lo subversion/tests/libsvn_subr/auth-test$(EXEEXT): $(auth_test_DEPS) cd subversion/tests/libsvn_subr && $(LINK) $(auth_test_LDFLAGS) -o auth-test$(EXEEXT) $(auth_test_OBJECTS) ../../../subversion/tests/libsvn_test-1.la ../../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APR_LIBS) $(LIBS) +authz_test_PATH = subversion/tests/libsvn_repos +authz_test_DEPS = subversion/tests/libsvn_repos/authz-test.lo subversion/tests/libsvn_test-1.la subversion/libsvn_repos/libsvn_repos-1.la subversion/libsvn_fs/libsvn_fs-1.la subversion/libsvn_delta/libsvn_delta-1.la subversion/libsvn_subr/libsvn_subr-1.la +authz_test_OBJECTS = authz-test.lo +subversion/tests/libsvn_repos/authz-test$(EXEEXT): $(authz_test_DEPS) + cd subversion/tests/libsvn_repos && $(LINK) $(authz_test_LDFLAGS) -o authz-test$(EXEEXT) $(authz_test_OBJECTS) ../../../subversion/tests/libsvn_test-1.la ../../../subversion/libsvn_repos/libsvn_repos-1.la ../../../subversion/libsvn_fs/libsvn_fs-1.la ../../../subversion/libsvn_delta/libsvn_delta-1.la ../../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS) $(LIBS) + bit_array_test_PATH = subversion/tests/libsvn_subr bit_array_test_DEPS = subversion/tests/libsvn_subr/bit-array-test.lo subversion/tests/libsvn_test-1.la subversion/libsvn_subr/libsvn_subr-1.la bit_array_test_OBJECTS = bit-array-test.lo @@ -141,6 +153,12 @@ compat_test_OBJECTS = compat-test.lo subversion/tests/libsvn_subr/compat-test$(EXEEXT): $(compat_test_DEPS) cd subversion/tests/libsvn_subr && $(LINK) $(compat_test_LDFLAGS) -o compat-test$(EXEEXT) $(compat_test_OBJECTS) ../../../subversion/tests/libsvn_test-1.la ../../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APR_LIBS) $(LIBS) +compress_test_PATH = subversion/tests/libsvn_subr +compress_test_DEPS = subversion/tests/libsvn_subr/compress-test.lo subversion/tests/libsvn_test-1.la subversion/libsvn_subr/libsvn_subr-1.la +compress_test_OBJECTS = compress-test.lo +subversion/tests/libsvn_subr/compress-test$(EXEEXT): $(compress_test_DEPS) + cd subversion/tests/libsvn_subr && $(LINK) $(compress_test_LDFLAGS) -o compress-test$(EXEEXT) $(compress_test_OBJECTS) ../../../subversion/tests/libsvn_test-1.la ../../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APR_LIBS) $(LIBS) + config_test_PATH = subversion/tests/libsvn_subr config_test_DEPS = subversion/tests/libsvn_subr/config-test.lo subversion/tests/libsvn_test-1.la subversion/libsvn_subr/libsvn_subr-1.la config_test_OBJECTS = config-test.lo @@ -153,6 +171,12 @@ conflict_data_test_OBJECTS = conflict-data-test.lo utils.lo subversion/tests/libsvn_wc/conflict-data-test$(EXEEXT): $(conflict_data_test_DEPS) cd subversion/tests/libsvn_wc && $(LINK) $(conflict_data_test_LDFLAGS) -o conflict-data-test$(EXEEXT) $(conflict_data_test_OBJECTS) ../../../subversion/libsvn_client/libsvn_client-1.la ../../../subversion/tests/libsvn_test-1.la ../../../subversion/libsvn_wc/libsvn_wc-1.la ../../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS) $(LIBS) +conflicts_test_PATH = subversion/tests/libsvn_client +conflicts_test_DEPS = subversion/tests/libsvn_wc/utils.lo subversion/tests/libsvn_client/conflicts-test.lo subversion/tests/libsvn_test-1.la subversion/libsvn_client/libsvn_client-1.la subversion/libsvn_wc/libsvn_wc-1.la subversion/libsvn_repos/libsvn_repos-1.la subversion/libsvn_ra/libsvn_ra-1.la subversion/libsvn_fs/libsvn_fs-1.la subversion/libsvn_delta/libsvn_delta-1.la subversion/libsvn_subr/libsvn_subr-1.la +conflicts_test_OBJECTS = ../libsvn_wc/utils.lo conflicts-test.lo +subversion/tests/libsvn_client/conflicts-test$(EXEEXT): $(conflicts_test_DEPS) + cd subversion/tests/libsvn_client && $(LINK) $(conflicts_test_LDFLAGS) -o conflicts-test$(EXEEXT) $(conflicts_test_OBJECTS) ../../../subversion/tests/libsvn_test-1.la ../../../subversion/libsvn_client/libsvn_client-1.la ../../../subversion/libsvn_wc/libsvn_wc-1.la ../../../subversion/libsvn_repos/libsvn_repos-1.la ../../../subversion/libsvn_ra/libsvn_ra-1.la ../../../subversion/libsvn_fs/libsvn_fs-1.la ../../../subversion/libsvn_delta/libsvn_delta-1.la ../../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS) $(LIBS) + crypto_test_PATH = subversion/tests/libsvn_subr crypto_test_DEPS = subversion/tests/libsvn_subr/crypto-test.lo subversion/tests/libsvn_test-1.la subversion/libsvn_subr/libsvn_subr-1.la crypto_test_OBJECTS = crypto-test.lo @@ -160,10 +184,10 @@ subversion/tests/libsvn_subr/crypto-test$(EXEEXT): $(crypto_test_DEPS) cd subversion/tests/libsvn_subr && $(LINK) $(crypto_test_LDFLAGS) -o crypto-test$(EXEEXT) $(crypto_test_OBJECTS) ../../../subversion/tests/libsvn_test-1.la ../../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS) $(LIBS) cxxhl_tests_PATH = subversion/bindings/cxxhl -cxxhl_tests_DEPS = subversion/bindings/cxxhl/tests/cxxhl-tests.lo subversion/bindings/cxxhl/tests/test_aprwrap.lo subversion/bindings/cxxhl/tests/test_exception.lo subversion/bindings/cxxhl/libsvncxxhl-1.la gmock-fused/libgmock-1.la subversion/libsvn_subr/libsvn_subr-1.la +cxxhl_tests_DEPS = subversion/bindings/cxxhl/tests/cxxhl-tests.lo subversion/bindings/cxxhl/tests/test_aprwrap.lo subversion/bindings/cxxhl/tests/test_exception.lo subversion/bindings/cxxhl/libsvncxxhl-1.la googlemock/libgooglemock-1.la subversion/libsvn_subr/libsvn_subr-1.la cxxhl_tests_OBJECTS = tests/cxxhl-tests.lo tests/test_aprwrap.lo tests/test_exception.lo subversion/bindings/cxxhl/cxxhl-tests$(EXEEXT): $(cxxhl_tests_DEPS) - if $(SVN_USE_GMOCK) ; then cd subversion/bindings/cxxhl && $(LINK_CXX) $(cxxhl_tests_LDFLAGS) -o cxxhl-tests$(EXEEXT) $(cxxhl_tests_OBJECTS) ../../../subversion/bindings/cxxhl/libsvncxxhl-1.la ../../../gmock-fused/libgmock-1.la ../../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APR_LIBS) $(LIBS) ; else echo "fake" > subversion/bindings/cxxhl/cxxhl-tests$(EXEEXT) ; fi + if $(SVN_USE_GOOGLEMOCK) ; then cd subversion/bindings/cxxhl && $(LINK_CXX) $(cxxhl_tests_LDFLAGS) -o cxxhl-tests$(EXEEXT) $(cxxhl_tests_OBJECTS) ../../../subversion/bindings/cxxhl/libsvncxxhl-1.la ../../../googlemock/libgooglemock-1.la ../../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APR_LIBS) $(LIBS) ; else echo "fake" > subversion/bindings/cxxhl/cxxhl-tests$(EXEEXT) ; fi db_test_PATH = subversion/tests/libsvn_wc db_test_DEPS = subversion/tests/libsvn_wc/db-test.lo subversion/tests/libsvn_wc/utils.lo subversion/libsvn_client/libsvn_client-1.la subversion/tests/libsvn_test-1.la subversion/libsvn_wc/libsvn_wc-1.la subversion/libsvn_subr/libsvn_subr-1.la @@ -255,6 +279,12 @@ fs_fs_private_test_OBJECTS = fs-fs-private-test.lo subversion/tests/libsvn_fs_fs/fs-fs-private-test$(EXEEXT): $(fs_fs_private_test_DEPS) cd subversion/tests/libsvn_fs_fs && $(LINK) $(fs_fs_private_test_LDFLAGS) -o fs-fs-private-test$(EXEEXT) $(fs_fs_private_test_OBJECTS) ../../../subversion/tests/libsvn_test-1.la ../../../subversion/libsvn_fs/libsvn_fs-1.la ../../../subversion/libsvn_fs_fs/libsvn_fs_fs-1.la ../../../subversion/libsvn_delta/libsvn_delta-1.la ../../../subversion/libsvn_repos/libsvn_repos-1.la ../../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS) $(LIBS) +fs_sequential_test_PATH = subversion/tests/libsvn_fs +fs_sequential_test_DEPS = subversion/tests/libsvn_fs/fs-sequential-test.lo subversion/tests/libsvn_test-1.la subversion/libsvn_fs/libsvn_fs-1.la subversion/libsvn_delta/libsvn_delta-1.la subversion/libsvn_fs_util/libsvn_fs_util-1.la subversion/libsvn_subr/libsvn_subr-1.la +fs_sequential_test_OBJECTS = fs-sequential-test.lo +subversion/tests/libsvn_fs/fs-sequential-test$(EXEEXT): $(fs_sequential_test_DEPS) + cd subversion/tests/libsvn_fs && $(LINK) $(fs_sequential_test_LDFLAGS) -o fs-sequential-test$(EXEEXT) $(fs_sequential_test_OBJECTS) ../../../subversion/tests/libsvn_test-1.la ../../../subversion/libsvn_fs/libsvn_fs-1.la ../../../subversion/libsvn_delta/libsvn_delta-1.la ../../../subversion/libsvn_fs_util/libsvn_fs_util-1.la ../../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS) $(LIBS) + fs_test_PATH = subversion/tests/libsvn_fs fs_test_DEPS = subversion/tests/libsvn_fs/fs-test.lo subversion/tests/libsvn_test-1.la subversion/libsvn_fs/libsvn_fs-1.la subversion/libsvn_delta/libsvn_delta-1.la subversion/libsvn_fs_util/libsvn_fs_util-1.la subversion/libsvn_subr/libsvn_subr-1.la fs_test_OBJECTS = fs-test.lo @@ -286,12 +316,12 @@ subversion/tests/libsvn_subr/io-test$(EXEEXT): $(io_test_DEPS) cd subversion/tests/libsvn_subr && $(LINK) $(io_test_LDFLAGS) -o io-test$(EXEEXT) $(io_test_OBJECTS) ../../../subversion/tests/libsvn_test-1.la ../../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS) $(LIBS) javahl_callback_javah_PATH = subversion/bindings/javahl/include -javahl_callback_javah_HEADERS = subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_AuthnCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_BlameCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_ChangelistCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_ClientNotifyCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_CommitCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_CommitMessageCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_ConfigEvent.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_ConflictResolverCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_DiffSummaryCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_ImportFilterCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_InfoCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_InheritedProplistCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_ListCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_LogMessageCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_PatchCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_ProgressCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_ProplistCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_RemoteFileRevisionsCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_RemoteLocationSegmentsCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_RemoteStatus.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_ReposFreezeAction.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_ReposNotifyCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_ReposVerifyCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_StatusCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_TunnelAgent.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_UserPasswordCallback.h +javahl_callback_javah_HEADERS = subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_AuthnCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_BlameCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_ChangelistCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_ClientNotifyCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_CommitCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_CommitMessageCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_ConfigEvent.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_ConflictResolverCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_DiffSummaryCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_ImportFilterCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_InfoCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_InheritedProplistCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_ListCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_ListItemCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_LogMessageCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_PatchCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_ProgressCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_ProplistCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_RemoteFileRevisionsCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_RemoteLocationSegmentsCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_RemoteStatus.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_ReposFreezeAction.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_ReposNotifyCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_ReposVerifyCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_StatusCallback.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_TunnelAgent.h subversion/bindings/javahl/include/org_apache_subversion_javahl_callback_UserPasswordCallback.h javahl_callback_javah_OBJECTS = javahl_callback_javah_DEPS = $(javahl_callback_javah_HEADERS) $(javahl_callback_javah_OBJECTS) $(javahl_java_DEPS) javahl-callback-javah: $(javahl_callback_javah_DEPS) -javahl_callback_javah_CLASS_FILENAMES = subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/AuthnCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/BlameCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ChangelistCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ClientNotifyCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/CommitCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/CommitMessageCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ConfigEvent.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ConflictResolverCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/DiffSummaryCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ImportFilterCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/InfoCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/InheritedProplistCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ListCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/LogMessageCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/PatchCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ProgressCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ProplistCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/RemoteFileRevisionsCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/RemoteLocationSegmentsCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/RemoteStatus.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ReposFreezeAction.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ReposNotifyCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ReposVerifyCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/StatusCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/TunnelAgent.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/UserPasswordCallback.class -javahl_callback_javah_CLASSES = org.apache.subversion.javahl.callback.AuthnCallback org.apache.subversion.javahl.callback.BlameCallback org.apache.subversion.javahl.callback.ChangelistCallback org.apache.subversion.javahl.callback.ClientNotifyCallback org.apache.subversion.javahl.callback.CommitCallback org.apache.subversion.javahl.callback.CommitMessageCallback org.apache.subversion.javahl.callback.ConfigEvent org.apache.subversion.javahl.callback.ConflictResolverCallback org.apache.subversion.javahl.callback.DiffSummaryCallback org.apache.subversion.javahl.callback.ImportFilterCallback org.apache.subversion.javahl.callback.InfoCallback org.apache.subversion.javahl.callback.InheritedProplistCallback org.apache.subversion.javahl.callback.ListCallback org.apache.subversion.javahl.callback.LogMessageCallback org.apache.subversion.javahl.callback.PatchCallback org.apache.subversion.javahl.callback.ProgressCallback org.apache.subversion.javahl.callback.ProplistCallback org.apache.subversion.javahl.callback.RemoteFileRevisionsCallback org.apache.subversion.javahl.callback.RemoteLocationSegmentsCallback org.apache.subversion.javahl.callback.RemoteStatus org.apache.subversion.javahl.callback.ReposFreezeAction org.apache.subversion.javahl.callback.ReposNotifyCallback org.apache.subversion.javahl.callback.ReposVerifyCallback org.apache.subversion.javahl.callback.StatusCallback org.apache.subversion.javahl.callback.TunnelAgent org.apache.subversion.javahl.callback.UserPasswordCallback +javahl_callback_javah_CLASS_FILENAMES = subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/AuthnCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/BlameCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ChangelistCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ClientNotifyCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/CommitCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/CommitMessageCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ConfigEvent.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ConflictResolverCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/DiffSummaryCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ImportFilterCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/InfoCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/InheritedProplistCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ListCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ListItemCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/LogMessageCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/PatchCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ProgressCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ProplistCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/RemoteFileRevisionsCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/RemoteLocationSegmentsCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/RemoteStatus.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ReposFreezeAction.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ReposNotifyCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ReposVerifyCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/StatusCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/TunnelAgent.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/UserPasswordCallback.class +javahl_callback_javah_CLASSES = org.apache.subversion.javahl.callback.AuthnCallback org.apache.subversion.javahl.callback.BlameCallback org.apache.subversion.javahl.callback.ChangelistCallback org.apache.subversion.javahl.callback.ClientNotifyCallback org.apache.subversion.javahl.callback.CommitCallback org.apache.subversion.javahl.callback.CommitMessageCallback org.apache.subversion.javahl.callback.ConfigEvent org.apache.subversion.javahl.callback.ConflictResolverCallback org.apache.subversion.javahl.callback.DiffSummaryCallback org.apache.subversion.javahl.callback.ImportFilterCallback org.apache.subversion.javahl.callback.InfoCallback org.apache.subversion.javahl.callback.InheritedProplistCallback org.apache.subversion.javahl.callback.ListCallback org.apache.subversion.javahl.callback.ListItemCallback org.apache.subversion.javahl.callback.LogMessageCallback org.apache.subversion.javahl.callback.PatchCallback org.apache.subversion.javahl.callback.ProgressCallback org.apache.subversion.javahl.callback.ProplistCallback org.apache.subversion.javahl.callback.RemoteFileRevisionsCallback org.apache.subversion.javahl.callback.RemoteLocationSegmentsCallback org.apache.subversion.javahl.callback.RemoteStatus org.apache.subversion.javahl.callback.ReposFreezeAction org.apache.subversion.javahl.callback.ReposNotifyCallback org.apache.subversion.javahl.callback.ReposVerifyCallback org.apache.subversion.javahl.callback.StatusCallback org.apache.subversion.javahl.callback.TunnelAgent org.apache.subversion.javahl.callback.UserPasswordCallback $(javahl_callback_javah_HEADERS): $(javahl_callback_javah_CLASS_FILENAMES) $(COMPILE_JAVAHL_JAVAH) -force -d subversion/bindings/javahl/include -classpath subversion/bindings/javahl/classes:$(javahl_callback_javah_CLASSPATH) $(javahl_callback_javah_CLASSES) @@ -318,10 +348,10 @@ $(javahl_compat_tests_OBJECTS): $(javahl_compat_tests_SRC) javahl_java_PATH = subversion/bindings/javahl/classes javahl_java_HEADERS = -javahl_java_OBJECTS = subversion/bindings/javahl/classes/org/apache/subversion/javahl/ClientException.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/ClientNotifyInformation.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/CommitInfo.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/CommitItem.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/CommitItemStateFlags.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/ConflictDescriptor.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/ConflictResult.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/DiffSummary.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/ISVNClient.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/ISVNConfig.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/ISVNEditor.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/ISVNRemote.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/ISVNReporter.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/ISVNRepos.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/JNIError.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/JNIObject.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/NativeException.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/NativeResources.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/OperationContext.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/ProgressEvent.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/ReposNotifyInformation.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/SVNClient.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/SVNRepos.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/SVNUtil.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/SubversionException.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/AuthnCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/BlameCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ChangelistCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ClientNotifyCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/CommitCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/CommitMessageCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ConfigEvent.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ConflictResolverCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/DiffSummaryCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ImportFilterCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/InfoCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/InheritedProplistCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ListCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/LogMessageCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/PatchCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ProgressCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ProplistCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/RemoteFileRevisionsCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/RemoteLocationSegmentsCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/RemoteStatus.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ReposFreezeAction.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ReposNotifyCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ReposVerifyCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/StatusCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/TunnelAgent.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/UserPasswordCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/remote/CommitEditor.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/remote/RemoteFactory.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/remote/RemoteSession.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/remote/RetryOpenSession.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/remote/StateReporter.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/remote/StatusEditor.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/ChangePath.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/Checksum.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/ConflictVersion.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/CopySource.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/Depth.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/DiffOptions.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/DirEntry.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/ExternalItem.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/Info.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/Lock.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/LogDate.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/Mergeinfo.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/NativeInputStream.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/NativeOutputStream.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/NodeKind.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/Property.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/Revision.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/RevisionRange.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/RevisionRangeList.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/RuntimeVersion.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/Status.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/Tristate.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/Version.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/VersionExtended.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/util/ConfigImpl.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/util/ConfigLib.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/util/DiffLib.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/util/PropLib.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/util/RequestChannel.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/util/ResponseChannel.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/util/SubstLib.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/util/TunnelChannel.class +javahl_java_OBJECTS = subversion/bindings/javahl/classes/org/apache/subversion/javahl/ClientException.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/ClientNotifyInformation.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/CommitInfo.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/CommitItem.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/CommitItemStateFlags.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/ConflictDescriptor.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/ConflictResult.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/DiffSummary.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/ISVNClient.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/ISVNConfig.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/ISVNEditor.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/ISVNRemote.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/ISVNReporter.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/ISVNRepos.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/JNIError.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/JNIObject.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/NativeException.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/NativeResources.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/OperationContext.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/ProgressEvent.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/ReposNotifyInformation.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/SVNClient.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/SVNRepos.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/SVNUtil.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/SubversionException.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/AuthnCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/BlameCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ChangelistCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ClientNotifyCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/CommitCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/CommitMessageCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ConfigEvent.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ConflictResolverCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/DiffSummaryCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ImportFilterCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/InfoCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/InheritedProplistCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ListCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ListItemCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/LogMessageCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/PatchCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ProgressCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ProplistCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/RemoteFileRevisionsCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/RemoteLocationSegmentsCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/RemoteStatus.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ReposFreezeAction.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ReposNotifyCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ReposVerifyCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/StatusCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/TunnelAgent.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/UserPasswordCallback.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/remote/CommitEditor.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/remote/RemoteFactory.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/remote/RemoteSession.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/remote/RetryOpenSession.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/remote/StateReporter.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/remote/StatusEditor.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/ChangePath.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/Checksum.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/ConflictVersion.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/CopySource.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/Depth.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/DiffOptions.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/DirEntry.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/ExternalItem.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/Info.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/Lock.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/LogDate.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/Mergeinfo.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/NativeInputStream.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/NativeOutputStream.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/NodeKind.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/Property.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/Revision.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/RevisionRange.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/RevisionRangeList.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/RuntimeVersion.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/Status.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/Tristate.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/Version.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/VersionExtended.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/util/ConfigImpl.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/util/ConfigLib.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/util/DiffLib.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/util/PropLib.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/util/RequestChannel.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/util/ResponseChannel.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/util/SubstLib.class subversion/bindings/javahl/classes/org/apache/subversion/javahl/util/TunnelChannel.class javahl_java_DEPS = $(javahl_java_HEADERS) $(javahl_java_OBJECTS) javahl-java: $(javahl_java_DEPS) -javahl_java_SRC = $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientException.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientNotifyInformation.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/CommitInfo.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/CommitItem.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/CommitItemStateFlags.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/ConflictDescriptor.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/ConflictResult.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/DiffSummary.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNConfig.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNEditor.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRemote.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNReporter.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRepos.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/JNIError.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/JNIObject.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/NativeException.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/NativeResources.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/OperationContext.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/ProgressEvent.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/ReposNotifyInformation.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNRepos.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNUtil.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/SubversionException.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/AuthnCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/BlameCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ChangelistCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ClientNotifyCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/CommitCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/CommitMessageCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ConfigEvent.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ConflictResolverCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/DiffSummaryCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ImportFilterCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/InfoCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/InheritedProplistCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ListCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/LogMessageCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/PatchCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ProgressCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ProplistCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/RemoteFileRevisionsCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/RemoteLocationSegmentsCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/RemoteStatus.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ReposFreezeAction.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ReposNotifyCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ReposVerifyCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/StatusCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/TunnelAgent.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/UserPasswordCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/CommitEditor.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteFactory.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteSession.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RetryOpenSession.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/StateReporter.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/StatusEditor.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/ChangePath.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Checksum.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/ConflictVersion.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/CopySource.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Depth.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/DiffOptions.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/DirEntry.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/ExternalItem.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Info.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Lock.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/LogDate.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Mergeinfo.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/NativeInputStream.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/NativeOutputStream.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/NodeKind.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Property.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Revision.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/RevisionRange.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/RevisionRangeList.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/RuntimeVersion.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Status.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Tristate.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Version.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/VersionExtended.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/ConfigImpl.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/ConfigLib.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/DiffLib.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/PropLib.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/RequestChannel.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/ResponseChannel.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/SubstLib.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/TunnelChannel.java +javahl_java_SRC = $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientException.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/ClientNotifyInformation.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/CommitInfo.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/CommitItem.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/CommitItemStateFlags.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/ConflictDescriptor.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/ConflictResult.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/DiffSummary.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNClient.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNConfig.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNEditor.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRemote.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNReporter.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRepos.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/JNIError.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/JNIObject.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/NativeException.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/NativeResources.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/OperationContext.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/ProgressEvent.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/ReposNotifyInformation.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNClient.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNRepos.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNUtil.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/SubversionException.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/AuthnCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/BlameCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ChangelistCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ClientNotifyCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/CommitCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/CommitMessageCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ConfigEvent.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ConflictResolverCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/DiffSummaryCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ImportFilterCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/InfoCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/InheritedProplistCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ListCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ListItemCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/LogMessageCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/PatchCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ProgressCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ProplistCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/RemoteFileRevisionsCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/RemoteLocationSegmentsCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/RemoteStatus.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ReposFreezeAction.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ReposNotifyCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ReposVerifyCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/StatusCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/TunnelAgent.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/UserPasswordCallback.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/CommitEditor.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteFactory.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RemoteSession.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/RetryOpenSession.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/StateReporter.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/remote/StatusEditor.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/ChangePath.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Checksum.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/ConflictVersion.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/CopySource.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Depth.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/DiffOptions.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/DirEntry.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/ExternalItem.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Info.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Lock.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/LogDate.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Mergeinfo.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/NativeInputStream.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/NativeOutputStream.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/NodeKind.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Property.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Revision.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/RevisionRange.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/RevisionRangeList.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/RuntimeVersion.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Status.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Tristate.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/Version.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/types/VersionExtended.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/ConfigImpl.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/ConfigLib.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/DiffLib.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/PropLib.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/RequestChannel.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/ResponseChannel.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/SubstLib.java $(abs_srcdir)/subversion/bindings/javahl/src/org/apache/subversion/javahl/util/TunnelChannel.java $(javahl_java_OBJECTS): $(javahl_java_SRC) $(COMPILE_JAVAHL_JAVAC) -d subversion/bindings/javahl/classes -classpath subversion/bindings/javahl/classes:$(javahl_java_CLASSPATH) $(javahl_java_SRC) @@ -380,33 +410,33 @@ $(javahl_util_javah_HEADERS): $(javahl_util_javah_CLASS_FILENAMES) $(COMPILE_JAVAHL_JAVAH) -force -d subversion/bindings/javahl/include -classpath subversion/bindings/javahl/classes:$(javahl_util_javah_CLASSPATH) $(javahl_util_javah_CLASSES) -libgmock_PATH = gmock-fused -libgmock_DEPS = -libgmock_OBJECTS = -gmock-fused/libgmock-1.la: $(libgmock_DEPS) - if $(SVN_USE_GMOCK) ; then cd gmock-fused && $(LINK_CXX_LIB) $(libgmock_LDFLAGS) -o libgmock-1.la $(LT_NO_UNDEFINED) $(libgmock_OBJECTS) $(LIBS) ; else echo "fake" > gmock-fused/libgmock-1.la ; fi +libgooglemock_PATH = googlemock +libgooglemock_DEPS = +libgooglemock_OBJECTS = +googlemock/libgooglemock-1.la: $(libgooglemock_DEPS) + if $(SVN_USE_GOOGLEMOCK) ; then cd googlemock && $(LINK_CXX_LIB) $(libgooglemock_LDFLAGS) -o libgooglemock-1.la $(LT_NO_UNDEFINED) $(libgooglemock_OBJECTS) $(LIBS) ; else echo "fake" > googlemock/libgooglemock-1.la ; fi libsvn_auth_gnome_keyring_PATH = subversion/libsvn_auth_gnome_keyring libsvn_auth_gnome_keyring_DEPS = subversion/libsvn_auth_gnome_keyring/gnome_keyring.lo subversion/libsvn_auth_gnome_keyring/version.lo subversion/libsvn_subr/libsvn_subr-1.la libsvn_auth_gnome_keyring_OBJECTS = gnome_keyring.lo version.lo subversion/libsvn_auth_gnome_keyring/libsvn_auth_gnome_keyring-1.la: $(libsvn_auth_gnome_keyring_DEPS) - cd subversion/libsvn_auth_gnome_keyring && $(LINK_LIB) $(libsvn_auth_gnome_keyring_LDFLAGS) -o libsvn_auth_gnome_keyring-1.la $(LT_NO_UNDEFINED) $(libsvn_auth_gnome_keyring_OBJECTS) ../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APR_LIBS) $(SVN_GNOME_KEYRING_LIBS) $(LIBS) + cd subversion/libsvn_auth_gnome_keyring && $(LINK_SHARED_ONLY_LIB) $(libsvn_auth_gnome_keyring_LDFLAGS) -o libsvn_auth_gnome_keyring-1.la $(LT_NO_UNDEFINED) $(libsvn_auth_gnome_keyring_OBJECTS) ../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APR_LIBS) $(SVN_GNOME_KEYRING_LIBS) $(LIBS) libsvn_auth_kwallet_PATH = subversion/libsvn_auth_kwallet libsvn_auth_kwallet_DEPS = subversion/libsvn_auth_kwallet/kwallet.lo subversion/libsvn_auth_kwallet/version.lo subversion/libsvn_subr/libsvn_subr-1.la libsvn_auth_kwallet_OBJECTS = kwallet.lo version.lo subversion/libsvn_auth_kwallet/libsvn_auth_kwallet-1.la: $(libsvn_auth_kwallet_DEPS) - cd subversion/libsvn_auth_kwallet && $(LINK_CXX_LIB) $(libsvn_auth_kwallet_LDFLAGS) -o libsvn_auth_kwallet-1.la $(LT_NO_UNDEFINED) $(libsvn_auth_kwallet_OBJECTS) ../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APR_LIBS) $(SVN_KWALLET_LIBS) $(LIBS) + cd subversion/libsvn_auth_kwallet && $(LINK_SHARED_ONLY_CXX_LIB) $(libsvn_auth_kwallet_LDFLAGS) -o libsvn_auth_kwallet-1.la $(LT_NO_UNDEFINED) $(libsvn_auth_kwallet_OBJECTS) ../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APR_LIBS) $(SVN_KWALLET_LIBS) $(LIBS) libsvn_client_PATH = subversion/libsvn_client -libsvn_client_DEPS = subversion/libsvn_client/add.lo subversion/libsvn_client/blame.lo subversion/libsvn_client/cat.lo subversion/libsvn_client/changelist.lo subversion/libsvn_client/checkout.lo subversion/libsvn_client/cleanup.lo subversion/libsvn_client/cmdline.lo subversion/libsvn_client/commit.lo subversion/libsvn_client/commit_util.lo subversion/libsvn_client/compat_providers.lo subversion/libsvn_client/copy.lo subversion/libsvn_client/copy_foreign.lo subversion/libsvn_client/ctx.lo subversion/libsvn_client/delete.lo subversion/libsvn_client/deprecated.lo subversion/libsvn_client/diff.lo subversion/libsvn_client/diff_local.lo subversion/libsvn_client/diff_summarize.lo subversion/libsvn_client/export.lo subversion/libsvn_client/externals.lo subversion/libsvn_client/import.lo subversion/libsvn_client/info.lo subversion/libsvn_client/iprops.lo subversion/libsvn_client/list.lo subversion/libsvn_client/locking_commands.lo subversion/libsvn_client/log.lo subversion/libsvn_client/merge.lo subversion/libsvn_client/mergeinfo.lo subversion/libsvn_client/mtcc.lo subversion/libsvn_client/patch.lo subversion/libsvn_client/prop_commands.lo subversion/libsvn_client/ra.lo subversion/libsvn_client/relocate.lo subversion/libsvn_client/repos_diff.lo subversion/libsvn_client/resolved.lo subversion/libsvn_client/revert.lo subversion/libsvn_client/revisions.lo subversion/libsvn_client/status.lo subversion/libsvn_client/switch.lo subversion/libsvn_client/update.lo subversion/libsvn_client/upgrade.lo subversion/libsvn_client/url.lo subversion/libsvn_client/util.lo subversion/libsvn_client/version.lo subversion/libsvn_wc/libsvn_wc-1.la subversion/libsvn_ra/libsvn_ra-1.la subversion/libsvn_delta/libsvn_delta-1.la subversion/libsvn_diff/libsvn_diff-1.la subversion/libsvn_subr/libsvn_subr-1.la -libsvn_client_OBJECTS = add.lo blame.lo cat.lo changelist.lo checkout.lo cleanup.lo cmdline.lo commit.lo commit_util.lo compat_providers.lo copy.lo copy_foreign.lo ctx.lo delete.lo deprecated.lo diff.lo diff_local.lo diff_summarize.lo export.lo externals.lo import.lo info.lo iprops.lo list.lo locking_commands.lo log.lo merge.lo mergeinfo.lo mtcc.lo patch.lo prop_commands.lo ra.lo relocate.lo repos_diff.lo resolved.lo revert.lo revisions.lo status.lo switch.lo update.lo upgrade.lo url.lo util.lo version.lo +libsvn_client_DEPS = subversion/libsvn_client/add.lo subversion/libsvn_client/blame.lo subversion/libsvn_client/cat.lo subversion/libsvn_client/changelist.lo subversion/libsvn_client/checkout.lo subversion/libsvn_client/cleanup.lo subversion/libsvn_client/cmdline.lo subversion/libsvn_client/commit.lo subversion/libsvn_client/commit_util.lo subversion/libsvn_client/compat_providers.lo subversion/libsvn_client/conflicts.lo subversion/libsvn_client/copy.lo subversion/libsvn_client/copy_foreign.lo subversion/libsvn_client/ctx.lo subversion/libsvn_client/delete.lo subversion/libsvn_client/deprecated.lo subversion/libsvn_client/diff.lo subversion/libsvn_client/diff_local.lo subversion/libsvn_client/diff_summarize.lo subversion/libsvn_client/export.lo subversion/libsvn_client/externals.lo subversion/libsvn_client/import.lo subversion/libsvn_client/info.lo subversion/libsvn_client/iprops.lo subversion/libsvn_client/list.lo subversion/libsvn_client/locking_commands.lo subversion/libsvn_client/log.lo subversion/libsvn_client/merge.lo subversion/libsvn_client/merge_elements.lo subversion/libsvn_client/mergeinfo.lo subversion/libsvn_client/mtcc.lo subversion/libsvn_client/patch.lo subversion/libsvn_client/prop_commands.lo subversion/libsvn_client/ra.lo subversion/libsvn_client/relocate.lo subversion/libsvn_client/repos_diff.lo subversion/libsvn_client/resolved.lo subversion/libsvn_client/revert.lo subversion/libsvn_client/revisions.lo subversion/libsvn_client/shelve.lo subversion/libsvn_client/status.lo subversion/libsvn_client/switch.lo subversion/libsvn_client/update.lo subversion/libsvn_client/upgrade.lo subversion/libsvn_client/url.lo subversion/libsvn_client/util.lo subversion/libsvn_client/version.lo subversion/libsvn_wc/libsvn_wc-1.la subversion/libsvn_ra/libsvn_ra-1.la subversion/libsvn_delta/libsvn_delta-1.la subversion/libsvn_diff/libsvn_diff-1.la subversion/libsvn_subr/libsvn_subr-1.la +libsvn_client_OBJECTS = add.lo blame.lo cat.lo changelist.lo checkout.lo cleanup.lo cmdline.lo commit.lo commit_util.lo compat_providers.lo conflicts.lo copy.lo copy_foreign.lo ctx.lo delete.lo deprecated.lo diff.lo diff_local.lo diff_summarize.lo export.lo externals.lo import.lo info.lo iprops.lo list.lo locking_commands.lo log.lo merge.lo merge_elements.lo mergeinfo.lo mtcc.lo patch.lo prop_commands.lo ra.lo relocate.lo repos_diff.lo resolved.lo revert.lo revisions.lo shelve.lo status.lo switch.lo update.lo upgrade.lo url.lo util.lo version.lo subversion/libsvn_client/libsvn_client-1.la: $(libsvn_client_DEPS) cd subversion/libsvn_client && $(LINK_LIB) $(libsvn_client_LDFLAGS) -o libsvn_client-1.la $(LT_NO_UNDEFINED) $(libsvn_client_OBJECTS) ../../subversion/libsvn_wc/libsvn_wc-1.la ../../subversion/libsvn_ra/libsvn_ra-1.la ../../subversion/libsvn_delta/libsvn_delta-1.la ../../subversion/libsvn_diff/libsvn_diff-1.la ../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS) $(LIBS) libsvn_delta_PATH = subversion/libsvn_delta -libsvn_delta_DEPS = subversion/libsvn_delta/cancel.lo subversion/libsvn_delta/compat.lo subversion/libsvn_delta/compose_delta.lo subversion/libsvn_delta/debug_editor.lo subversion/libsvn_delta/default_editor.lo subversion/libsvn_delta/deprecated.lo subversion/libsvn_delta/depth_filter_editor.lo subversion/libsvn_delta/editor.lo subversion/libsvn_delta/path_driver.lo subversion/libsvn_delta/svndiff.lo subversion/libsvn_delta/text_delta.lo subversion/libsvn_delta/version.lo subversion/libsvn_delta/xdelta.lo subversion/libsvn_subr/libsvn_subr-1.la -libsvn_delta_OBJECTS = cancel.lo compat.lo compose_delta.lo debug_editor.lo default_editor.lo deprecated.lo depth_filter_editor.lo editor.lo path_driver.lo svndiff.lo text_delta.lo version.lo xdelta.lo +libsvn_delta_DEPS = subversion/libsvn_delta/branch.lo subversion/libsvn_delta/branch_compat.lo subversion/libsvn_delta/branch_migrate.lo subversion/libsvn_delta/branch_nested.lo subversion/libsvn_delta/branch_repos.lo subversion/libsvn_delta/cancel.lo subversion/libsvn_delta/compat.lo subversion/libsvn_delta/compose_delta.lo subversion/libsvn_delta/debug_editor.lo subversion/libsvn_delta/default_editor.lo subversion/libsvn_delta/deprecated.lo subversion/libsvn_delta/depth_filter_editor.lo subversion/libsvn_delta/editor.lo subversion/libsvn_delta/element.lo subversion/libsvn_delta/path_driver.lo subversion/libsvn_delta/svndiff.lo subversion/libsvn_delta/text_delta.lo subversion/libsvn_delta/version.lo subversion/libsvn_delta/xdelta.lo subversion/libsvn_subr/libsvn_subr-1.la +libsvn_delta_OBJECTS = branch.lo branch_compat.lo branch_migrate.lo branch_nested.lo branch_repos.lo cancel.lo compat.lo compose_delta.lo debug_editor.lo default_editor.lo deprecated.lo depth_filter_editor.lo editor.lo element.lo path_driver.lo svndiff.lo text_delta.lo version.lo xdelta.lo subversion/libsvn_delta/libsvn_delta-1.la: $(libsvn_delta_DEPS) cd subversion/libsvn_delta && $(LINK_LIB) $(libsvn_delta_LDFLAGS) -o libsvn_delta-1.la $(LT_NO_UNDEFINED) $(libsvn_delta_OBJECTS) ../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS) $(SVN_ZLIB_LIBS) $(LIBS) @@ -442,8 +472,8 @@ subversion/libsvn_fs_util/libsvn_fs_util-1.la: $(libsvn_fs_util_DEPS) cd subversion/libsvn_fs_util && $(LINK_LIB) $(libsvn_fs_util_LDFLAGS) -o libsvn_fs_util-1.la $(LT_NO_UNDEFINED) $(libsvn_fs_util_OBJECTS) ../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS) $(LIBS) libsvn_fs_x_PATH = subversion/libsvn_fs_x -libsvn_fs_x_DEPS = subversion/libsvn_fs_x/cached_data.lo subversion/libsvn_fs_x/caching.lo subversion/libsvn_fs_x/changes.lo subversion/libsvn_fs_x/dag.lo subversion/libsvn_fs_x/fs.lo subversion/libsvn_fs_x/fs_id.lo subversion/libsvn_fs_x/fs_x.lo subversion/libsvn_fs_x/hotcopy.lo subversion/libsvn_fs_x/id.lo subversion/libsvn_fs_x/index.lo subversion/libsvn_fs_x/lock.lo subversion/libsvn_fs_x/low_level.lo subversion/libsvn_fs_x/noderevs.lo subversion/libsvn_fs_x/pack.lo subversion/libsvn_fs_x/recovery.lo subversion/libsvn_fs_x/rep-cache.lo subversion/libsvn_fs_x/reps.lo subversion/libsvn_fs_x/rev_file.lo subversion/libsvn_fs_x/revprops.lo subversion/libsvn_fs_x/string_table.lo subversion/libsvn_fs_x/temp_serializer.lo subversion/libsvn_fs_x/transaction.lo subversion/libsvn_fs_x/tree.lo subversion/libsvn_fs_x/util.lo subversion/libsvn_fs_x/verify.lo subversion/libsvn_delta/libsvn_delta-1.la subversion/libsvn_subr/libsvn_subr-1.la subversion/libsvn_fs_util/libsvn_fs_util-1.la -libsvn_fs_x_OBJECTS = cached_data.lo caching.lo changes.lo dag.lo fs.lo fs_id.lo fs_x.lo hotcopy.lo id.lo index.lo lock.lo low_level.lo noderevs.lo pack.lo recovery.lo rep-cache.lo reps.lo rev_file.lo revprops.lo string_table.lo temp_serializer.lo transaction.lo tree.lo util.lo verify.lo +libsvn_fs_x_DEPS = subversion/libsvn_fs_x/batch_fsync.lo subversion/libsvn_fs_x/cached_data.lo subversion/libsvn_fs_x/caching.lo subversion/libsvn_fs_x/changes.lo subversion/libsvn_fs_x/dag.lo subversion/libsvn_fs_x/dag_cache.lo subversion/libsvn_fs_x/fs.lo subversion/libsvn_fs_x/fs_id.lo subversion/libsvn_fs_x/fs_x.lo subversion/libsvn_fs_x/hotcopy.lo subversion/libsvn_fs_x/id.lo subversion/libsvn_fs_x/index.lo subversion/libsvn_fs_x/lock.lo subversion/libsvn_fs_x/low_level.lo subversion/libsvn_fs_x/noderevs.lo subversion/libsvn_fs_x/pack.lo subversion/libsvn_fs_x/recovery.lo subversion/libsvn_fs_x/rep-cache.lo subversion/libsvn_fs_x/reps.lo subversion/libsvn_fs_x/rev_file.lo subversion/libsvn_fs_x/revprops.lo subversion/libsvn_fs_x/string_table.lo subversion/libsvn_fs_x/temp_serializer.lo subversion/libsvn_fs_x/transaction.lo subversion/libsvn_fs_x/tree.lo subversion/libsvn_fs_x/util.lo subversion/libsvn_fs_x/verify.lo subversion/libsvn_delta/libsvn_delta-1.la subversion/libsvn_subr/libsvn_subr-1.la subversion/libsvn_fs_util/libsvn_fs_util-1.la +libsvn_fs_x_OBJECTS = batch_fsync.lo cached_data.lo caching.lo changes.lo dag.lo dag_cache.lo fs.lo fs_id.lo fs_x.lo hotcopy.lo id.lo index.lo lock.lo low_level.lo noderevs.lo pack.lo recovery.lo rep-cache.lo reps.lo rev_file.lo revprops.lo string_table.lo temp_serializer.lo transaction.lo tree.lo util.lo verify.lo subversion/libsvn_fs_x/libsvn_fs_x-1.la: $(libsvn_fs_x_DEPS) cd subversion/libsvn_fs_x && $(LINK_LIB) $(libsvn_fs_x_LDFLAGS) -o libsvn_fs_x-1.la $(LT_NO_UNDEFINED) $(libsvn_fs_x_OBJECTS) ../../subversion/libsvn_delta/libsvn_delta-1.la ../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS) ../../subversion/libsvn_fs_util/libsvn_fs_util-1.la $(LIBS) @@ -461,28 +491,28 @@ subversion/libsvn_ra_local/libsvn_ra_local-1.la: $(libsvn_ra_local_DEPS) cd subversion/libsvn_ra_local && $(LINK_LIB) $(libsvn_ra_local_LDFLAGS) -o libsvn_ra_local-1.la $(LT_NO_UNDEFINED) $(libsvn_ra_local_OBJECTS) ../../subversion/libsvn_repos/libsvn_repos-1.la ../../subversion/libsvn_fs/libsvn_fs-1.la ../../subversion/libsvn_delta/libsvn_delta-1.la ../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS) $(LIBS) libsvn_ra_serf_PATH = subversion/libsvn_ra_serf -libsvn_ra_serf_DEPS = subversion/libsvn_ra_serf/blame.lo subversion/libsvn_ra_serf/blncache.lo subversion/libsvn_ra_serf/commit.lo subversion/libsvn_ra_serf/eagain_bucket.lo subversion/libsvn_ra_serf/get_deleted_rev.lo subversion/libsvn_ra_serf/get_file.lo subversion/libsvn_ra_serf/get_lock.lo subversion/libsvn_ra_serf/getdate.lo subversion/libsvn_ra_serf/getlocations.lo subversion/libsvn_ra_serf/getlocationsegments.lo subversion/libsvn_ra_serf/getlocks.lo subversion/libsvn_ra_serf/inherited_props.lo subversion/libsvn_ra_serf/lock.lo subversion/libsvn_ra_serf/log.lo subversion/libsvn_ra_serf/merge.lo subversion/libsvn_ra_serf/mergeinfo.lo subversion/libsvn_ra_serf/multistatus.lo subversion/libsvn_ra_serf/options.lo subversion/libsvn_ra_serf/property.lo subversion/libsvn_ra_serf/replay.lo subversion/libsvn_ra_serf/sb_bucket.lo subversion/libsvn_ra_serf/serf.lo subversion/libsvn_ra_serf/stat.lo subversion/libsvn_ra_serf/update.lo subversion/libsvn_ra_serf/util.lo subversion/libsvn_ra_serf/util_error.lo subversion/libsvn_ra_serf/xml.lo subversion/libsvn_delta/libsvn_delta-1.la subversion/libsvn_subr/libsvn_subr-1.la -libsvn_ra_serf_OBJECTS = blame.lo blncache.lo commit.lo eagain_bucket.lo get_deleted_rev.lo get_file.lo get_lock.lo getdate.lo getlocations.lo getlocationsegments.lo getlocks.lo inherited_props.lo lock.lo log.lo merge.lo mergeinfo.lo multistatus.lo options.lo property.lo replay.lo sb_bucket.lo serf.lo stat.lo update.lo util.lo util_error.lo xml.lo +libsvn_ra_serf_DEPS = subversion/libsvn_ra_serf/blame.lo subversion/libsvn_ra_serf/blncache.lo subversion/libsvn_ra_serf/commit.lo subversion/libsvn_ra_serf/eagain_bucket.lo subversion/libsvn_ra_serf/get_deleted_rev.lo subversion/libsvn_ra_serf/get_file.lo subversion/libsvn_ra_serf/get_lock.lo subversion/libsvn_ra_serf/getdate.lo subversion/libsvn_ra_serf/getlocations.lo subversion/libsvn_ra_serf/getlocationsegments.lo subversion/libsvn_ra_serf/getlocks.lo subversion/libsvn_ra_serf/inherited_props.lo subversion/libsvn_ra_serf/list.lo subversion/libsvn_ra_serf/lock.lo subversion/libsvn_ra_serf/log.lo subversion/libsvn_ra_serf/merge.lo subversion/libsvn_ra_serf/mergeinfo.lo subversion/libsvn_ra_serf/multistatus.lo subversion/libsvn_ra_serf/options.lo subversion/libsvn_ra_serf/property.lo subversion/libsvn_ra_serf/replay.lo subversion/libsvn_ra_serf/request_body.lo subversion/libsvn_ra_serf/sb_bucket.lo subversion/libsvn_ra_serf/serf.lo subversion/libsvn_ra_serf/stat.lo subversion/libsvn_ra_serf/stream_bucket.lo subversion/libsvn_ra_serf/update.lo subversion/libsvn_ra_serf/util.lo subversion/libsvn_ra_serf/util_error.lo subversion/libsvn_ra_serf/xml.lo subversion/libsvn_delta/libsvn_delta-1.la subversion/libsvn_subr/libsvn_subr-1.la +libsvn_ra_serf_OBJECTS = blame.lo blncache.lo commit.lo eagain_bucket.lo get_deleted_rev.lo get_file.lo get_lock.lo getdate.lo getlocations.lo getlocationsegments.lo getlocks.lo inherited_props.lo list.lo lock.lo log.lo merge.lo mergeinfo.lo multistatus.lo options.lo property.lo replay.lo request_body.lo sb_bucket.lo serf.lo stat.lo stream_bucket.lo update.lo util.lo util_error.lo xml.lo subversion/libsvn_ra_serf/libsvn_ra_serf-1.la: $(libsvn_ra_serf_DEPS) - cd subversion/libsvn_ra_serf && $(LINK_LIB) $(libsvn_ra_serf_LDFLAGS) -o libsvn_ra_serf-1.la $(LT_NO_UNDEFINED) $(libsvn_ra_serf_OBJECTS) ../../subversion/libsvn_delta/libsvn_delta-1.la ../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS) $(SVN_SERF_LIBS) $(SVN_XML_LIBS) $(SVN_ZLIB_LIBS) $(LIBS) + cd subversion/libsvn_ra_serf && $(LINK_LIB) $(libsvn_ra_serf_LDFLAGS) -o libsvn_ra_serf-1.la $(LT_NO_UNDEFINED) $(libsvn_ra_serf_OBJECTS) ../../subversion/libsvn_delta/libsvn_delta-1.la ../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS) $(SVN_SERF_LIBS) $(SVN_ZLIB_LIBS) $(LIBS) libsvn_ra_svn_PATH = subversion/libsvn_ra_svn -libsvn_ra_svn_DEPS = subversion/libsvn_ra_svn/client.lo subversion/libsvn_ra_svn/cram.lo subversion/libsvn_ra_svn/cyrus_auth.lo subversion/libsvn_ra_svn/deprecated.lo subversion/libsvn_ra_svn/editorp.lo subversion/libsvn_ra_svn/internal_auth.lo subversion/libsvn_ra_svn/marshal.lo subversion/libsvn_ra_svn/streams.lo subversion/libsvn_ra_svn/version.lo subversion/libsvn_delta/libsvn_delta-1.la subversion/libsvn_subr/libsvn_subr-1.la -libsvn_ra_svn_OBJECTS = client.lo cram.lo cyrus_auth.lo deprecated.lo editorp.lo internal_auth.lo marshal.lo streams.lo version.lo +libsvn_ra_svn_DEPS = subversion/libsvn_ra_svn/client.lo subversion/libsvn_ra_svn/cram.lo subversion/libsvn_ra_svn/cyrus_auth.lo subversion/libsvn_ra_svn/deprecated.lo subversion/libsvn_ra_svn/editorp.lo subversion/libsvn_ra_svn/internal_auth.lo subversion/libsvn_ra_svn/marshal.lo subversion/libsvn_ra_svn/streams.lo subversion/libsvn_ra_svn/version.lo subversion/libsvn_ra_svn/wrapped_sasl.lo subversion/libsvn_delta/libsvn_delta-1.la subversion/libsvn_subr/libsvn_subr-1.la +libsvn_ra_svn_OBJECTS = client.lo cram.lo cyrus_auth.lo deprecated.lo editorp.lo internal_auth.lo marshal.lo streams.lo version.lo wrapped_sasl.lo subversion/libsvn_ra_svn/libsvn_ra_svn-1.la: $(libsvn_ra_svn_DEPS) cd subversion/libsvn_ra_svn && $(LINK_LIB) $(libsvn_ra_svn_LDFLAGS) -o libsvn_ra_svn-1.la $(LT_NO_UNDEFINED) $(libsvn_ra_svn_OBJECTS) ../../subversion/libsvn_delta/libsvn_delta-1.la ../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS) $(SVN_SASL_LIBS) $(LIBS) libsvn_repos_PATH = subversion/libsvn_repos -libsvn_repos_DEPS = subversion/libsvn_repos/authz.lo subversion/libsvn_repos/authz_pool.lo subversion/libsvn_repos/commit.lo subversion/libsvn_repos/config_pool.lo subversion/libsvn_repos/delta.lo subversion/libsvn_repos/deprecated.lo subversion/libsvn_repos/dump.lo subversion/libsvn_repos/fs-wrap.lo subversion/libsvn_repos/hooks.lo subversion/libsvn_repos/load-fs-vtable.lo subversion/libsvn_repos/load.lo subversion/libsvn_repos/log.lo subversion/libsvn_repos/node_tree.lo subversion/libsvn_repos/notify.lo subversion/libsvn_repos/replay.lo subversion/libsvn_repos/reporter.lo subversion/libsvn_repos/repos.lo subversion/libsvn_repos/rev_hunt.lo subversion/libsvn_fs/libsvn_fs-1.la subversion/libsvn_delta/libsvn_delta-1.la subversion/libsvn_subr/libsvn_subr-1.la -libsvn_repos_OBJECTS = authz.lo authz_pool.lo commit.lo config_pool.lo delta.lo deprecated.lo dump.lo fs-wrap.lo hooks.lo load-fs-vtable.lo load.lo log.lo node_tree.lo notify.lo replay.lo reporter.lo repos.lo rev_hunt.lo +libsvn_repos_DEPS = subversion/libsvn_repos/authz.lo subversion/libsvn_repos/authz_info.lo subversion/libsvn_repos/authz_parse.lo subversion/libsvn_repos/commit.lo subversion/libsvn_repos/compat.lo subversion/libsvn_repos/config_file.lo subversion/libsvn_repos/config_pool.lo subversion/libsvn_repos/delta.lo subversion/libsvn_repos/deprecated.lo subversion/libsvn_repos/dump.lo subversion/libsvn_repos/fs-wrap.lo subversion/libsvn_repos/hooks.lo subversion/libsvn_repos/list.lo subversion/libsvn_repos/load-fs-vtable.lo subversion/libsvn_repos/load.lo subversion/libsvn_repos/log.lo subversion/libsvn_repos/node_tree.lo subversion/libsvn_repos/notify.lo subversion/libsvn_repos/replay.lo subversion/libsvn_repos/reporter.lo subversion/libsvn_repos/repos.lo subversion/libsvn_repos/rev_hunt.lo subversion/libsvn_fs/libsvn_fs-1.la subversion/libsvn_delta/libsvn_delta-1.la subversion/libsvn_subr/libsvn_subr-1.la +libsvn_repos_OBJECTS = authz.lo authz_info.lo authz_parse.lo commit.lo compat.lo config_file.lo config_pool.lo delta.lo deprecated.lo dump.lo fs-wrap.lo hooks.lo list.lo load-fs-vtable.lo load.lo log.lo node_tree.lo notify.lo replay.lo reporter.lo repos.lo rev_hunt.lo subversion/libsvn_repos/libsvn_repos-1.la: $(libsvn_repos_DEPS) cd subversion/libsvn_repos && $(LINK_LIB) $(libsvn_repos_LDFLAGS) -o libsvn_repos-1.la $(LT_NO_UNDEFINED) $(libsvn_repos_OBJECTS) ../../subversion/libsvn_fs/libsvn_fs-1.la ../../subversion/libsvn_delta/libsvn_delta-1.la ../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS) $(LIBS) libsvn_subr_PATH = subversion/libsvn_subr -libsvn_subr_DEPS = subversion/libsvn_subr/adler32.lo subversion/libsvn_subr/atomic.lo subversion/libsvn_subr/auth.lo subversion/libsvn_subr/base64.lo subversion/libsvn_subr/bit_array.lo subversion/libsvn_subr/cache-inprocess.lo subversion/libsvn_subr/cache-membuffer.lo subversion/libsvn_subr/cache-memcache.lo subversion/libsvn_subr/cache.lo subversion/libsvn_subr/cache_config.lo subversion/libsvn_subr/checksum.lo subversion/libsvn_subr/cmdline.lo subversion/libsvn_subr/compat.lo subversion/libsvn_subr/compress.lo subversion/libsvn_subr/config.lo subversion/libsvn_subr/config_auth.lo subversion/libsvn_subr/config_file.lo subversion/libsvn_subr/config_win.lo subversion/libsvn_subr/crypto.lo subversion/libsvn_subr/ctype.lo subversion/libsvn_subr/date.lo subversion/libsvn_subr/debug.lo subversion/libsvn_subr/deprecated.lo subversion/libsvn_subr/dirent_uri.lo subversion/libsvn_subr/dso.lo subversion/libsvn_subr/eol.lo subversion/libsvn_subr/error.lo subversion/libsvn_subr/fnv1a.lo subversion/libsvn_subr/gpg_agent.lo subversion/libsvn_subr/hash.lo subversion/libsvn_subr/io.lo subversion/libsvn_subr/iter.lo subversion/libsvn_subr/lock.lo subversion/libsvn_subr/log.lo subversion/libsvn_subr/macos_keychain.lo subversion/libsvn_subr/magic.lo subversion/libsvn_subr/md5.lo subversion/libsvn_subr/mergeinfo.lo subversion/libsvn_subr/mutex.lo subversion/libsvn_subr/nls.lo subversion/libsvn_subr/object_pool.lo subversion/libsvn_subr/opt.lo subversion/libsvn_subr/packed_data.lo subversion/libsvn_subr/path.lo subversion/libsvn_subr/pool.lo subversion/libsvn_subr/prefix_string.lo subversion/libsvn_subr/prompt.lo subversion/libsvn_subr/properties.lo subversion/libsvn_subr/quoprint.lo subversion/libsvn_subr/root_pools.lo subversion/libsvn_subr/simple_providers.lo subversion/libsvn_subr/skel.lo subversion/libsvn_subr/sorts.lo subversion/libsvn_subr/spillbuf.lo subversion/libsvn_subr/sqlite.lo subversion/libsvn_subr/sqlite3wrapper.lo subversion/libsvn_subr/ssl_client_cert_providers.lo subversion/libsvn_subr/ssl_client_cert_pw_providers.lo subversion/libsvn_subr/ssl_server_trust_providers.lo subversion/libsvn_subr/stream.lo subversion/libsvn_subr/string.lo subversion/libsvn_subr/subst.lo subversion/libsvn_subr/sysinfo.lo subversion/libsvn_subr/target.lo subversion/libsvn_subr/temp_serializer.lo subversion/libsvn_subr/time.lo subversion/libsvn_subr/token.lo subversion/libsvn_subr/types.lo subversion/libsvn_subr/user.lo subversion/libsvn_subr/username_providers.lo subversion/libsvn_subr/utf.lo subversion/libsvn_subr/utf8proc.lo subversion/libsvn_subr/utf_validate.lo subversion/libsvn_subr/utf_width.lo subversion/libsvn_subr/validate.lo subversion/libsvn_subr/version.lo subversion/libsvn_subr/win32_crashrpt.lo subversion/libsvn_subr/win32_crypto.lo subversion/libsvn_subr/win32_xlate.lo subversion/libsvn_subr/x509info.lo subversion/libsvn_subr/x509parse.lo subversion/libsvn_subr/xml.lo -libsvn_subr_OBJECTS = adler32.lo atomic.lo auth.lo base64.lo bit_array.lo cache-inprocess.lo cache-membuffer.lo cache-memcache.lo cache.lo cache_config.lo checksum.lo cmdline.lo compat.lo compress.lo config.lo config_auth.lo config_file.lo config_win.lo crypto.lo ctype.lo date.lo debug.lo deprecated.lo dirent_uri.lo dso.lo eol.lo error.lo fnv1a.lo gpg_agent.lo hash.lo io.lo iter.lo lock.lo log.lo macos_keychain.lo magic.lo md5.lo mergeinfo.lo mutex.lo nls.lo object_pool.lo opt.lo packed_data.lo path.lo pool.lo prefix_string.lo prompt.lo properties.lo quoprint.lo root_pools.lo simple_providers.lo skel.lo sorts.lo spillbuf.lo sqlite.lo sqlite3wrapper.lo ssl_client_cert_providers.lo ssl_client_cert_pw_providers.lo ssl_server_trust_providers.lo stream.lo string.lo subst.lo sysinfo.lo target.lo temp_serializer.lo time.lo token.lo types.lo user.lo username_providers.lo utf.lo utf8proc.lo utf_validate.lo utf_width.lo validate.lo version.lo win32_crashrpt.lo win32_crypto.lo win32_xlate.lo x509info.lo x509parse.lo xml.lo +libsvn_subr_DEPS = subversion/libsvn_subr/adler32.lo subversion/libsvn_subr/atomic.lo subversion/libsvn_subr/auth.lo subversion/libsvn_subr/base64.lo subversion/libsvn_subr/bit_array.lo subversion/libsvn_subr/cache-inprocess.lo subversion/libsvn_subr/cache-membuffer.lo subversion/libsvn_subr/cache-memcache.lo subversion/libsvn_subr/cache-null.lo subversion/libsvn_subr/cache.lo subversion/libsvn_subr/cache_config.lo subversion/libsvn_subr/checksum.lo subversion/libsvn_subr/cmdline.lo subversion/libsvn_subr/compat.lo subversion/libsvn_subr/compress_lz4.lo subversion/libsvn_subr/compress_zlib.lo subversion/libsvn_subr/config.lo subversion/libsvn_subr/config_auth.lo subversion/libsvn_subr/config_file.lo subversion/libsvn_subr/config_win.lo subversion/libsvn_subr/crypto.lo subversion/libsvn_subr/ctype.lo subversion/libsvn_subr/date.lo subversion/libsvn_subr/debug.lo subversion/libsvn_subr/deprecated.lo subversion/libsvn_subr/dirent_uri.lo subversion/libsvn_subr/dso.lo subversion/libsvn_subr/encode.lo subversion/libsvn_subr/eol.lo subversion/libsvn_subr/error.lo subversion/libsvn_subr/fnv1a.lo subversion/libsvn_subr/gpg_agent.lo subversion/libsvn_subr/hash.lo subversion/libsvn_subr/io.lo subversion/libsvn_subr/iter.lo subversion/libsvn_subr/lock.lo subversion/libsvn_subr/log.lo subversion/libsvn_subr/lz4/lz4.lo subversion/libsvn_subr/macos_keychain.lo subversion/libsvn_subr/magic.lo subversion/libsvn_subr/md5.lo subversion/libsvn_subr/mergeinfo.lo subversion/libsvn_subr/mutex.lo subversion/libsvn_subr/nls.lo subversion/libsvn_subr/object_pool.lo subversion/libsvn_subr/opt.lo subversion/libsvn_subr/packed_data.lo subversion/libsvn_subr/path.lo subversion/libsvn_subr/pool.lo subversion/libsvn_subr/prefix_string.lo subversion/libsvn_subr/prompt.lo subversion/libsvn_subr/properties.lo subversion/libsvn_subr/quoprint.lo subversion/libsvn_subr/root_pools.lo subversion/libsvn_subr/simple_providers.lo subversion/libsvn_subr/skel.lo subversion/libsvn_subr/sorts.lo subversion/libsvn_subr/spillbuf.lo subversion/libsvn_subr/sqlite.lo subversion/libsvn_subr/sqlite3wrapper.lo subversion/libsvn_subr/ssl_client_cert_providers.lo subversion/libsvn_subr/ssl_client_cert_pw_providers.lo subversion/libsvn_subr/ssl_server_trust_providers.lo subversion/libsvn_subr/stream.lo subversion/libsvn_subr/string.lo subversion/libsvn_subr/subst.lo subversion/libsvn_subr/sysinfo.lo subversion/libsvn_subr/target.lo subversion/libsvn_subr/temp_serializer.lo subversion/libsvn_subr/time.lo subversion/libsvn_subr/token.lo subversion/libsvn_subr/types.lo subversion/libsvn_subr/user.lo subversion/libsvn_subr/username_providers.lo subversion/libsvn_subr/utf.lo subversion/libsvn_subr/utf8proc.lo subversion/libsvn_subr/utf_validate.lo subversion/libsvn_subr/utf_width.lo subversion/libsvn_subr/validate.lo subversion/libsvn_subr/version.lo subversion/libsvn_subr/win32_crashrpt.lo subversion/libsvn_subr/win32_crypto.lo subversion/libsvn_subr/win32_xlate.lo subversion/libsvn_subr/x509info.lo subversion/libsvn_subr/x509parse.lo subversion/libsvn_subr/xml.lo +libsvn_subr_OBJECTS = adler32.lo atomic.lo auth.lo base64.lo bit_array.lo cache-inprocess.lo cache-membuffer.lo cache-memcache.lo cache-null.lo cache.lo cache_config.lo checksum.lo cmdline.lo compat.lo compress_lz4.lo compress_zlib.lo config.lo config_auth.lo config_file.lo config_win.lo crypto.lo ctype.lo date.lo debug.lo deprecated.lo dirent_uri.lo dso.lo encode.lo eol.lo error.lo fnv1a.lo gpg_agent.lo hash.lo io.lo iter.lo lock.lo log.lo lz4/lz4.lo macos_keychain.lo magic.lo md5.lo mergeinfo.lo mutex.lo nls.lo object_pool.lo opt.lo packed_data.lo path.lo pool.lo prefix_string.lo prompt.lo properties.lo quoprint.lo root_pools.lo simple_providers.lo skel.lo sorts.lo spillbuf.lo sqlite.lo sqlite3wrapper.lo ssl_client_cert_providers.lo ssl_client_cert_pw_providers.lo ssl_server_trust_providers.lo stream.lo string.lo subst.lo sysinfo.lo target.lo temp_serializer.lo time.lo token.lo types.lo user.lo username_providers.lo utf.lo utf8proc.lo utf_validate.lo utf_width.lo validate.lo version.lo win32_crashrpt.lo win32_crypto.lo win32_xlate.lo x509info.lo x509parse.lo xml.lo subversion/libsvn_subr/libsvn_subr-1.la: $(libsvn_subr_DEPS) - cd subversion/libsvn_subr && $(LINK_LIB) $(libsvn_subr_LDFLAGS) -o libsvn_subr-1.la $(LT_NO_UNDEFINED) $(libsvn_subr_OBJECTS) $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS) $(SVN_XML_LIBS) $(SVN_ZLIB_LIBS) $(SVN_APR_MEMCACHE_LIBS) $(SVN_SQLITE_LIBS) $(SVN_MAGIC_LIBS) $(SVN_INTL_LIBS) $(LIBS) + cd subversion/libsvn_subr && $(LINK_LIB) $(libsvn_subr_LDFLAGS) -o libsvn_subr-1.la $(LT_NO_UNDEFINED) $(libsvn_subr_OBJECTS) $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS) $(SVN_XML_LIBS) $(SVN_ZLIB_LIBS) $(SVN_APR_MEMCACHE_LIBS) $(SVN_SQLITE_LIBS) $(SVN_MAGIC_LIBS) $(SVN_INTL_LIBS) $(SVN_LZ4_LIBS) $(SVN_UTF8PROC_LIBS) $(LIBS) libsvn_swig_perl_PATH = subversion/bindings/swig/perl/libsvn_swig_perl libsvn_swig_perl_DEPS = subversion/bindings/swig/perl/libsvn_swig_perl/swigutil_pl.lo subversion/libsvn_delta/libsvn_delta-1.la subversion/libsvn_subr/libsvn_subr-1.la @@ -555,8 +585,8 @@ subversion/mod_authz_svn/mod_authz_svn.la: $(mod_authz_svn_DEPS) if $(INSTALL_APACHE_MODS) ; then cd subversion/mod_authz_svn && $(LINK_APACHE_MOD) $(mod_authz_svn_LDFLAGS) -o mod_authz_svn.la $(LT_NO_UNDEFINED) $(mod_authz_svn_OBJECTS) ../../subversion/libsvn_repos/libsvn_repos-1.la ../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_HTTPD_LIBS) $(LIBS) ; else echo "fake" > subversion/mod_authz_svn/mod_authz_svn.la ; fi mod_dav_svn_PATH = subversion/mod_dav_svn -mod_dav_svn_DEPS = subversion/mod_dav_svn/activity.lo subversion/mod_dav_svn/authz.lo subversion/mod_dav_svn/deadprops.lo subversion/mod_dav_svn/liveprops.lo subversion/mod_dav_svn/lock.lo subversion/mod_dav_svn/merge.lo subversion/mod_dav_svn/mirror.lo subversion/mod_dav_svn/mod_dav_svn.lo subversion/mod_dav_svn/posts/create_txn.lo subversion/mod_dav_svn/reports/dated-rev.lo subversion/mod_dav_svn/reports/deleted-rev.lo subversion/mod_dav_svn/reports/file-revs.lo subversion/mod_dav_svn/reports/get-location-segments.lo subversion/mod_dav_svn/reports/get-locations.lo subversion/mod_dav_svn/reports/get-locks.lo subversion/mod_dav_svn/reports/inherited-props.lo subversion/mod_dav_svn/reports/log.lo subversion/mod_dav_svn/reports/mergeinfo.lo subversion/mod_dav_svn/reports/replay.lo subversion/mod_dav_svn/reports/update.lo subversion/mod_dav_svn/repos.lo subversion/mod_dav_svn/status.lo subversion/mod_dav_svn/util.lo subversion/mod_dav_svn/version.lo subversion/libsvn_repos/libsvn_repos-1.la subversion/libsvn_fs/libsvn_fs-1.la subversion/libsvn_delta/libsvn_delta-1.la subversion/libsvn_subr/libsvn_subr-1.la -mod_dav_svn_OBJECTS = activity.lo authz.lo deadprops.lo liveprops.lo lock.lo merge.lo mirror.lo mod_dav_svn.lo posts/create_txn.lo reports/dated-rev.lo reports/deleted-rev.lo reports/file-revs.lo reports/get-location-segments.lo reports/get-locations.lo reports/get-locks.lo reports/inherited-props.lo reports/log.lo reports/mergeinfo.lo reports/replay.lo reports/update.lo repos.lo status.lo util.lo version.lo +mod_dav_svn_DEPS = subversion/mod_dav_svn/activity.lo subversion/mod_dav_svn/authz.lo subversion/mod_dav_svn/deadprops.lo subversion/mod_dav_svn/liveprops.lo subversion/mod_dav_svn/lock.lo subversion/mod_dav_svn/merge.lo subversion/mod_dav_svn/mirror.lo subversion/mod_dav_svn/mod_dav_svn.lo subversion/mod_dav_svn/posts/create_txn.lo subversion/mod_dav_svn/reports/dated-rev.lo subversion/mod_dav_svn/reports/deleted-rev.lo subversion/mod_dav_svn/reports/file-revs.lo subversion/mod_dav_svn/reports/get-location-segments.lo subversion/mod_dav_svn/reports/get-locations.lo subversion/mod_dav_svn/reports/get-locks.lo subversion/mod_dav_svn/reports/inherited-props.lo subversion/mod_dav_svn/reports/list.lo subversion/mod_dav_svn/reports/log.lo subversion/mod_dav_svn/reports/mergeinfo.lo subversion/mod_dav_svn/reports/replay.lo subversion/mod_dav_svn/reports/update.lo subversion/mod_dav_svn/repos.lo subversion/mod_dav_svn/status.lo subversion/mod_dav_svn/util.lo subversion/mod_dav_svn/version.lo subversion/libsvn_repos/libsvn_repos-1.la subversion/libsvn_fs/libsvn_fs-1.la subversion/libsvn_delta/libsvn_delta-1.la subversion/libsvn_subr/libsvn_subr-1.la +mod_dav_svn_OBJECTS = activity.lo authz.lo deadprops.lo liveprops.lo lock.lo merge.lo mirror.lo mod_dav_svn.lo posts/create_txn.lo reports/dated-rev.lo reports/deleted-rev.lo reports/file-revs.lo reports/get-location-segments.lo reports/get-locations.lo reports/get-locks.lo reports/inherited-props.lo reports/list.lo reports/log.lo reports/mergeinfo.lo reports/replay.lo reports/update.lo repos.lo status.lo util.lo version.lo subversion/mod_dav_svn/mod_dav_svn.la: $(mod_dav_svn_DEPS) if $(INSTALL_APACHE_MODS) ; then cd subversion/mod_dav_svn && $(LINK_APACHE_MOD) $(mod_dav_svn_LDFLAGS) -o mod_dav_svn.la $(LT_NO_UNDEFINED) $(mod_dav_svn_OBJECTS) ../../subversion/libsvn_repos/libsvn_repos-1.la ../../subversion/libsvn_fs/libsvn_fs-1.la ../../subversion/libsvn_delta/libsvn_delta-1.la ../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_HTTPD_LIBS) $(SVN_MOD_DAV_LIBS) $(LIBS) ; else echo "fake" > subversion/mod_dav_svn/mod_dav_svn.la ; fi @@ -564,7 +594,7 @@ mod_dontdothat_PATH = tools/server-side/mod_dontdothat mod_dontdothat_DEPS = tools/server-side/mod_dontdothat/mod_dontdothat.lo subversion/libsvn_subr/libsvn_subr-1.la subversion/mod_dav_svn/mod_dav_svn.la mod_dontdothat_OBJECTS = mod_dontdothat.lo tools/server-side/mod_dontdothat/mod_dontdothat.la: $(mod_dontdothat_DEPS) - if $(INSTALL_APACHE_MODS) ; then cd tools/server-side/mod_dontdothat && $(LINK_APACHE_MOD) $(mod_dontdothat_LDFLAGS) -o mod_dontdothat.la $(LT_NO_UNDEFINED) $(mod_dontdothat_OBJECTS) ../../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_XML_LIBS) $(SVN_HTTPD_LIBS) $(LIBS) ; else echo "fake" > tools/server-side/mod_dontdothat/mod_dontdothat.la ; fi + if $(INSTALL_APACHE_MODS) ; then cd tools/server-side/mod_dontdothat && $(LINK_APACHE_MOD) $(mod_dontdothat_LDFLAGS) -o mod_dontdothat.la $(LT_NO_UNDEFINED) $(mod_dontdothat_OBJECTS) ../../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_HTTPD_LIBS) $(LIBS) ; else echo "fake" > tools/server-side/mod_dontdothat/mod_dontdothat.la ; fi mtcc_test_PATH = subversion/tests/libsvn_client mtcc_test_DEPS = subversion/tests/libsvn_client/mtcc-test.lo subversion/tests/libsvn_test-1.la subversion/libsvn_client/libsvn_client-1.la subversion/libsvn_wc/libsvn_wc-1.la subversion/libsvn_repos/libsvn_repos-1.la subversion/libsvn_ra/libsvn_ra-1.la subversion/libsvn_fs/libsvn_fs-1.la subversion/libsvn_delta/libsvn_delta-1.la subversion/libsvn_subr/libsvn_subr-1.la @@ -849,11 +879,17 @@ subversion/tests/libsvn_subr/subst_translate-test$(EXEEXT): $(subst_translate_te cd subversion/tests/libsvn_subr && $(LINK) $(subst_translate_test_LDFLAGS) -o subst_translate-test$(EXEEXT) $(subst_translate_test_OBJECTS) ../../../subversion/tests/libsvn_test-1.la ../../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS) $(LIBS) svn_PATH = subversion/svn -svn_DEPS = subversion/svn/add-cmd.lo subversion/svn/auth-cmd.lo subversion/svn/blame-cmd.lo subversion/svn/cat-cmd.lo subversion/svn/changelist-cmd.lo subversion/svn/checkout-cmd.lo subversion/svn/cl-conflicts.lo subversion/svn/cleanup-cmd.lo subversion/svn/commit-cmd.lo subversion/svn/conflict-callbacks.lo subversion/svn/copy-cmd.lo subversion/svn/delete-cmd.lo subversion/svn/deprecated.lo subversion/svn/diff-cmd.lo subversion/svn/export-cmd.lo subversion/svn/file-merge.lo subversion/svn/help-cmd.lo subversion/svn/import-cmd.lo subversion/svn/info-cmd.lo subversion/svn/list-cmd.lo subversion/svn/lock-cmd.lo subversion/svn/log-cmd.lo subversion/svn/merge-cmd.lo subversion/svn/mergeinfo-cmd.lo subversion/svn/mkdir-cmd.lo subversion/svn/move-cmd.lo subversion/svn/notify.lo subversion/svn/patch-cmd.lo subversion/svn/propdel-cmd.lo subversion/svn/propedit-cmd.lo subversion/svn/propget-cmd.lo subversion/svn/proplist-cmd.lo subversion/svn/props.lo subversion/svn/propset-cmd.lo subversion/svn/relocate-cmd.lo subversion/svn/resolve-cmd.lo subversion/svn/resolved-cmd.lo subversion/svn/revert-cmd.lo subversion/svn/similarity.lo subversion/svn/status-cmd.lo subversion/svn/status.lo subversion/svn/svn.lo subversion/svn/switch-cmd.lo subversion/svn/unlock-cmd.lo subversion/svn/update-cmd.lo subversion/svn/upgrade-cmd.lo subversion/svn/util.lo subversion/libsvn_client/libsvn_client-1.la subversion/libsvn_wc/libsvn_wc-1.la subversion/libsvn_ra/libsvn_ra-1.la subversion/libsvn_delta/libsvn_delta-1.la subversion/libsvn_diff/libsvn_diff-1.la subversion/libsvn_subr/libsvn_subr-1.la -svn_OBJECTS = add-cmd.lo auth-cmd.lo blame-cmd.lo cat-cmd.lo changelist-cmd.lo checkout-cmd.lo cl-conflicts.lo cleanup-cmd.lo commit-cmd.lo conflict-callbacks.lo copy-cmd.lo delete-cmd.lo deprecated.lo diff-cmd.lo export-cmd.lo file-merge.lo help-cmd.lo import-cmd.lo info-cmd.lo list-cmd.lo lock-cmd.lo log-cmd.lo merge-cmd.lo mergeinfo-cmd.lo mkdir-cmd.lo move-cmd.lo notify.lo patch-cmd.lo propdel-cmd.lo propedit-cmd.lo propget-cmd.lo proplist-cmd.lo props.lo propset-cmd.lo relocate-cmd.lo resolve-cmd.lo resolved-cmd.lo revert-cmd.lo similarity.lo status-cmd.lo status.lo svn.lo switch-cmd.lo unlock-cmd.lo update-cmd.lo upgrade-cmd.lo util.lo +svn_DEPS = subversion/svn/add-cmd.lo subversion/svn/auth-cmd.lo subversion/svn/blame-cmd.lo subversion/svn/cat-cmd.lo subversion/svn/changelist-cmd.lo subversion/svn/checkout-cmd.lo subversion/svn/cl-conflicts.lo subversion/svn/cleanup-cmd.lo subversion/svn/commit-cmd.lo subversion/svn/conflict-callbacks.lo subversion/svn/copy-cmd.lo subversion/svn/delete-cmd.lo subversion/svn/deprecated.lo subversion/svn/diff-cmd.lo subversion/svn/export-cmd.lo subversion/svn/file-merge.lo subversion/svn/help-cmd.lo subversion/svn/import-cmd.lo subversion/svn/info-cmd.lo subversion/svn/list-cmd.lo subversion/svn/lock-cmd.lo subversion/svn/log-cmd.lo subversion/svn/merge-cmd.lo subversion/svn/mergeinfo-cmd.lo subversion/svn/mkdir-cmd.lo subversion/svn/move-cmd.lo subversion/svn/notify.lo subversion/svn/patch-cmd.lo subversion/svn/propdel-cmd.lo subversion/svn/propedit-cmd.lo subversion/svn/propget-cmd.lo subversion/svn/proplist-cmd.lo subversion/svn/props.lo subversion/svn/propset-cmd.lo subversion/svn/relocate-cmd.lo subversion/svn/resolve-cmd.lo subversion/svn/resolved-cmd.lo subversion/svn/revert-cmd.lo subversion/svn/shelve-cmd.lo subversion/svn/similarity.lo subversion/svn/status-cmd.lo subversion/svn/status.lo subversion/svn/svn.lo subversion/svn/switch-cmd.lo subversion/svn/unlock-cmd.lo subversion/svn/update-cmd.lo subversion/svn/upgrade-cmd.lo subversion/svn/util.lo subversion/libsvn_client/libsvn_client-1.la subversion/libsvn_wc/libsvn_wc-1.la subversion/libsvn_ra/libsvn_ra-1.la subversion/libsvn_delta/libsvn_delta-1.la subversion/libsvn_diff/libsvn_diff-1.la subversion/libsvn_subr/libsvn_subr-1.la +svn_OBJECTS = add-cmd.lo auth-cmd.lo blame-cmd.lo cat-cmd.lo changelist-cmd.lo checkout-cmd.lo cl-conflicts.lo cleanup-cmd.lo commit-cmd.lo conflict-callbacks.lo copy-cmd.lo delete-cmd.lo deprecated.lo diff-cmd.lo export-cmd.lo file-merge.lo help-cmd.lo import-cmd.lo info-cmd.lo list-cmd.lo lock-cmd.lo log-cmd.lo merge-cmd.lo mergeinfo-cmd.lo mkdir-cmd.lo move-cmd.lo notify.lo patch-cmd.lo propdel-cmd.lo propedit-cmd.lo propget-cmd.lo proplist-cmd.lo props.lo propset-cmd.lo relocate-cmd.lo resolve-cmd.lo resolved-cmd.lo revert-cmd.lo shelve-cmd.lo similarity.lo status-cmd.lo status.lo svn.lo switch-cmd.lo unlock-cmd.lo update-cmd.lo upgrade-cmd.lo util.lo subversion/svn/svn$(EXEEXT): $(svn_DEPS) cd subversion/svn && $(LINK) $(svn_LDFLAGS) -o svn$(EXEEXT) $(svn_OBJECTS) ../../subversion/libsvn_client/libsvn_client-1.la ../../subversion/libsvn_wc/libsvn_wc-1.la ../../subversion/libsvn_ra/libsvn_ra-1.la ../../subversion/libsvn_delta/libsvn_delta-1.la ../../subversion/libsvn_diff/libsvn_diff-1.la ../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS) $(LIBS) +svn_mergeinfo_normalizer_PATH = tools/client-side/svn-mergeinfo-normalizer +svn_mergeinfo_normalizer_DEPS = tools/client-side/svn-mergeinfo-normalizer/analyze-cmd.lo tools/client-side/svn-mergeinfo-normalizer/help-cmd.lo tools/client-side/svn-mergeinfo-normalizer/log.lo tools/client-side/svn-mergeinfo-normalizer/logic.lo tools/client-side/svn-mergeinfo-normalizer/missing-branches.lo tools/client-side/svn-mergeinfo-normalizer/normalize-cmd.lo tools/client-side/svn-mergeinfo-normalizer/remove-branches-cmd.lo tools/client-side/svn-mergeinfo-normalizer/svn-mergeinfo-normalizer.lo tools/client-side/svn-mergeinfo-normalizer/wc_mergeinfo.lo subversion/libsvn_client/libsvn_client-1.la subversion/libsvn_wc/libsvn_wc-1.la subversion/libsvn_ra/libsvn_ra-1.la subversion/libsvn_delta/libsvn_delta-1.la subversion/libsvn_diff/libsvn_diff-1.la subversion/libsvn_subr/libsvn_subr-1.la +svn_mergeinfo_normalizer_OBJECTS = analyze-cmd.lo help-cmd.lo log.lo logic.lo missing-branches.lo normalize-cmd.lo remove-branches-cmd.lo svn-mergeinfo-normalizer.lo wc_mergeinfo.lo +tools/client-side/svn-mergeinfo-normalizer/svn-mergeinfo-normalizer$(EXEEXT): $(svn_mergeinfo_normalizer_DEPS) + cd tools/client-side/svn-mergeinfo-normalizer && $(LINK) $(svn_mergeinfo_normalizer_LDFLAGS) -o svn-mergeinfo-normalizer$(EXEEXT) $(svn_mergeinfo_normalizer_OBJECTS) ../../../subversion/libsvn_client/libsvn_client-1.la ../../../subversion/libsvn_wc/libsvn_wc-1.la ../../../subversion/libsvn_ra/libsvn_ra-1.la ../../../subversion/libsvn_delta/libsvn_delta-1.la ../../../subversion/libsvn_diff/libsvn_diff-1.la ../../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS) $(LIBS) + svn_populate_node_origins_index_PATH = tools/server-side svn_populate_node_origins_index_DEPS = tools/server-side/svn-populate-node-origins-index.lo subversion/libsvn_repos/libsvn_repos-1.la subversion/libsvn_fs/libsvn_fs-1.la subversion/libsvn_subr/libsvn_subr-1.la svn_populate_node_origins_index_OBJECTS = svn-populate-node-origins-index.lo @@ -890,6 +926,18 @@ svnbench_OBJECTS = help-cmd.lo notify.lo null-blame-cmd.lo null-export-cmd.lo nu subversion/svnbench/svnbench$(EXEEXT): $(svnbench_DEPS) cd subversion/svnbench && $(LINK) $(svnbench_LDFLAGS) -o svnbench$(EXEEXT) $(svnbench_OBJECTS) ../../subversion/libsvn_client/libsvn_client-1.la ../../subversion/libsvn_wc/libsvn_wc-1.la ../../subversion/libsvn_ra/libsvn_ra-1.la ../../subversion/libsvn_subr/libsvn_subr-1.la ../../subversion/libsvn_delta/libsvn_delta-1.la $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS) $(LIBS) +svnconflict_PATH = tools/client-side/svnconflict +svnconflict_DEPS = tools/client-side/svnconflict/svnconflict.lo subversion/libsvn_client/libsvn_client-1.la subversion/libsvn_wc/libsvn_wc-1.la subversion/libsvn_ra/libsvn_ra-1.la subversion/libsvn_subr/libsvn_subr-1.la +svnconflict_OBJECTS = svnconflict.lo +tools/client-side/svnconflict/svnconflict$(EXEEXT): $(svnconflict_DEPS) + cd tools/client-side/svnconflict && $(LINK) $(svnconflict_LDFLAGS) -o svnconflict$(EXEEXT) $(svnconflict_OBJECTS) ../../../subversion/libsvn_client/libsvn_client-1.la ../../../subversion/libsvn_wc/libsvn_wc-1.la ../../../subversion/libsvn_ra/libsvn_ra-1.la ../../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS) $(LIBS) + +svndiff_stream_test_PATH = subversion/tests/libsvn_delta +svndiff_stream_test_DEPS = subversion/tests/libsvn_delta/svndiff-stream-test.lo subversion/tests/libsvn_test-1.la subversion/libsvn_delta/libsvn_delta-1.la subversion/libsvn_subr/libsvn_subr-1.la +svndiff_stream_test_OBJECTS = svndiff-stream-test.lo +subversion/tests/libsvn_delta/svndiff-stream-test$(EXEEXT): $(svndiff_stream_test_DEPS) + cd subversion/tests/libsvn_delta && $(LINK) $(svndiff_stream_test_LDFLAGS) -o svndiff-stream-test$(EXEEXT) $(svndiff_stream_test_OBJECTS) ../../../subversion/tests/libsvn_test-1.la ../../../subversion/libsvn_delta/libsvn_delta-1.la ../../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS) $(LIBS) + svndiff_test_PATH = subversion/tests/libsvn_delta svndiff_test_DEPS = subversion/tests/libsvn_delta/svndiff-test.lo subversion/libsvn_delta/libsvn_delta-1.la subversion/libsvn_subr/libsvn_subr-1.la svndiff_test_OBJECTS = svndiff-test.lo @@ -914,6 +962,12 @@ svnlook_OBJECTS = svnlook.lo subversion/svnlook/svnlook$(EXEEXT): $(svnlook_DEPS) cd subversion/svnlook && $(LINK) $(svnlook_LDFLAGS) -o svnlook$(EXEEXT) $(svnlook_OBJECTS) ../../subversion/libsvn_repos/libsvn_repos-1.la ../../subversion/libsvn_fs/libsvn_fs-1.la ../../subversion/libsvn_delta/libsvn_delta-1.la ../../subversion/libsvn_diff/libsvn_diff-1.la ../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS) $(LIBS) +svnmover_PATH = tools/dev/svnmover +svnmover_DEPS = tools/dev/svnmover/merge3.lo tools/dev/svnmover/ra.lo tools/dev/svnmover/scanlog.lo tools/dev/svnmover/svnmover.lo tools/dev/svnmover/util.lo subversion/libsvn_client/libsvn_client-1.la subversion/libsvn_ra/libsvn_ra-1.la subversion/libsvn_subr/libsvn_subr-1.la subversion/libsvn_delta/libsvn_delta-1.la +svnmover_OBJECTS = merge3.lo ra.lo scanlog.lo svnmover.lo util.lo +tools/dev/svnmover/svnmover$(EXEEXT): $(svnmover_DEPS) + cd tools/dev/svnmover && $(LINK) $(svnmover_LDFLAGS) -o svnmover$(EXEEXT) $(svnmover_OBJECTS) ../../../subversion/libsvn_client/libsvn_client-1.la ../../../subversion/libsvn_ra/libsvn_ra-1.la ../../../subversion/libsvn_subr/libsvn_subr-1.la ../../../subversion/libsvn_delta/libsvn_delta-1.la $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS) $(LIBS) + svnmucc_PATH = subversion/svnmucc svnmucc_DEPS = subversion/svnmucc/svnmucc.lo subversion/libsvn_client/libsvn_client-1.la subversion/libsvn_ra/libsvn_ra-1.la subversion/libsvn_subr/libsvn_subr-1.la subversion/libsvn_delta/libsvn_delta-1.la svnmucc_OBJECTS = svnmucc.lo @@ -1016,6 +1070,12 @@ x509_test_OBJECTS = x509-test.lo subversion/tests/libsvn_subr/x509-test$(EXEEXT): $(x509_test_DEPS) cd subversion/tests/libsvn_subr && $(LINK) $(x509_test_LDFLAGS) -o x509-test$(EXEEXT) $(x509_test_OBJECTS) ../../../subversion/tests/libsvn_test-1.la ../../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS) $(LIBS) +xml_test_PATH = subversion/tests/libsvn_subr +xml_test_DEPS = subversion/tests/libsvn_subr/xml-test.lo subversion/tests/libsvn_test-1.la subversion/libsvn_subr/libsvn_subr-1.la +xml_test_OBJECTS = xml-test.lo +subversion/tests/libsvn_subr/xml-test$(EXEEXT): $(xml_test_DEPS) + cd subversion/tests/libsvn_subr && $(LINK) $(xml_test_LDFLAGS) -o xml-test$(EXEEXT) $(xml_test_OBJECTS) ../../../subversion/tests/libsvn_test-1.la ../../../subversion/libsvn_subr/libsvn_subr-1.la $(SVN_APRUTIL_LIBS) $(SVN_APR_LIBS) $(LIBS) + ######################################## # Section 6: Install-Group build targets @@ -1031,6 +1091,8 @@ bin: subversion/svn/svn$(EXEEXT) subversion/svnadmin/svnadmin$(EXEEXT) subversio cxxhl-lib: subversion/bindings/cxxhl/libsvncxxhl-1.la +cxxhl-tests: subversion/bindings/cxxhl/cxxhl-tests$(EXEEXT) googlemock/libgooglemock-1.la + fsmod-lib: subversion/libsvn_delta/libsvn_delta-1.la subversion/libsvn_fs_fs/libsvn_fs_fs-1.la subversion/libsvn_fs_util/libsvn_fs_util-1.la subversion/libsvn_fs_x/libsvn_fs_x-1.la subversion/libsvn_subr/libsvn_subr-1.la gnome-keyring-lib: subversion/libsvn_auth_gnome_keyring/libsvn_auth_gnome_keyring-1.la @@ -1077,11 +1139,9 @@ swig-rb: subversion/bindings/swig/ruby/client.la subversion/bindings/swig/ruby/c swig-rb-lib: subversion/bindings/swig/ruby/libsvn_swig_ruby/libsvn_swig_ruby-1.la -test: subversion/tests/cmdline/atomic-ra-revprop-change$(EXEEXT) subversion/tests/libsvn_subr/auth-test$(EXEEXT) subversion/tests/libsvn_subr/bit-array-test$(EXEEXT) subversion/tests/libsvn_subr/cache-test$(EXEEXT) subversion/tests/libsvn_subr/checksum-test$(EXEEXT) subversion/tests/libsvn_client/client-test$(EXEEXT) subversion/tests/libsvn_subr/compat-test$(EXEEXT) subversion/tests/libsvn_subr/config-test$(EXEEXT) subversion/tests/libsvn_wc/conflict-data-test$(EXEEXT) subversion/tests/libsvn_subr/crypto-test$(EXEEXT) subversion/tests/libsvn_wc/db-test$(EXEEXT) subversion/tests/libsvn_diff/diff-diff3-test$(EXEEXT) subversion/tests/libsvn_subr/dirent_uri-test$(EXEEXT) subversion/tests/libsvn_repos/dump-load-test$(EXEEXT) subversion/tests/libsvn_wc/entries-compat-test$(EXEEXT) subversion/tests/cmdline/entries-dump$(EXEEXT) subversion/tests/libsvn_subr/error-code-test$(EXEEXT) subversion/tests/libsvn_subr/error-test$(EXEEXT) subversion/tests/libsvn_fs_fs/fs-fs-pack-test$(EXEEXT) subversion/tests/libsvn_fs_fs/fs-fs-private-test$(EXEEXT) subversion/tests/libsvn_fs/fs-test$(EXEEXT) subversion/tests/libsvn_fs_x/fs-x-pack-test$(EXEEXT) subversion/tests/libsvn_subr/hashdump-test$(EXEEXT) subversion/tests/libsvn_subr/io-test$(EXEEXT) subversion/tests/libsvn_test-1.la subversion/tests/cmdline/lock-helper$(EXEEXT) subversion/tests/libsvn_fs/locks-test$(EXEEXT) subversion/tests/libsvn_subr/mergeinfo-test$(EXEEXT) subversion/tests/libsvn_client/mtcc-test$(EXEEXT) subversion/tests/libsvn_wc/op-depth-test$(EXEEXT) subversion/tests/libsvn_subr/opt-test$(EXEEXT) subversion/tests/libsvn_subr/packed-data-test$(EXEEXT) subversion/tests/libsvn_diff/parse-diff-test$(EXEEXT) subversion/tests/libsvn_subr/path-test$(EXEEXT) subversion/tests/libsvn_subr/prefix-string-test$(EXEEXT) subversion/tests/libsvn_subr/priority-queue-test$(EXEEXT) subversion/tests/libsvn_wc/pristine-store-test$(EXEEXT) subversion/tests/libsvn_ra_local/ra-local-test$(EXEEXT) subversion/tests/libsvn_ra/ra-test$(EXEEXT) subversion/tests/libsvn_delta/random-test$(EXEEXT) subversion/tests/libsvn_repos/repos-test$(EXEEXT) subversion/tests/libsvn_subr/revision-test$(EXEEXT) subversion/tests/libsvn_subr/root-pools-test$(EXEEXT) subversion/tests/libsvn_subr/skel-test$(EXEEXT) subversion/tests/libsvn_subr/spillbuf-test$(EXEEXT) subversion/tests/libsvn_subr/sqlite-test$(EXEEXT) subversion/tests/libsvn_subr/stream-test$(EXEEXT) subversion/tests/libsvn_fs_x/string-table-test$(EXEEXT) subversion/tests/libsvn_subr/string-test$(EXEEXT) subversion/tests/libsvn_subr/subst_translate-test$(EXEEXT) tools/dev/wc-ng/svn-wc-db-tester$(EXEEXT) subversion/tests/libsvn_delta/svndiff-test$(EXEEXT) subversion/tests/libsvn_subr/time-test$(EXEEXT) subversion/tests/libsvn_subr/translate-test$(EXEEXT) subversion/tests/libsvn_subr/utf-test$(EXEEXT) subversion/tests/libsvn_delta/vdelta-test$(EXEEXT) subversion/tests/libsvn_wc/wc-incomplete-tester$(EXEEXT) subversion/tests/libsvn_wc/wc-lock-tester$(EXEEXT) subversion/tests/libsvn_wc/wc-queries-test$(EXEEXT) subversion/tests/libsvn_wc/wc-test$(EXEEXT) subversion/tests/libsvn_delta/window-test$(EXEEXT) subversion/tests/libsvn_subr/x509-test$(EXEEXT) +test: subversion/tests/afl/afl-x509$(EXEEXT) subversion/tests/cmdline/atomic-ra-revprop-change$(EXEEXT) subversion/tests/libsvn_subr/auth-test$(EXEEXT) subversion/tests/libsvn_repos/authz-test$(EXEEXT) subversion/tests/libsvn_subr/bit-array-test$(EXEEXT) subversion/tests/libsvn_subr/cache-test$(EXEEXT) subversion/tests/libsvn_subr/checksum-test$(EXEEXT) subversion/tests/libsvn_client/client-test$(EXEEXT) subversion/tests/libsvn_subr/compat-test$(EXEEXT) subversion/tests/libsvn_subr/compress-test$(EXEEXT) subversion/tests/libsvn_subr/config-test$(EXEEXT) subversion/tests/libsvn_wc/conflict-data-test$(EXEEXT) subversion/tests/libsvn_client/conflicts-test$(EXEEXT) subversion/tests/libsvn_subr/crypto-test$(EXEEXT) subversion/tests/libsvn_wc/db-test$(EXEEXT) subversion/tests/libsvn_diff/diff-diff3-test$(EXEEXT) subversion/tests/libsvn_subr/dirent_uri-test$(EXEEXT) subversion/tests/libsvn_repos/dump-load-test$(EXEEXT) subversion/tests/libsvn_wc/entries-compat-test$(EXEEXT) subversion/tests/cmdline/entries-dump$(EXEEXT) subversion/tests/libsvn_subr/error-code-test$(EXEEXT) subversion/tests/libsvn_subr/error-test$(EXEEXT) subversion/tests/libsvn_fs_fs/fs-fs-pack-test$(EXEEXT) subversion/tests/libsvn_fs_fs/fs-fs-private-test$(EXEEXT) subversion/tests/libsvn_fs/fs-sequential-test$(EXEEXT) subversion/tests/libsvn_fs/fs-test$(EXEEXT) subversion/tests/libsvn_fs_x/fs-x-pack-test$(EXEEXT) subversion/tests/libsvn_subr/hashdump-test$(EXEEXT) subversion/tests/libsvn_subr/io-test$(EXEEXT) subversion/tests/libsvn_test-1.la subversion/tests/cmdline/lock-helper$(EXEEXT) subversion/tests/libsvn_fs/locks-test$(EXEEXT) subversion/tests/libsvn_subr/mergeinfo-test$(EXEEXT) subversion/tests/libsvn_client/mtcc-test$(EXEEXT) subversion/tests/libsvn_wc/op-depth-test$(EXEEXT) subversion/tests/libsvn_subr/opt-test$(EXEEXT) subversion/tests/libsvn_subr/packed-data-test$(EXEEXT) subversion/tests/libsvn_diff/parse-diff-test$(EXEEXT) subversion/tests/libsvn_subr/path-test$(EXEEXT) subversion/tests/libsvn_subr/prefix-string-test$(EXEEXT) subversion/tests/libsvn_subr/priority-queue-test$(EXEEXT) subversion/tests/libsvn_wc/pristine-store-test$(EXEEXT) subversion/tests/libsvn_ra_local/ra-local-test$(EXEEXT) subversion/tests/libsvn_ra/ra-test$(EXEEXT) subversion/tests/libsvn_delta/random-test$(EXEEXT) subversion/tests/libsvn_repos/repos-test$(EXEEXT) subversion/tests/libsvn_subr/revision-test$(EXEEXT) subversion/tests/libsvn_subr/root-pools-test$(EXEEXT) subversion/tests/libsvn_subr/skel-test$(EXEEXT) subversion/tests/libsvn_subr/spillbuf-test$(EXEEXT) subversion/tests/libsvn_subr/sqlite-test$(EXEEXT) subversion/tests/libsvn_subr/stream-test$(EXEEXT) subversion/tests/libsvn_fs_x/string-table-test$(EXEEXT) subversion/tests/libsvn_subr/string-test$(EXEEXT) subversion/tests/libsvn_subr/subst_translate-test$(EXEEXT) tools/dev/wc-ng/svn-wc-db-tester$(EXEEXT) subversion/tests/libsvn_delta/svndiff-stream-test$(EXEEXT) subversion/tests/libsvn_delta/svndiff-test$(EXEEXT) subversion/tests/libsvn_subr/time-test$(EXEEXT) subversion/tests/libsvn_subr/translate-test$(EXEEXT) subversion/tests/libsvn_subr/utf-test$(EXEEXT) subversion/tests/libsvn_delta/vdelta-test$(EXEEXT) subversion/tests/libsvn_wc/wc-incomplete-tester$(EXEEXT) subversion/tests/libsvn_wc/wc-lock-tester$(EXEEXT) subversion/tests/libsvn_wc/wc-queries-test$(EXEEXT) subversion/tests/libsvn_wc/wc-test$(EXEEXT) subversion/tests/libsvn_delta/window-test$(EXEEXT) subversion/tests/libsvn_subr/x509-test$(EXEEXT) subversion/tests/libsvn_subr/xml-test$(EXEEXT) -tests: subversion/bindings/cxxhl/cxxhl-tests$(EXEEXT) gmock-fused/libgmock-1.la - -tools: tools/diff/diff$(EXEEXT) tools/diff/diff3$(EXEEXT) tools/diff/diff4$(EXEEXT) tools/dev/fsfs-access-map$(EXEEXT) tools/server-side/mod_dontdothat/mod_dontdothat.la tools/server-side/svn-populate-node-origins-index$(EXEEXT) tools/server-side/svnauthz$(EXEEXT) tools/server-side/svnauthz-validate$(EXEEXT) tools/dev/svnraisetreeconflict/svnraisetreeconflict$(EXEEXT) tools/dev/x509-parser$(EXEEXT) +tools: tools/diff/diff$(EXEEXT) tools/diff/diff3$(EXEEXT) tools/diff/diff4$(EXEEXT) tools/dev/fsfs-access-map$(EXEEXT) tools/server-side/mod_dontdothat/mod_dontdothat.la tools/client-side/svn-mergeinfo-normalizer/svn-mergeinfo-normalizer$(EXEEXT) tools/server-side/svn-populate-node-origins-index$(EXEEXT) tools/server-side/svnauthz$(EXEEXT) tools/server-side/svnauthz-validate$(EXEEXT) tools/client-side/svnconflict/svnconflict$(EXEEXT) tools/dev/svnmover/svnmover$(EXEEXT) tools/dev/svnraisetreeconflict/svnraisetreeconflict$(EXEEXT) tools/dev/x509-parser$(EXEEXT) ######################################## @@ -1128,6 +1188,14 @@ install-cxxhl-lib: subversion/bindings/cxxhl/libsvncxxhl-1.la $(INSTALL_EXTRA_CXXHL_LIB) +install-cxxhl-tests: googlemock/libgooglemock-1.la subversion/bindings/cxxhl/cxxhl-tests$(EXEEXT) + $(MKDIR) $(DESTDIR)$(cxxhl_testsdir) + if $(SVN_USE_GOOGLEMOCK) ; then cd googlemock ; $(INSTALL_CXXHL_TESTS) libgooglemock-1.la $(DESTDIR)$(cxxhl_testsdir)/libgooglemock-1.la ; fi + + if $(SVN_USE_GOOGLEMOCK) ; then cd subversion/bindings/cxxhl ; $(INSTALL_CXXHL_TESTS) cxxhl-tests$(EXEEXT) $(DESTDIR)$(cxxhl_testsdir)/cxxhl-tests$(EXEEXT) ; fi + + $(INSTALL_EXTRA_CXXHL_TESTS) + install-fsmod-lib: subversion/libsvn_subr/libsvn_subr-1.la subversion/libsvn_delta/libsvn_delta-1.la subversion/libsvn_fs_util/libsvn_fs_util-1.la subversion/libsvn_fs_fs/libsvn_fs_fs-1.la subversion/libsvn_fs_x/libsvn_fs_x-1.la $(MKDIR) $(DESTDIR)$(fsmod_libdir) $(DESTDIR)$(pkgconfig_dir) cd subversion/libsvn_subr ; $(INSTALL_FSMOD_LIB) libsvn_subr-1.la $(DESTDIR)$(fsmod_libdir)/libsvn_subr-1.la @@ -1307,14 +1375,7 @@ install-swig-rb-lib: subversion/bindings/swig/ruby/libsvn_swig_ruby/libsvn_swig_ cd subversion/bindings/swig/ruby/libsvn_swig_ruby ; $(INSTALL_SWIG_RB_LIB) libsvn_swig_ruby-1.la $(DESTDIR)$(swig_rb_libdir)/libsvn_swig_ruby-1.la -install-tests: gmock-fused/libgmock-1.la subversion/bindings/cxxhl/cxxhl-tests$(EXEEXT) - $(MKDIR) $(DESTDIR)$(testsdir) - if $(SVN_USE_GMOCK) ; then cd gmock-fused ; $(INSTALL_TESTS) libgmock-1.la $(DESTDIR)$(testsdir)/libgmock-1.la ; fi - - if $(SVN_USE_GMOCK) ; then cd subversion/bindings/cxxhl ; $(INSTALL_TESTS) cxxhl-tests$(EXEEXT) $(DESTDIR)$(testsdir)/cxxhl-tests$(EXEEXT) ; fi - - -install-tools: tools/diff/diff$(EXEEXT) tools/diff/diff3$(EXEEXT) tools/diff/diff4$(EXEEXT) tools/dev/fsfs-access-map$(EXEEXT) tools/server-side/mod_dontdothat/mod_dontdothat.la tools/server-side/svn-populate-node-origins-index$(EXEEXT) tools/server-side/svnauthz$(EXEEXT) tools/server-side/svnauthz-validate$(EXEEXT) tools/dev/svnraisetreeconflict/svnraisetreeconflict$(EXEEXT) tools/dev/x509-parser$(EXEEXT) +install-tools: tools/diff/diff$(EXEEXT) tools/diff/diff3$(EXEEXT) tools/diff/diff4$(EXEEXT) tools/dev/fsfs-access-map$(EXEEXT) tools/server-side/mod_dontdothat/mod_dontdothat.la tools/client-side/svn-mergeinfo-normalizer/svn-mergeinfo-normalizer$(EXEEXT) tools/server-side/svn-populate-node-origins-index$(EXEEXT) tools/server-side/svnauthz$(EXEEXT) tools/server-side/svnauthz-validate$(EXEEXT) tools/client-side/svnconflict/svnconflict$(EXEEXT) tools/dev/svnmover/svnmover$(EXEEXT) tools/dev/svnraisetreeconflict/svnraisetreeconflict$(EXEEXT) tools/dev/x509-parser$(EXEEXT) $(MKDIR) $(DESTDIR)$(toolsdir) cd tools/diff ; $(INSTALL_TOOLS) diff$(EXEEXT) $(DESTDIR)$(toolsdir)/diff$(EXEEXT) @@ -1325,12 +1386,18 @@ install-tools: tools/diff/diff$(EXEEXT) tools/diff/diff3$(EXEEXT) tools/diff/dif cd tools/dev ; $(INSTALL_TOOLS) fsfs-access-map$(EXEEXT) $(DESTDIR)$(toolsdir)/fsfs-access-map$(EXEEXT) if $(INSTALL_APACHE_MODS) ; then cd tools/server-side/mod_dontdothat ; $(MKDIR) "$(APACHE_LIBEXECDIR)" ; $(INSTALL_MOD_SHARED) -n dontdothat mod_dontdothat.la ; fi + cd tools/client-side/svn-mergeinfo-normalizer ; $(INSTALL_TOOLS) svn-mergeinfo-normalizer$(EXEEXT) $(DESTDIR)$(toolsdir)/svn-mergeinfo-normalizer$(EXEEXT) + cd tools/server-side ; $(INSTALL_TOOLS) svn-populate-node-origins-index$(EXEEXT) $(DESTDIR)$(toolsdir)/svn-populate-node-origins-index$(EXEEXT) cd tools/server-side ; $(INSTALL_TOOLS) svnauthz$(EXEEXT) $(DESTDIR)$(toolsdir)/svnauthz$(EXEEXT) cd tools/server-side ; $(INSTALL_TOOLS) svnauthz-validate$(EXEEXT) $(DESTDIR)$(toolsdir)/svnauthz-validate$(EXEEXT) + cd tools/client-side/svnconflict ; $(INSTALL_TOOLS) svnconflict$(EXEEXT) $(DESTDIR)$(toolsdir)/svnconflict$(EXEEXT) + + cd tools/dev/svnmover ; $(INSTALL_TOOLS) svnmover$(EXEEXT) $(DESTDIR)$(toolsdir)/svnmover$(EXEEXT) + cd tools/dev/svnraisetreeconflict ; $(INSTALL_TOOLS) svnraisetreeconflict$(EXEEXT) $(DESTDIR)$(toolsdir)/svnraisetreeconflict$(EXEEXT) cd tools/dev ; $(INSTALL_TOOLS) x509-parser$(EXEEXT) $(DESTDIR)$(toolsdir)/x509-parser$(EXEEXT) @@ -1393,16 +1460,20 @@ install-include: subversion/include/mod_authz_svn.h subversion/include/mod_dav_s # Section 9: Shortcut targets for manual builds of specific items ######################################## +afl-x509: subversion/tests/afl/afl-x509$(EXEEXT) atomic-ra-revprop-change: subversion/tests/cmdline/atomic-ra-revprop-change$(EXEEXT) auth-test: subversion/tests/libsvn_subr/auth-test$(EXEEXT) +authz-test: subversion/tests/libsvn_repos/authz-test$(EXEEXT) bit-array-test: subversion/tests/libsvn_subr/bit-array-test$(EXEEXT) cache-test: subversion/tests/libsvn_subr/cache-test$(EXEEXT) changes-test: subversion/tests/libsvn_fs_base/changes-test$(EXEEXT) checksum-test: subversion/tests/libsvn_subr/checksum-test$(EXEEXT) client-test: subversion/tests/libsvn_client/client-test$(EXEEXT) compat-test: subversion/tests/libsvn_subr/compat-test$(EXEEXT) +compress-test: subversion/tests/libsvn_subr/compress-test$(EXEEXT) config-test: subversion/tests/libsvn_subr/config-test$(EXEEXT) conflict-data-test: subversion/tests/libsvn_wc/conflict-data-test$(EXEEXT) +conflicts-test: subversion/tests/libsvn_client/conflicts-test$(EXEEXT) crypto-test: subversion/tests/libsvn_subr/crypto-test$(EXEEXT) cxxhl-tests: subversion/bindings/cxxhl/cxxhl-tests$(EXEEXT) db-test: subversion/tests/libsvn_wc/db-test$(EXEEXT) @@ -1420,12 +1491,13 @@ fs-base-test: subversion/tests/libsvn_fs_base/fs-base-test$(EXEEXT) fs-fs-fuzzy-test: subversion/tests/libsvn_fs_fs/fs-fs-fuzzy-test$(EXEEXT) fs-fs-pack-test: subversion/tests/libsvn_fs_fs/fs-fs-pack-test$(EXEEXT) fs-fs-private-test: subversion/tests/libsvn_fs_fs/fs-fs-private-test$(EXEEXT) +fs-sequential-test: subversion/tests/libsvn_fs/fs-sequential-test$(EXEEXT) fs-test: subversion/tests/libsvn_fs/fs-test$(EXEEXT) fs-x-pack-test: subversion/tests/libsvn_fs_x/fs-x-pack-test$(EXEEXT) fsfs-access-map: tools/dev/fsfs-access-map$(EXEEXT) hashdump-test: subversion/tests/libsvn_subr/hashdump-test$(EXEEXT) io-test: subversion/tests/libsvn_subr/io-test$(EXEEXT) -libgmock: gmock-fused/libgmock-1.la +libgooglemock: googlemock/libgooglemock-1.la libsvn_auth_gnome_keyring: subversion/libsvn_auth_gnome_keyring/libsvn_auth_gnome_keyring-1.la libsvn_auth_kwallet: subversion/libsvn_auth_kwallet/libsvn_auth_kwallet-1.la libsvn_client: subversion/libsvn_client/libsvn_client-1.la @@ -1503,16 +1575,20 @@ string-test: subversion/tests/libsvn_subr/string-test$(EXEEXT) strings-reps-test: subversion/tests/libsvn_fs_base/strings-reps-test$(EXEEXT) subst_translate-test: subversion/tests/libsvn_subr/subst_translate-test$(EXEEXT) svn: subversion/svn/svn$(EXEEXT) +svn-mergeinfo-normalizer: tools/client-side/svn-mergeinfo-normalizer/svn-mergeinfo-normalizer$(EXEEXT) svn-populate-node-origins-index: tools/server-side/svn-populate-node-origins-index$(EXEEXT) svn-wc-db-tester: tools/dev/wc-ng/svn-wc-db-tester$(EXEEXT) svnadmin: subversion/svnadmin/svnadmin$(EXEEXT) svnauthz: tools/server-side/svnauthz$(EXEEXT) svnauthz-validate: tools/server-side/svnauthz-validate$(EXEEXT) svnbench: subversion/svnbench/svnbench$(EXEEXT) +svnconflict: tools/client-side/svnconflict/svnconflict$(EXEEXT) +svndiff-stream-test: subversion/tests/libsvn_delta/svndiff-stream-test$(EXEEXT) svndiff-test: subversion/tests/libsvn_delta/svndiff-test$(EXEEXT) svndumpfilter: subversion/svndumpfilter/svndumpfilter$(EXEEXT) svnfsfs: subversion/svnfsfs/svnfsfs$(EXEEXT) svnlook: subversion/svnlook/svnlook$(EXEEXT) +svnmover: tools/dev/svnmover/svnmover$(EXEEXT) svnmucc: subversion/svnmucc/svnmucc$(EXEEXT) svnraisetreeconflict: tools/dev/svnraisetreeconflict/svnraisetreeconflict$(EXEEXT) svnrdump: subversion/svnrdump/svnrdump$(EXEEXT) @@ -1530,6 +1606,7 @@ wc-test: subversion/tests/libsvn_wc/wc-test$(EXEEXT) window-test: subversion/tests/libsvn_delta/window-test$(EXEEXT) x509-parser: tools/dev/x509-parser$(EXEEXT) x509-test: subversion/tests/libsvn_subr/x509-test$(EXEEXT) +xml-test: subversion/tests/libsvn_subr/xml-test$(EXEEXT) ######################################## # Section 10: Rules to build all other kinds of object-like files @@ -1545,13 +1622,13 @@ subversion/bindings/cxxhl/src/tristate.lo: subversion/bindings/cxxhl/src/tristat $(COMPILE_CXXHL_CXX) $(canonicalized_srcdir)subversion/bindings/cxxhl/src/tristate.cpp subversion/bindings/cxxhl/tests/cxxhl-tests.lo: subversion/bindings/cxxhl/tests/cxxhl-tests.cpp - if $(SVN_USE_GMOCK) ; then $(COMPILE_CXXHL_GMOCK_CXX) $(canonicalized_srcdir)subversion/bindings/cxxhl/tests/cxxhl-tests.cpp ; else echo "fake" > subversion/bindings/cxxhl/tests/cxxhl-tests.lo ; fi + if $(SVN_USE_GOOGLEMOCK) ; then $(COMPILE_CXXHL_GOOGLEMOCK_CXX) $(canonicalized_srcdir)subversion/bindings/cxxhl/tests/cxxhl-tests.cpp ; else echo "fake" > subversion/bindings/cxxhl/tests/cxxhl-tests.lo ; fi subversion/bindings/cxxhl/tests/test_aprwrap.lo: subversion/bindings/cxxhl/tests/test_aprwrap.cpp subversion/bindings/cxxhl/include/svncxxhl/_compat.hpp subversion/bindings/cxxhl/include/svncxxhl/exception.hpp subversion/bindings/cxxhl/src/aprwrap.hpp subversion/bindings/cxxhl/src/aprwrap/array.hpp subversion/bindings/cxxhl/src/aprwrap/hash.hpp subversion/bindings/cxxhl/src/aprwrap/pool.hpp subversion/include/private/svn_debug.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_pools.h subversion/include/svn_types.h subversion/svn_private_config.h - if $(SVN_USE_GMOCK) ; then $(COMPILE_CXXHL_GMOCK_CXX) $(canonicalized_srcdir)subversion/bindings/cxxhl/tests/test_aprwrap.cpp ; else echo "fake" > subversion/bindings/cxxhl/tests/test_aprwrap.lo ; fi + if $(SVN_USE_GOOGLEMOCK) ; then $(COMPILE_CXXHL_GOOGLEMOCK_CXX) $(canonicalized_srcdir)subversion/bindings/cxxhl/tests/test_aprwrap.cpp ; else echo "fake" > subversion/bindings/cxxhl/tests/test_aprwrap.lo ; fi subversion/bindings/cxxhl/tests/test_exception.lo: subversion/bindings/cxxhl/tests/test_exception.cpp subversion/bindings/cxxhl/include/svncxxhl.hpp subversion/bindings/cxxhl/include/svncxxhl/_compat.hpp subversion/bindings/cxxhl/include/svncxxhl/exception.hpp subversion/bindings/cxxhl/include/svncxxhl/tristate.hpp subversion/bindings/cxxhl/src/private.hpp subversion/bindings/cxxhl/src/private/exception-private.hpp subversion/include/private/svn_debug.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_types.h - if $(SVN_USE_GMOCK) ; then $(COMPILE_CXXHL_GMOCK_CXX) $(canonicalized_srcdir)subversion/bindings/cxxhl/tests/test_exception.cpp ; else echo "fake" > subversion/bindings/cxxhl/tests/test_exception.lo ; fi + if $(SVN_USE_GOOGLEMOCK) ; then $(COMPILE_CXXHL_GOOGLEMOCK_CXX) $(canonicalized_srcdir)subversion/bindings/cxxhl/tests/test_exception.cpp ; else echo "fake" > subversion/bindings/cxxhl/tests/test_exception.lo ; fi subversion/bindings/javahl/classes/org/apache/subversion/javahl/BasicTests.class: subversion/bindings/javahl/tests/org/apache/subversion/javahl/BasicTests.java @@ -1645,6 +1722,8 @@ subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/Inherit subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ListCallback.class: subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ListCallback.java +subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ListItemCallback.class: subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/ListItemCallback.java + subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/LogMessageCallback.class: subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/LogMessageCallback.java subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/PatchCallback.class: subversion/bindings/javahl/src/org/apache/subversion/javahl/callback/PatchCallback.java @@ -1973,6 +2052,8 @@ subversion/bindings/javahl/include/JNIObject.h: subversion/bindings/javahl/class subversion/bindings/javahl/include/ListCallback.h: subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ListCallback.class +subversion/bindings/javahl/include/ListItemCallback.h: subversion/bindings/javahl/classes/org/apache/subversion/javahl/callback/ListItemCallback.class + subversion/bindings/javahl/include/Lock.h: subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/Lock.class subversion/bindings/javahl/include/LogDate.h: subversion/bindings/javahl/classes/org/apache/subversion/javahl/types/LogDate.class @@ -2400,13 +2481,17 @@ subversion/bindings/swig/ruby/svn_repos.lo: subversion/bindings/swig/ruby/svn_re subversion/bindings/swig/ruby/svn_wc.lo: subversion/bindings/swig/ruby/svn_wc.c subversion/bindings/swig/perl/libsvn_swig_perl/swigutil_pl.h subversion/bindings/swig/python/libsvn_swig_py/swigutil_py.h subversion/bindings/swig/ruby/libsvn_swig_ruby/swigutil_rb.h subversion/bindings/swig/ruby/libsvn_swig_ruby/swigutil_rb__pre_ruby.h subversion/include/svn_client.h subversion/include/svn_fs.h subversion/include/svn_repos.h subversion/svn_private_config.h $(COMPILE_RB_WRAPPER) $(canonicalized_srcdir)subversion/bindings/swig/ruby/svn_wc.c -subversion/libsvn_auth_gnome_keyring/gnome_keyring.lo: subversion/libsvn_auth_gnome_keyring/gnome_keyring.c subversion/include/private/svn_auth_private.h subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/svn_private_config.h +subversion/libsvn_auth_gnome_keyring/gnome_keyring.lo: subversion/libsvn_auth_gnome_keyring/gnome_keyring.c subversion/include/private/svn_auth_private.h subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/svn_private_config.h + $(COMPILE_SHARED_ONLY_LIB) $(canonicalized_srcdir)subversion/libsvn_auth_gnome_keyring/gnome_keyring.c subversion/libsvn_auth_gnome_keyring/version.lo: subversion/libsvn_auth_gnome_keyring/version.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h + $(COMPILE_SHARED_ONLY_LIB) $(canonicalized_srcdir)subversion/libsvn_auth_gnome_keyring/version.c subversion/libsvn_auth_kwallet/kwallet.lo: subversion/libsvn_auth_kwallet/kwallet.cpp subversion/include/private/svn_auth_private.h subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/svn_private_config.h + $(COMPILE_SHARED_ONLY_CXX_LIB) $(canonicalized_srcdir)subversion/libsvn_auth_kwallet/kwallet.cpp subversion/libsvn_auth_kwallet/version.lo: subversion/libsvn_auth_kwallet/version.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h + $(COMPILE_SHARED_ONLY_CXX_LIB) $(canonicalized_srcdir)subversion/libsvn_auth_kwallet/version.c subversion/libsvn_client/add.lo: subversion/libsvn_client/add.c subversion/include/private/svn_client_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_editor.h subversion/include/private/svn_magic.h subversion/include/private/svn_ra_private.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_client/client.h subversion/svn_private_config.h @@ -2428,6 +2513,8 @@ subversion/libsvn_client/commit_util.lo: subversion/libsvn_client/commit_util.c subversion/libsvn_client/compat_providers.lo: subversion/libsvn_client/compat_providers.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h +subversion/libsvn_client/conflicts.lo: subversion/libsvn_client/conflicts.c subversion/include/private/svn_client_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_editor.h subversion/include/private/svn_magic.h subversion/include/private/svn_ra_private.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_token.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_client/client.h subversion/svn_private_config.h + subversion/libsvn_client/copy.lo: subversion/libsvn_client/copy.c subversion/include/private/svn_client_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_editor.h subversion/include/private/svn_magic.h subversion/include/private/svn_mergeinfo_private.h subversion/include/private/svn_ra_private.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_client/client.h subversion/libsvn_client/mergeinfo.h subversion/svn_private_config.h subversion/libsvn_client/copy_foreign.lo: subversion/libsvn_client/copy_foreign.c subversion/include/private/svn_client_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_editor.h subversion/include/private/svn_magic.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_client/client.h subversion/svn_private_config.h @@ -2454,7 +2541,7 @@ subversion/libsvn_client/info.lo: subversion/libsvn_client/info.c subversion/inc subversion/libsvn_client/iprops.lo: subversion/libsvn_client/iprops.c subversion/include/private/svn_client_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_editor.h subversion/include/private/svn_magic.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_client/client.h subversion/svn_private_config.h -subversion/libsvn_client/list.lo: subversion/libsvn_client/list.c subversion/include/private/svn_client_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_magic.h subversion/include/private/svn_ra_private.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_client/client.h subversion/svn_private_config.h +subversion/libsvn_client/list.lo: subversion/libsvn_client/list.c subversion/include/private/svn_client_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_magic.h subversion/include/private/svn_ra_private.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_utf_private.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_client/client.h subversion/svn_private_config.h subversion/libsvn_client/locking_commands.lo: subversion/libsvn_client/locking_commands.c subversion/include/private/svn_client_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_editor.h subversion/include/private/svn_magic.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/include/svn_xml.h subversion/libsvn_client/client.h subversion/svn_private_config.h @@ -2462,11 +2549,13 @@ subversion/libsvn_client/log.lo: subversion/libsvn_client/log.c subversion/inclu subversion/libsvn_client/merge.lo: subversion/libsvn_client/merge.c subversion/include/private/svn_client_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_magic.h subversion/include/private/svn_mergeinfo_private.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_wc.h subversion/libsvn_client/client.h subversion/libsvn_client/mergeinfo.h subversion/svn_private_config.h +subversion/libsvn_client/merge_elements.lo: subversion/libsvn_client/merge_elements.c subversion/include/private/svn_client_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_editor.h subversion/include/private/svn_element.h subversion/include/private/svn_magic.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_client/client.h subversion/svn_private_config.h + subversion/libsvn_client/mergeinfo.lo: subversion/libsvn_client/mergeinfo.c subversion/include/private/svn_client_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_magic.h subversion/include/private/svn_mergeinfo_private.h subversion/include/private/svn_opt_private.h subversion/include/private/svn_ra_private.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_client/client.h subversion/libsvn_client/mergeinfo.h subversion/svn_private_config.h subversion/libsvn_client/mtcc.lo: subversion/libsvn_client/mtcc.c subversion/include/private/svn_client_mtcc.h subversion/include/private/svn_client_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_editor.h subversion/include/private/svn_magic.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_client/client.h subversion/svn_private_config.h -subversion/libsvn_client/patch.lo: subversion/libsvn_client/patch.c subversion/include/private/svn_client_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_editor.h subversion/include/private/svn_eol_private.h subversion/include/private/svn_magic.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_client/client.h subversion/svn_private_config.h +subversion/libsvn_client/patch.lo: subversion/libsvn_client/patch.c subversion/include/private/svn_client_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_diff_private.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_editor.h subversion/include/private/svn_eol_private.h subversion/include/private/svn_magic.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_client/client.h subversion/svn_private_config.h subversion/libsvn_client/prop_commands.lo: subversion/libsvn_client/prop_commands.c subversion/include/private/svn_client_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_editor.h subversion/include/private/svn_magic.h subversion/include/private/svn_ra_private.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_client/client.h subversion/svn_private_config.h @@ -2482,6 +2571,8 @@ subversion/libsvn_client/revert.lo: subversion/libsvn_client/revert.c subversion subversion/libsvn_client/revisions.lo: subversion/libsvn_client/revisions.c subversion/include/private/svn_client_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_editor.h subversion/include/private/svn_magic.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_client/client.h subversion/svn_private_config.h +subversion/libsvn_client/shelve.lo: subversion/libsvn_client/shelve.c subversion/include/private/svn_client_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_editor.h subversion/include/private/svn_magic.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_wc.h subversion/libsvn_client/client.h subversion/svn_private_config.h + subversion/libsvn_client/status.lo: subversion/libsvn_client/status.c subversion/include/private/svn_client_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_editor.h subversion/include/private/svn_magic.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_client/client.h subversion/svn_private_config.h subversion/libsvn_client/switch.lo: subversion/libsvn_client/switch.c subversion/include/private/svn_client_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_editor.h subversion/include/private/svn_magic.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_client/client.h subversion/svn_private_config.h @@ -2496,13 +2587,23 @@ subversion/libsvn_client/util.lo: subversion/libsvn_client/util.c subversion/inc subversion/libsvn_client/version.lo: subversion/libsvn_client/version.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/include/svn_wc.h +subversion/libsvn_delta/branch.lo: subversion/libsvn_delta/branch.c subversion/include/private/svn_branch.h subversion/include/private/svn_branch_impl.h subversion/include/private/svn_debug.h subversion/include/private/svn_element.h subversion/include/private/svn_sorts_private.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_pools.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/svn_private_config.h + +subversion/libsvn_delta/branch_compat.lo: subversion/libsvn_delta/branch_compat.c subversion/include/private/svn_branch.h subversion/include/private/svn_branch_compat.h subversion/include/private/svn_branch_impl.h subversion/include/private/svn_branch_nested.h subversion/include/private/svn_branch_repos.h subversion/include/private/svn_debug.h subversion/include/private/svn_delta_private.h subversion/include/private/svn_editor.h subversion/include/private/svn_element.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/svn_private_config.h + +subversion/libsvn_delta/branch_migrate.lo: subversion/libsvn_delta/branch_migrate.c subversion/include/private/svn_branch.h subversion/include/private/svn_branch_compat.h subversion/include/private/svn_debug.h subversion/include/private/svn_element.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/svn_private_config.h + +subversion/libsvn_delta/branch_nested.lo: subversion/libsvn_delta/branch_nested.c subversion/include/private/svn_branch.h subversion/include/private/svn_branch_impl.h subversion/include/private/svn_branch_nested.h subversion/include/private/svn_branch_repos.h subversion/include/private/svn_debug.h subversion/include/private/svn_element.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/svn_private_config.h + +subversion/libsvn_delta/branch_repos.lo: subversion/libsvn_delta/branch_repos.c subversion/include/private/svn_branch.h subversion/include/private/svn_branch_repos.h subversion/include/private/svn_debug.h subversion/include/private/svn_element.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/svn_private_config.h + subversion/libsvn_delta/cancel.lo: subversion/libsvn_delta/cancel.c subversion/include/private/svn_debug.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_delta/compat.lo: subversion/libsvn_delta/compat.c subversion/include/private/svn_debug.h subversion/include/private/svn_delta_private.h subversion/include/private/svn_editor.h subversion/include/private/svn_sorts_private.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/svn_private_config.h subversion/libsvn_delta/compose_delta.lo: subversion/libsvn_delta/compose_delta.c subversion/include/private/svn_debug.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_delta/delta.h -subversion/libsvn_delta/debug_editor.lo: subversion/libsvn_delta/debug_editor.c subversion/include/private/svn_debug.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_delta/debug_editor.h +subversion/libsvn_delta/debug_editor.lo: subversion/libsvn_delta/debug_editor.c subversion/include/private/svn_debug.h subversion/include/private/svn_delta_private.h subversion/include/private/svn_editor.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_delta/default_editor.lo: subversion/libsvn_delta/default_editor.c subversion/include/private/svn_debug.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_string.h subversion/include/svn_types.h @@ -2512,6 +2613,8 @@ subversion/libsvn_delta/depth_filter_editor.lo: subversion/libsvn_delta/depth_fi subversion/libsvn_delta/editor.lo: subversion/libsvn_delta/editor.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h +subversion/libsvn_delta/element.lo: subversion/libsvn_delta/element.c subversion/include/private/svn_debug.h subversion/include/private/svn_element.h subversion/include/private/svn_sorts_private.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_iter.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/svn_private_config.h + subversion/libsvn_delta/path_driver.lo: subversion/libsvn_delta/path_driver.c subversion/include/private/svn_debug.h subversion/include/private/svn_fspath.h subversion/include/private/svn_sorts_private.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_delta/svndiff.lo: subversion/libsvn_delta/svndiff.c subversion/include/private/svn_debug.h subversion/include/private/svn_delta_private.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_error_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_delta/delta.h subversion/svn_private_config.h @@ -2522,13 +2625,13 @@ subversion/libsvn_delta/version.lo: subversion/libsvn_delta/version.c subversion subversion/libsvn_delta/xdelta.lo: subversion/libsvn_delta/xdelta.c subversion/include/private/svn_debug.h subversion/include/private/svn_string_private.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_delta/delta.h -subversion/libsvn_diff/binary_diff.lo: subversion/libsvn_diff/binary_diff.c subversion/include/private/svn_debug.h subversion/include/svn_checksum.h subversion/include/svn_diff.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h +subversion/libsvn_diff/binary_diff.lo: subversion/libsvn_diff/binary_diff.c subversion/include/private/svn_debug.h subversion/include/svn_checksum.h subversion/include/svn_diff.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_diff/diff.h subversion/svn_private_config.h subversion/libsvn_diff/deprecated.lo: subversion/libsvn_diff/deprecated.c subversion/include/private/svn_debug.h subversion/include/svn_checksum.h subversion/include/svn_diff.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/svn_private_config.h subversion/libsvn_diff/diff.lo: subversion/libsvn_diff/diff.c subversion/include/private/svn_debug.h subversion/include/svn_checksum.h subversion/include/svn_diff.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_diff/diff.h -subversion/libsvn_diff/diff3.lo: subversion/libsvn_diff/diff3.c subversion/include/private/svn_debug.h subversion/include/svn_checksum.h subversion/include/svn_diff.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_diff/diff.h +subversion/libsvn_diff/diff3.lo: subversion/libsvn_diff/diff3.c subversion/include/private/svn_debug.h subversion/include/svn_checksum.h subversion/include/svn_diff.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_diff/diff.h subversion/libsvn_diff/diff4.lo: subversion/libsvn_diff/diff4.c subversion/include/private/svn_debug.h subversion/include/svn_checksum.h subversion/include/svn_diff.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_diff/diff.h @@ -2540,177 +2643,181 @@ subversion/libsvn_diff/diff_tree.lo: subversion/libsvn_diff/diff_tree.c subversi subversion/libsvn_diff/lcs.lo: subversion/libsvn_diff/lcs.c subversion/include/private/svn_debug.h subversion/include/svn_checksum.h subversion/include/svn_diff.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_diff/diff.h -subversion/libsvn_diff/parse-diff.lo: subversion/libsvn_diff/parse-diff.c subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_eol_private.h subversion/include/private/svn_sorts_private.h subversion/include/svn_checksum.h subversion/include/svn_ctype.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h +subversion/libsvn_diff/parse-diff.lo: subversion/libsvn_diff/parse-diff.c subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_diff_private.h subversion/include/private/svn_eol_private.h subversion/include/private/svn_sorts_private.h subversion/include/svn_checksum.h subversion/include/svn_ctype.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/libsvn_diff/diff.h subversion/svn_private_config.h subversion/libsvn_diff/token.lo: subversion/libsvn_diff/token.c subversion/include/private/svn_debug.h subversion/include/svn_checksum.h subversion/include/svn_diff.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_diff/diff.h subversion/libsvn_diff/util.lo: subversion/libsvn_diff/util.c subversion/include/private/svn_debug.h subversion/include/private/svn_diff_private.h subversion/include/private/svn_sorts_private.h subversion/include/svn_checksum.h subversion/include/svn_ctype.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/libsvn_diff/diff.h subversion/svn_private_config.h -subversion/libsvn_fs/access.lo: subversion/libsvn_fs/access.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h +subversion/libsvn_fs/access.lo: subversion/libsvn_fs/access.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h -subversion/libsvn_fs/deprecated.lo: subversion/libsvn_fs/deprecated.c subversion/include/private/svn_debug.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_string.h subversion/include/svn_types.h +subversion/libsvn_fs/deprecated.lo: subversion/libsvn_fs/deprecated.c subversion/include/private/svn_debug.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_string.h subversion/include/svn_types.h -subversion/libsvn_fs/editor.lo: subversion/libsvn_fs/editor.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/svn_private_config.h +subversion/libsvn_fs/editor.lo: subversion/libsvn_fs/editor.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs/fs-loader.lo: subversion/libsvn_fs/fs-loader.c subversion/include/private/svn_atomic.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_mutex.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_utf_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_dso.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/include/svn_xml.h subversion/libsvn_fs/fs-loader.h subversion/svn_private_config.h +subversion/libsvn_fs/fs-loader.lo: subversion/libsvn_fs/fs-loader.c subversion/include/private/svn_atomic.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_utf_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_dso.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/include/svn_xml.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_base/bdb/bdb-err.lo: subversion/libsvn_fs_base/bdb/bdb-err.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/svn_private_config.h +subversion/libsvn_fs_base/bdb/bdb-err.lo: subversion/libsvn_fs_base/bdb/bdb-err.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h subversion/libsvn_fs_base/bdb/bdb_compat.lo: subversion/libsvn_fs_base/bdb/bdb_compat.c subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/svn_private_config.h -subversion/libsvn_fs_base/bdb/changes-table.lo: subversion/libsvn_fs_base/bdb/changes-table.c subversion/include/private/svn_debug.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/changes-table.h subversion/libsvn_fs_base/bdb/dbt.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/id.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/util/fs_skels.h subversion/svn_private_config.h +subversion/libsvn_fs_base/bdb/changes-table.lo: subversion/libsvn_fs_base/bdb/changes-table.c subversion/include/private/svn_debug.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/changes-table.h subversion/libsvn_fs_base/bdb/dbt.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_base/id.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/util/fs_skels.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_base/bdb/checksum-reps-table.lo: subversion/libsvn_fs_base/bdb/checksum-reps-table.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/checksum-reps-table.h subversion/libsvn_fs_base/bdb/dbt.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/key-gen.h subversion/libsvn_fs_base/trail.h subversion/svn_private_config.h +subversion/libsvn_fs_base/bdb/checksum-reps-table.lo: subversion/libsvn_fs_base/bdb/checksum-reps-table.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/checksum-reps-table.h subversion/libsvn_fs_base/bdb/dbt.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_base/key-gen.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_base/bdb/copies-table.lo: subversion/libsvn_fs_base/bdb/copies-table.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/copies-table.h subversion/libsvn_fs_base/bdb/dbt.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/rev-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/key-gen.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/util/fs_skels.h subversion/svn_private_config.h +subversion/libsvn_fs_base/bdb/copies-table.lo: subversion/libsvn_fs_base/bdb/copies-table.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/copies-table.h subversion/libsvn_fs_base/bdb/dbt.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/rev-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_base/key-gen.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/util/fs_skels.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h subversion/libsvn_fs_base/bdb/dbt.lo: subversion/libsvn_fs_base/bdb/dbt.c subversion/include/private/svn_debug.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs_base/bdb/dbt.h subversion/libsvn_fs_base/id.h subversion/svn_private_config.h subversion/libsvn_fs_base/bdb/env.lo: subversion/libsvn_fs_base/bdb/env.c subversion/include/private/svn_atomic.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_mutex.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/env.h subversion/svn_private_config.h -subversion/libsvn_fs_base/bdb/lock-tokens-table.lo: subversion/libsvn_fs_base/bdb/lock-tokens-table.c subversion/include/private/svn_debug.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/dbt.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/lock-tokens-table.h subversion/libsvn_fs_base/bdb/locks-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/util/fs_skels.h subversion/svn_private_config.h +subversion/libsvn_fs_base/bdb/lock-tokens-table.lo: subversion/libsvn_fs_base/bdb/lock-tokens-table.c subversion/include/private/svn_debug.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/dbt.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/lock-tokens-table.h subversion/libsvn_fs_base/bdb/locks-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/util/fs_skels.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_base/bdb/locks-table.lo: subversion/libsvn_fs_base/bdb/locks-table.c subversion/include/private/svn_debug.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/dbt.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/lock-tokens-table.h subversion/libsvn_fs_base/bdb/locks-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/util/fs_skels.h subversion/svn_private_config.h +subversion/libsvn_fs_base/bdb/locks-table.lo: subversion/libsvn_fs_base/bdb/locks-table.c subversion/include/private/svn_debug.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/dbt.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/lock-tokens-table.h subversion/libsvn_fs_base/bdb/locks-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/util/fs_skels.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_base/bdb/miscellaneous-table.lo: subversion/libsvn_fs_base/bdb/miscellaneous-table.c subversion/include/private/svn_debug.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/dbt.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/miscellaneous-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/trail.h subversion/svn_private_config.h +subversion/libsvn_fs_base/bdb/miscellaneous-table.lo: subversion/libsvn_fs_base/bdb/miscellaneous-table.c subversion/include/private/svn_debug.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/dbt.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/miscellaneous-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_base/bdb/node-origins-table.lo: subversion/libsvn_fs_base/bdb/node-origins-table.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/dbt.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/node-origins-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/id.h subversion/libsvn_fs_base/trail.h subversion/svn_private_config.h +subversion/libsvn_fs_base/bdb/node-origins-table.lo: subversion/libsvn_fs_base/bdb/node-origins-table.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/dbt.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/node-origins-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_base/id.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_base/bdb/nodes-table.lo: subversion/libsvn_fs_base/bdb/nodes-table.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/dbt.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/nodes-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/id.h subversion/libsvn_fs_base/key-gen.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/util/fs_skels.h subversion/svn_private_config.h +subversion/libsvn_fs_base/bdb/nodes-table.lo: subversion/libsvn_fs_base/bdb/nodes-table.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/dbt.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/nodes-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_base/id.h subversion/libsvn_fs_base/key-gen.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/util/fs_skels.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_base/bdb/reps-table.lo: subversion/libsvn_fs_base/bdb/reps-table.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/dbt.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/reps-table.h subversion/libsvn_fs_base/bdb/strings-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/key-gen.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/util/fs_skels.h subversion/svn_private_config.h +subversion/libsvn_fs_base/bdb/reps-table.lo: subversion/libsvn_fs_base/bdb/reps-table.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/dbt.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/reps-table.h subversion/libsvn_fs_base/bdb/strings-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_base/key-gen.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/util/fs_skels.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_base/bdb/rev-table.lo: subversion/libsvn_fs_base/bdb/rev-table.c subversion/include/private/svn_debug.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/dbt.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/rev-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/util/fs_skels.h subversion/svn_private_config.h +subversion/libsvn_fs_base/bdb/rev-table.lo: subversion/libsvn_fs_base/bdb/rev-table.c subversion/include/private/svn_debug.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/dbt.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/rev-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/util/fs_skels.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_base/bdb/strings-table.lo: subversion/libsvn_fs_base/bdb/strings-table.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/dbt.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/strings-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/key-gen.h subversion/libsvn_fs_base/trail.h subversion/svn_private_config.h +subversion/libsvn_fs_base/bdb/strings-table.lo: subversion/libsvn_fs_base/bdb/strings-table.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/dbt.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/strings-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_base/key-gen.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_base/bdb/txn-table.lo: subversion/libsvn_fs_base/bdb/txn-table.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/dbt.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/txn-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/key-gen.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/util/fs_skels.h subversion/svn_private_config.h +subversion/libsvn_fs_base/bdb/txn-table.lo: subversion/libsvn_fs_base/bdb/txn-table.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/dbt.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/txn-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_base/key-gen.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/util/fs_skels.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_base/bdb/uuids-table.lo: subversion/libsvn_fs_base/bdb/uuids-table.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/dbt.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/uuids-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/trail.h subversion/svn_private_config.h +subversion/libsvn_fs_base/bdb/uuids-table.lo: subversion/libsvn_fs_base/bdb/uuids-table.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/dbt.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/uuids-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_base/dag.lo: subversion/libsvn_fs_base/dag.c subversion/include/private/svn_debug.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/changes-table.h subversion/libsvn_fs_base/bdb/checksum-reps-table.h subversion/libsvn_fs_base/bdb/copies-table.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/node-origins-table.h subversion/libsvn_fs_base/bdb/nodes-table.h subversion/libsvn_fs_base/bdb/reps-table.h subversion/libsvn_fs_base/bdb/rev-table.h subversion/libsvn_fs_base/bdb/strings-table.h subversion/libsvn_fs_base/bdb/txn-table.h subversion/libsvn_fs_base/dag.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/id.h subversion/libsvn_fs_base/key-gen.h subversion/libsvn_fs_base/node-rev.h subversion/libsvn_fs_base/reps-strings.h subversion/libsvn_fs_base/revs-txns.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/util/fs_skels.h subversion/svn_private_config.h +subversion/libsvn_fs_base/dag.lo: subversion/libsvn_fs_base/dag.c subversion/include/private/svn_debug.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/changes-table.h subversion/libsvn_fs_base/bdb/checksum-reps-table.h subversion/libsvn_fs_base/bdb/copies-table.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/node-origins-table.h subversion/libsvn_fs_base/bdb/nodes-table.h subversion/libsvn_fs_base/bdb/reps-table.h subversion/libsvn_fs_base/bdb/rev-table.h subversion/libsvn_fs_base/bdb/strings-table.h subversion/libsvn_fs_base/bdb/txn-table.h subversion/libsvn_fs_base/dag.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_base/id.h subversion/libsvn_fs_base/key-gen.h subversion/libsvn_fs_base/node-rev.h subversion/libsvn_fs_base/reps-strings.h subversion/libsvn_fs_base/revs-txns.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/util/fs_skels.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_base/err.lo: subversion/libsvn_fs_base/err.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/id.h subversion/svn_private_config.h +subversion/libsvn_fs_base/err.lo: subversion/libsvn_fs_base/err.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_base/id.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_base/fs.lo: subversion/libsvn_fs_base/fs.c subversion/include/private/svn_debug.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_mutex.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/changes-table.h subversion/libsvn_fs_base/bdb/checksum-reps-table.h subversion/libsvn_fs_base/bdb/copies-table.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/lock-tokens-table.h subversion/libsvn_fs_base/bdb/locks-table.h subversion/libsvn_fs_base/bdb/miscellaneous-table.h subversion/libsvn_fs_base/bdb/node-origins-table.h subversion/libsvn_fs_base/bdb/nodes-table.h subversion/libsvn_fs_base/bdb/reps-table.h subversion/libsvn_fs_base/bdb/rev-table.h subversion/libsvn_fs_base/bdb/strings-table.h subversion/libsvn_fs_base/bdb/txn-table.h subversion/libsvn_fs_base/bdb/uuids-table.h subversion/libsvn_fs_base/dag.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/id.h subversion/libsvn_fs_base/lock.h subversion/libsvn_fs_base/revs-txns.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/tree.h subversion/libsvn_fs_base/uuid.h subversion/svn_private_config.h +subversion/libsvn_fs_base/fs.lo: subversion/libsvn_fs_base/fs.c subversion/include/private/svn_debug.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_mutex.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/changes-table.h subversion/libsvn_fs_base/bdb/checksum-reps-table.h subversion/libsvn_fs_base/bdb/copies-table.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/lock-tokens-table.h subversion/libsvn_fs_base/bdb/locks-table.h subversion/libsvn_fs_base/bdb/miscellaneous-table.h subversion/libsvn_fs_base/bdb/node-origins-table.h subversion/libsvn_fs_base/bdb/nodes-table.h subversion/libsvn_fs_base/bdb/reps-table.h subversion/libsvn_fs_base/bdb/rev-table.h subversion/libsvn_fs_base/bdb/strings-table.h subversion/libsvn_fs_base/bdb/txn-table.h subversion/libsvn_fs_base/bdb/uuids-table.h subversion/libsvn_fs_base/dag.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_base/id.h subversion/libsvn_fs_base/lock.h subversion/libsvn_fs_base/revs-txns.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/tree.h subversion/libsvn_fs_base/uuid.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_base/id.lo: subversion/libsvn_fs_base/id.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/id.h +subversion/libsvn_fs_base/id.lo: subversion/libsvn_fs_base/id.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_base/id.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/libsvn_fs_base/key-gen.lo: subversion/libsvn_fs_base/key-gen.c subversion/include/private/svn_debug.h subversion/include/private/svn_skel.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs_base/key-gen.h -subversion/libsvn_fs_base/lock.lo: subversion/libsvn_fs_base/lock.c subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/lock-tokens-table.h subversion/libsvn_fs_base/bdb/locks-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/lock.h subversion/libsvn_fs_base/revs-txns.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/tree.h subversion/libsvn_fs_base/util/fs_skels.h subversion/svn_private_config.h +subversion/libsvn_fs_base/lock.lo: subversion/libsvn_fs_base/lock.c subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/lock-tokens-table.h subversion/libsvn_fs_base/bdb/locks-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_base/lock.h subversion/libsvn_fs_base/revs-txns.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/tree.h subversion/libsvn_fs_base/util/fs_skels.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_base/node-rev.lo: subversion/libsvn_fs_base/node-rev.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/node-origins-table.h subversion/libsvn_fs_base/bdb/nodes-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/id.h subversion/libsvn_fs_base/node-rev.h subversion/libsvn_fs_base/reps-strings.h subversion/libsvn_fs_base/trail.h subversion/svn_private_config.h +subversion/libsvn_fs_base/node-rev.lo: subversion/libsvn_fs_base/node-rev.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/node-origins-table.h subversion/libsvn_fs_base/bdb/nodes-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_base/id.h subversion/libsvn_fs_base/node-rev.h subversion/libsvn_fs_base/reps-strings.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_base/reps-strings.lo: subversion/libsvn_fs_base/reps-strings.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/reps-table.h subversion/libsvn_fs_base/bdb/strings-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/reps-strings.h subversion/libsvn_fs_base/trail.h subversion/svn_private_config.h +subversion/libsvn_fs_base/reps-strings.lo: subversion/libsvn_fs_base/reps-strings.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/reps-table.h subversion/libsvn_fs_base/bdb/strings-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_base/reps-strings.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_base/revs-txns.lo: subversion/libsvn_fs_base/revs-txns.c subversion/include/private/svn_debug.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/changes-table.h subversion/libsvn_fs_base/bdb/copies-table.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/rev-table.h subversion/libsvn_fs_base/bdb/txn-table.h subversion/libsvn_fs_base/dag.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/id.h subversion/libsvn_fs_base/key-gen.h subversion/libsvn_fs_base/revs-txns.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/tree.h subversion/svn_private_config.h +subversion/libsvn_fs_base/revs-txns.lo: subversion/libsvn_fs_base/revs-txns.c subversion/include/private/svn_debug.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/changes-table.h subversion/libsvn_fs_base/bdb/copies-table.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/rev-table.h subversion/libsvn_fs_base/bdb/txn-table.h subversion/libsvn_fs_base/dag.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_base/id.h subversion/libsvn_fs_base/key-gen.h subversion/libsvn_fs_base/revs-txns.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/tree.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_base/trail.lo: subversion/libsvn_fs_base/trail.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/trail.h subversion/svn_private_config.h +subversion/libsvn_fs_base/trail.lo: subversion/libsvn_fs_base/trail.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb-err.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_base/tree.lo: subversion/libsvn_fs_base/tree.c subversion/include/private/svn_debug.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mergeinfo_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/changes-table.h subversion/libsvn_fs_base/bdb/copies-table.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/miscellaneous-table.h subversion/libsvn_fs_base/bdb/node-origins-table.h subversion/libsvn_fs_base/bdb/nodes-table.h subversion/libsvn_fs_base/bdb/rev-table.h subversion/libsvn_fs_base/bdb/txn-table.h subversion/libsvn_fs_base/dag.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/id.h subversion/libsvn_fs_base/key-gen.h subversion/libsvn_fs_base/lock.h subversion/libsvn_fs_base/node-rev.h subversion/libsvn_fs_base/revs-txns.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/tree.h subversion/svn_private_config.h +subversion/libsvn_fs_base/tree.lo: subversion/libsvn_fs_base/tree.c subversion/include/private/svn_debug.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mergeinfo_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/private/svn_sorts_private.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/changes-table.h subversion/libsvn_fs_base/bdb/copies-table.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/miscellaneous-table.h subversion/libsvn_fs_base/bdb/node-origins-table.h subversion/libsvn_fs_base/bdb/nodes-table.h subversion/libsvn_fs_base/bdb/rev-table.h subversion/libsvn_fs_base/bdb/txn-table.h subversion/libsvn_fs_base/dag.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_base/id.h subversion/libsvn_fs_base/key-gen.h subversion/libsvn_fs_base/lock.h subversion/libsvn_fs_base/node-rev.h subversion/libsvn_fs_base/revs-txns.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/tree.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h subversion/libsvn_fs_base/util/fs_skels.lo: subversion/libsvn_fs_base/util/fs_skels.c subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_skel.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/id.h subversion/libsvn_fs_base/util/fs_skels.h subversion/svn_private_config.h -subversion/libsvn_fs_base/uuid.lo: subversion/libsvn_fs_base/uuid.c subversion/include/private/svn_debug.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_mutex.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/uuids-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/uuid.h subversion/svn_private_config.h +subversion/libsvn_fs_base/uuid.lo: subversion/libsvn_fs_base/uuid.c subversion/include/private/svn_debug.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_mutex.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/uuids-table.h subversion/libsvn_fs_base/err.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/uuid.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_fs/cached_data.lo: subversion/libsvn_fs_fs/cached_data.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_delta_private.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_io_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_delta/delta.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_fs/cached_data.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/index.h subversion/libsvn_fs_fs/low_level.h subversion/libsvn_fs_fs/pack.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/temp_serializer.h subversion/libsvn_fs_fs/util.h subversion/svn_private_config.h +subversion/libsvn_fs_fs/cached_data.lo: subversion/libsvn_fs_fs/cached_data.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_delta_private.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_io_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_delta/delta.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/cached_data.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/index.h subversion/libsvn_fs_fs/low_level.h subversion/libsvn_fs_fs/pack.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/temp_serializer.h subversion/libsvn_fs_fs/util.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_fs/caching.lo: subversion/libsvn_fs_fs/caching.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_token.h subversion/include/svn_cache_config.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_fs/dag.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/index.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/temp_serializer.h subversion/libsvn_fs_fs/tree.h subversion/svn_private_config.h +subversion/libsvn_fs_fs/caching.lo: subversion/libsvn_fs_fs/caching.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_token.h subversion/include/svn_cache_config.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/dag.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/index.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/temp_serializer.h subversion/libsvn_fs_fs/tree.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_fs/dag.lo: subversion/libsvn_fs_fs/dag.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_fs/cached_data.h subversion/libsvn_fs_fs/dag.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/temp_serializer.h subversion/libsvn_fs_fs/transaction.h subversion/svn_private_config.h +subversion/libsvn_fs_fs/dag.lo: subversion/libsvn_fs_fs/dag.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/cached_data.h subversion/libsvn_fs_fs/dag.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/temp_serializer.h subversion/libsvn_fs_fs/transaction.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_fs/dump-index.lo: subversion/libsvn_fs_fs/dump-index.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/index.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/util.h +subversion/libsvn_fs_fs/dump-index.lo: subversion/libsvn_fs_fs/dump-index.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/index.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/util.h subversion/libsvn_fs_x/fs_init.h -subversion/libsvn_fs_fs/fs.lo: subversion/libsvn_fs_fs/fs.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/hotcopy.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/lock.h subversion/libsvn_fs_fs/pack.h subversion/libsvn_fs_fs/recovery.h subversion/libsvn_fs_fs/rep-cache.h subversion/libsvn_fs_fs/revprops.h subversion/libsvn_fs_fs/transaction.h subversion/libsvn_fs_fs/tree.h subversion/libsvn_fs_fs/util.h subversion/libsvn_fs_fs/verify.h subversion/svn_private_config.h +subversion/libsvn_fs_fs/fs.lo: subversion/libsvn_fs_fs/fs.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_fs/hotcopy.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/lock.h subversion/libsvn_fs_fs/pack.h subversion/libsvn_fs_fs/recovery.h subversion/libsvn_fs_fs/rep-cache.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/revprops.h subversion/libsvn_fs_fs/transaction.h subversion/libsvn_fs_fs/tree.h subversion/libsvn_fs_fs/util.h subversion/libsvn_fs_fs/verify.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_fs/fs_fs.lo: subversion/libsvn_fs_fs/fs_fs.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_io_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_fs/cached_data.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/index.h subversion/libsvn_fs_fs/rep-cache.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/revprops.h subversion/libsvn_fs_fs/transaction.h subversion/libsvn_fs_fs/tree.h subversion/libsvn_fs_fs/util.h subversion/svn_private_config.h +subversion/libsvn_fs_fs/fs_fs.lo: subversion/libsvn_fs_fs/fs_fs.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_io_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/cached_data.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/index.h subversion/libsvn_fs_fs/rep-cache.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/revprops.h subversion/libsvn_fs_fs/transaction.h subversion/libsvn_fs_fs/tree.h subversion/libsvn_fs_fs/util.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_fs/hotcopy.lo: subversion/libsvn_fs_fs/hotcopy.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/hotcopy.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/recovery.h subversion/libsvn_fs_fs/rep-cache.h subversion/libsvn_fs_fs/revprops.h subversion/libsvn_fs_fs/util.h subversion/svn_private_config.h +subversion/libsvn_fs_fs/hotcopy.lo: subversion/libsvn_fs_fs/hotcopy.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_fs/hotcopy.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/recovery.h subversion/libsvn_fs_fs/rep-cache.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/revprops.h subversion/libsvn_fs_fs/util.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_fs/id.lo: subversion/libsvn_fs_fs/id.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/index.h subversion/libsvn_fs_fs/rev_file.h +subversion/libsvn_fs_fs/id.lo: subversion/libsvn_fs_fs/id.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/index.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_x/fs_init.h -subversion/libsvn_fs_fs/index.lo: subversion/libsvn_fs_fs/index.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/index.h subversion/libsvn_fs_fs/pack.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/temp_serializer.h subversion/libsvn_fs_fs/util.h subversion/svn_private_config.h +subversion/libsvn_fs_fs/index.lo: subversion/libsvn_fs_fs/index.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/index.h subversion/libsvn_fs_fs/pack.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/temp_serializer.h subversion/libsvn_fs_fs/util.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h subversion/libsvn_fs_fs/load-index.lo: subversion/libsvn_fs_fs/load-index.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/index.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/transaction.h subversion/libsvn_fs_fs/util.h -subversion/libsvn_fs_fs/lock.lo: subversion/libsvn_fs_fs/lock.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/lock.h subversion/libsvn_fs_fs/tree.h subversion/libsvn_fs_fs/util.h subversion/svn_private_config.h +subversion/libsvn_fs_fs/lock.lo: subversion/libsvn_fs_fs/lock.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/lock.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/tree.h subversion/libsvn_fs_fs/util.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_fs/low_level.lo: subversion/libsvn_fs_fs/low_level.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/low_level.h subversion/svn_private_config.h +subversion/libsvn_fs_fs/low_level.lo: subversion/libsvn_fs_fs/low_level.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/low_level.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_fs/pack.lo: subversion/libsvn_fs_fs/pack.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_io_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/index.h subversion/libsvn_fs_fs/low_level.h subversion/libsvn_fs_fs/pack.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/revprops.h subversion/libsvn_fs_fs/temp_serializer.h subversion/libsvn_fs_fs/transaction.h subversion/libsvn_fs_fs/util.h subversion/svn_private_config.h +subversion/libsvn_fs_fs/pack.lo: subversion/libsvn_fs_fs/pack.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_io_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/index.h subversion/libsvn_fs_fs/low_level.h subversion/libsvn_fs_fs/pack.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/revprops.h subversion/libsvn_fs_fs/temp_serializer.h subversion/libsvn_fs_fs/transaction.h subversion/libsvn_fs_fs/util.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_fs/recovery.lo: subversion/libsvn_fs_fs/recovery.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_fs/cached_data.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/index.h subversion/libsvn_fs_fs/low_level.h subversion/libsvn_fs_fs/recovery.h subversion/libsvn_fs_fs/rep-cache.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/revprops.h subversion/libsvn_fs_fs/util.h subversion/svn_private_config.h +subversion/libsvn_fs_fs/recovery.lo: subversion/libsvn_fs_fs/recovery.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/cached_data.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/index.h subversion/libsvn_fs_fs/low_level.h subversion/libsvn_fs_fs/recovery.h subversion/libsvn_fs_fs/rep-cache.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/revprops.h subversion/libsvn_fs_fs/util.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_fs/rep-cache.lo: subversion/libsvn_fs_fs/rep-cache.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/rep-cache-db.h subversion/libsvn_fs_fs/rep-cache.h subversion/svn_private_config.h +subversion/libsvn_fs_fs/rep-cache.lo: subversion/libsvn_fs_fs/rep-cache.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/cached_data.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/rep-cache-db.h subversion/libsvn_fs_fs/rep-cache.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_fs/rev_file.lo: subversion/libsvn_fs_fs/rev_file.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_io_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/index.h subversion/libsvn_fs_fs/low_level.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/util.h subversion/svn_private_config.h +subversion/libsvn_fs_fs/rev_file.lo: subversion/libsvn_fs_fs/rev_file.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_io_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/index.h subversion/libsvn_fs_fs/low_level.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/util.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_fs/revprops.lo: subversion/libsvn_fs_fs/revprops.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/revprops.h subversion/libsvn_fs_fs/util.h subversion/svn_private_config.h +subversion/libsvn_fs_fs/revprops.lo: subversion/libsvn_fs_fs/revprops.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/revprops.h subversion/libsvn_fs_fs/temp_serializer.h subversion/libsvn_fs_fs/util.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_fs/stats.lo: subversion/libsvn_fs_fs/stats.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_fs/cached_data.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/index.h subversion/libsvn_fs_fs/low_level.h subversion/libsvn_fs_fs/pack.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/util.h subversion/svn_private_config.h +subversion/libsvn_fs_fs/stats.lo: subversion/libsvn_fs_fs/stats.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/cached_data.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/index.h subversion/libsvn_fs_fs/low_level.h subversion/libsvn_fs_fs/pack.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/util.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_fs/temp_serializer.lo: subversion/libsvn_fs_fs/temp_serializer.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs_fs/cached_data.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/low_level.h subversion/libsvn_fs_fs/temp_serializer.h +subversion/libsvn_fs_fs/temp_serializer.lo: subversion/libsvn_fs_fs/temp_serializer.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs_fs/cached_data.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/low_level.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/temp_serializer.h -subversion/libsvn_fs_fs/transaction.lo: subversion/libsvn_fs_fs/transaction.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_fs/cached_data.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/index.h subversion/libsvn_fs_fs/lock.h subversion/libsvn_fs_fs/low_level.h subversion/libsvn_fs_fs/rep-cache.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/temp_serializer.h subversion/libsvn_fs_fs/transaction.h subversion/libsvn_fs_fs/tree.h subversion/libsvn_fs_fs/util.h subversion/svn_private_config.h +subversion/libsvn_fs_fs/transaction.lo: subversion/libsvn_fs_fs/transaction.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/cached_data.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/index.h subversion/libsvn_fs_fs/lock.h subversion/libsvn_fs_fs/low_level.h subversion/libsvn_fs_fs/rep-cache.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/temp_serializer.h subversion/libsvn_fs_fs/transaction.h subversion/libsvn_fs_fs/tree.h subversion/libsvn_fs_fs/util.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_fs/tree.lo: subversion/libsvn_fs_fs/tree.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mergeinfo_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_fs/cached_data.h subversion/libsvn_fs_fs/dag.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/lock.h subversion/libsvn_fs_fs/pack.h subversion/libsvn_fs_fs/temp_serializer.h subversion/libsvn_fs_fs/transaction.h subversion/libsvn_fs_fs/tree.h subversion/libsvn_fs_fs/util.h subversion/svn_private_config.h +subversion/libsvn_fs_fs/tree.lo: subversion/libsvn_fs_fs/tree.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mergeinfo_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/cached_data.h subversion/libsvn_fs_fs/dag.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/lock.h subversion/libsvn_fs_fs/pack.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/temp_serializer.h subversion/libsvn_fs_fs/transaction.h subversion/libsvn_fs_fs/tree.h subversion/libsvn_fs_fs/util.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_fs/util.lo: subversion/libsvn_fs_fs/util.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/pack.h subversion/libsvn_fs_fs/util.h subversion/svn_private_config.h +subversion/libsvn_fs_fs/util.lo: subversion/libsvn_fs_fs/util.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/pack.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/util.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_fs/verify.lo: subversion/libsvn_fs_fs/verify.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_fs/cached_data.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/index.h subversion/libsvn_fs_fs/rep-cache.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/util.h subversion/libsvn_fs_fs/verify.h subversion/svn_private_config.h +subversion/libsvn_fs_fs/verify.lo: subversion/libsvn_fs_fs/verify.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/cached_data.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/index.h subversion/libsvn_fs_fs/rep-cache.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/revprops.h subversion/libsvn_fs_fs/util.h subversion/libsvn_fs_fs/verify.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_util/fs-util.lo: subversion/libsvn_fs_util/fs-util.c subversion/include/private/svn_debug.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/svn_private_config.h +subversion/libsvn_fs_util/fs-util.lo: subversion/libsvn_fs_util/fs-util.c subversion/include/private/svn_debug.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h -subversion/libsvn_fs_x/cached_data.lo: subversion/libsvn_fs_x/cached_data.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_io_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_delta/delta.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_x/cached_data.h subversion/libsvn_fs_x/changes.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/low_level.h subversion/libsvn_fs_x/noderevs.h subversion/libsvn_fs_x/pack.h subversion/libsvn_fs_x/reps.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/temp_serializer.h subversion/libsvn_fs_x/util.h subversion/svn_private_config.h +subversion/libsvn_fs_x/batch_fsync.lo: subversion/libsvn_fs_x/batch_fsync.c subversion/include/private/svn_atomic.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_mutex.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs_x/batch_fsync.h subversion/svn_private_config.h -subversion/libsvn_fs_x/caching.lo: subversion/libsvn_fs_x/caching.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_cache_config.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_x/changes.h subversion/libsvn_fs_x/dag.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/noderevs.h subversion/libsvn_fs_x/reps.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/temp_serializer.h subversion/libsvn_fs_x/tree.h subversion/svn_private_config.h +subversion/libsvn_fs_x/cached_data.lo: subversion/libsvn_fs_x/cached_data.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_io_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_delta/delta.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/batch_fsync.h subversion/libsvn_fs_x/cached_data.h subversion/libsvn_fs_x/changes.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_init.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/low_level.h subversion/libsvn_fs_x/noderevs.h subversion/libsvn_fs_x/pack.h subversion/libsvn_fs_x/reps.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/temp_serializer.h subversion/libsvn_fs_x/util.h subversion/svn_private_config.h -subversion/libsvn_fs_x/changes.lo: subversion/libsvn_fs_x/changes.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_packed_data.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs_x/changes.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/string_table.h subversion/libsvn_fs_x/temp_serializer.h subversion/svn_private_config.h +subversion/libsvn_fs_x/caching.lo: subversion/libsvn_fs_x/caching.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_cache_config.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/changes.h subversion/libsvn_fs_x/dag.h subversion/libsvn_fs_x/dag_cache.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_init.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/noderevs.h subversion/libsvn_fs_x/reps.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/temp_serializer.h subversion/svn_private_config.h -subversion/libsvn_fs_x/dag.lo: subversion/libsvn_fs_x/dag.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_x/cached_data.h subversion/libsvn_fs_x/dag.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_id.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/temp_serializer.h subversion/libsvn_fs_x/transaction.h subversion/svn_private_config.h +subversion/libsvn_fs_x/changes.lo: subversion/libsvn_fs_x/changes.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_packed_data.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs_x/changes.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/string_table.h subversion/libsvn_fs_x/temp_serializer.h subversion/svn_private_config.h -subversion/libsvn_fs_x/fs.lo: subversion/libsvn_fs_x/fs.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/hotcopy.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/lock.h subversion/libsvn_fs_x/pack.h subversion/libsvn_fs_x/recovery.h subversion/libsvn_fs_x/rep-cache.h subversion/libsvn_fs_x/revprops.h subversion/libsvn_fs_x/transaction.h subversion/libsvn_fs_x/tree.h subversion/libsvn_fs_x/util.h subversion/libsvn_fs_x/verify.h subversion/svn_private_config.h +subversion/libsvn_fs_x/dag.lo: subversion/libsvn_fs_x/dag.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/cached_data.h subversion/libsvn_fs_x/dag.h subversion/libsvn_fs_x/dag_cache.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_id.h subversion/libsvn_fs_x/fs_init.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/temp_serializer.h subversion/libsvn_fs_x/transaction.h subversion/svn_private_config.h -subversion/libsvn_fs_x/fs_id.lo: subversion/libsvn_fs_x/fs_id.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_x/cached_data.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_id.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/rev_file.h +subversion/libsvn_fs_x/dag_cache.lo: subversion/libsvn_fs_x/dag_cache.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mergeinfo_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/batch_fsync.h subversion/libsvn_fs_x/cached_data.h subversion/libsvn_fs_x/dag.h subversion/libsvn_fs_x/dag_cache.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_id.h subversion/libsvn_fs_x/fs_init.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/lock.h subversion/libsvn_fs_x/pack.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/temp_serializer.h subversion/libsvn_fs_x/transaction.h subversion/libsvn_fs_x/tree.h subversion/libsvn_fs_x/util.h subversion/svn_private_config.h -subversion/libsvn_fs_x/fs_x.lo: subversion/libsvn_fs_x/fs_x.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_x/cached_data.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/rep-cache.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/revprops.h subversion/libsvn_fs_x/transaction.h subversion/libsvn_fs_x/tree.h subversion/libsvn_fs_x/util.h subversion/svn_private_config.h +subversion/libsvn_fs_x/fs.lo: subversion/libsvn_fs_x/fs.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/batch_fsync.h subversion/libsvn_fs_x/dag.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_init.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/hotcopy.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/lock.h subversion/libsvn_fs_x/pack.h subversion/libsvn_fs_x/recovery.h subversion/libsvn_fs_x/rep-cache.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/revprops.h subversion/libsvn_fs_x/transaction.h subversion/libsvn_fs_x/tree.h subversion/libsvn_fs_x/util.h subversion/libsvn_fs_x/verify.h subversion/svn_private_config.h -subversion/libsvn_fs_x/hotcopy.lo: subversion/libsvn_fs_x/hotcopy.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/hotcopy.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/recovery.h subversion/libsvn_fs_x/rep-cache.h subversion/libsvn_fs_x/revprops.h subversion/libsvn_fs_x/transaction.h subversion/libsvn_fs_x/util.h subversion/svn_private_config.h +subversion/libsvn_fs_x/fs_id.lo: subversion/libsvn_fs_x/fs_id.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/cached_data.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_id.h subversion/libsvn_fs_x/fs_init.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/rev_file.h -subversion/libsvn_fs_x/id.lo: subversion/libsvn_fs_x/id.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/util.h +subversion/libsvn_fs_x/fs_x.lo: subversion/libsvn_fs_x/fs_x.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/batch_fsync.h subversion/libsvn_fs_x/cached_data.h subversion/libsvn_fs_x/dag.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_init.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/low_level.h subversion/libsvn_fs_x/rep-cache.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/revprops.h subversion/libsvn_fs_x/transaction.h subversion/libsvn_fs_x/tree.h subversion/libsvn_fs_x/util.h subversion/svn_private_config.h -subversion/libsvn_fs_x/index.lo: subversion/libsvn_fs_x/index.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/pack.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/temp_serializer.h subversion/libsvn_fs_x/util.h subversion/svn_private_config.h +subversion/libsvn_fs_x/hotcopy.lo: subversion/libsvn_fs_x/hotcopy.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/batch_fsync.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_init.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/hotcopy.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/recovery.h subversion/libsvn_fs_x/rep-cache.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/revprops.h subversion/libsvn_fs_x/transaction.h subversion/libsvn_fs_x/util.h subversion/svn_private_config.h -subversion/libsvn_fs_x/lock.lo: subversion/libsvn_fs_x/lock.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/lock.h subversion/libsvn_fs_x/transaction.h subversion/libsvn_fs_x/tree.h subversion/libsvn_fs_x/util.h subversion/svn_private_config.h +subversion/libsvn_fs_x/id.lo: subversion/libsvn_fs_x/id.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs_x/batch_fsync.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/util.h -subversion/libsvn_fs_x/low_level.lo: subversion/libsvn_fs_x/low_level.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_x/cached_data.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/low_level.h subversion/libsvn_fs_x/pack.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/util.h subversion/svn_private_config.h +subversion/libsvn_fs_x/index.lo: subversion/libsvn_fs_x/index.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/batch_fsync.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_init.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/pack.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/temp_serializer.h subversion/libsvn_fs_x/util.h subversion/svn_private_config.h -subversion/libsvn_fs_x/noderevs.lo: subversion/libsvn_fs_x/noderevs.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_packed_data.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/noderevs.h subversion/libsvn_fs_x/string_table.h subversion/libsvn_fs_x/temp_serializer.h subversion/svn_private_config.h +subversion/libsvn_fs_x/lock.lo: subversion/libsvn_fs_x/lock.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/batch_fsync.h subversion/libsvn_fs_x/dag.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_init.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/lock.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/transaction.h subversion/libsvn_fs_x/tree.h subversion/libsvn_fs_x/util.h subversion/svn_private_config.h -subversion/libsvn_fs_x/pack.lo: subversion/libsvn_fs_x/pack.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_x/cached_data.h subversion/libsvn_fs_x/changes.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/low_level.h subversion/libsvn_fs_x/noderevs.h subversion/libsvn_fs_x/pack.h subversion/libsvn_fs_x/reps.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/revprops.h subversion/libsvn_fs_x/temp_serializer.h subversion/libsvn_fs_x/transaction.h subversion/libsvn_fs_x/util.h subversion/svn_private_config.h +subversion/libsvn_fs_x/low_level.lo: subversion/libsvn_fs_x/low_level.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/batch_fsync.h subversion/libsvn_fs_x/cached_data.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_init.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/low_level.h subversion/libsvn_fs_x/pack.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/util.h subversion/svn_private_config.h -subversion/libsvn_fs_x/recovery.lo: subversion/libsvn_fs_x/recovery.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_x/cached_data.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/low_level.h subversion/libsvn_fs_x/recovery.h subversion/libsvn_fs_x/rep-cache.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/revprops.h subversion/libsvn_fs_x/transaction.h subversion/libsvn_fs_x/util.h subversion/svn_private_config.h +subversion/libsvn_fs_x/noderevs.lo: subversion/libsvn_fs_x/noderevs.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_packed_data.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/noderevs.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/string_table.h subversion/libsvn_fs_x/temp_serializer.h subversion/svn_private_config.h -subversion/libsvn_fs_x/rep-cache.lo: subversion/libsvn_fs_x/rep-cache.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/rep-cache-db.h subversion/libsvn_fs_x/rep-cache.h subversion/libsvn_fs_x/util.h subversion/svn_private_config.h +subversion/libsvn_fs_x/pack.lo: subversion/libsvn_fs_x/pack.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/batch_fsync.h subversion/libsvn_fs_x/cached_data.h subversion/libsvn_fs_x/changes.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_init.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/low_level.h subversion/libsvn_fs_x/noderevs.h subversion/libsvn_fs_x/pack.h subversion/libsvn_fs_x/reps.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/revprops.h subversion/libsvn_fs_x/temp_serializer.h subversion/libsvn_fs_x/transaction.h subversion/libsvn_fs_x/util.h subversion/svn_private_config.h + +subversion/libsvn_fs_x/recovery.lo: subversion/libsvn_fs_x/recovery.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/batch_fsync.h subversion/libsvn_fs_x/cached_data.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_init.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/low_level.h subversion/libsvn_fs_x/recovery.h subversion/libsvn_fs_x/rep-cache.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/revprops.h subversion/libsvn_fs_x/transaction.h subversion/libsvn_fs_x/util.h subversion/svn_private_config.h + +subversion/libsvn_fs_x/rep-cache.lo: subversion/libsvn_fs_x/rep-cache.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/batch_fsync.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_init.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/rep-cache-db.h subversion/libsvn_fs_x/rep-cache.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/util.h subversion/svn_private_config.h subversion/libsvn_fs_x/reps.lo: subversion/libsvn_fs_x/reps.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_packed_data.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs_x/cached_data.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/reps.h subversion/libsvn_fs_x/rev_file.h subversion/svn_private_config.h -subversion/libsvn_fs_x/rev_file.lo: subversion/libsvn_fs_x/rev_file.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_io_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/low_level.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/util.h subversion/svn_private_config.h +subversion/libsvn_fs_x/rev_file.lo: subversion/libsvn_fs_x/rev_file.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_io_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/batch_fsync.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_init.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/low_level.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/util.h subversion/svn_private_config.h -subversion/libsvn_fs_x/revprops.lo: subversion/libsvn_fs_x/revprops.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/revprops.h subversion/libsvn_fs_x/transaction.h subversion/libsvn_fs_x/util.h subversion/svn_private_config.h +subversion/libsvn_fs_x/revprops.lo: subversion/libsvn_fs_x/revprops.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_packed_data.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/batch_fsync.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_init.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/low_level.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/revprops.h subversion/libsvn_fs_x/transaction.h subversion/libsvn_fs_x/util.h subversion/svn_private_config.h subversion/libsvn_fs_x/string_table.lo: subversion/libsvn_fs_x/string_table.c subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_packed_data.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_temp_serializer.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs_x/string_table.h subversion/libsvn_fs_x/temp_serializer.lo: subversion/libsvn_fs_x/temp_serializer.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs_x/cached_data.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/low_level.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/temp_serializer.h -subversion/libsvn_fs_x/transaction.lo: subversion/libsvn_fs_x/transaction.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_fspath.h subversion/include/private/svn_io_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_x/cached_data.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/lock.h subversion/libsvn_fs_x/low_level.h subversion/libsvn_fs_x/rep-cache.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/temp_serializer.h subversion/libsvn_fs_x/transaction.h subversion/libsvn_fs_x/tree.h subversion/libsvn_fs_x/util.h subversion/svn_private_config.h +subversion/libsvn_fs_x/transaction.lo: subversion/libsvn_fs_x/transaction.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_fspath.h subversion/include/private/svn_io_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/batch_fsync.h subversion/libsvn_fs_x/cached_data.h subversion/libsvn_fs_x/dag.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_init.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/lock.h subversion/libsvn_fs_x/low_level.h subversion/libsvn_fs_x/rep-cache.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/revprops.h subversion/libsvn_fs_x/temp_serializer.h subversion/libsvn_fs_x/transaction.h subversion/libsvn_fs_x/tree.h subversion/libsvn_fs_x/util.h subversion/svn_private_config.h -subversion/libsvn_fs_x/tree.lo: subversion/libsvn_fs_x/tree.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mergeinfo_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_x/cached_data.h subversion/libsvn_fs_x/dag.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_id.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/lock.h subversion/libsvn_fs_x/pack.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/temp_serializer.h subversion/libsvn_fs_x/transaction.h subversion/libsvn_fs_x/tree.h subversion/libsvn_fs_x/util.h subversion/svn_private_config.h +subversion/libsvn_fs_x/tree.lo: subversion/libsvn_fs_x/tree.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mergeinfo_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_temp_serializer.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/batch_fsync.h subversion/libsvn_fs_x/cached_data.h subversion/libsvn_fs_x/dag.h subversion/libsvn_fs_x/dag_cache.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_id.h subversion/libsvn_fs_x/fs_init.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/lock.h subversion/libsvn_fs_x/pack.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/temp_serializer.h subversion/libsvn_fs_x/transaction.h subversion/libsvn_fs_x/tree.h subversion/libsvn_fs_x/util.h subversion/svn_private_config.h -subversion/libsvn_fs_x/util.lo: subversion/libsvn_fs_x/util.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/util.h subversion/svn_private_config.h +subversion/libsvn_fs_x/util.lo: subversion/libsvn_fs_x/util.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/batch_fsync.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_init.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/util.h subversion/svn_private_config.h -subversion/libsvn_fs_x/verify.lo: subversion/libsvn_fs_x/verify.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_x/cached_data.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/rep-cache.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/util.h subversion/libsvn_fs_x/verify.h subversion/svn_private_config.h +subversion/libsvn_fs_x/verify.lo: subversion/libsvn_fs_x/verify.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_token.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/batch_fsync.h subversion/libsvn_fs_x/cached_data.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/fs_init.h subversion/libsvn_fs_x/fs_x.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/index.h subversion/libsvn_fs_x/rep-cache.h subversion/libsvn_fs_x/rev_file.h subversion/libsvn_fs_x/revprops.h subversion/libsvn_fs_x/util.h subversion/libsvn_fs_x/verify.h subversion/svn_private_config.h subversion/libsvn_ra/compat.lo: subversion/libsvn_ra/compat.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_ra_private.h subversion/include/private/svn_sorts_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_compat.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_ra/ra_loader.h subversion/svn_private_config.h @@ -2724,7 +2831,7 @@ subversion/libsvn_ra/ra_loader.lo: subversion/libsvn_ra/ra_loader.c subversion/i subversion/libsvn_ra/util.lo: subversion/libsvn_ra/util.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_ra_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/svn_private_config.h -subversion/libsvn_ra_local/ra_plugin.lo: subversion/libsvn_ra_local/ra_plugin.c subversion/include/private/svn_atomic.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mergeinfo_private.h subversion/include/private/svn_ra_private.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_cache_config.h subversion/include/svn_checksum.h subversion/include/svn_compat.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_ra/ra_loader.h subversion/libsvn_ra/wrapper_template.h subversion/libsvn_ra_local/ra_local.h subversion/svn_private_config.h +subversion/libsvn_ra_local/ra_plugin.lo: subversion/libsvn_ra_local/ra_plugin.c subversion/include/private/svn_atomic.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mergeinfo_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_ra_private.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_cache_config.h subversion/include/svn_checksum.h subversion/include/svn_compat.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_ra/ra_loader.h subversion/libsvn_ra/wrapper_template.h subversion/libsvn_ra_local/ra_local.h subversion/svn_private_config.h subversion/libsvn_ra_local/split_url.lo: subversion/libsvn_ra_local/split_url.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_ra.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_ra_local/ra_local.h subversion/svn_private_config.h @@ -2752,6 +2859,8 @@ subversion/libsvn_ra_serf/getlocks.lo: subversion/libsvn_ra_serf/getlocks.c subv subversion/libsvn_ra_serf/inherited_props.lo: subversion/libsvn_ra_serf/inherited_props.c subversion/include/private/svn_dav_protocol.h subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_ra_private.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_base64.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_dav.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/include/svn_xml.h subversion/libsvn_ra/ra_loader.h subversion/libsvn_ra_serf/blncache.h subversion/libsvn_ra_serf/ra_serf.h subversion/svn_private_config.h +subversion/libsvn_ra_serf/list.lo: subversion/libsvn_ra_serf/list.c subversion/include/private/svn_dav_protocol.h subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_ra_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_base64.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_dav.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/include/svn_xml.h subversion/libsvn_ra/ra_loader.h subversion/libsvn_ra_serf/blncache.h subversion/libsvn_ra_serf/ra_serf.h subversion/svn_private_config.h + subversion/libsvn_ra_serf/lock.lo: subversion/libsvn_ra_serf/lock.c subversion/include/private/svn_dav_protocol.h subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_ra_private.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_dav.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_ra/ra_loader.h subversion/libsvn_ra_serf/blncache.h subversion/libsvn_ra_serf/ra_serf.h subversion/svn_private_config.h subversion/libsvn_ra_serf/log.lo: subversion/libsvn_ra_serf/log.c subversion/include/private/svn_dav_protocol.h subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_ra_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_base64.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_dav.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/include/svn_xml.h subversion/libsvn_ra/ra_loader.h subversion/libsvn_ra_serf/blncache.h subversion/libsvn_ra_serf/ra_serf.h subversion/svn_private_config.h @@ -2768,12 +2877,16 @@ subversion/libsvn_ra_serf/property.lo: subversion/libsvn_ra_serf/property.c subv subversion/libsvn_ra_serf/replay.lo: subversion/libsvn_ra_serf/replay.c subversion/include/private/svn_dav_protocol.h subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_ra_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_base64.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_dav.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/include/svn_xml.h subversion/libsvn_ra/ra_loader.h subversion/libsvn_ra_serf/blncache.h subversion/libsvn_ra_serf/ra_serf.h subversion/svn_private_config.h +subversion/libsvn_ra_serf/request_body.lo: subversion/libsvn_ra_serf/request_body.c subversion/include/private/svn_dav_protocol.h subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_dav.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_ra_serf/blncache.h subversion/libsvn_ra_serf/ra_serf.h + subversion/libsvn_ra_serf/sb_bucket.lo: subversion/libsvn_ra_serf/sb_bucket.c subversion/include/private/svn_dav_protocol.h subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_dav.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_ra_serf/blncache.h subversion/libsvn_ra_serf/ra_serf.h subversion/svn_private_config.h subversion/libsvn_ra_serf/serf.lo: subversion/libsvn_ra_serf/serf.c subversion/include/private/svn_dav_protocol.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_ra_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_compat.h subversion/include/svn_config.h subversion/include/svn_dav.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/include/svn_xml.h subversion/libsvn_ra/ra_loader.h subversion/libsvn_ra/wrapper_template.h subversion/libsvn_ra_serf/blncache.h subversion/libsvn_ra_serf/ra_serf.h subversion/svn_private_config.h subversion/libsvn_ra_serf/stat.lo: subversion/libsvn_ra_serf/stat.c subversion/include/private/svn_dav_protocol.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_ra_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_dav.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/include/svn_xml.h subversion/libsvn_ra/ra_loader.h subversion/libsvn_ra_serf/blncache.h subversion/libsvn_ra_serf/ra_serf.h subversion/svn_private_config.h +subversion/libsvn_ra_serf/stream_bucket.lo: subversion/libsvn_ra_serf/stream_bucket.c subversion/include/private/svn_dav_protocol.h subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_dav.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_ra_serf/blncache.h subversion/libsvn_ra_serf/ra_serf.h + subversion/libsvn_ra_serf/update.lo: subversion/libsvn_ra_serf/update.c subversion/include/private/svn_dav_protocol.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_ra_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_base64.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_dav.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/include/svn_xml.h subversion/libsvn_ra/ra_loader.h subversion/libsvn_ra_serf/blncache.h subversion/libsvn_ra_serf/ra_serf.h subversion/svn_private_config.h subversion/libsvn_ra_serf/util.lo: subversion/libsvn_ra_serf/util.c subversion/include/private/svn_auth_private.h subversion/include/private/svn_cert.h subversion/include/private/svn_dav_protocol.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_ra_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_dav.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_ra/ra_loader.h subversion/libsvn_ra_serf/blncache.h subversion/libsvn_ra_serf/ra_serf.h subversion/svn_private_config.h @@ -2782,15 +2895,15 @@ subversion/libsvn_ra_serf/util_error.lo: subversion/libsvn_ra_serf/util_error.c subversion/libsvn_ra_serf/xml.lo: subversion/libsvn_ra_serf/xml.c subversion/include/private/svn_dav_protocol.h subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_ra_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_dav.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/include/svn_xml.h subversion/libsvn_ra/ra_loader.h subversion/libsvn_ra_serf/blncache.h subversion/libsvn_ra_serf/ra_serf.h subversion/svn_private_config.h -subversion/libsvn_ra_svn/client.lo: subversion/libsvn_ra_svn/client.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_ra_private.h subversion/include/private/svn_ra_svn_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_compat.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_ra_svn.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_ra/ra_loader.h subversion/libsvn_ra/wrapper_template.h subversion/libsvn_ra_svn/ra_svn.h subversion/svn_private_config.h +subversion/libsvn_ra_svn/client.lo: subversion/libsvn_ra_svn/client.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_ra_private.h subversion/include/private/svn_ra_svn_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_compat.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_ra_svn.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_ra/ra_loader.h subversion/libsvn_ra/wrapper_template.h subversion/libsvn_ra_svn/ra_svn.h subversion/svn_private_config.h subversion/libsvn_ra_svn/cram.lo: subversion/libsvn_ra_svn/cram.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_ra_svn_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_ra.h subversion/include/svn_ra_svn.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_ra_svn/ra_svn.h subversion/svn_private_config.h -subversion/libsvn_ra_svn/cyrus_auth.lo: subversion/libsvn_ra_svn/cyrus_auth.c subversion/include/private/ra_svn_sasl.h subversion/include/private/svn_atomic.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_mutex.h subversion/include/private/svn_ra_svn_private.h subversion/include/svn_auth.h subversion/include/svn_base64.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_ra_svn.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_ra_svn/ra_svn.h subversion/svn_private_config.h +subversion/libsvn_ra_svn/cyrus_auth.lo: subversion/libsvn_ra_svn/cyrus_auth.c subversion/include/private/ra_svn_sasl.h subversion/include/private/ra_svn_wrapped_sasl.h subversion/include/private/svn_atomic.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_mutex.h subversion/include/private/svn_ra_svn_private.h subversion/include/svn_auth.h subversion/include/svn_base64.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_ra_svn.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_ra_svn/ra_svn.h subversion/svn_private_config.h subversion/libsvn_ra_svn/deprecated.lo: subversion/libsvn_ra_svn/deprecated.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_ra_svn_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_ra_svn.h subversion/include/svn_string.h subversion/include/svn_types.h -subversion/libsvn_ra_svn/editorp.lo: subversion/libsvn_ra_svn/editorp.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_ra_svn_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_ra_svn.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_ra_svn/ra_svn.h subversion/svn_private_config.h +subversion/libsvn_ra_svn/editorp.lo: subversion/libsvn_ra_svn/editorp.c subversion/include/private/svn_atomic.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_ra_svn_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_ra_svn.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_ra_svn/ra_svn.h subversion/svn_private_config.h subversion/libsvn_ra_svn/internal_auth.lo: subversion/libsvn_ra_svn/internal_auth.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_ra_svn_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_ra.h subversion/include/svn_ra_svn.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_ra_svn/ra_svn.h subversion/svn_private_config.h @@ -2800,45 +2913,55 @@ subversion/libsvn_ra_svn/streams.lo: subversion/libsvn_ra_svn/streams.c subversi subversion/libsvn_ra_svn/version.lo: subversion/libsvn_ra_svn/version.c subversion/include/private/svn_debug.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_ra_svn.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h -subversion/libsvn_repos/authz.lo: subversion/libsvn_repos/authz.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_repos/repos.h +subversion/libsvn_ra_svn/wrapped_sasl.lo: subversion/libsvn_ra_svn/wrapped_sasl.c subversion/include/private/ra_svn_wrapped_sasl.h subversion/svn_private_config.h -subversion/libsvn_repos/authz_pool.lo: subversion/libsvn_repos/authz_pool.c subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_repos/repos.h +subversion/libsvn_repos/authz.lo: subversion/libsvn_repos/authz.c subversion/include/private/svn_atomic.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_repos.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_repos/authz.h subversion/libsvn_repos/config_file.h subversion/libsvn_repos/repos.h -subversion/libsvn_repos/commit.lo: subversion/libsvn_repos/commit.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fspath.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/svn_checksum.h subversion/include/svn_compat.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_repos/repos.h subversion/svn_private_config.h +subversion/libsvn_repos/authz_info.lo: subversion/libsvn_repos/authz_info.c subversion/include/private/svn_debug.h subversion/include/private/svn_string_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_repos/authz.h subversion/svn_private_config.h -subversion/libsvn_repos/config_pool.lo: subversion/libsvn_repos/config_pool.c subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/svn_private_config.h +subversion/libsvn_repos/authz_parse.lo: subversion/libsvn_repos/authz_parse.c subversion/include/private/svn_config_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_fspath.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_repos.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_repos/authz.h subversion/svn_private_config.h -subversion/libsvn_repos/delta.lo: subversion/libsvn_repos/delta.c subversion/include/private/svn_debug.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_repos/repos.h subversion/svn_private_config.h +subversion/libsvn_repos/commit.lo: subversion/libsvn_repos/commit.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/svn_checksum.h subversion/include/svn_compat.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_repos/repos.h subversion/svn_private_config.h -subversion/libsvn_repos/deprecated.lo: subversion/libsvn_repos/deprecated.c subversion/include/private/svn_debug.h subversion/include/svn_checksum.h subversion/include/svn_compat.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_repos/repos.h subversion/svn_private_config.h +subversion/libsvn_repos/compat.lo: subversion/libsvn_repos/compat.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_compat.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_repos/repos.h subversion/svn_private_config.h -subversion/libsvn_repos/dump.lo: subversion/libsvn_repos/dump.c subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mergeinfo_private.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_utf_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/svn_private_config.h +subversion/libsvn_repos/config_file.lo: subversion/libsvn_repos/config_file.c subversion/include/private/svn_config_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_repos/config_file.h subversion/svn_private_config.h -subversion/libsvn_repos/fs-wrap.lo: subversion/libsvn_repos/fs-wrap.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_utf_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/libsvn_repos/repos.h subversion/svn_private_config.h +subversion/libsvn_repos/config_pool.lo: subversion/libsvn_repos/config_pool.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_repos/config_file.h subversion/svn_private_config.h -subversion/libsvn_repos/hooks.lo: subversion/libsvn_repos/hooks.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/libsvn_repos/repos.h subversion/svn_private_config.h +subversion/libsvn_repos/delta.lo: subversion/libsvn_repos/delta.c subversion/include/private/svn_debug.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_repos/repos.h subversion/svn_private_config.h -subversion/libsvn_repos/load-fs-vtable.lo: subversion/libsvn_repos/load-fs-vtable.c subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mergeinfo_private.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_types.h subversion/libsvn_repos/repos.h subversion/svn_private_config.h +subversion/libsvn_repos/deprecated.lo: subversion/libsvn_repos/deprecated.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_compat.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_repos/repos.h subversion/svn_private_config.h -subversion/libsvn_repos/load.lo: subversion/libsvn_repos/load.c subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/svn_checksum.h subversion/include/svn_ctype.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_repos/repos.h subversion/svn_private_config.h +subversion/libsvn_repos/dump.lo: subversion/libsvn_repos/dump.c subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mergeinfo_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_utf_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/svn_private_config.h -subversion/libsvn_repos/log.lo: subversion/libsvn_repos/log.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mergeinfo_private.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_compat.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_repos/repos.h subversion/svn_private_config.h +subversion/libsvn_repos/fs-wrap.lo: subversion/libsvn_repos/fs-wrap.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_utf_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/libsvn_repos/repos.h subversion/svn_private_config.h -subversion/libsvn_repos/node_tree.lo: subversion/libsvn_repos/node_tree.c subversion/include/private/svn_debug.h subversion/include/private/svn_fspath.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_repos/repos.h subversion/svn_private_config.h +subversion/libsvn_repos/hooks.lo: subversion/libsvn_repos/hooks.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/libsvn_repos/repos.h subversion/svn_private_config.h -subversion/libsvn_repos/notify.lo: subversion/libsvn_repos/notify.c subversion/include/private/svn_debug.h subversion/include/private/svn_string_private.h subversion/include/private/svn_utf_private.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_repos/repos.h subversion/svn_private_config.h +subversion/libsvn_repos/list.lo: subversion/libsvn_repos/list.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_utf_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_repos.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/libsvn_repos/repos.h subversion/svn_private_config.h -subversion/libsvn_repos/replay.lo: subversion/libsvn_repos/replay.c subversion/include/private/svn_debug.h subversion/include/private/svn_delta_private.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_string_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/svn_private_config.h +subversion/libsvn_repos/load-fs-vtable.lo: subversion/libsvn_repos/load-fs-vtable.c subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mergeinfo_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_types.h subversion/libsvn_repos/repos.h subversion/svn_private_config.h + +subversion/libsvn_repos/load.lo: subversion/libsvn_repos/load.c subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_repos/repos.h subversion/svn_private_config.h + +subversion/libsvn_repos/log.lo: subversion/libsvn_repos/log.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mergeinfo_private.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_compat.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_repos/repos.h subversion/svn_private_config.h + +subversion/libsvn_repos/node_tree.lo: subversion/libsvn_repos/node_tree.c subversion/include/private/svn_debug.h subversion/include/private/svn_fspath.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_repos/repos.h subversion/svn_private_config.h + +subversion/libsvn_repos/notify.lo: subversion/libsvn_repos/notify.c subversion/include/private/svn_debug.h subversion/include/private/svn_string_private.h subversion/include/private/svn_utf_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_repos/repos.h subversion/svn_private_config.h + +subversion/libsvn_repos/replay.lo: subversion/libsvn_repos/replay.c subversion/include/private/svn_debug.h subversion/include/private/svn_delta_private.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_string_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/svn_private_config.h subversion/libsvn_repos/reporter.lo: subversion/libsvn_repos/reporter.c subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_fspath.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_repos/repos.h subversion/svn_private_config.h -subversion/libsvn_repos/repos.lo: subversion/libsvn_repos/repos.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/libsvn_repos/repos.h subversion/svn_private_config.h +subversion/libsvn_repos/repos.lo: subversion/libsvn_repos/repos.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/libsvn_repos/repos.h subversion/svn_private_config.h -subversion/libsvn_repos/rev_hunt.lo: subversion/libsvn_repos/rev_hunt.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fspath.h subversion/include/private/svn_sorts_private.h subversion/include/svn_checksum.h subversion/include/svn_compat.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/libsvn_repos/repos.h subversion/svn_private_config.h +subversion/libsvn_repos/rev_hunt.lo: subversion/libsvn_repos/rev_hunt.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fspath.h subversion/include/private/svn_sorts_private.h subversion/include/svn_checksum.h subversion/include/svn_compat.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/libsvn_repos/repos.h subversion/svn_private_config.h subversion/libsvn_subr/adler32.lo: subversion/libsvn_subr/adler32.c subversion/include/private/svn_adler32.h -subversion/libsvn_subr/atomic.lo: subversion/libsvn_subr/atomic.c subversion/include/private/svn_atomic.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_types.h +subversion/libsvn_subr/atomic.lo: subversion/libsvn_subr/atomic.c subversion/include/private/svn_atomic.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_mutex.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_pools.h subversion/include/svn_types.h subversion/libsvn_subr/auth.lo: subversion/libsvn_subr/auth.c subversion/include/private/svn_auth_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_dso.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_subr/auth.h subversion/svn_private_config.h @@ -2848,10 +2971,12 @@ subversion/libsvn_subr/bit_array.lo: subversion/libsvn_subr/bit_array.c subversi subversion/libsvn_subr/cache-inprocess.lo: subversion/libsvn_subr/cache-inprocess.c subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_subr/cache.h subversion/svn_private_config.h -subversion/libsvn_subr/cache-membuffer.lo: subversion/libsvn_subr/cache-membuffer.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_mutex.h subversion/include/private/svn_string_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_pools.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_subr/cache.h subversion/libsvn_subr/fnv1a.h subversion/svn_private_config.h +subversion/libsvn_subr/cache-membuffer.lo: subversion/libsvn_subr/cache-membuffer.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_mutex.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_pools.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_subr/cache.h subversion/libsvn_subr/fnv1a.h subversion/svn_private_config.h subversion/libsvn_subr/cache-memcache.lo: subversion/libsvn_subr/cache-memcache.c subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/svn_base64.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_subr/cache.h subversion/svn_private_config.h +subversion/libsvn_subr/cache-null.lo: subversion/libsvn_subr/cache-null.c subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_subr/cache.h subversion/svn_private_config.h + subversion/libsvn_subr/cache.lo: subversion/libsvn_subr/cache.c subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_subr/cache.h subversion/libsvn_subr/cache_config.lo: subversion/libsvn_subr/cache_config.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/svn_cache_config.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_pools.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h @@ -2862,13 +2987,15 @@ subversion/libsvn_subr/cmdline.lo: subversion/libsvn_subr/cmdline.c subversion/i subversion/libsvn_subr/compat.lo: subversion/libsvn_subr/compat.c subversion/include/private/svn_debug.h subversion/include/svn_checksum.h subversion/include/svn_compat.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h -subversion/libsvn_subr/compress.lo: subversion/libsvn_subr/compress.c subversion/include/private/svn_debug.h subversion/include/private/svn_error_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/svn_private_config.h +subversion/libsvn_subr/compress_lz4.lo: subversion/libsvn_subr/compress_lz4.c subversion/include/private/svn_debug.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_subr/lz4/lz4internal.h subversion/svn_private_config.h -subversion/libsvn_subr/config.lo: subversion/libsvn_subr/config.c subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_subr/config_impl.h subversion/svn_private_config.h +subversion/libsvn_subr/compress_zlib.lo: subversion/libsvn_subr/compress_zlib.c subversion/include/private/svn_debug.h subversion/include/private/svn_error_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/svn_private_config.h + +subversion/libsvn_subr/config.lo: subversion/libsvn_subr/config.c subversion/include/private/svn_config_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_subr/config_impl.h subversion/svn_private_config.h subversion/libsvn_subr/config_auth.lo: subversion/libsvn_subr/config_auth.c subversion/include/private/svn_auth_private.h subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_subr/auth.h subversion/libsvn_subr/config_impl.h subversion/svn_private_config.h -subversion/libsvn_subr/config_file.lo: subversion/libsvn_subr/config_file.c subversion/include/private/svn_debug.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_types.h subversion/include/svn_user.h subversion/include/svn_utf.h subversion/libsvn_subr/config_impl.h subversion/svn_private_config.h +subversion/libsvn_subr/config_file.lo: subversion/libsvn_subr/config_file.c subversion/include/private/svn_config_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_types.h subversion/include/svn_user.h subversion/include/svn_utf.h subversion/libsvn_subr/config_impl.h subversion/svn_private_config.h subversion/libsvn_subr/config_win.lo: subversion/libsvn_subr/config_win.c subversion/include/private/svn_debug.h subversion/include/private/svn_string_private.h subversion/include/private/svn_utf_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/libsvn_subr/config_impl.h subversion/svn_private_config.h @@ -2880,15 +3007,17 @@ subversion/libsvn_subr/date.lo: subversion/libsvn_subr/date.c subversion/include subversion/libsvn_subr/debug.lo: subversion/libsvn_subr/debug.c subversion/include/private/svn_debug.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_string.h subversion/include/svn_types.h -subversion/libsvn_subr/deprecated.lo: subversion/libsvn_subr/deprecated.c subversion/include/private/svn_debug.h subversion/include/private/svn_mergeinfo_private.h subversion/include/private/svn_opt_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_dirent_uri.h subversion/include/svn_dso.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/include/svn_xml.h subversion/libsvn_subr/auth.h subversion/libsvn_subr/opt.h subversion/svn_private_config.h +subversion/libsvn_subr/deprecated.lo: subversion/libsvn_subr/deprecated.c subversion/include/private/svn_debug.h subversion/include/private/svn_mergeinfo_private.h subversion/include/private/svn_opt_private.h subversion/include/svn_auth.h subversion/include/svn_base64.h subversion/include/svn_checksum.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_dirent_uri.h subversion/include/svn_dso.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/include/svn_xml.h subversion/libsvn_subr/auth.h subversion/libsvn_subr/opt.h subversion/svn_private_config.h subversion/libsvn_subr/dirent_uri.lo: subversion/libsvn_subr/dirent_uri.c subversion/include/private/svn_cert.h subversion/include/private/svn_debug.h subversion/include/private/svn_fspath.h subversion/include/svn_ctype.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_path.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_subr/dirent_uri.h subversion/svn_private_config.h subversion/libsvn_subr/dso.lo: subversion/libsvn_subr/dso.c subversion/include/private/svn_atomic.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_mutex.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_dso.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/svn_private_config.h +subversion/libsvn_subr/encode.lo: subversion/libsvn_subr/encode.c subversion/include/private/svn_debug.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/svn_private_config.h + subversion/libsvn_subr/eol.lo: subversion/libsvn_subr/eol.c subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_eol_private.h subversion/include/svn_checksum.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_string.h subversion/include/svn_types.h -subversion/libsvn_subr/error.lo: subversion/libsvn_subr/error.c subversion/include/private/svn_debug.h subversion/include/private/svn_error_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/svn_private_config.h +subversion/libsvn_subr/error.lo: subversion/libsvn_subr/error.c subversion/include/private/svn_atomic.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_error_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/libsvn_subr/pools.h subversion/svn_private_config.h subversion/libsvn_subr/fnv1a.lo: subversion/libsvn_subr/fnv1a.c subversion/include/private/svn_debug.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_subr/fnv1a.h @@ -2904,6 +3033,8 @@ subversion/libsvn_subr/lock.lo: subversion/libsvn_subr/lock.c subversion/include subversion/libsvn_subr/log.lo: subversion/libsvn_subr/log.c subversion/include/private/svn_debug.h subversion/include/private/svn_log.h subversion/include/svn_checksum.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h +subversion/libsvn_subr/lz4/lz4.lo: subversion/libsvn_subr/lz4/lz4.c subversion/libsvn_subr/lz4/lz4internal.h subversion/svn_private_config.h + subversion/libsvn_subr/macos_keychain.lo: subversion/libsvn_subr/macos_keychain.c subversion/include/private/svn_auth_private.h subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_user.h subversion/include/svn_utf.h subversion/libsvn_subr/auth.h subversion/svn_private_config.h subversion/libsvn_subr/magic.lo: subversion/libsvn_subr/magic.c subversion/include/private/svn_debug.h subversion/include/private/svn_magic.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/svn_private_config.h @@ -2924,7 +3055,7 @@ subversion/libsvn_subr/packed_data.lo: subversion/libsvn_subr/packed_data.c subv subversion/libsvn_subr/path.lo: subversion/libsvn_subr/path.c subversion/include/private/svn_debug.h subversion/include/svn_checksum.h subversion/include/svn_ctype.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_path.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/libsvn_subr/dirent_uri.h subversion/svn_private_config.h -subversion/libsvn_subr/pool.lo: subversion/libsvn_subr/pool.c subversion/include/private/svn_debug.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_pools.h subversion/include/svn_types.h +subversion/libsvn_subr/pool.lo: subversion/libsvn_subr/pool.c subversion/include/private/svn_debug.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_pools.h subversion/include/svn_types.h subversion/libsvn_subr/pools.h subversion/libsvn_subr/prefix_string.lo: subversion/libsvn_subr/prefix_string.c subversion/include/private/svn_debug.h subversion/include/private/svn_string_private.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_string.h subversion/include/svn_types.h @@ -2954,7 +3085,7 @@ subversion/libsvn_subr/ssl_client_cert_pw_providers.lo: subversion/libsvn_subr/s subversion/libsvn_subr/ssl_server_trust_providers.lo: subversion/libsvn_subr/ssl_server_trust_providers.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_string.h subversion/include/svn_types.h -subversion/libsvn_subr/stream.lo: subversion/libsvn_subr/stream.c subversion/include/private/svn_atomic.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_eol_private.h subversion/include/private/svn_error_private.h subversion/include/private/svn_io_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_utf_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/svn_private_config.h +subversion/libsvn_subr/stream.lo: subversion/libsvn_subr/stream.c subversion/include/private/svn_atomic.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_eol_private.h subversion/include/private/svn_error_private.h subversion/include/private/svn_io_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_utf_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/svn_private_config.h subversion/libsvn_subr/string.lo: subversion/libsvn_subr/string.c subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_string_private.h subversion/include/svn_ctype.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/svn_private_config.h @@ -2972,13 +3103,13 @@ subversion/libsvn_subr/token.lo: subversion/libsvn_subr/token.c subversion/inclu subversion/libsvn_subr/types.lo: subversion/libsvn_subr/types.c subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_string_private.h subversion/include/svn_checksum.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_props.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/svn_private_config.h -subversion/libsvn_subr/user.lo: subversion/libsvn_subr/user.c subversion/include/private/svn_debug.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_user.h subversion/include/svn_utf.h +subversion/libsvn_subr/user.lo: subversion/libsvn_subr/user.c subversion/include/private/svn_debug.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_user.h subversion/include/svn_utf.h subversion/libsvn_subr/username_providers.lo: subversion/libsvn_subr/username_providers.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_user.h subversion/include/svn_utf.h subversion/libsvn_subr/utf.lo: subversion/libsvn_subr/utf.c subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_mutex.h subversion/include/private/svn_string_private.h subversion/include/private/svn_utf_private.h subversion/include/svn_checksum.h subversion/include/svn_ctype.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/libsvn_subr/win32_xlate.h subversion/svn_private_config.h -subversion/libsvn_subr/utf8proc.lo: subversion/libsvn_subr/utf8proc.c subversion/include/private/svn_debug.h subversion/include/private/svn_string_private.h subversion/include/private/svn_utf_private.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_subr/utf8proc/utf8proc.c subversion/libsvn_subr/utf8proc/utf8proc.h subversion/libsvn_subr/utf8proc/utf8proc_data.c subversion/svn_private_config.h +subversion/libsvn_subr/utf8proc.lo: subversion/libsvn_subr/utf8proc.c subversion/include/private/svn_debug.h subversion/include/private/svn_string_private.h subversion/include/private/svn_utf_private.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_subr/utf8proc/utf8proc.c subversion/libsvn_subr/utf8proc/utf8proc_data.c subversion/libsvn_subr/utf8proc/utf8proc_internal.h subversion/svn_private_config.h subversion/libsvn_subr/utf_validate.lo: subversion/libsvn_subr/utf_validate.c subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_eol_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_utf_private.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_string.h subversion/include/svn_types.h @@ -3010,7 +3141,7 @@ subversion/libsvn_wc/ambient_depth_filter_editor.lo: subversion/libsvn_wc/ambien subversion/libsvn_wc/cleanup.lo: subversion/libsvn_wc/cleanup.c subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_skel.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_wc/adm_files.h subversion/libsvn_wc/lock.h subversion/libsvn_wc/props.h subversion/libsvn_wc/wc.h subversion/libsvn_wc/wc_db.h subversion/libsvn_wc/workqueue.h subversion/svn_private_config.h -subversion/libsvn_wc/conflicts.lo: subversion/libsvn_wc/conflicts.c subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_skel.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_token.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_wc/conflicts.h subversion/libsvn_wc/props.h subversion/libsvn_wc/wc.h subversion/libsvn_wc/wc_db.h subversion/libsvn_wc/workqueue.h subversion/svn_private_config.h +subversion/libsvn_wc/conflicts.lo: subversion/libsvn_wc/conflicts.c subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_skel.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_token.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_wc/conflicts.h subversion/libsvn_wc/props.h subversion/libsvn_wc/wc.h subversion/libsvn_wc/wc_db.h subversion/libsvn_wc/workqueue.h subversion/svn_private_config.h subversion/libsvn_wc/context.lo: subversion/libsvn_wc/context.c subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_skel.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_wc/wc.h subversion/libsvn_wc/wc_db.h subversion/svn_private_config.h @@ -3020,7 +3151,7 @@ subversion/libsvn_wc/crop.lo: subversion/libsvn_wc/crop.c subversion/include/pri subversion/libsvn_wc/delete.lo: subversion/libsvn_wc/delete.c subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_skel.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_wc/adm_files.h subversion/libsvn_wc/conflicts.h subversion/libsvn_wc/props.h subversion/libsvn_wc/wc.h subversion/libsvn_wc/wc_db.h subversion/libsvn_wc/workqueue.h subversion/svn_private_config.h -subversion/libsvn_wc/deprecated.lo: subversion/libsvn_wc/deprecated.c subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_skel.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_token.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_wc/entries.h subversion/libsvn_wc/lock.h subversion/libsvn_wc/props.h subversion/libsvn_wc/translate.h subversion/libsvn_wc/wc.h subversion/libsvn_wc/wc_db.h subversion/libsvn_wc/workqueue.h subversion/svn_private_config.h +subversion/libsvn_wc/deprecated.lo: subversion/libsvn_wc/deprecated.c subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_io_private.h subversion/include/private/svn_skel.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_token.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_wc/entries.h subversion/libsvn_wc/lock.h subversion/libsvn_wc/props.h subversion/libsvn_wc/translate.h subversion/libsvn_wc/wc.h subversion/libsvn_wc/wc_db.h subversion/libsvn_wc/workqueue.h subversion/svn_private_config.h subversion/libsvn_wc/diff_editor.lo: subversion/libsvn_wc/diff_editor.c subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_editor.h subversion/include/private/svn_skel.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_token.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_wc/adm_files.h subversion/libsvn_wc/diff.h subversion/libsvn_wc/props.h subversion/libsvn_wc/translate.h subversion/libsvn_wc/wc.h subversion/libsvn_wc/wc_db.h subversion/svn_private_config.h @@ -3127,6 +3258,9 @@ subversion/mod_dav_svn/reports/get-locks.lo: subversion/mod_dav_svn/reports/get- subversion/mod_dav_svn/reports/inherited-props.lo: subversion/mod_dav_svn/reports/inherited-props.c subversion/include/mod_authz_svn.h subversion/include/private/svn_dav_protocol.h subversion/include/private/svn_debug.h subversion/include/private/svn_fspath.h subversion/include/private/svn_log.h subversion/include/private/svn_mergeinfo_private.h subversion/include/private/svn_skel.h subversion/include/svn_base64.h subversion/include/svn_checksum.h subversion/include/svn_dav.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_xml.h subversion/mod_dav_svn/dav_svn.h if $(INSTALL_APACHE_MODS) ; then $(COMPILE_APACHE_MOD) $(canonicalized_srcdir)subversion/mod_dav_svn/reports/inherited-props.c ; else echo "fake" > subversion/mod_dav_svn/reports/inherited-props.lo ; fi +subversion/mod_dav_svn/reports/list.lo: subversion/mod_dav_svn/reports/list.c subversion/include/mod_authz_svn.h subversion/include/private/svn_dav_protocol.h subversion/include/private/svn_debug.h subversion/include/private/svn_fspath.h subversion/include/private/svn_log.h subversion/include/private/svn_skel.h subversion/include/svn_base64.h subversion/include/svn_checksum.h subversion/include/svn_ctype.h subversion/include/svn_dav.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_xml.h subversion/mod_dav_svn/dav_svn.h + if $(INSTALL_APACHE_MODS) ; then $(COMPILE_APACHE_MOD) $(canonicalized_srcdir)subversion/mod_dav_svn/reports/list.c ; else echo "fake" > subversion/mod_dav_svn/reports/list.lo ; fi + subversion/mod_dav_svn/reports/log.lo: subversion/mod_dav_svn/reports/log.c subversion/include/mod_authz_svn.h subversion/include/private/svn_dav_protocol.h subversion/include/private/svn_debug.h subversion/include/private/svn_fspath.h subversion/include/private/svn_log.h subversion/include/private/svn_skel.h subversion/include/svn_base64.h subversion/include/svn_checksum.h subversion/include/svn_dav.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_xml.h subversion/mod_dav_svn/dav_svn.h if $(INSTALL_APACHE_MODS) ; then $(COMPILE_APACHE_MOD) $(canonicalized_srcdir)subversion/mod_dav_svn/reports/log.c ; else echo "fake" > subversion/mod_dav_svn/reports/log.lo ; fi @@ -3139,16 +3273,16 @@ subversion/mod_dav_svn/reports/replay.lo: subversion/mod_dav_svn/reports/replay. subversion/mod_dav_svn/reports/update.lo: subversion/mod_dav_svn/reports/update.c subversion/include/mod_authz_svn.h subversion/include/private/svn_dav_protocol.h subversion/include/private/svn_debug.h subversion/include/private/svn_fspath.h subversion/include/private/svn_log.h subversion/include/private/svn_skel.h subversion/include/svn_base64.h subversion/include/svn_checksum.h subversion/include/svn_dav.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_xml.h subversion/mod_dav_svn/dav_svn.h if $(INSTALL_APACHE_MODS) ; then $(COMPILE_APACHE_MOD) $(canonicalized_srcdir)subversion/mod_dav_svn/reports/update.c ; else echo "fake" > subversion/mod_dav_svn/reports/update.lo ; fi -subversion/mod_dav_svn/repos.lo: subversion/mod_dav_svn/repos.c subversion/include/mod_authz_svn.h subversion/include/mod_dav_svn.h subversion/include/private/svn_dav_protocol.h subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_log.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_skel.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_string_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_dav.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_repos.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/include/svn_xml.h subversion/mod_dav_svn/dav_svn.h +subversion/mod_dav_svn/repos.lo: subversion/mod_dav_svn/repos.c subversion/include/mod_authz_svn.h subversion/include/mod_dav_svn.h subversion/include/private/svn_dav_protocol.h subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_log.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_skel.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_string_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_dav.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_repos.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/include/svn_xml.h subversion/mod_dav_svn/dav_svn.h if $(INSTALL_APACHE_MODS) ; then $(COMPILE_APACHE_MOD) $(canonicalized_srcdir)subversion/mod_dav_svn/repos.c ; else echo "fake" > subversion/mod_dav_svn/repos.lo ; fi subversion/mod_dav_svn/status.lo: subversion/mod_dav_svn/status.c subversion/include/mod_authz_svn.h subversion/include/private/svn_cache.h subversion/include/private/svn_dav_protocol.h subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_skel.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_xml.h subversion/mod_dav_svn/dav_svn.h subversion/svn_private_config.h if $(INSTALL_APACHE_MODS) ; then $(COMPILE_APACHE_MOD) $(canonicalized_srcdir)subversion/mod_dav_svn/status.c ; else echo "fake" > subversion/mod_dav_svn/status.lo ; fi -subversion/mod_dav_svn/util.lo: subversion/mod_dav_svn/util.c subversion/include/mod_authz_svn.h subversion/include/private/svn_dav_protocol.h subversion/include/private/svn_debug.h subversion/include/private/svn_fspath.h subversion/include/private/svn_skel.h subversion/include/svn_base64.h subversion/include/svn_checksum.h subversion/include/svn_dav.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_xml.h subversion/mod_dav_svn/dav_svn.h +subversion/mod_dav_svn/util.lo: subversion/mod_dav_svn/util.c subversion/include/mod_authz_svn.h subversion/include/private/svn_dav_protocol.h subversion/include/private/svn_debug.h subversion/include/private/svn_fspath.h subversion/include/private/svn_skel.h subversion/include/private/svn_string_private.h subversion/include/svn_base64.h subversion/include/svn_checksum.h subversion/include/svn_ctype.h subversion/include/svn_dav.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_xml.h subversion/mod_dav_svn/dav_svn.h if $(INSTALL_APACHE_MODS) ; then $(COMPILE_APACHE_MOD) $(canonicalized_srcdir)subversion/mod_dav_svn/util.c ; else echo "fake" > subversion/mod_dav_svn/util.lo ; fi -subversion/mod_dav_svn/version.lo: subversion/mod_dav_svn/version.c subversion/include/mod_authz_svn.h subversion/include/private/svn_dav_protocol.h subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_log.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_skel.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_base64.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_dav.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/include/svn_xml.h subversion/mod_dav_svn/dav_svn.h +subversion/mod_dav_svn/version.lo: subversion/mod_dav_svn/version.c subversion/include/mod_authz_svn.h subversion/include/private/svn_dav_protocol.h subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_log.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_skel.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_base64.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_dav.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/include/svn_xml.h subversion/mod_dav_svn/dav_svn.h if $(INSTALL_APACHE_MODS) ; then $(COMPILE_APACHE_MOD) $(canonicalized_srcdir)subversion/mod_dav_svn/version.c ; else echo "fake" > subversion/mod_dav_svn/version.lo ; fi subversion/po/de.mo: subversion/po/de.po @@ -3217,17 +3351,17 @@ subversion/svn/list-cmd.lo: subversion/svn/list-cmd.c subversion/include/private subversion/svn/lock-cmd.lo: subversion/svn/lock-cmd.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/svn/cl.h subversion/svn_private_config.h -subversion/svn/log-cmd.lo: subversion/svn/log-cmd.c subversion/include/private/svn_cmdline_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_sorts_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_compat.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/include/svn_xml.h subversion/svn/cl-log.h subversion/svn/cl.h subversion/svn_private_config.h +subversion/svn/log-cmd.lo: subversion/svn/log-cmd.c subversion/include/private/svn_cmdline_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_utf_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_compat.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/include/svn_xml.h subversion/svn/cl-log.h subversion/svn/cl.h subversion/svn_private_config.h subversion/svn/merge-cmd.lo: subversion/svn/merge-cmd.c subversion/include/private/svn_client_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/svn/cl.h subversion/svn_private_config.h -subversion/svn/mergeinfo-cmd.lo: subversion/svn/mergeinfo-cmd.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_compat.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/svn/cl-log.h subversion/svn/cl.h subversion/svn_private_config.h +subversion/svn/mergeinfo-cmd.lo: subversion/svn/mergeinfo-cmd.c subversion/include/private/svn_debug.h subversion/include/private/svn_string_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_compat.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/svn/cl-log.h subversion/svn/cl.h subversion/svn_private_config.h subversion/svn/mkdir-cmd.lo: subversion/svn/mkdir-cmd.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/svn/cl.h subversion/svn_private_config.h subversion/svn/move-cmd.lo: subversion/svn/move-cmd.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/svn/cl.h subversion/svn_private_config.h -subversion/svn/notify.lo: subversion/svn/notify.c subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/svn/cl.h subversion/svn_private_config.h +subversion/svn/notify.lo: subversion/svn/notify.c subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/svn/cl.h subversion/svn_private_config.h subversion/svn/patch-cmd.lo: subversion/svn/patch-cmd.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/svn/cl.h subversion/svn_private_config.h @@ -3245,19 +3379,21 @@ subversion/svn/propset-cmd.lo: subversion/svn/propset-cmd.c subversion/include/p subversion/svn/relocate-cmd.lo: subversion/svn/relocate-cmd.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/svn/cl.h subversion/svn_private_config.h -subversion/svn/resolve-cmd.lo: subversion/svn/resolve-cmd.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/svn/cl.h subversion/svn_private_config.h +subversion/svn/resolve-cmd.lo: subversion/svn/resolve-cmd.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/svn/cl.h subversion/svn_private_config.h subversion/svn/resolved-cmd.lo: subversion/svn/resolved-cmd.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/svn/cl.h subversion/svn_private_config.h subversion/svn/revert-cmd.lo: subversion/svn/revert-cmd.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/svn/cl.h subversion/svn_private_config.h +subversion/svn/shelve-cmd.lo: subversion/svn/shelve-cmd.c subversion/include/private/svn_debug.h subversion/include/private/svn_sorts_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_ra.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_wc.h subversion/svn/cl.h subversion/svn_private_config.h + subversion/svn/similarity.lo: subversion/svn/similarity.c subversion/include/private/svn_debug.h subversion/include/private/svn_string_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/svn/cl.h subversion/svn_private_config.h subversion/svn/status-cmd.lo: subversion/svn/status-cmd.c subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/include/svn_xml.h subversion/svn/cl.h subversion/svn_private_config.h subversion/svn/status.lo: subversion/svn/status.c subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/include/svn_xml.h subversion/svn/cl-conflicts.h subversion/svn/cl.h subversion/svn_private_config.h -subversion/svn/svn.lo: subversion/svn/svn.c subversion/include/private/svn_cmdline_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_opt_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/include/svn_wc.h subversion/svn/cl.h subversion/svn_private_config.h +subversion/svn/svn.lo: subversion/svn/svn.c subversion/include/private/svn_cmdline_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_opt_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_utf_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/include/svn_wc.h subversion/svn/cl.h subversion/svn_private_config.h subversion/svn/switch-cmd.lo: subversion/svn/switch-cmd.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/svn/cl.h subversion/svn_private_config.h @@ -3269,7 +3405,7 @@ subversion/svn/upgrade-cmd.lo: subversion/svn/upgrade-cmd.c subversion/include/p subversion/svn/util.lo: subversion/svn/util.c subversion/include/private/svn_client_private.h subversion/include/private/svn_cmdline_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_opt_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_token.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_wc.h subversion/include/svn_xml.h subversion/svn/cl.h subversion/svn_private_config.h -subversion/svnadmin/svnadmin.lo: subversion/svnadmin/svnadmin.c subversion/include/private/svn_cmdline_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_opt_private.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_cache_config.h subversion/include/svn_checksum.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_user.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/include/svn_xml.h subversion/svn_private_config.h +subversion/svnadmin/svnadmin.lo: subversion/svnadmin/svnadmin.c subversion/include/private/svn_cmdline_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_fspath.h subversion/include/private/svn_opt_private.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_cache_config.h subversion/include/svn_checksum.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_user.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/include/svn_xml.h subversion/svn_private_config.h subversion/svnbench/help-cmd.lo: subversion/svnbench/help-cmd.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/include/svn_wc.h subversion/svn_private_config.h subversion/svnbench/cl.h @@ -3285,11 +3421,11 @@ subversion/svnbench/null-list-cmd.lo: subversion/svnbench/null-list-cmd.c subver subversion/svnbench/null-log-cmd.lo: subversion/svnbench/null-log-cmd.c subversion/include/private/svn_debug.h subversion/include/private/svn_string_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_compat.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/svn_private_config.h subversion/svnbench/cl.h -subversion/svnbench/svnbench.lo: subversion/svnbench/svnbench.c subversion/include/private/svn_cmdline_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_opt_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/include/svn_wc.h subversion/svn_private_config.h subversion/svnbench/cl.h +subversion/svnbench/svnbench.lo: subversion/svnbench/svnbench.c subversion/include/private/svn_cmdline_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_opt_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_utf_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/include/svn_wc.h subversion/svn_private_config.h subversion/svnbench/cl.h subversion/svnbench/util.lo: subversion/svnbench/util.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/svn_private_config.h subversion/svnbench/cl.h -subversion/svndumpfilter/svndumpfilter.lo: subversion/svndumpfilter/svndumpfilter.c subversion/include/private/svn_cmdline_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_mergeinfo_private.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_string_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/svn_private_config.h +subversion/svndumpfilter/svndumpfilter.lo: subversion/svndumpfilter/svndumpfilter.c subversion/include/private/svn_cmdline_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_mergeinfo_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_string_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/svn_private_config.h subversion/svnfsfs/dump-index-cmd.lo: subversion/svnfsfs/dump-index-cmd.c subversion/include/private/svn_debug.h subversion/include/private/svn_fs_fs_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/svnfsfs/svnfsfs.h @@ -3299,27 +3435,27 @@ subversion/svnfsfs/stats-cmd.lo: subversion/svnfsfs/stats-cmd.c subversion/inclu subversion/svnfsfs/svnfsfs.lo: subversion/svnfsfs/svnfsfs.c subversion/include/private/svn_cmdline_private.h subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_cache_config.h subversion/include/svn_checksum.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/svn_private_config.h subversion/svnfsfs/svnfsfs.h -subversion/svnlook/svnlook.lo: subversion/svnlook/svnlook.c subversion/include/private/svn_cmdline_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_diff_private.h subversion/include/private/svn_fspath.h subversion/include/private/svn_io_private.h subversion/include/private/svn_sorts_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/include/svn_xml.h subversion/svn_private_config.h +subversion/svnlook/svnlook.lo: subversion/svnlook/svnlook.c subversion/include/private/svn_cmdline_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_diff_private.h subversion/include/private/svn_fspath.h subversion/include/private/svn_io_private.h subversion/include/private/svn_sorts_private.h subversion/include/svn_auth.h subversion/include/svn_cache_config.h subversion/include/svn_checksum.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/include/svn_xml.h subversion/svn_private_config.h subversion/svnmucc/svnmucc.lo: subversion/svnmucc/svnmucc.c subversion/include/private/svn_client_mtcc.h subversion/include/private/svn_cmdline_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/include/svn_wc.h subversion/svn_private_config.h -subversion/svnrdump/dump_editor.lo: subversion/svnrdump/dump_editor.c subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_types.h subversion/svnrdump/svnrdump.h +subversion/svnrdump/dump_editor.lo: subversion/svnrdump/dump_editor.c subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_types.h subversion/svnrdump/svnrdump.h -subversion/svnrdump/load_editor.lo: subversion/svnrdump/load_editor.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mergeinfo_private.h subversion/include/private/svn_ra_private.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_types.h subversion/svn_private_config.h subversion/svnrdump/svnrdump.h +subversion/svnrdump/load_editor.lo: subversion/svnrdump/load_editor.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mergeinfo_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_ra_private.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_types.h subversion/svn_private_config.h subversion/svnrdump/svnrdump.h -subversion/svnrdump/svnrdump.lo: subversion/svnrdump/svnrdump.c subversion/include/private/svn_cmdline_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_ra_private.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_wc.h subversion/svn_private_config.h subversion/svnrdump/svnrdump.h +subversion/svnrdump/svnrdump.lo: subversion/svnrdump/svnrdump.c subversion/include/private/svn_cmdline_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_ra_private.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_wc.h subversion/svn_private_config.h subversion/svnrdump/svnrdump.h -subversion/svnrdump/util.lo: subversion/svnrdump/util.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_types.h subversion/svnrdump/svnrdump.h +subversion/svnrdump/util.lo: subversion/svnrdump/util.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/svnrdump/svnrdump.h -subversion/svnserve/cyrus_auth.lo: subversion/svnserve/cyrus_auth.c subversion/include/private/ra_svn_sasl.h subversion/include/private/svn_atomic.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_mutex.h subversion/include/private/svn_ra_svn_private.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_base64.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_ra_svn.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/svn_private_config.h subversion/svnserve/server.h +subversion/svnserve/cyrus_auth.lo: subversion/svnserve/cyrus_auth.c subversion/include/private/ra_svn_sasl.h subversion/include/private/ra_svn_wrapped_sasl.h subversion/include/private/svn_atomic.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_ra_svn_private.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_base64.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_ra_svn.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/svn_private_config.h subversion/svnserve/server.h -subversion/svnserve/log-escape.lo: subversion/svnserve/log-escape.c subversion/include/private/svn_atomic.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_mutex.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_ra_svn.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/svnserve/server.h +subversion/svnserve/log-escape.lo: subversion/svnserve/log-escape.c subversion/include/private/svn_atomic.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_ra_svn.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/svnserve/server.h -subversion/svnserve/logger.lo: subversion/svnserve/logger.c subversion/include/private/svn_atomic.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_mutex.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_ra_svn.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/svn_private_config.h subversion/svnserve/logger.h subversion/svnserve/server.h +subversion/svnserve/logger.lo: subversion/svnserve/logger.c subversion/include/private/svn_atomic.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_ra_svn.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/svn_private_config.h subversion/svnserve/logger.h subversion/svnserve/server.h -subversion/svnserve/serve.lo: subversion/svnserve/serve.c subversion/include/private/svn_atomic.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_log.h subversion/include/private/svn_mergeinfo_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_ra_svn_private.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_compat.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_ra_svn.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_user.h subversion/svn_private_config.h subversion/svnserve/logger.h subversion/svnserve/server.h +subversion/svnserve/serve.lo: subversion/svnserve/serve.c subversion/include/private/svn_atomic.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fspath.h subversion/include/private/svn_log.h subversion/include/private/svn_mergeinfo_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_ra_svn_private.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_compat.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_ra_svn.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_user.h subversion/svn_private_config.h subversion/svnserve/logger.h subversion/svnserve/server.h -subversion/svnserve/svnserve.lo: subversion/svnserve/svnserve.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cmdline_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_mutex.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_cache_config.h subversion/include/svn_checksum.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra_svn.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/svn_private_config.h subversion/svnserve/logger.h subversion/svnserve/server.h subversion/svnserve/winservice.h +subversion/svnserve/svnserve.lo: subversion/svnserve/svnserve.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cmdline_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_cache_config.h subversion/include/svn_checksum.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra_svn.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/svn_private_config.h subversion/svnserve/logger.h subversion/svnserve/server.h subversion/svnserve/winservice.h subversion/svnserve/winservice.lo: subversion/svnserve/winservice.c subversion/include/private/svn_debug.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_types.h subversion/svn_private_config.h subversion/svnserve/winservice.h @@ -3329,18 +3465,26 @@ subversion/svnsync/sync.lo: subversion/svnsync/sync.c subversion/include/private subversion/svnversion/svnversion.lo: subversion/svnversion/svnversion.c subversion/include/private/svn_cmdline_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_opt_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/include/svn_wc.h subversion/svn_private_config.h +subversion/tests/afl/afl-x509.lo: subversion/tests/afl/afl-x509.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_x509.h + subversion/tests/cmdline/atomic-ra-revprop-change.lo: subversion/tests/cmdline/atomic-ra-revprop-change.c subversion/include/private/svn_debug.h subversion/include/private/svn_skel.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/svn_private_config.h subversion/tests/cmdline/entries-dump.lo: subversion/tests/cmdline/entries-dump.c subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_skel.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_wc/lock.h subversion/libsvn_wc/wc.h subversion/libsvn_wc/wc_db.h subversion/svn_private_config.h subversion/tests/cmdline/lock-helper.lo: subversion/tests/cmdline/lock-helper.c subversion/include/private/svn_debug.h subversion/include/svn_checksum.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h -subversion/tests/libsvn_client/client-test.lo: subversion/tests/libsvn_client/client-test.c subversion/include/private/svn_client_mtcc.h subversion/include/private/svn_client_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_editor.h subversion/include/private/svn_magic.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_client/client.h subversion/libsvn_client/mergeinfo.h subversion/tests/svn_test.h subversion/tests/svn_test_fs.h +subversion/tests/libsvn_wc/utils.lo: subversion/tests/libsvn_wc/utils.c subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_skel.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_wc/token-map.h subversion/libsvn_wc/wc-queries.h subversion/libsvn_wc/wc.h subversion/libsvn_wc/wc_db.h subversion/libsvn_wc/wc_db_private.h subversion/svn_private_config.h subversion/tests/libsvn_wc/utils.h subversion/tests/svn_test.h subversion/tests/svn_test_fs.h + +subversion/tests/libsvn_client/client-test.lo: subversion/tests/libsvn_client/client-test.c subversion/include/private/svn_client_mtcc.h subversion/include/private/svn_client_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_editor.h subversion/include/private/svn_magic.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_repos.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_client/client.h subversion/libsvn_client/mergeinfo.h subversion/tests/svn_test.h subversion/tests/svn_test_fs.h + +subversion/tests/libsvn_client/conflicts-test.lo: subversion/tests/libsvn_client/conflicts-test.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/tests/libsvn_wc/utils.h subversion/tests/svn_test.h subversion/tests/svn_test_fs.h subversion/tests/libsvn_client/mtcc-test.lo: subversion/tests/libsvn_client/mtcc-test.c subversion/include/private/svn_client_mtcc.h subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/tests/svn_test.h subversion/tests/svn_test_fs.h subversion/tests/libsvn_delta/random-test.lo: subversion/tests/libsvn_delta/random-test.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_delta/compose_delta.c subversion/libsvn_delta/delta.h subversion/tests/libsvn_delta/delta-window-test.h subversion/tests/libsvn_delta/range-index-test.h subversion/tests/svn_test.h +subversion/tests/libsvn_delta/svndiff-stream-test.lo: subversion/tests/libsvn_delta/svndiff-stream-test.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_path.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/tests/svn_test.h + subversion/tests/libsvn_delta/svndiff-test.lo: subversion/tests/libsvn_delta/svndiff-test.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_base64.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_quoprint.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/tests/svn_test.h subversion/tests/libsvn_delta/vdelta-test.lo: subversion/tests/libsvn_delta/vdelta-test.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_delta/delta.h subversion/tests/libsvn_delta/delta-window-test.h subversion/tests/svn_test.h @@ -3351,7 +3495,9 @@ subversion/tests/libsvn_diff/diff-diff3-test.lo: subversion/tests/libsvn_diff/di subversion/tests/libsvn_diff/parse-diff-test.lo: subversion/tests/libsvn_diff/parse-diff-test.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/tests/svn_test.h -subversion/tests/libsvn_fs/fs-test.lo: subversion/tests/libsvn_fs/fs-test.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_delta/delta.h subversion/libsvn_fs/fs-loader.h subversion/svn_private_config.h subversion/tests/svn_test.h subversion/tests/svn_test_fs.h +subversion/tests/libsvn_fs/fs-sequential-test.lo: subversion/tests/libsvn_fs/fs-sequential-test.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_delta/delta.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h subversion/tests/svn_test.h subversion/tests/svn_test_fs.h + +subversion/tests/libsvn_fs/fs-test.lo: subversion/tests/libsvn_fs/fs-test.c subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_fspath.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_delta/delta.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h subversion/tests/svn_test.h subversion/tests/svn_test_fs.h subversion/tests/libsvn_fs/locks-test.lo: subversion/tests/libsvn_fs/locks-test.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/tests/svn_test.h subversion/tests/svn_test_fs.h @@ -3359,15 +3505,15 @@ subversion/tests/libsvn_fs_base/changes-test.lo: subversion/tests/libsvn_fs_base subversion/tests/libsvn_fs_base/fs-base-test.lo: subversion/tests/libsvn_fs_base/fs-base-test.c subversion/include/private/svn_debug.h subversion/include/private/svn_fs_util.h subversion/include/private/svn_skel.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_delta/delta.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/nodes-table.h subversion/libsvn_fs_base/bdb/txn-table.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/id.h subversion/libsvn_fs_base/key-gen.h subversion/libsvn_fs_base/trail.h subversion/svn_private_config.h subversion/tests/svn_test.h subversion/tests/svn_test_fs.h -subversion/tests/libsvn_fs_base/strings-reps-test.lo: subversion/tests/libsvn_fs_base/strings-reps-test.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/reps-table.h subversion/libsvn_fs_base/bdb/strings-table.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/util/fs_skels.h subversion/svn_private_config.h subversion/tests/svn_test.h subversion/tests/svn_test_fs.h +subversion/tests/libsvn_fs_base/strings-reps-test.lo: subversion/tests/libsvn_fs_base/strings-reps-test.c subversion/include/private/svn_debug.h subversion/include/private/svn_mutex.h subversion/include/private/svn_skel.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/bdb/bdb_compat.h subversion/libsvn_fs_base/bdb/env.h subversion/libsvn_fs_base/bdb/reps-table.h subversion/libsvn_fs_base/bdb/strings-table.h subversion/libsvn_fs_base/fs.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_base/trail.h subversion/libsvn_fs_base/util/fs_skels.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_x/fs_init.h subversion/svn_private_config.h subversion/tests/svn_test.h subversion/tests/svn_test_fs.h subversion/tests/libsvn_fs_fs/fs-fs-fuzzy-test.lo: subversion/tests/libsvn_fs_fs/fs-fs-fuzzy-test.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_token.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/rev_file.h subversion/tests/svn_test.h subversion/tests/svn_test_fs.h -subversion/tests/libsvn_fs_fs/fs-fs-pack-test.lo: subversion/tests/libsvn_fs_fs/fs-fs-pack-test.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_token.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/low_level.h subversion/libsvn_fs_fs/pack.h subversion/libsvn_fs_fs/util.h subversion/tests/svn_test.h subversion/tests/svn_test_fs.h +subversion/tests/libsvn_fs_fs/fs-fs-pack-test.lo: subversion/tests/libsvn_fs_fs/fs-fs-pack-test.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_token.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs/fs-loader.h subversion/libsvn_fs_base/fs_init.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/fs_fs.h subversion/libsvn_fs_fs/fs_init.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/low_level.h subversion/libsvn_fs_fs/pack.h subversion/libsvn_fs_fs/rev_file.h subversion/libsvn_fs_fs/util.h subversion/libsvn_fs_x/fs_init.h subversion/tests/svn_test.h subversion/tests/svn_test_fs.h subversion/tests/libsvn_fs_fs/fs-fs-private-test.lo: subversion/tests/libsvn_fs_fs/fs-fs-private-test.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_fs_private.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_token.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs_fs/fs.h subversion/libsvn_fs_fs/id.h subversion/libsvn_fs_fs/index.h subversion/libsvn_fs_fs/rev_file.h subversion/tests/svn_test.h subversion/tests/svn_test_fs.h -subversion/tests/libsvn_fs_x/fs-x-pack-test.lo: subversion/tests/libsvn_fs_x/fs-x-pack-test.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_token.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/reps.h subversion/tests/svn_test.h subversion/tests/svn_test_fs.h +subversion/tests/libsvn_fs_x/fs-x-pack-test.lo: subversion/tests/libsvn_fs_x/fs-x-pack-test.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cache.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_fs_private.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_string_private.h subversion/include/private/svn_token.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs_x/batch_fsync.h subversion/libsvn_fs_x/fs.h subversion/libsvn_fs_x/id.h subversion/libsvn_fs_x/reps.h subversion/libsvn_fs_x/rev_file.h subversion/tests/svn_test.h subversion/tests/svn_test_fs.h subversion/tests/libsvn_fs_x/string-table-test.lo: subversion/tests/libsvn_fs_x/string-table-test.c subversion/include/private/svn_debug.h subversion/include/private/svn_temp_serializer.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_fs_x/string_table.h subversion/tests/svn_test.h @@ -3375,11 +3521,13 @@ subversion/tests/libsvn_ra/ra-test.lo: subversion/tests/libsvn_ra/ra-test.c subv subversion/tests/libsvn_ra_local/ra-local-test.lo: subversion/tests/libsvn_ra_local/ra-local-test.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_ra.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_ra_local/ra_local.h subversion/tests/svn_test.h subversion/tests/svn_test_fs.h +subversion/tests/libsvn_repos/authz-test.lo: subversion/tests/libsvn_repos/authz-test.c subversion/include/private/svn_debug.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_repos/authz.h subversion/tests/svn_test.h + subversion/tests/libsvn_repos/dir-delta-editor.lo: subversion/tests/libsvn_repos/dir-delta-editor.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/tests/libsvn_repos/dir-delta-editor.h subversion/tests/svn_test.h -subversion/tests/libsvn_repos/dump-load-test.lo: subversion/tests/libsvn_repos/dump-load-test.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/tests/svn_test.h subversion/tests/svn_test_fs.h +subversion/tests/libsvn_repos/dump-load-test.lo: subversion/tests/libsvn_repos/dump-load-test.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/tests/svn_test.h subversion/tests/svn_test_fs.h -subversion/tests/libsvn_repos/repos-test.lo: subversion/tests/libsvn_repos/repos-test.c subversion/include/private/svn_debug.h subversion/include/private/svn_editor.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_subr/config_impl.h subversion/tests/libsvn_repos/dir-delta-editor.h subversion/tests/svn_test.h subversion/tests/svn_test_fs.h +subversion/tests/libsvn_repos/repos-test.lo: subversion/tests/libsvn_repos/repos-test.c subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_editor.h subversion/include/private/svn_mutex.h subversion/include/private/svn_object_pool.h subversion/include/private/svn_repos_private.h subversion/include/private/svn_string_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_repos.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/libsvn_subr/config_impl.h subversion/tests/libsvn_repos/dir-delta-editor.h subversion/tests/svn_test.h subversion/tests/svn_test_fs.h subversion/tests/libsvn_subr/auth-test.lo: subversion/tests/libsvn_subr/auth-test.c subversion/include/private/svn_auth_private.h subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_path.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/svn_private_config.h subversion/tests/svn_test.h @@ -3391,7 +3539,9 @@ subversion/tests/libsvn_subr/checksum-test.lo: subversion/tests/libsvn_subr/chec subversion/tests/libsvn_subr/compat-test.lo: subversion/tests/libsvn_subr/compat-test.c subversion/include/private/svn_debug.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_version.h subversion/svn_private_config.h subversion/tests/svn_test.h -subversion/tests/libsvn_subr/config-test.lo: subversion/tests/libsvn_subr/config-test.c subversion/include/private/svn_debug.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_path.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/tests/svn_test.h +subversion/tests/libsvn_subr/compress-test.lo: subversion/tests/libsvn_subr/compress-test.c subversion/include/private/svn_debug.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/tests/svn_test.h + +subversion/tests/libsvn_subr/config-test.lo: subversion/tests/libsvn_subr/config-test.c subversion/include/private/svn_config_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_path.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/tests/svn_test.h subversion/tests/libsvn_subr/crypto-test.lo: subversion/tests/libsvn_subr/crypto-test.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/libsvn_subr/crypto.h subversion/tests/svn_test.h @@ -3441,6 +3591,8 @@ subversion/tests/libsvn_subr/utf-test.lo: subversion/tests/libsvn_subr/utf-test. subversion/tests/libsvn_subr/x509-test.lo: subversion/tests/libsvn_subr/x509-test.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_base64.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_x509.h subversion/tests/svn_test.h +subversion/tests/libsvn_subr/xml-test.lo: subversion/tests/libsvn_subr/xml-test.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_xml.h subversion/tests/svn_test.h + subversion/libsvn_subr/sqlite3wrapper.lo: subversion/libsvn_subr/sqlite3wrapper.c subversion/svn_private_config.h subversion/tests/libsvn_wc/conflict-data-test.lo: subversion/tests/libsvn_wc/conflict-data-test.c subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_skel.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/libsvn_wc/conflicts.h subversion/libsvn_wc/tree_conflicts.h subversion/libsvn_wc/wc.h subversion/libsvn_wc/wc_db.h subversion/svn_private_config.h subversion/tests/libsvn_wc/utils.h subversion/tests/svn_test.h @@ -3477,8 +3629,38 @@ subversion/tests/svn_test_fs.lo: subversion/tests/svn_test_fs.c subversion/inclu subversion/tests/svn_test_main.lo: subversion/tests/svn_test_main.c subversion/include/private/svn_atomic.h subversion/include/private/svn_cmdline_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_dep_compat.h subversion/include/private/svn_mutex.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_ctype.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/svn_private_config.h subversion/tests/svn_test.h +tools/client-side/svn-mergeinfo-normalizer/analyze-cmd.lo: tools/client-side/svn-mergeinfo-normalizer/analyze-cmd.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h tools/client-side/svn-mergeinfo-normalizer/mergeinfo-normalizer.h + +tools/client-side/svn-mergeinfo-normalizer/help-cmd.lo: tools/client-side/svn-mergeinfo-normalizer/help-cmd.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/svn_private_config.h tools/client-side/svn-mergeinfo-normalizer/mergeinfo-normalizer.h + +tools/client-side/svn-mergeinfo-normalizer/log.lo: tools/client-side/svn-mergeinfo-normalizer/log.c subversion/include/private/svn_debug.h subversion/include/private/svn_fspath.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/svn_private_config.h tools/client-side/svn-mergeinfo-normalizer/mergeinfo-normalizer.h + +tools/client-side/svn-mergeinfo-normalizer/logic.lo: tools/client-side/svn-mergeinfo-normalizer/logic.c subversion/include/private/svn_debug.h subversion/include/private/svn_fspath.h subversion/include/private/svn_sorts_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/svn_private_config.h tools/client-side/svn-mergeinfo-normalizer/mergeinfo-normalizer.h + +tools/client-side/svn-mergeinfo-normalizer/missing-branches.lo: tools/client-side/svn-mergeinfo-normalizer/missing-branches.c subversion/include/private/svn_debug.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h tools/client-side/svn-mergeinfo-normalizer/mergeinfo-normalizer.h + +tools/client-side/svn-mergeinfo-normalizer/normalize-cmd.lo: tools/client-side/svn-mergeinfo-normalizer/normalize-cmd.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h tools/client-side/svn-mergeinfo-normalizer/mergeinfo-normalizer.h + +tools/client-side/svn-mergeinfo-normalizer/remove-branches-cmd.lo: tools/client-side/svn-mergeinfo-normalizer/remove-branches-cmd.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/svn_private_config.h tools/client-side/svn-mergeinfo-normalizer/mergeinfo-normalizer.h + +tools/client-side/svn-mergeinfo-normalizer/svn-mergeinfo-normalizer.lo: tools/client-side/svn-mergeinfo-normalizer/svn-mergeinfo-normalizer.c subversion/include/private/svn_cmdline_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_opt_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/include/svn_wc.h subversion/svn_private_config.h tools/client-side/svn-mergeinfo-normalizer/mergeinfo-normalizer.h + +tools/client-side/svn-mergeinfo-normalizer/wc_mergeinfo.lo: tools/client-side/svn-mergeinfo-normalizer/wc_mergeinfo.c subversion/include/private/svn_debug.h subversion/include/private/svn_fspath.h subversion/include/private/svn_opt_private.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/svn_private_config.h tools/client-side/svn-mergeinfo-normalizer/mergeinfo-normalizer.h + +tools/client-side/svnconflict/svnconflict.lo: tools/client-side/svnconflict/svnconflict.c subversion/include/private/svn_cmdline_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_opt_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/include/svn_wc.h subversion/svn_private_config.h + tools/dev/fsfs-access-map.lo: tools/dev/fsfs-access-map.c subversion/include/private/svn_debug.h subversion/include/private/svn_string_private.h subversion/include/svn_checksum.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h +tools/dev/svnmover/merge3.lo: tools/dev/svnmover/merge3.c subversion/include/private/svn_branch.h subversion/include/private/svn_branch_compat.h subversion/include/private/svn_branch_nested.h subversion/include/private/svn_branch_repos.h subversion/include/private/svn_client_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_element.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_subr_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/svn_private_config.h tools/dev/svnmover/svnmover.h + +tools/dev/svnmover/ra.lo: tools/dev/svnmover/ra.c subversion/include/private/svn_branch.h subversion/include/private/svn_branch_compat.h subversion/include/private/svn_branch_repos.h subversion/include/private/svn_debug.h subversion/include/private/svn_delta_private.h subversion/include/private/svn_editor.h subversion/include/private/svn_element.h subversion/include/private/svn_ra_private.h subversion/include/private/svn_string_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/svn_private_config.h tools/dev/svnmover/svnmover.h + +tools/dev/svnmover/scanlog.lo: tools/dev/svnmover/scanlog.c subversion/include/private/svn_branch.h subversion/include/private/svn_branch_compat.h subversion/include/private/svn_client_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_editor.h subversion/include/private/svn_element.h subversion/include/private/svn_ra_private.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_time.h subversion/include/svn_types.h subversion/include/svn_wc.h subversion/svn_private_config.h tools/dev/svnmover/svnmover.h + +tools/dev/svnmover/svnmover.lo: tools/dev/svnmover/svnmover.c subversion/include/private/svn_branch.h subversion/include/private/svn_branch_compat.h subversion/include/private/svn_branch_nested.h subversion/include/private/svn_branch_repos.h subversion/include/private/svn_client_private.h subversion/include/private/svn_cmdline_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_delta_private.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_editor.h subversion/include/private/svn_element.h subversion/include/private/svn_ra_private.h subversion/include/private/svn_sorts_private.h subversion/include/private/svn_string_private.h subversion/include/private/svn_subr_private.h subversion/include/private/svn_token.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_hash.h subversion/include/svn_io.h subversion/include/svn_iter.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_props.h subversion/include/svn_ra.h subversion/include/svn_sorts.h subversion/include/svn_string.h subversion/include/svn_subst.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/include/svn_wc.h subversion/svn_private_config.h tools/dev/svnmover/linenoise/linenoise.h tools/dev/svnmover/svnmover.h + +tools/dev/svnmover/util.lo: tools/dev/svnmover/util.c subversion/include/private/svn_branch.h subversion/include/private/svn_branch_compat.h subversion/include/private/svn_debug.h subversion/include/private/svn_element.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_client.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_diff.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_wc.h tools/dev/svnmover/linenoise/linenoise.c tools/dev/svnmover/linenoise/linenoise.h tools/dev/svnmover/svnmover.h + tools/dev/svnraisetreeconflict/svnraisetreeconflict.lo: tools/dev/svnraisetreeconflict/svnraisetreeconflict.c subversion/include/private/svn_cmdline_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/include/svn_wc.h subversion/svn_private_config.h tools/dev/wc-ng/svn-wc-db-tester.lo: tools/dev/wc-ng/svn-wc-db-tester.c subversion/include/private/svn_cmdline_private.h subversion/include/private/svn_debug.h subversion/include/private/svn_diff_tree.h subversion/include/private/svn_skel.h subversion/include/private/svn_sqlite.h subversion/include/private/svn_token.h subversion/include/private/svn_wc_private.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_opt.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_ra.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h subversion/include/svn_version.h subversion/include/svn_wc.h subversion/libsvn_wc/wc.h subversion/libsvn_wc/wc_db.h subversion/svn_private_config.h @@ -3491,7 +3673,7 @@ tools/diff/diff3.lo: tools/diff/diff3.c subversion/include/private/svn_debug.h s tools/diff/diff4.lo: tools/diff/diff4.c subversion/include/private/svn_debug.h subversion/include/svn_checksum.h subversion/include/svn_diff.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_pools.h subversion/include/svn_string.h subversion/include/svn_types.h -tools/server-side/mod_dontdothat/mod_dontdothat.lo: tools/server-side/mod_dontdothat/mod_dontdothat.c subversion/include/mod_dav_svn.h subversion/include/private/svn_debug.h subversion/include/private/svn_fspath.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_path.h subversion/include/svn_string.h subversion/include/svn_types.h +tools/server-side/mod_dontdothat/mod_dontdothat.lo: tools/server-side/mod_dontdothat/mod_dontdothat.c subversion/include/mod_dav_svn.h subversion/include/private/svn_debug.h subversion/include/private/svn_fspath.h subversion/include/svn_checksum.h subversion/include/svn_config.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_io.h subversion/include/svn_path.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_xml.h if $(INSTALL_APACHE_MODS) ; then $(COMPILE_APACHE_MOD) $(canonicalized_srcdir)tools/server-side/mod_dontdothat/mod_dontdothat.c ; else echo "fake" > tools/server-side/mod_dontdothat/mod_dontdothat.lo ; fi tools/server-side/svn-populate-node-origins-index.lo: tools/server-side/svn-populate-node-origins-index.c subversion/include/private/svn_debug.h subversion/include/svn_auth.h subversion/include/svn_checksum.h subversion/include/svn_cmdline.h subversion/include/svn_config.h subversion/include/svn_delta.h subversion/include/svn_dirent_uri.h subversion/include/svn_error.h subversion/include/svn_error_codes.h subversion/include/svn_fs.h subversion/include/svn_io.h subversion/include/svn_mergeinfo.h subversion/include/svn_path.h subversion/include/svn_pools.h subversion/include/svn_repos.h subversion/include/svn_string.h subversion/include/svn_types.h subversion/include/svn_utf.h diff --git a/build.conf b/build.conf index 4f020da1b055..8f5617b0a679 100644 --- a/build.conf +++ b/build.conf @@ -45,7 +45,9 @@ private-includes = subversion/bindings/cxxhl/src/private/*.hpp subversion/bindings/javahl/native/*.hpp subversion/bindings/javahl/native/jniwrapper/jni_*.hpp - subversion/libsvn_subr/utf8proc/utf8proc.h + tools/dev/svnmover/linenoise/linenoise.h + tools/dev/svnmover/linenoise/linenoise.c + subversion/libsvn_subr/utf8proc/utf8proc_internal.h subversion/libsvn_subr/utf8proc/utf8proc.c subversion/libsvn_subr/utf8proc/utf8proc_data.c private-built-includes = @@ -96,9 +98,9 @@ test-scripts = bdb-test-scripts = -swig-python-opts = $(SWIG_CPPFLAGS) -python -classic -swig-perl-opts = $(SWIG_CPPFLAGS) -perl -nopm -noproxy -swig-ruby-opts = $(SWIG_CPPFLAGS) -ruby +swig-python-opts = $(SWIG_FEATURES) -python $(SWIG_PY_FEATURES) -classic +swig-perl-opts = $(SWIG_FEATURES) -perl $(SWIG_PL_FEATURES) -nopm -noproxy +swig-ruby-opts = $(SWIG_FEATURES) -ruby $(SWIG_RB_FEATURES) swig-languages = python perl ruby swig-dirs = subversion/bindings/swig/python @@ -222,7 +224,7 @@ manpages = subversion/svnmucc/svnmucc.1 # Support for GNOME Keyring [libsvn_auth_gnome_keyring] description = Subversion GNOME Keyring Library -type = lib +type = shared-only-lib install = gnome-keyring-lib path = subversion/libsvn_auth_gnome_keyring libs = libsvn_subr apr gnome-keyring @@ -230,7 +232,7 @@ libs = libsvn_subr apr gnome-keyring # Support for KWallet [libsvn_auth_kwallet] description = Subversion KWallet Library -type = lib +type = shared-only-cxx-lib install = kwallet-lib path = subversion/libsvn_auth_kwallet libs = libsvn_subr apr kwallet @@ -252,7 +254,7 @@ type = lib install = fsmod-lib path = subversion/libsvn_delta libs = libsvn_subr aprutil apriconv apr zlib -msvc-export = svn_delta.h private/svn_editor.h private/svn_delta_private.h +msvc-export = svn_delta.h private/svn_editor.h private/svn_delta_private.h private/svn_element.h private/svn_branch.h private/svn_branch_compat.h private/svn_branch_impl.h private/svn_branch_nested.h private/svn_branch_repos.h # Routines for diffing [libsvn_diff] @@ -282,7 +284,8 @@ path = subversion/libsvn_fs_base sources = *.c bdb/*.c util/*.c install = bdb-lib libs = libsvn_delta libsvn_subr aprutil apriconv apr bdb libsvn_fs_util -msvc-static = yes +msvc-export = ../libsvn_fs_base/fs_init.h +msvc-delayload = yes [libsvn_fs_fs] description = Subversion FSFS Repository Filesystem Library @@ -290,7 +293,8 @@ type = fs-module path = subversion/libsvn_fs_fs install = fsmod-lib libs = libsvn_delta libsvn_subr aprutil apriconv apr libsvn_fs_util -msvc-static = yes +msvc-export = private/svn_fs_fs_private.h ../libsvn_fs_fs/fs_init.h +msvc-delayload = yes [libsvn_fs_x] description = Subversion FSX Repository Filesystem Library @@ -298,7 +302,8 @@ type = fs-module path = subversion/libsvn_fs_x install = fsmod-lib libs = libsvn_delta libsvn_subr aprutil apriconv apr libsvn_fs_util -msvc-static = yes +msvc-export = ../libsvn_fs_x/fs_init.h +msvc-delayload = yes # Low-level grab bag of utilities [libsvn_fs_util] @@ -308,7 +313,7 @@ install = fsmod-lib path = subversion/libsvn_fs_util libs = libsvn_subr aprutil apriconv apr msvc-libs = advapi32.lib shfolder.lib -msvc-static = yes +msvc-export = private/svn_fs_util.h # General API for accessing repositories [libsvn_ra] @@ -321,6 +326,7 @@ add-deps = $(SVN_RA_LIB_DEPS) add-install-deps = $(SVN_RA_LIB_INSTALL_DEPS) install = lib msvc-export = svn_ra.h private\svn_ra_private.h +msvc-delayload = yes # Accessing repositories via DAV through serf [libsvn_ra_serf] @@ -328,7 +334,7 @@ description = Subversion HTTP/WebDAV Protocol Repository Access Library type = ra-module path = subversion/libsvn_ra_serf install = serf-lib -libs = libsvn_delta libsvn_subr aprutil apriconv apr serf xml zlib +libs = libsvn_delta libsvn_subr aprutil apriconv apr serf zlib msvc-static = yes # Accessing repositories via SVN @@ -356,7 +362,7 @@ type = lib path = subversion/libsvn_repos install = ramod-lib libs = libsvn_fs libsvn_delta libsvn_subr apriconv apr -msvc-export = svn_repos.h private/svn_repos_private.h +msvc-export = svn_repos.h private/svn_repos_private.h ../libsvn_repos/authz.h # Low-level grab bag of utilities [libsvn_subr] @@ -364,7 +370,8 @@ description = Subversion General Utility Library type = lib install = fsmod-lib path = subversion/libsvn_subr -libs = aprutil apriconv apr xml zlib apr_memcache sqlite magic intl +sources = *.c lz4/*.c +libs = aprutil apriconv apr xml zlib apr_memcache sqlite magic intl lz4 utf8proc msvc-libs = kernel32.lib advapi32.lib shfolder.lib ole32.lib crypt32.lib version.lib msvc-export = @@ -385,6 +392,7 @@ msvc-export = private\svn_string_private.h private\svn_magic.h private\svn_subr_private.h private\svn_mutex.h private\svn_packed_data.h private\svn_object_pool.h private\svn_cert.h + private\svn_config_private.h # Working copy management lib [libsvn_wc] @@ -421,7 +429,7 @@ when = INSTALL_APACHE_MODS type = apache-mod path = tools/server-side/mod_dontdothat nonlibs = mod_dav_svn apr aprutil -libs = libsvn_subr xml libhttpd +libs = libsvn_subr libhttpd install = tools # The Subversion FSFS repository manipulation tool @@ -431,7 +439,6 @@ type = exe path = subversion/svnfsfs install = bin libs = libsvn_repos libsvn_fs libsvn_fs_fs libsvn_delta libsvn_subr apriconv apr -msvc-libs = setargv.obj # ---------------------------------------------------------------------------- # @@ -567,6 +574,7 @@ install = swig-py-lib compile-cmd = $(COMPILE_SWIG_PY) msvc-static = no msvc-export = ../bindings/swig/python/libsvn_swig_py/swigutil_py.h +description = Subversion utility library for Python bindings # SWIG utility library for Perl modules [libsvn_swig_perl] @@ -736,30 +744,30 @@ link-cmd = $(LINK_CXX_LIB) [cxxhl-tests] description = Unit tests for Subversion C++ HighLevel bindings -when = SVN_USE_GMOCK +when = SVN_USE_GOOGLEMOCK type = exe path = subversion/bindings/cxxhl -libs = libsvncxxhl libgmock libsvn_subr apr +libs = libsvncxxhl libgooglemock libsvn_subr apr sources = tests/*.cpp -install = tests -compile-cmd = $(COMPILE_CXXHL_GMOCK_CXX) +install = cxxhl-tests +compile-cmd = $(COMPILE_CXXHL_GOOGLEMOCK_CXX) link-cmd = $(LINK_CXX) # ---------------------------------------------------------------------------- # -# Gmock targets +# Googlemock targets # -[libgmock] +[libgooglemock] description = Googlemock Library -when = SVN_USE_GMOCK +when = SVN_USE_GOOGLEMOCK type = lib -path = gmock-fused -sources = gmock-gtest-all.cc -install = tests +path = googlemock +sources = googletest/src/gtest-all.cc googlemock/src/gmock-all.cc +install = cxxhl-tests msvc-static = yes -compile-cmd = $(COMPILE_GMOCK_CXX) +compile-cmd = $(COMPILE_GOOGLEMOCK_CXX) link-cmd = $(LINK_CXX_LIB) # ---------------------------------------------------------------------------- @@ -787,6 +795,7 @@ sources = fs-base-test.c install = bdb-test libs = libsvn_test libsvn_fs libsvn_fs_base libsvn_delta libsvn_fs_util libsvn_subr apriconv apr +msvc-force-static = yes [strings-reps-test] description = Test strings/reps in libsvn_fs_base @@ -796,6 +805,7 @@ sources = strings-reps-test.c install = bdb-test libs = libsvn_test libsvn_fs libsvn_fs_base libsvn_delta libsvn_subr apriconv apr +msvc-force-static = yes [changes-test] description = Test changes in libsvn_fs_base @@ -805,6 +815,7 @@ sources = changes-test.c install = bdb-test libs = libsvn_test libsvn_fs libsvn_fs_base libsvn_delta libsvn_subr apriconv apr +msvc-force-static = yes # ---------------------------------------------------------------------------- # Tests for libsvn_fs_fs @@ -816,6 +827,7 @@ sources = fs-fs-pack-test.c install = test libs = libsvn_test libsvn_fs libsvn_fs_fs libsvn_delta libsvn_subr apriconv apr +msvc-force-static = yes [fs-fs-fuzzy-test] description = Use fuzzying to test FSFS corruption resilience @@ -825,6 +837,7 @@ sources = fs-fs-fuzzy-test.c install = sub-test libs = libsvn_test libsvn_fs libsvn_fs_fs libsvn_delta libsvn_repos libsvn_subr apriconv apr +msvc-force-static = yes [fs-fs-private-test] description = Test FSSF private API @@ -834,6 +847,7 @@ sources = fs-fs-private-test.c install = test libs = libsvn_test libsvn_fs libsvn_fs_fs libsvn_delta libsvn_repos libsvn_subr apriconv apr +msvc-force-static = yes # ---------------------------------------------------------------------------- # Tests for libsvn_fs_x @@ -845,6 +859,7 @@ sources = fs-x-pack-test.c install = test libs = libsvn_test libsvn_fs libsvn_fs_x libsvn_delta libsvn_subr apriconv apr +msvc-force-static = yes [string-table-test] description = Test fsfs string tables @@ -853,6 +868,7 @@ path = subversion/tests/libsvn_fs_x sources = string-table-test.c install = test libs = libsvn_test libsvn_fs_x libsvn_subr apr +msvc-force-static = yes # ---------------------------------------------------------------------------- # Tests for libsvn_fs @@ -867,7 +883,7 @@ libs = libsvn_test libsvn_fs libsvn_delta libsvn_subr apriconv apr msvc-force-static = yes [fs-test] -description = Test locks in libsvn_fs +description = Tests in libsvn_fs type = exe path = subversion/tests/libsvn_fs sources = fs-test.c @@ -875,9 +891,26 @@ install = test libs = libsvn_test libsvn_fs libsvn_delta libsvn_fs_util libsvn_subr aprutil apriconv apr +[fs-sequential-test] +description = Tests in libsvn_fs run sequentially +type = exe +path = subversion/tests/libsvn_fs +sources = fs-sequential-test.c +install = test +libs = libsvn_test libsvn_fs libsvn_delta + libsvn_fs_util libsvn_subr aprutil apriconv apr + # ---------------------------------------------------------------------------- # Tests for libsvn_repos +[authz-test] +description = Test authz parsing in libsvn_repos +type = exe +path = subversion/tests/libsvn_repos +sources = authz-test.c +install = test +libs = libsvn_test libsvn_repos libsvn_fs libsvn_delta libsvn_subr apriconv apr + [repos-test] description = Test delta editor in libsvn_repos type = exe @@ -1139,6 +1172,21 @@ sources = x509-test.c install = test libs = libsvn_test libsvn_subr apriconv apr +[xml-test] +description = Test XML parser in libsvn_subr +type = exe +path = subversion/tests/libsvn_subr +sources = xml-test.c +install = test +libs = libsvn_test libsvn_subr apriconv apr + +[compress-test] +description = Test compression functions +type = exe +path = subversion/tests/libsvn_subr +sources = compress-test.c +install = test +libs = libsvn_test libsvn_subr apr # ---------------------------------------------------------------------------- # Tests for libsvn_delta @@ -1159,6 +1207,14 @@ sources = window-test.c install = test libs = libsvn_test libsvn_delta libsvn_subr apriconv apr +[svndiff-stream-test] +description = Test svndiff streams +type = exe +path = subversion/tests/libsvn_delta +sources = svndiff-stream-test.c +install = test +libs = libsvn_test libsvn_delta libsvn_subr apriconv apr + # ---------------------------------------------------------------------------- # Tests for libsvn_client @@ -1179,6 +1235,15 @@ sources = mtcc-test.c install = test libs = libsvn_test libsvn_client libsvn_wc libsvn_repos libsvn_ra libsvn_fs libsvn_delta libsvn_subr apriconv apr +[conflicts-test] +description = Test libsvn_client conflict resolver +type = exe +path = subversion/tests/libsvn_client +sources = conflicts-test.c ../libsvn_wc/utils.c +install = test +libs = libsvn_test libsvn_client libsvn_wc libsvn_repos libsvn_ra libsvn_fs libsvn_delta libsvn_subr apriconv apr +msvc-force-static = yes + # ---------------------------------------------------------------------------- # Tests for libsvn_diff @@ -1414,8 +1479,7 @@ external-lib = $(SVN_SASL_LIBS) [openssl] type = lib -external-lib = $(SVN_OPENSSL_LIBS) -msvc-libs = ssleay32.lib libeay32.lib +external-lib = $(SVN_OPENSSL_LIBS) $(SVN_LIBCRYPTO_LIBS) [intl] type = lib @@ -1426,6 +1490,14 @@ type = lib external-lib = $(SVN_ZLIB_LIBS) msvc-static = yes +[lz4] +type = lib +external-lib = $(SVN_LZ4_LIBS) + +[utf8proc] +type = lib +external-lib = $(SVN_UTF8PROC_LIBS) + [apr_memcache] type = lib external-lib = $(SVN_APR_MEMCACHE_LIBS) @@ -1433,7 +1505,7 @@ external-lib = $(SVN_APR_MEMCACHE_LIBS) [serf] type = lib external-lib = $(SVN_SERF_LIBS) -libs = apr aprutil openssl xml zlib +libs = apr aprutil openssl zlib msvc-libs = secur32.lib pkg-config = serf-1 pkg-config-private = yes @@ -1485,16 +1557,16 @@ libs = svn svnadmin svndumpfilter svnlook svnmucc svnserve svnrdump svnsync svnversion mod_authz_svn mod_dav_svn mod_dontdothat svnauthz svnauthz-validate svnraisetreeconflict - svnfsfs svnbench + svnfsfs svnbench svnmover [__ALL_TESTS__] type = project path = build/win32 libs = __ALL__ fs-test fs-base-test fs-fsfs-test fs-fs-pack-test fs-fs-fuzzy-test - fs-fs-private-test fs-x-pack-test string-table-test + fs-fs-private-test fs-x-pack-test string-table-test fs-sequential-test skel-test strings-reps-test changes-test locks-test - repos-test dump-load-test + repos-test authz-test dump-load-test checksum-test compat-test config-test hashdump-test mergeinfo-test opt-test packed-data-test path-test prefix-string-test priority-queue-test root-pools-test stream-test @@ -1511,18 +1583,20 @@ libs = __ALL__ svndiff-test vdelta-test entries-dump atomic-ra-revprop-change wc-lock-tester wc-incomplete-tester lock-helper - client-test mtcc-test + client-test conflicts-test mtcc-test conflict-data-test db-test pristine-store-test entries-compat-test op-depth-test dirent_uri-test wc-queries-test wc-test auth-test - parse-diff-test x509-test + parse-diff-test x509-test xml-test afl-x509 compress-test + svndiff-stream-test [__MORE__] type = project path = build/win32 libs = __ALL_TESTS__ - diff diff3 diff4 fsfs-access-map svnauth + diff diff3 diff4 fsfs-access-map svn-populate-node-origins-index x509-parser svn-wc-db-tester + svn-mergeinfo-normalizer svnconflict [__LIBS__] type = project @@ -1637,6 +1711,13 @@ path = tools/dev/svnraisetreeconflict libs = libsvn_wc libsvn_subr apriconv apr install = tools +[svn-mergeinfo-normalizer] +type = exe +path = tools/client-side/svn-mergeinfo-normalizer +install = tools +libs = libsvn_client libsvn_wc libsvn_ra libsvn_delta libsvn_diff libsvn_subr + apriconv apr + [x509-parser] description = Tool to verify x509 certificates type = exe @@ -1644,3 +1725,26 @@ path = tools/dev sources = x509-parser.c install = tools libs = libsvn_subr apr + +[svnmover] +description = Subversion Mover Command Client +type = exe +path = tools/dev/svnmover +sources = *.c +libs = libsvn_client libsvn_ra libsvn_subr libsvn_delta apriconv apr +install = tools + +[svnconflict] +type = exe +path = tools/client-side/svnconflict +install = tools +libs = libsvn_client libsvn_wc libsvn_ra libsvn_subr apriconv apr + +[afl-x509] +description = AFL fuzzer for x509 parser +type = exe +path = subversion/tests/afl +sources = afl-x509.c +install = test +libs = libsvn_subr apr +testing = skip diff --git a/configure b/configure index 62356fa19994..7f2a14b7698e 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for subversion 1.9.7. +# Generated by GNU Autoconf 2.69 for subversion 1.10.0. # # Report bugs to . # @@ -590,8 +590,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='subversion' PACKAGE_TARNAME='subversion' -PACKAGE_VERSION='1.9.7' -PACKAGE_STRING='subversion 1.9.7' +PACKAGE_VERSION='1.10.0' +PACKAGE_STRING='subversion 1.10.0' PACKAGE_BUGREPORT='http://subversion.apache.org/' PACKAGE_URL='' @@ -635,7 +635,6 @@ ac_includes_default="\ ac_subst_vars='LTLIBOBJS SVN_CONFIG_SCRIPT_FILES INCLUDE_OUTPUTS -SWIG_CPPFLAGS JAVAHL_COMPAT_TESTS_TARGET JAVAHL_TESTS_TARGET JAVA_CLASSPATH @@ -650,6 +649,10 @@ SVN_RA_LIB_LINK SVN_RA_LIB_INSTALL_DEPS SVN_RA_LIB_DEPS CTYPESGEN +SWIG_PY_FEATURES +SWIG_PL_FEATURES +SWIG_RB_FEATURES +SWIG_FEATURES SWIG_RB_TEST_VERBOSE SWIG_RB_SITE_ARCH_DIR SWIG_RB_SITE_LIB_DIR @@ -657,6 +660,7 @@ SWIG_RB_COMPILE SWIG_RB_INCLUDES SWIG_RB_LIBS SWIG_RB_LINK +SWIG_PL_LINK SWIG_PL_INCLUDES SWIG_PY_LIBS SWIG_PY_LINK @@ -680,8 +684,13 @@ JAVA JDK PYTHON MOD_ACTIVATION +SVN_UTF8PROC_LIBS +SVN_UTF8PROC_INCLUDES +SVN_LZ4_LIBS +SVN_LZ4_INCLUDES SVN_ZLIB_LIBS SVN_ZLIB_INCLUDES +shared_only_LDFLAGS libsvn_wc_LDFLAGS libsvn_subr_LDFLAGS libsvn_repos_LDFLAGS @@ -696,8 +705,6 @@ libsvn_fs_LDFLAGS libsvn_diff_LDFLAGS libsvn_delta_LDFLAGS libsvn_client_LDFLAGS -libsvn_auth_kwallet_LDFLAGS -libsvn_auth_gnome_keyring_LDFLAGS LIBOBJS BDB_TEST_PROGRAMS BDB_TEST_DEPS @@ -706,7 +713,7 @@ INSTALL_STATIC_RULES BUILD_RULES SVN_KWALLET_LIBS SVN_KWALLET_INCLUDES -KDE4_CONFIG +KDE_CONFIG SVN_MAGIC_LIBS SVN_MAGIC_INCLUDES MSGFMTFLAGS @@ -716,8 +723,8 @@ SVN_INTL_LIBS XGETTEXT MSGMERGE MSGFMT -SVN_USE_GMOCK -GMOCK_SRCDIR +SVN_USE_GOOGLEMOCK +GOOGLEMOCK_SRCDIR SVN_GNOME_KEYRING_LIBS SVN_GNOME_KEYRING_INCLUDES SVN_HAVE_GPG_AGENT @@ -764,6 +771,7 @@ APACHE_LIBEXECDIR APACHE_INCLUDES APACHE_LDFLAGS APXS +HTTPD_WHITELIST SVN_APR_MEMCACHE_LIBS SVN_APR_MEMCACHE_INCLUDES SVN_SERF_LIBS @@ -866,6 +874,7 @@ with_apr with_apr_util with_serf with_apr_memcache +enable_apache_whitelist with_apxs with_apache_libexecdir enable_broken_httpd_auth @@ -890,8 +899,9 @@ enable_bdb6 with_sasl enable_keychain with_gpg_agent +with_old_gnome_keyring with_gnome_keyring -enable_gmock +enable_googlemock enable_ev2_impl enable_nls with_libmagic @@ -904,6 +914,8 @@ enable_maintainer_mode enable_full_version_match with_editor with_zlib +with_lz4 +with_utf8proc enable_mod_activation enable_gcov enable_gprof @@ -930,7 +942,11 @@ CXXFLAGS CCC CPP LT_SYS_LIBRARY_PATH -CXXCPP' +CXXCPP +SWIG_FEATURES +SWIG_RB_FEATURES +SWIG_PL_FEATURES +SWIG_PY_FEATURES' # Initialize some variables set by options. @@ -1471,7 +1487,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures subversion 1.9.7 to adapt to many kinds of systems. +\`configure' configures subversion 1.10.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1537,7 +1553,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of subversion 1.9.7:";; + short | recursive ) echo "Configuration of subversion 1.10.0:";; esac cat <<\_ACEOF @@ -1545,8 +1561,14 @@ Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-apache-whitelist=VER + Whitelist a particular Apache version number, + typically used to enable the use of a old version + patched by a distribution. --enable-broken-httpd-auth - Force build against httpd 2.4 with broken auth + Force build against httpd 2.4 with broken auth. + (This is not recommended as Subversion will be + vulnerable to CVE-2015-3184.) --enable-sqlite-compatibility-version=X.Y.Z Allow binary to run against SQLite as old as ARG --enable-shared[=PKGS] build shared libraries [default=yes] @@ -1570,7 +1592,7 @@ Optional Features: the Berkeley DB installation. Using BDB 6 will fail if this option is not used. --disable-keychain Disable use of Mac OS KeyChain for auth credentials - --disable-gmock Do not use the Googlemock testing framework + --disable-googlemock Do not use the Googlemock testing framework --enable-ev2-impl Use Ev2 implementations, where available [EXPERIMENTAL] --disable-nls Disable gettext functionality @@ -1604,10 +1626,10 @@ Optional Features: Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --with-apr=PATH prefix for installed APR, path to APR build tree, - or the full path to apr-config - --with-apr-util=PATH prefix for installed APU, path to APU build tree, - or the full path to apu-config + --with-apr=PATH prefix for installed APR or the full path to + apr-config + --with-apr-util=PATH prefix for installed APU or the full path to + apu-config --with-serf=PREFIX Serf HTTP client library (enabled by default if found) --with-apr_memcache=PREFIX @@ -1642,19 +1664,27 @@ Optional Packages: Berkeley DB used by APR-UTIL. --with-sasl=PATH Compile with libsasl2 in PATH --without-gpg-agent Disable support for GPG-Agent - --with-gnome-keyring Enable use of GNOME Keyring for auth credentials - (enabled by default if found) + --with-old-gnome-keyring + Enable old GNOME Keyring for auth credentials + (prefer --with-gnome-keyring) + --with-gnome-keyring Enable GNOME Keyring for auth credentials (enabled + by default if found) --with-libmagic=PREFIX libmagic filetype detection library - --with-kwallet[=PATH] Enable use of KWallet (KDE 4) for auth credentials + --with-kwallet[=PATH|INCDIR:LIBDIR] + Enable use of KWallet (KDE 5 or 4) for auth + credentials. PATH is the KDE install path, + alternatively INCDIR:LIBDIR are the header and + library install paths. --with-editor=PATH Specify a default editor for the subversion client. --with-zlib=PREFIX zlib compression library + --with-lz4=PREFIX|internal + look for lz4 in PREFIX or use the internal code + --with-utf8proc=PREFIX|internal + look for utf8proc in PREFIX or use the internal code --with-jdk=PATH Try to use 'PATH/include' to find the JNI headers. If PATH is not specified, look for a Java Development Kit at JAVA_HOME. - --with-jikes=PATH Specify the path to a jikes binary to use it as your - Java compiler. The default is to look for jikes - (PATH optional). This behavior can be switched off - by supplying 'no'. + --with-jikes=PATH Deprecated. Provided for backward compatibility. --with-swig=PATH Try to use 'PATH/bin/swig' to build the swig bindings. If PATH is not specified, look for a 'swig' binary in your PATH. @@ -1684,6 +1714,14 @@ Some influential environment variables: LT_SYS_LIBRARY_PATH User-defined run-time library search path. CXXCPP C++ preprocessor + SWIG_FEATURES + SWIG feature flags common to all bindings + SWIG_RB_FEATURES + SWIG feature flags specific to Ruby bindings + SWIG_PL_FEATURES + SWIG feature flags specific to Perl bindings + SWIG_PY_FEATURES + SWIG feature flags specific to Python bindings Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. @@ -1751,7 +1789,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -subversion configure 1.9.7 +subversion configure 1.10.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2295,7 +2333,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by subversion $as_me 1.9.7, which was +It was created by subversion $as_me 1.10.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2675,8 +2713,8 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. -{ $as_echo "$as_me:${as_lineno-$LINENO}: Configuring Subversion 1.9.7" >&5 -$as_echo "$as_me: Configuring Subversion 1.9.7" >&6;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: Configuring Subversion 1.10.0" >&5 +$as_echo "$as_me: Configuring Subversion 1.10.0" >&6;} abs_srcdir="`cd $srcdir && pwd`" @@ -4709,7 +4747,7 @@ $as_echo "$as_me: Apache Portable Runtime (APR) library configuration" >&6;} apr_found="no" - if test "$ac_cv_emxos2" = "yes"; then + if test "$target_os" = "os2-emx"; then # Scripts don't pass test -x on OS/2 TEST_X="test -f" else @@ -4746,16 +4784,17 @@ if test "${with_apr+set}" = set; then : for lookdir in "$withval/bin" "$withval" do if $TEST_X "$lookdir/$apr_temp_apr_config_file"; then - apr_found="yes" apr_config="$lookdir/$apr_temp_apr_config_file" + + apr_found="yes" break 2 fi done done if test "$apr_found" != "yes" && $TEST_X "$withval" && $withval --help > /dev/null 2>&1 ; then - apr_found="yes" apr_config="$withval" + apr_found="yes" fi if test "$apr_found" != "yes"; then @@ -4764,8 +4803,28 @@ if test "${with_apr+set}" = set; then : else - if test -d """"; then - apr_temp_abs_srcdir="`cd "" && pwd`" + if test -n "1" && test "1" = "1"; then + for apr_temp_apr_config_file in $apr_temp_acceptable_apr_config + do + if $apr_temp_apr_config_file --help > /dev/null 2>&1 ; then + apr_config="$apr_temp_apr_config_file" + + apr_found="yes" + break + else + for lookdir in /usr /usr/local /usr/local/apr /opt/apr; do + if $TEST_X "$lookdir/bin/$apr_temp_apr_config_file"; then + apr_config="$lookdir/bin/$apr_temp_apr_config_file" + + apr_found="yes" + break 2 + fi + done + fi + done + fi + if test "$apr_found" = "no" && test -d """"; then + apr_temp_abs_srcdir="`cd \"""\" && pwd`" apr_found="reconfig" apr_bundled_major="`sed -n '/#define.*APR_MAJOR_VERSION/s/^[^0-9]*\([0-9]*\).*$/\1/p' \"""/include/apr_version.h\"`" case $apr_bundled_major in @@ -4785,24 +4844,6 @@ else apr_config="""/$apr_temp_apr_config_file" fi fi - if test "$apr_found" = "no" && test -n "1" && test "1" = "1"; then - for apr_temp_apr_config_file in $apr_temp_acceptable_apr_config - do - if $apr_temp_apr_config_file --help > /dev/null 2>&1 ; then - apr_found="yes" - apr_config="$apr_temp_apr_config_file" - break - else - for lookdir in /usr /usr/local /opt/apr /usr/local/apache2 ; do - if $TEST_X "$lookdir/bin/$apr_temp_apr_config_file"; then - apr_found="yes" - apr_config="$lookdir/bin/$apr_temp_apr_config_file" - break 2 - fi - done - fi - done - fi fi @@ -4959,7 +5000,7 @@ $as_echo "$as_me: Apache Portable Runtime Utility (APRUTIL) library configuratio apu_found="no" - if test "$ac_cv_emxos2" = "yes"; then + if test "$target_os" = "os2-emx"; then # Scripts don't pass test -x on OS/2 TEST_X="test -f" else @@ -4996,16 +5037,17 @@ if test "${with_apr_util+set}" = set; then : for lookdir in "$withval/bin" "$withval" do if $TEST_X "$lookdir/$apu_temp_apu_config_file"; then - apu_found="yes" apu_config="$lookdir/$apu_temp_apu_config_file" + + apu_found="yes" break 2 fi done done if test "$apu_found" != "yes" && $TEST_X "$withval" && $withval --help > /dev/null 2>&1 ; then - apu_found="yes" apu_config="$withval" + apu_found="yes" fi if test "$apu_found" != "yes"; then @@ -5014,8 +5056,28 @@ if test "${with_apr_util+set}" = set; then : else - if test -d """"; then - apu_temp_abs_srcdir="`cd "" && pwd`" + if test -n "1" && test "1" = "1"; then + for apu_temp_apu_config_file in $apu_temp_acceptable_apu_config + do + if $apu_temp_apu_config_file --help > /dev/null 2>&1 ; then + apu_config="$apu_temp_apu_config_file" + + apu_found="yes" + break + else + for lookdir in /usr /usr/local /usr/local/apr /opt/apr; do + if $TEST_X "$lookdir/bin/$apu_temp_apu_config_file"; then + apu_config="$lookdir/bin/$apu_temp_apu_config_file" + + apu_found="yes" + break 2 + fi + done + fi + done + fi + if test "$apu_found" = "no" && test -d """"; then + apu_temp_abs_srcdir="`cd \"""\" && pwd`" apu_found="reconfig" apu_bundled_major="`sed -n '/#define.*APU_MAJOR_VERSION/s/^[^0-9]*\([0-9]*\).*$/\1/p' \"""/include/apu_version.h\"`" case $apu_bundled_major in @@ -5035,24 +5097,6 @@ else apu_config="""/$apu_temp_apu_config_file" fi fi - if test "$apu_found" = "no" && test -n "1" && test "1" = "1"; then - for apu_temp_apu_config_file in $apu_temp_acceptable_apu_config - do - if $apu_temp_apu_config_file --help > /dev/null 2>&1 ; then - apu_found="yes" - apu_config="$apu_temp_apu_config_file" - break - else - for lookdir in /usr /usr/local /opt/apr /usr/local/apache2 ; do - if $TEST_X "$lookdir/bin/$apu_temp_apu_config_file"; then - apu_found="yes" - apu_config="$lookdir/bin/$apu_temp_apu_config_file" - break 2 - fi - done - fi - done - fi fi @@ -5426,7 +5470,7 @@ $as_echo_n "checking serf version is suitable... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } serf_found=yes - SVN_SERF_INCLUDES=`$PKG_CONFIG $serf_pc_arg --cflags | $SED -e 's/-D[^ ]*//g'` + SVN_SERF_INCLUDES=`$PKG_CONFIG $serf_pc_arg --cflags | $SED -e 's/ -D[^ ]*//g' -e 's/^-D[^ ]*//g'` SVN_SERF_LIBS=`$PKG_CONFIG $serf_pc_arg --libs-only-l` LDFLAGS="$LDFLAGS `$PKG_CONFIG $serf_pc_arg --libs | $SED -e 's/-l[^ ]*//g'`" break @@ -5774,12 +5818,23 @@ $as_echo "#define SVN_HAVE_MEMCACHE 1" >>confdefs.h fi +# Check whether --enable-apache-whitelist was given. +if test "${enable_apache_whitelist+set}" = set; then : + enableval=$enable_apache_whitelist; apache_whitelist_ver=$enableval +else + apache_whitelist_ver=no +fi + +HTTPD_WHITELIST="$apache_whitelist_ver" + HTTPD_WANTED_MMN="20051115" +HTTPD_WHITELIST_VER="$apache_whitelist_ver" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Apache module support via DSO through APXS" >&5 $as_echo_n "checking for Apache module support via DSO through APXS... " >&6; } @@ -5797,7 +5852,7 @@ fi if test -z "$APXS"; then - for i in /usr/sbin /usr/local/apache/bin /usr/local/apache2/bin /usr/bin ; do + for i in /usr/local/apache2/bin /usr/local/apache/bin /usr/bin /usr/sbin ; do if test -f "$i/apxs2"; then APXS="$i/apxs2" break @@ -5868,6 +5923,10 @@ $as_echo_n "checking mod_dav version... " >&6; } HTTPD_PATCH=`$SED -ne '/^#define AP_SERVER_PATCHLEVEL_NUMBER/p' "$APXS_INCLUDE/ap_release.h" | $SED -e 's/^.*NUMBER *//'` HTTPD_VERSION="${HTTPD_MAJOR}.${HTTPD_MINOR}.${HTTPD_PATCH}" case "$HTTPD_VERSION" in + $HTTPD_WHITELIST_VER) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: acceptable (whitelist)" >&5 +$as_echo "acceptable (whitelist)" >&6; } + ;; 2.2.25 | 2.4.[5-6]) { $as_echo "$as_me:${as_lineno-$LINENO}: result: broken" >&5 $as_echo "broken" >&6; } @@ -6053,9 +6112,10 @@ fi -SQLITE_MINIMUM_VER="3.7.12" -SQLITE_RECOMMENDED_VER="3.7.15.1" -SQLITE_URL="http://www.sqlite.org/sqlite-amalgamation-$(printf %d%02d%02d%02d $(echo ${SQLITE_RECOMMENDED_VER} | sed -e 's/\./ /g')).zip" +SQLITE_MINIMUM_VER="3.8.2" +SQLITE_RECOMMENDED_VER="3.8.11.1" +SQLITE_RECOMMENDED_VER_REL_YEAR="2015" +SQLITE_URL="https://www.sqlite.org/$SQLITE_RECOMMENDED_VER_REL_YEAR/sqlite-amalgamation-$(printf %d%02d%02d%02d $(echo ${SQLITE_RECOMMENDED_VER} | sed -e 's/\./ /g')).zip" SQLITE_MINIMUM_VER="${SQLITE_MINIMUM_VER}" @@ -19500,26 +19560,26 @@ fi -# Check whether --with-gnome_keyring was given. -if test "${with_gnome_keyring+set}" = set; then : - withval=$with_gnome_keyring; with_gnome_keyring="$withval" +# Check whether --with-old_gnome_keyring was given. +if test "${with_old_gnome_keyring+set}" = set; then : + withval=$with_old_gnome_keyring; with_old_gnome_keyring="$withval" else - with_gnome_keyring=auto + with_old_gnome_keyring=no fi -found_gnome_keyring=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to look for GNOME Keyring" >&5 -$as_echo_n "checking whether to look for GNOME Keyring... " >&6; } -if test "$with_gnome_keyring" != "no"; then +found_old_gnome_keyring=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to look for old GNOME Keyring" >&5 +$as_echo_n "checking whether to look for old GNOME Keyring... " >&6; } +if test "$with_old_gnome_keyring" != "no"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } case "$host" in *-*-darwin*) - if test "$with_gnome_keyring" = "yes"; then - as_fn_error $? "--with-gnome-keyring is not supported on Mac OS X." "$LINENO" 5 + if test "$with_old_gnome_keyring" = "yes"; then + as_fn_error $? "--with-old-gnome-keyring is not supported on Mac OS X." "$LINENO" 5 else - with_gnome_keyring=no + with_old_gnome_keyring=no fi ;; *) @@ -19536,15 +19596,15 @@ $as_echo "yes" >&6; } CPPFLAGS="$CPPFLAGS $SVN_GNOME_KEYRING_INCLUDES" ac_fn_c_check_header_mongrel "$LINENO" "gnome-keyring.h" "ac_cv_header_gnome_keyring_h" "$ac_includes_default" if test "x$ac_cv_header_gnome_keyring_h" = xyes; then : - found_gnome_keyring=yes + found_old_gnome_keyring=yes else - found_gnome_keyring=no + found_old_gnome_keyring=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNOME Keyring" >&5 $as_echo_n "checking for GNOME Keyring... " >&6; } - if test "$found_gnome_keyring" = "yes"; then + if test "$found_old_gnome_keyring" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } @@ -19555,38 +19615,38 @@ $as_echo "#define SVN_HAVE_GNOME_KEYRING 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - if test "$with_gnome_keyring" = "yes"; then + if test "$with_old_gnome_keyring" = "yes"; then as_fn_error $? "cannot find GNOME Keyring" "$LINENO" 5 fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - if test "$with_gnome_keyring" = "yes"; then + if test "$with_old_gnome_keyring" = "yes"; then as_fn_error $? "cannot find GLib and GNOME Keyring .pc files." "$LINENO" 5 else - with_gnome_keyring=no + with_old_gnome_keyring=no fi fi else - if test "$with_gnome_keyring" = "yes"; then + if test "$with_old_gnome_keyring" = "yes"; then as_fn_error $? "cannot find pkg-config. GNOME Keyring requires this." "$LINENO" 5 else - with_gnome_keyring=no + with_old_gnome_keyring=no fi fi else - if test "$with_gnome_keyring" = "yes"; then + if test "$with_old_gnome_keyring" = "yes"; then as_fn_error $? "APR does not have support for DSOs. GNOME Keyring requires this." "$LINENO" 5 else - with_gnome_keyring=no + with_old_gnome_keyring=no fi fi else - if test "$with_gnome_keyring" = "yes"; then - as_fn_error $? "--with-gnome-keyring conflicts with --disable-shared" "$LINENO" 5 + if test "$with_old_gnome_keyring" = "yes"; then + as_fn_error $? "--with-old-gnome-keyring conflicts with --disable-shared" "$LINENO" 5 else - with_gnome_keyring=no + with_old_gnome_keyring=no fi fi ;; @@ -19598,32 +19658,112 @@ fi -# Check whether --enable-gmock was given. -if test "${enable_gmock+set}" = set; then : - enableval=$enable_gmock; + + +# Check whether --with-gnome_keyring was given. +if test "${with_gnome_keyring+set}" = set; then : + withval=$with_gnome_keyring; with_gnome_keyring="$withval" else - enable_gmock=yes + with_gnome_keyring=auto fi -GMOCK_SRCDIR=$abs_srcdir/gmock-fused - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether use Googlemock" >&5 -$as_echo_n "checking whether use Googlemock... " >&6; } -if test "$enable_gmock" != "no"; then - if test -d "$GMOCK_SRCDIR"; then + found_gnome_keyring="no" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to look for GNOME Keyring" >&5 +$as_echo_n "checking whether to look for GNOME Keyring... " >&6; } + if test "$found_old_gnome_keyring" = "yes" && test "$with_gnome_keyring" = "auto"; then + with_gnome_keyring="no" + fi + if test "$with_gnome_keyring" != "no"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - SVN_USE_GMOCK=true + case "$host" in + *-*-darwin*) + if test "$with_gnome_keyring" = "yes"; then + as_fn_error $? "--with-gnome-keyring is not supported on Mac OS X." "$LINENO" 5 + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNOME Keyring" >&5 +$as_echo_n "checking for GNOME Keyring... " >&6; } + if test "$found_old_gnome_keyring" = "no"; then + if test "$svn_enable_shared" = "yes"; then + if test "$APR_HAS_DSO" = "yes"; then + if test -n "$PKG_CONFIG"; then + if $PKG_CONFIG --exists libsecret-1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +$as_echo "#define SVN_HAVE_LIBSECRET 1" >>confdefs.h + + SVN_GNOME_KEYRING_INCLUDES="`$PKG_CONFIG --cflags libsecret-1`" + SVN_GNOME_KEYRING_LIBS="`$PKG_CONFIG --libs libsecret-1`" + found_gnome_keyring="yes" + else + if test "$with_gnome_keyring" = "yes"; then + as_fn_error $? "cannot find libsecret" "$LINENO" 5 + fi + fi + else + if test "$with_gnome_keyring" = "yes"; then + as_fn_error $? "cannot find pkg-config" "$LINENO" 5 + fi + fi + else + if test "$with_gnome_keyring" = "yes"; then + as_fn_error $? "APR does not support DSOs" "$LINENO" 5 + fi + fi + else + if test "$with_gnome_keyring" = "yes"; then + as_fn_error $? "--with-gnome-keyring conflicts with --disable-shared" "$LINENO" 5 + fi + fi + else + if test "$with_gnome_keyring" = "yes"; then + as_fn_error $? "--with-gnome-keyring conflicts with --with-old-gnome-keyring" "$LINENO" 5 + fi + fi + if test "$found_gnome_keyring" = "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + ;; + esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - SVN_USE_GMOCK=false + fi + + + + +# Check whether --enable-googlemock was given. +if test "${enable_googlemock+set}" = set; then : + enableval=$enable_googlemock; +else + enable_googlemock=yes +fi + + +GOOGLEMOCK_SRCDIR=$abs_srcdir/googlemock + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether use Googlemock" >&5 +$as_echo_n "checking whether use Googlemock... " >&6; } +if test "$enable_googlemock" != "no"; then + if test -d "$GOOGLEMOCK_SRCDIR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + SVN_USE_GOOGLEMOCK=true + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + SVN_USE_GOOGLEMOCK=false fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - SVN_USE_GMOCK_SOURCES=false + SVN_USE_GOOGLEMOCK=false fi @@ -20246,34 +20386,55 @@ $as_echo "yes" >&6; } if test "$APR_HAS_DSO" = "yes"; then if test -n "$PKG_CONFIG"; then if test "$HAVE_DBUS" = "yes"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for QtCore, QtDBus, QtGui" >&5 -$as_echo_n "checking for QtCore, QtDBus, QtGui... " >&6; } - if $PKG_CONFIG --exists QtCore QtDBus QtGui; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Qt" >&5 +$as_echo_n "checking for Qt... " >&6; } + if $PKG_CONFIG --exists Qt5Core Qt5DBus Qt5Gui; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, Qt5" >&5 +$as_echo "yes, Qt5" >&6; } + qt_pkg_config_names="Qt5Core Qt5DBus Qt5Gui" + kde_config_name="kf5-config" + kde_inc_names="KF5/KWallet KF5/KCoreAddons KF5/KI18n" + kde_lib_names="-lKF5Wallet -lKF5I18n -lKF5CoreAddons -lQt5Gui -lQt5DBus -lQt5Core" + elif $PKG_CONFIG --exists QtCore QtDBus QtGui; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, Qt4" >&5 +$as_echo "yes, Qt4" >&6; } + qt_pkg_config_names="QtCore QtDBus QtGui" + kde_config_name="kde4-config" + kde_inc_names="/" + kde_lib_names="-lkdeui -lkdecore -lQtGui -lQtDBus -lQtCore" + fi + if test -n "$qt_pkg_config_names"; then if test "$svn_lib_kwallet" != "yes"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for kde4-config" >&5 -$as_echo_n "checking for kde4-config... " >&6; } - KDE4_CONFIG="$svn_lib_kwallet/bin/kde4-config" - if test -f "$KDE4_CONFIG" && test -x "$KDE4_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $kde_config_name" >&5 +$as_echo_n "checking for $kde_config_name... " >&6; } + KDE_CONFIG="$svn_lib_kwallet/bin/$kde_config_name" + if test -f "$KDE_CONFIG" && test -x "$KDE_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else - KDE4_CONFIG="" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + if echo "$svn_lib_kwallet" | $EGREP ":" > /dev/null; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unneeded" >&5 +$as_echo "unneeded" >&6; } + KDE_CONFIG="unneeded" + kde_incdir="`echo "$svn_lib_kwallet" | $SED -e "s/:.*//"`" + kde_libdir="`echo "$svn_lib_kwallet" | $SED -e "s/.*://"`" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } + KDE_CONFIG="" + fi fi else - # Extract the first word of "kde4-config", so it can be a program name with args. -set dummy kde4-config; ac_word=$2 + # Extract the first word of "$kde_config_name", so it can be a program name with args. +set dummy $kde_config_name; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_KDE4_CONFIG+:} false; then : +if ${ac_cv_path_KDE_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else - case $KDE4_CONFIG in + case $KDE_CONFIG in [\\/]* | ?:[\\/]*) - ac_cv_path_KDE4_CONFIG="$KDE4_CONFIG" # Let the user override the test with a path. + ac_cv_path_KDE_CONFIG="$KDE_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -20283,7 +20444,7 @@ do test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_KDE4_CONFIG="$as_dir/$ac_word$ac_exec_ext" + ac_cv_path_KDE_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -20294,37 +20455,94 @@ IFS=$as_save_IFS ;; esac fi -KDE4_CONFIG=$ac_cv_path_KDE4_CONFIG -if test -n "$KDE4_CONFIG"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $KDE4_CONFIG" >&5 -$as_echo "$KDE4_CONFIG" >&6; } +KDE_CONFIG=$ac_cv_path_KDE_CONFIG +if test -n "$KDE_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $KDE_CONFIG" >&5 +$as_echo "$KDE_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi + if test -n "$KDE_CONFIG"; then + kde_incdir="`$KDE_CONFIG --install include`" + kde_libdir="`$KDE_CONFIG --install lib`" + fi fi - if test -n "$KDE4_CONFIG"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for KWallet" >&5 -$as_echo_n "checking for KWallet... " >&6; } + if test -n "$KDE_CONFIG"; then + if test $kde_config_name = "kf5-config"; then + + CXXFLAGS_KEEP="$CXXFLAGS" + CXXFLAGS="" + + if test "$GXX" = "yes"; then + + _svn_xxflags__save="$CXXFLAGS" + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CXX accepts -std=c++11" >&5 +$as_echo_n "checking if $CXX accepts -std=c++11... " >&6; } + CXXFLAGS="-std=c++11 $CXXFLAGS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int main(){} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + CXXFLAGS="$_svn_xxflags__save" + + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + fi + + CXXMODEFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS_KEEP" + + + fi old_CXXFLAGS="$CXXFLAGS" old_LDFLAGS="$LDFLAGS" old_LIBS="$LIBS" - for d in `$PKG_CONFIG --cflags QtCore QtDBus QtGui`; do + CXXFLAGS="$CXXFLAGS $CXXMODEFLAGS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for KWallet" >&5 +$as_echo_n "checking for KWallet... " >&6; } + for d in `$PKG_CONFIG --cflags $qt_pkg_config_names`; do if test -n "`echo "$d" | $EGREP -- '^-D[^[:space:]]*'`"; then CPPFLAGS="$CPPFLAGS $d" fi done - qt_include_dirs="`$PKG_CONFIG --cflags-only-I QtCore QtDBus QtGui`" - kde_incdir="`$KDE4_CONFIG --install include`" - SVN_KWALLET_INCLUDES="$DBUS_CPPFLAGS $qt_include_dirs -I$kde_incdir" - qt_libs_other_options="`$PKG_CONFIG --libs-only-other QtCore QtDBus QtGui`" - SVN_KWALLET_LIBS="$DBUS_LIBS -lQtCore -lQtDBus -lQtGui -lkdecore -lkdeui $qt_libs_other_options" - CXXFLAGS="$CXXFLAGS $SVN_KWALLET_INCLUDES" + qt_include_dirs="`$PKG_CONFIG --cflags-only-I $qt_pkg_config_names`" + for kde_inc_name in $kde_inc_names; do + kde_kwallet_includes="$kde_kwallet_includes -I$kde_incdir/$kde_inc_name" + done + SVN_KWALLET_INCLUDES="$DBUS_CPPFLAGS $qt_include_dirs $kde_kwallet_includes" + qt_libs_other_options="`$PKG_CONFIG --libs-only-other $qt_pkg_config_names`" + SVN_KWALLET_LIBS="$DBUS_LIBS $kde_lib_names $qt_libs_other_options" + CXXFLAGS="$CXXFLAGS $SVN_KWALLET_INCLUDES -fPIC" LIBS="$LIBS $SVN_KWALLET_LIBS" - qt_lib_dirs="`$PKG_CONFIG --libs-only-L QtCore QtDBus QtGui`" - kde_libdir="`$KDE4_CONFIG --install lib`" + qt_lib_dirs="`$PKG_CONFIG --libs-only-L $qt_pkg_config_names`" LDFLAGS="$old_LDFLAGS ` input_flags="$qt_lib_dirs -L$kde_libdir" output_flags="" @@ -20376,18 +20594,23 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu $as_echo "yes" >&6; } CXXFLAGS="$old_CXXFLAGS" LIBS="$old_LIBS" + if test "$kde_config_name" = "kf5-config"; then + +$as_echo "#define SVN_HAVE_KF5 1" >>confdefs.h + + fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "cannot find KWallet" "$LINENO" 5 fi else - as_fn_error $? "cannot find kde4-config" "$LINENO" 5 + as_fn_error $? "cannot find $kde_config_name" "$LINENO" 5 fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - as_fn_error $? "cannot find QtCore, QtDBus, QtGui" "$LINENO" 5 + as_fn_error $? "cannot find Qt" "$LINENO" 5 fi else as_fn_error $? "cannot find D-Bus" "$LINENO" 5 @@ -20457,7 +20680,7 @@ if test "$svn_lib_kwallet" = "yes"; then INSTALL_STATIC_RULES="$INSTALL_STATIC_RULES install-kwallet-lib" fi -if test "$found_gnome_keyring" = "yes"; then +if test "$found_old_gnome_keyring" = "yes" || test "$found_gnome_keyring" = "yes"; then BUILD_RULES="$BUILD_RULES gnome-keyring-lib" INSTALL_RULES="`echo $INSTALL_RULES | $SED 's/install-lib/install-lib install-gnome-keyring-lib/'`" INSTALL_STATIC_RULES="$INSTALL_STATIC_RULES install-gnome-keyring-lib" @@ -20894,6 +21117,7 @@ $as_echo "yes" >&6; } for library_dir in "$abs_srcdir/subversion/libsvn_"*; do eval "`basename $library_dir`_LDFLAGS=-Wl,--no-undefined" done + shared_only_LDFLAGS="-Wl,--no-undefined" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } @@ -20919,7 +21143,6 @@ fi - # Check whether --enable-maintainer-mode was given. if test "${enable_maintainer_mode+set}" = set; then : enableval=$enable_maintainer_mode; @@ -21262,6 +21485,44 @@ if ac_fn_c_try_link "$LINENO"; then : $as_echo "yes" >&6; } +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + CFLAGS="$_svn_xxflags__save" + + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + _svn_xxflags__save="$CFLAGS" + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC accepts -Wno-unused-const-variable" >&5 +$as_echo_n "checking if $CC accepts -Wno-unused-const-variable... " >&6; } + CFLAGS="-Wno-unused-const-variable $CFLAGS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int main(void){return 0;} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 @@ -21283,7 +21544,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu CMAINTAINERFLAGS="$CFLAGS" CFLAGS="$CFLAGS_KEEP" - CMAINTAINERFLAGS="-Wall -Wpointer-arith -Wwrite-strings -Wshadow -Wformat=2 -Wunused -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wno-multichar -Wredundant-decls -Wnested-externs -Winline -Wno-long-long -Wbad-function-cast $CMAINTAINERFLAGS" + CMAINTAINERFLAGS="-Wall -Wpointer-arith -Wwrite-strings -Wshadow -Wformat=2 -Wunused -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wno-multichar -Wredundant-decls -Wnested-externs -Winline -Wno-long-long -Wbad-function-cast $CMAINTAINERFLAGS" fi if test "$GXX" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: maintainer-mode: adding G++ warning flags" >&5 @@ -22764,6 +23025,354 @@ fi + + +# Check whether --with-lz4 was given. +if test "${with_lz4+set}" = set; then : + withval=$with_lz4; + if test "$withval" = internal; then + lz4_prefix=internal + elif test "$withval" = yes; then + lz4_prefix=std + else + lz4_prefix="$withval" + fi + +else + lz4_prefix=std +fi + + + if test "$lz4_prefix" = "internal"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: using internal lz4" >&5 +$as_echo "$as_me: using internal lz4" >&6;} + +$as_echo "#define SVN_INTERNAL_LZ4 1" >>confdefs.h + + else + if test "$lz4_prefix" = "std"; then + + if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lz4 library via pkg-config" >&5 +$as_echo_n "checking for lz4 library via pkg-config... " >&6; } + if $PKG_CONFIG liblz4 --atleast-version=129 || $PKG_CONFIG liblz4 --max-version=3; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + lz4_found=yes + SVN_LZ4_INCLUDES=`$PKG_CONFIG liblz4 --cflags` + SVN_LZ4_LIBS=`$PKG_CONFIG liblz4 --libs` + SVN_LZ4_LIBS="` + input_flags="$SVN_LZ4_LIBS" + output_flags="" + filtered_dirs="/lib /lib64 /usr/lib /usr/lib64" + for flag in $input_flags; do + filter="no" + for dir in $filtered_dirs; do + if test "$flag" = "-L$dir" || test "$flag" = "-L$dir/"; then + filter="yes" + break + fi + done + if test "$filter" = "no"; then + output_flags="$output_flags $flag" + fi + done + if test -n "$output_flags"; then + printf "%s" "${output_flags# }" + fi +`" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + fi + if test "$lz4_found" != "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: lz4 configuration without pkg-config" >&5 +$as_echo "$as_me: lz4 configuration without pkg-config" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LZ4_compress_default in -llz4" >&5 +$as_echo_n "checking for LZ4_compress_default in -llz4... " >&6; } +if ${ac_cv_lib_lz4_LZ4_compress_default+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-llz4 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char LZ4_compress_default (); +int +main () +{ +return LZ4_compress_default (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_lz4_LZ4_compress_default=yes +else + ac_cv_lib_lz4_LZ4_compress_default=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lz4_LZ4_compress_default" >&5 +$as_echo "$ac_cv_lib_lz4_LZ4_compress_default" >&6; } +if test "x$ac_cv_lib_lz4_LZ4_compress_default" = xyes; then : + + lz4_found=yes + SVN_LZ4_LIBS="-llz4" + +fi + + fi + + else + + { $as_echo "$as_me:${as_lineno-$LINENO}: lz4 configuration via prefix" >&5 +$as_echo "$as_me: lz4 configuration via prefix" >&6;} + save_cppflags="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I$lz4_prefix/include" + save_ldflags="$LDFLAGS" + LDFLAGS="$LDFLAGS -L$lz4_prefix/lib" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LZ4_compress_default in -llz4" >&5 +$as_echo_n "checking for LZ4_compress_default in -llz4... " >&6; } +if ${ac_cv_lib_lz4_LZ4_compress_default+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-llz4 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char LZ4_compress_default (); +int +main () +{ +return LZ4_compress_default (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_lz4_LZ4_compress_default=yes +else + ac_cv_lib_lz4_LZ4_compress_default=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lz4_LZ4_compress_default" >&5 +$as_echo "$ac_cv_lib_lz4_LZ4_compress_default" >&6; } +if test "x$ac_cv_lib_lz4_LZ4_compress_default" = xyes; then : + + lz4_found=yes + SVN_LZ4_INCLUDES="-I$lz4_prefix/include" + SVN_LZ4_LIBS="` + input_flags="-L$lz4_prefix/lib" + output_flags="" + filtered_dirs="/lib /lib64 /usr/lib /usr/lib64" + for flag in $input_flags; do + filter="no" + for dir in $filtered_dirs; do + if test "$flag" = "-L$dir" || test "$flag" = "-L$dir/"; then + filter="yes" + break + fi + done + if test "$filter" = "no"; then + output_flags="$output_flags $flag" + fi + done + if test -n "$output_flags"; then + printf "%s" "${output_flags# }" + fi +` -llz4" + +fi + + LDFLAGS="$save_ldflags" + CPPFLAGS="$save_cppflags" + + fi + if test "$lz4_found" != "yes"; then + as_fn_error $? "Subversion requires LZ4 >= r129, or use --with-lz4=internal" "$LINENO" 5 + fi + fi + + + + + + +# Check whether --with-utf8proc was given. +if test "${with_utf8proc+set}" = set; then : + withval=$with_utf8proc; + if test "$withval" = internal; then + utf8proc_prefix=internal + elif test "$withval" = yes; then + utf8proc_prefix=std + else + utf8proc_prefix="$withval" + fi + +else + utf8proc_prefix=std +fi + + + if test "$utf8proc_prefix" = "internal"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: using internal utf8proc" >&5 +$as_echo "$as_me: using internal utf8proc" >&6;} + +$as_echo "#define SVN_INTERNAL_UTF8PROC 1" >>confdefs.h + + else + if test "$utf8proc_prefix" = "std"; then + + { $as_echo "$as_me:${as_lineno-$LINENO}: utf8proc configuration without pkg-config" >&5 +$as_echo "$as_me: utf8proc configuration without pkg-config" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for utf8proc_version in -lutf8proc" >&5 +$as_echo_n "checking for utf8proc_version in -lutf8proc... " >&6; } +if ${ac_cv_lib_utf8proc_utf8proc_version+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lutf8proc $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char utf8proc_version (); +int +main () +{ +return utf8proc_version (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_utf8proc_utf8proc_version=yes +else + ac_cv_lib_utf8proc_utf8proc_version=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_utf8proc_utf8proc_version" >&5 +$as_echo "$ac_cv_lib_utf8proc_utf8proc_version" >&6; } +if test "x$ac_cv_lib_utf8proc_utf8proc_version" = xyes; then : + + utf8proc_found=yes + SVN_UTF8PROC_LIBS="-lutf8proc" + +fi + + + else + + { $as_echo "$as_me:${as_lineno-$LINENO}: utf8proc configuration via prefix" >&5 +$as_echo "$as_me: utf8proc configuration via prefix" >&6;} + save_cppflags="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -I$utf8proc_prefix/include" + save_ldflags="$LDFLAGS" + LDFLAGS="$LDFLAGS -L$utf8proc_prefix/lib" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for utf8proc_version in -lutf8proc" >&5 +$as_echo_n "checking for utf8proc_version in -lutf8proc... " >&6; } +if ${ac_cv_lib_utf8proc_utf8proc_version+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lutf8proc $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char utf8proc_version (); +int +main () +{ +return utf8proc_version (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_utf8proc_utf8proc_version=yes +else + ac_cv_lib_utf8proc_utf8proc_version=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_utf8proc_utf8proc_version" >&5 +$as_echo "$ac_cv_lib_utf8proc_utf8proc_version" >&6; } +if test "x$ac_cv_lib_utf8proc_utf8proc_version" = xyes; then : + + utf8proc_found=yes + SVN_UTF8PROC_INCLUDES="-I$utf8proc_prefix/include" + SVN_UTF8PROC_LIBS="` + input_flags="-L$utf8proc_prefix/lib" + output_flags="" + filtered_dirs="/lib /lib64 /usr/lib /usr/lib64" + for flag in $input_flags; do + filter="no" + for dir in $filtered_dirs; do + if test "$flag" = "-L$dir" || test "$flag" = "-L$dir/"; then + filter="yes" + break + fi + done + if test "$filter" = "no"; then + output_flags="$output_flags $flag" + fi + done + if test -n "$output_flags"; then + printf "%s" "${output_flags# }" + fi +` -lutf8proc" + +fi + + LDFLAGS="$save_ldflags" + CPPFLAGS="$save_cppflags" + + fi + if test "$utf8proc_found" != "yes"; then + as_fn_error $? "Subversion requires UTF8PROC" "$LINENO" 5 + fi + fi + + + + MOD_ACTIVATION="" # Check whether --enable-mod-activation was given. if test "${enable_mod_activation+set}" = set; then : @@ -23013,39 +23622,17 @@ $as_echo "$as_me: WARNING: You may need to install the latest Java Development p JAVADOC="$JAVA_BIN/javadoc" JAR="$JAVA_BIN/jar" - jikes_options="/usr/local/bin/jikes /usr/bin/jikes" # Check whether --with-jikes was given. if test "${with_jikes+set}" = set; then : withval=$with_jikes; - if test "$withval" != "no" && test "$withval" != "yes"; then - jikes_options="$withval $jikes_options" - fi - requested_jikes="$withval" # will be 'yes' if path unspecified + if test "$withval" != "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: The --with-jikes option was ignored" >&5 +$as_echo "$as_me: WARNING: The --with-jikes option was ignored" >&2;} + fi fi - if test "$requested_jikes" != "no"; then - for jikes in $jikes_options; do - if test -z "$jikes_found" && test -x "$jikes"; then - jikes_found="yes" - JAVAC="$jikes" - JAVA_CLASSPATH="$JRE_LIB_DIR" - for jar in $JRE_LIB_DIR/*.jar; do - JAVA_CLASSPATH="$JAVA_CLASSPATH:$jar" - done - fi - done - fi - if test -n "$requested_jikes" && test "$requested_jikes" != "no"; then - if test -z "$jikes_found"; then - as_fn_error $? "Could not find a usable version of Jikes" "$LINENO" 5 - elif test -n "$jikes_found" && test "$requested_jikes" != "yes" && - test "$JAVAC" != "$requested_jikes"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-jikes PATH was invalid, substitute found" >&5 -$as_echo "$as_me: WARNING: --with-jikes PATH was invalid, substitute found" >&2;} - fi - fi # The release for "-source" could actually be greater than that # of "-target", if we want to cross-compile for lesser JVMs. @@ -23175,39 +23762,17 @@ $as_echo "$as_me: WARNING: You may need to install the latest Java Development p JAVADOC="$JAVA_BIN/javadoc" JAR="$JAVA_BIN/jar" - jikes_options="/usr/local/bin/jikes /usr/bin/jikes" # Check whether --with-jikes was given. if test "${with_jikes+set}" = set; then : withval=$with_jikes; - if test "$withval" != "no" && test "$withval" != "yes"; then - jikes_options="$withval $jikes_options" - fi - requested_jikes="$withval" # will be 'yes' if path unspecified + if test "$withval" != "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: The --with-jikes option was ignored" >&5 +$as_echo "$as_me: WARNING: The --with-jikes option was ignored" >&2;} + fi fi - if test "$requested_jikes" != "no"; then - for jikes in $jikes_options; do - if test -z "$jikes_found" && test -x "$jikes"; then - jikes_found="yes" - JAVAC="$jikes" - JAVA_CLASSPATH="$JRE_LIB_DIR" - for jar in $JRE_LIB_DIR/*.jar; do - JAVA_CLASSPATH="$JAVA_CLASSPATH:$jar" - done - fi - done - fi - if test -n "$requested_jikes" && test "$requested_jikes" != "no"; then - if test -z "$jikes_found"; then - as_fn_error $? "Could not find a usable version of Jikes" "$LINENO" 5 - elif test -n "$jikes_found" && test "$requested_jikes" != "yes" && - test "$JAVAC" != "$requested_jikes"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-jikes PATH was invalid, substitute found" >&5 -$as_echo "$as_me: WARNING: --with-jikes PATH was invalid, substitute found" >&2;} - fi - fi # The release for "-source" could actually be greater than that # of "-target", if we want to cross-compile for lesser JVMs. @@ -23340,39 +23905,17 @@ $as_echo "$as_me: WARNING: You may need to install the latest Java Development p JAVADOC="$JAVA_BIN/javadoc" JAR="$JAVA_BIN/jar" - jikes_options="/usr/local/bin/jikes /usr/bin/jikes" # Check whether --with-jikes was given. if test "${with_jikes+set}" = set; then : withval=$with_jikes; - if test "$withval" != "no" && test "$withval" != "yes"; then - jikes_options="$withval $jikes_options" - fi - requested_jikes="$withval" # will be 'yes' if path unspecified + if test "$withval" != "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: The --with-jikes option was ignored" >&5 +$as_echo "$as_me: WARNING: The --with-jikes option was ignored" >&2;} + fi fi - if test "$requested_jikes" != "no"; then - for jikes in $jikes_options; do - if test -z "$jikes_found" && test -x "$jikes"; then - jikes_found="yes" - JAVAC="$jikes" - JAVA_CLASSPATH="$JRE_LIB_DIR" - for jar in $JRE_LIB_DIR/*.jar; do - JAVA_CLASSPATH="$JAVA_CLASSPATH:$jar" - done - fi - done - fi - if test -n "$requested_jikes" && test "$requested_jikes" != "no"; then - if test -z "$jikes_found"; then - as_fn_error $? "Could not find a usable version of Jikes" "$LINENO" 5 - elif test -n "$jikes_found" && test "$requested_jikes" != "yes" && - test "$JAVAC" != "$requested_jikes"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-jikes PATH was invalid, substitute found" >&5 -$as_echo "$as_me: WARNING: --with-jikes PATH was invalid, substitute found" >&2;} - fi - fi # The release for "-source" could actually be greater than that # of "-target", if we want to cross-compile for lesser JVMs. @@ -23493,7 +24036,7 @@ fi else - for ac_prog in ruby ruby1.8 ruby18 ruby1.9 ruby1 ruby1.9.3 ruby193 ruby2.0 ruby2.1 + for ac_prog in ruby ruby1 ruby1.8 ruby18 ruby1.9 ruby19 ruby1.9.3 ruby193 ruby2 ruby2.0 ruby20 ruby2.1 ruby21 ruby2.2 ruby22 ruby2.3 ruby23 ruby2.4 ruby24 do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 @@ -23589,18 +24132,18 @@ fi else - for ac_prog in rdoc rdoc1.8 rdoc18 rdoc1.9 rdoc19 rdoc1.9.3 rdoc193 rdoc2.0 rdoc2.1 + for ac_prog in rdoc rdoc1 rdoc1.8 rdoc18 rdoc1.9 rdoc19 rdoc1.9.3 rdoc193 rdoc2 rdoc2.0 rdoc20 rdoc2.1 rdoc21 rdoc2.2 rdoc22 rdoc2.3 rdoc23 rdoc2.4 rdoc24 do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_RDOC+:} false; then : +if ${ac_cv_path_RUBY+:} false; then : $as_echo_n "(cached) " >&6 else - case $RDOC in + case $RUBY in [\\/]* | ?:[\\/]*) - ac_cv_path_RDOC="$RDOC" # Let the user override the test with a path. + ac_cv_path_RUBY="$RUBY" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -23610,7 +24153,7 @@ do test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_RDOC="$as_dir/$ac_word$ac_exec_ext" + ac_cv_path_RUBY="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -23621,19 +24164,19 @@ IFS=$as_save_IFS ;; esac fi -RDOC=$ac_cv_path_RDOC -if test -n "$RDOC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RDOC" >&5 -$as_echo "$RDOC" >&6; } +RUBY=$ac_cv_path_RUBY +if test -n "$RUBY"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RUBY" >&5 +$as_echo "$RUBY" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi - test -n "$RDOC" && break + test -n "$RUBY" && break done -test -n "$RDOC" || RDOC="none" +test -n "$RUBY" || RUBY="none" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Ruby major version" >&5 @@ -23683,8 +24226,8 @@ $as_echo "$svn_cv_ruby_teeny" >&6; } RUBY="none" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: The detected Ruby is between 1.9 and 1.9.3" >&5 $as_echo "$as_me: WARNING: The detected Ruby is between 1.9 and 1.9.3" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Only 1.8.x and 1.9.3 releases are supported at this time" >&5 -$as_echo "$as_me: WARNING: Only 1.8.x and 1.9.3 releases are supported at this time" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Only 1.8.x and 1.9.3 or later are supported at this time" >&5 +$as_echo "$as_me: WARNING: Only 1.8.x and 1.9.3 or later are supported at this time" >&2;} fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 @@ -23714,7 +24257,7 @@ if test "${with_swig+set}" = set; then : if test $where = no; then SWIG=none - elif test $where = check; then + elif test $where = required || test $where = check; then # Extract the first word of "swig", so it can be a program name with args. set dummy swig; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 @@ -23756,6 +24299,9 @@ $as_echo "no" >&6; } fi + if test "$SWIG" = "none" && test $where = required; then + as_fn_error $? "SWIG required, but not found" "$LINENO" 5 + fi else if test -f "$where"; then SWIG="$where" @@ -23788,10 +24334,6 @@ $as_echo_n "checking swig version... " >&6; } $as_echo "$SWIG_VERSION_RAW" >&6; } # If you change the required swig version number, don't forget to update: # subversion/bindings/swig/INSTALL - # packages/rpm/redhat-8+/subversion.spec - # packages/rpm/redhat-7.x/subversion.spec - # packages/rpm/rhel-3/subversion.spec - # packages/rpm/rhel-4/subversion.spec if test -n "$SWIG_VERSION" && test "$SWIG_VERSION" -ge "103024"; then SWIG_SUITABLE=yes else @@ -23801,70 +24343,69 @@ $as_echo "$as_me: WARNING: Detected SWIG version $SWIG_VERSION_RAW" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Subversion requires SWIG >= 1.3.24" >&5 $as_echo "$as_me: WARNING: Subversion requires SWIG >= 1.3.24" >&2;} fi - fi - SWIG_PY_COMPILE="none" - SWIG_PY_LINK="none" - if test "$PYTHON" != "none"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Configuring python swig binding" >&5 + SWIG_PY_COMPILE="none" + SWIG_PY_LINK="none" + if test "$PYTHON" != "none"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Configuring python swig binding" >&5 $as_echo "$as_me: Configuring python swig binding" >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python includes" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python includes" >&5 $as_echo_n "checking for Python includes... " >&6; } if ${ac_cv_python_includes+:} false; then : $as_echo_n "(cached) " >&6 else - ac_cv_python_includes="`$PYTHON ${abs_srcdir}/build/get-py-info.py --includes`" + ac_cv_python_includes="`$PYTHON ${abs_srcdir}/build/get-py-info.py --includes`" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_python_includes" >&5 $as_echo "$ac_cv_python_includes" >&6; } - SWIG_PY_INCLUDES="\$(SWIG_INCLUDES) $ac_cv_python_includes" + SWIG_PY_INCLUDES="\$(SWIG_INCLUDES) $ac_cv_python_includes" - if test "$ac_cv_python_includes" = "none"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: python bindings cannot be built without distutils module" >&5 + if test "$ac_cv_python_includes" = "none"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: python bindings cannot be built without distutils module" >&5 $as_echo "$as_me: WARNING: python bindings cannot be built without distutils module" >&2;} - fi + fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for compiling Python extensions" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for compiling Python extensions" >&5 $as_echo_n "checking for compiling Python extensions... " >&6; } if ${ac_cv_python_compile+:} false; then : $as_echo_n "(cached) " >&6 else - ac_cv_python_compile="`$PYTHON ${abs_srcdir}/build/get-py-info.py --compile`" + ac_cv_python_compile="`$PYTHON ${abs_srcdir}/build/get-py-info.py --compile`" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_python_compile" >&5 $as_echo "$ac_cv_python_compile" >&6; } - SWIG_PY_COMPILE="$ac_cv_python_compile $CFLAGS" + SWIG_PY_COMPILE="$ac_cv_python_compile $CFLAGS" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linking Python extensions" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linking Python extensions" >&5 $as_echo_n "checking for linking Python extensions... " >&6; } if ${ac_cv_python_link+:} false; then : $as_echo_n "(cached) " >&6 else - ac_cv_python_link="`$PYTHON ${abs_srcdir}/build/get-py-info.py --link`" + ac_cv_python_link="`$PYTHON ${abs_srcdir}/build/get-py-info.py --link`" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_python_link" >&5 $as_echo "$ac_cv_python_link" >&6; } - SWIG_PY_LINK="$ac_cv_python_link" + SWIG_PY_LINK="$ac_cv_python_link" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linking Python libraries" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linking Python libraries" >&5 $as_echo_n "checking for linking Python libraries... " >&6; } if ${ac_cv_python_libs+:} false; then : $as_echo_n "(cached) " >&6 else - ac_cv_python_libs="`$PYTHON ${abs_srcdir}/build/get-py-info.py --libs`" + ac_cv_python_libs="`$PYTHON ${abs_srcdir}/build/get-py-info.py --libs`" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_python_libs" >&5 $as_echo "$ac_cv_python_libs" >&6; } - SWIG_PY_LIBS="` + SWIG_PY_LIBS="` input_flags="$ac_cv_python_libs" output_flags="" filtered_dirs="/lib /lib64 /usr/lib /usr/lib64" @@ -23885,19 +24426,19 @@ $as_echo "$ac_cv_python_libs" >&6; } fi `" - SVN_PYCFMT_SAVE_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $SVN_APR_INCLUDES" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for apr_int64_t Python/C API format string" >&5 + SVN_PYCFMT_SAVE_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $SVN_APR_INCLUDES" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for apr_int64_t Python/C API format string" >&5 $as_echo_n "checking for apr_int64_t Python/C API format string... " >&6; } if ${svn_cv_pycfmt_apr_int64_t+:} false; then : $as_echo_n "(cached) " >&6 else - if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include - MaTcHtHiS APR_INT64_T_FMT EnDeNd + MaTcHtHiS APR_INT64_T_FMT EnDeNd _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "MaTcHtHiS +\"lld\" +EnDeNd" >/dev/null 2>&1; then : @@ -23905,13 +24446,13 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | fi rm -f conftest* - fi - if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + fi + if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ r - #include - MaTcHtHiS APR_INT64_T_FMT EnDeNd + #include + MaTcHtHiS APR_INT64_T_FMT EnDeNd _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "MaTcHtHiS +\"ld\" +EnDeNd" >/dev/null 2>&1; then : @@ -23919,12 +24460,12 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | fi rm -f conftest* - fi - if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + fi + if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include - MaTcHtHiS APR_INT64_T_FMT EnDeNd + MaTcHtHiS APR_INT64_T_FMT EnDeNd _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "MaTcHtHiS +\"d\" +EnDeNd" >/dev/null 2>&1; then : @@ -23932,85 +24473,106 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | fi rm -f conftest* - fi + fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $svn_cv_pycfmt_apr_int64_t" >&5 $as_echo "$svn_cv_pycfmt_apr_int64_t" >&6; } - CPPFLAGS="$SVN_PYCFMT_SAVE_CPPFLAGS" - if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then - as_fn_error $? "failed to recognize APR_INT64_T_FMT on this platform" "$LINENO" 5 - fi + CPPFLAGS="$SVN_PYCFMT_SAVE_CPPFLAGS" + if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then + as_fn_error $? "failed to recognize APR_INT64_T_FMT on this platform" "$LINENO" 5 + fi cat >>confdefs.h <<_ACEOF #define SVN_APR_INT64_T_PYCFMT "$svn_cv_pycfmt_apr_int64_t" _ACEOF - fi - - if test "$PERL" != "none"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking perl version" >&5 -$as_echo_n "checking perl version... " >&6; } - PERL_VERSION="`$PERL -e 'q([); print $] * 1000000,$/;'`" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL_VERSION" >&5 -$as_echo "$PERL_VERSION" >&6; } - if test "$PERL_VERSION" -ge "5008000"; then - SWIG_PL_INCLUDES="\$(SWIG_INCLUDES) `$PERL -MExtUtils::Embed -e ccopts`" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: perl bindings require perl 5.8.0 or newer." >&5 -$as_echo "$as_me: WARNING: perl bindings require perl 5.8.0 or newer." >&2;} fi - fi - SWIG_RB_COMPILE="none" - SWIG_RB_LINK="none" - if test "$RUBY" != "none"; then - rbconfig="$RUBY -rrbconfig -e " - - for var_name in arch archdir CC LDSHARED DLEXT LIBS LIBRUBYARG \ - rubyhdrdir rubyarchhdrdir sitedir sitelibdir sitearchdir libdir - do - rbconfig_tmp=`$rbconfig "print RbConfig::CONFIG['$var_name']"` - eval "rbconfig_$var_name=\"$rbconfig_tmp\"" + if test "$PERL" != "none"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking perl version" >&5 +$as_echo_n "checking perl version... " >&6; } + PERL_VERSION="`$PERL -e 'q([); print $] * 1000000,$/;'`" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL_VERSION" >&5 +$as_echo "$PERL_VERSION" >&6; } + if test "$PERL_VERSION" -ge "5008000"; then + SWIG_PL_INCLUDES="\$(SWIG_INCLUDES) `$PERL -MExtUtils::Embed -e ccopts`" + SWIG_PL_LINK="`$PERL -MExtUtils::Embed -e ldopts`" + SWIG_PL_LINK="` + input_flags="$SWIG_PL_LINK" + output_flags="" + filtered_dirs="/lib /lib64 /usr/lib /usr/lib64" + for flag in $input_flags; do + filter="no" + for dir in $filtered_dirs; do + if test "$flag" = "-L$dir" || test "$flag" = "-L$dir/"; then + filter="yes" + break + fi done + if test "$filter" = "no"; then + output_flags="$output_flags $flag" + fi + done + if test -n "$output_flags"; then + printf "%s" "${output_flags# }" + fi +`" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: perl bindings require perl 5.8.0 or newer." >&5 +$as_echo "$as_me: WARNING: perl bindings require perl 5.8.0 or newer." >&2;} + fi + fi - { $as_echo "$as_me:${as_lineno-$LINENO}: Configuring Ruby SWIG binding" >&5 + SWIG_RB_COMPILE="none" + SWIG_RB_LINK="none" + if test "$RUBY" != "none"; then + rbconfig="$RUBY -rrbconfig -e " + + for var_name in arch archdir CC LDSHARED DLEXT LIBS LIBRUBYARG \ + rubyhdrdir rubyarchhdrdir sitedir sitelibdir sitearchdir libdir + do + rbconfig_tmp=`$rbconfig "print RbConfig::CONFIG['$var_name']"` + eval "rbconfig_$var_name=\"$rbconfig_tmp\"" + done + + { $as_echo "$as_me:${as_lineno-$LINENO}: Configuring Ruby SWIG binding" >&5 $as_echo "$as_me: Configuring Ruby SWIG binding" >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Ruby include path" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Ruby include path" >&5 $as_echo_n "checking for Ruby include path... " >&6; } if ${svn_cv_ruby_includes+:} false; then : $as_echo_n "(cached) " >&6 else - if test -d "$rbconfig_rubyhdrdir"; then - svn_cv_ruby_includes="-I. -I$rbconfig_rubyhdrdir -I$rbconfig_rubyhdrdir/ruby -I$rbconfig_rubyhdrdir/ruby/backward" - if test -d "$rbconfig_rubyarchhdrdir"; then - svn_cv_ruby_includes="$svn_cv_ruby_includes -I$rbconfig_rubyarchhdrdir" + if test -d "$rbconfig_rubyhdrdir"; then + svn_cv_ruby_includes="-I. -I$rbconfig_rubyhdrdir -I$rbconfig_rubyhdrdir/ruby -I$rbconfig_rubyhdrdir/ruby/backward" + if test -d "$rbconfig_rubyarchhdrdir"; then + svn_cv_ruby_includes="$svn_cv_ruby_includes -I$rbconfig_rubyarchhdrdir" + else + svn_cv_ruby_includes="$svn_cv_ruby_includes -I$rbconfig_rubyhdrdir/$rbconfig_arch" + fi else - svn_cv_ruby_includes="$svn_cv_ruby_includes -I$rbconfig_rubyhdrdir/$rbconfig_arch" + svn_cv_ruby_includes="-I. -I$rbconfig_archdir" fi - else - svn_cv_ruby_includes="-I. -I$rbconfig_archdir" - fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $svn_cv_ruby_includes" >&5 $as_echo "$svn_cv_ruby_includes" >&6; } - SWIG_RB_INCLUDES="\$(SWIG_INCLUDES) $svn_cv_ruby_includes" + SWIG_RB_INCLUDES="\$(SWIG_INCLUDES) $svn_cv_ruby_includes" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to compile Ruby extensions" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to compile Ruby extensions" >&5 $as_echo_n "checking how to compile Ruby extensions... " >&6; } if ${svn_cv_ruby_compile+:} false; then : $as_echo_n "(cached) " >&6 else - svn_cv_ruby_compile="$rbconfig_CC $CFLAGS" + svn_cv_ruby_compile="$rbconfig_CC $CFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $svn_cv_ruby_compile" >&5 $as_echo "$svn_cv_ruby_compile" >&6; } - SWIG_RB_COMPILE="$svn_cv_ruby_compile" + SWIG_RB_COMPILE="$svn_cv_ruby_compile" SWIG_RB_COMPILE=`echo "$SWIG_RB_COMPILE" | $SED -e 's/-ansi//'` @@ -24020,36 +24582,36 @@ $as_echo "$svn_cv_ruby_compile" >&6; } SWIG_RB_COMPILE=`echo "$SWIG_RB_COMPILE" | $SED -e 's/-std=c90//'` - SWIG_RB_COMPILE="$SWIG_RB_COMPILE -Wno-int-to-pointer-cast" + SWIG_RB_COMPILE="$SWIG_RB_COMPILE -Wno-int-to-pointer-cast" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link Ruby extensions" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link Ruby extensions" >&5 $as_echo_n "checking how to link Ruby extensions... " >&6; } if ${svn_cv_ruby_link+:} false; then : $as_echo_n "(cached) " >&6 else - svn_cv_ruby_link="`$RUBY -e 'ARGV.shift; print ARGV.join(%q( ))' \ - $rbconfig_LDSHARED`" - svn_cv_ruby_link="$rbconfig_CC $svn_cv_ruby_link" - svn_cv_ruby_link="$svn_cv_ruby_link -shrext .$rbconfig_DLEXT" + svn_cv_ruby_link="`$RUBY -e 'ARGV.shift; print ARGV.join(%q( ))' \ + $rbconfig_LDSHARED`" + svn_cv_ruby_link="$rbconfig_CC $svn_cv_ruby_link" + svn_cv_ruby_link="$svn_cv_ruby_link -shrext .$rbconfig_DLEXT" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $svn_cv_ruby_link" >&5 $as_echo "$svn_cv_ruby_link" >&6; } - SWIG_RB_LINK="$svn_cv_ruby_link" + SWIG_RB_LINK="$svn_cv_ruby_link" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link Ruby libraries" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link Ruby libraries" >&5 $as_echo_n "checking how to link Ruby libraries... " >&6; } if ${ac_cv_ruby_libs+:} false; then : $as_echo_n "(cached) " >&6 else - ac_cv_ruby_libs="$rbconfig_LIBRUBYARG $rbconfig_LIBS" + ac_cv_ruby_libs="$rbconfig_LIBRUBYARG $rbconfig_LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_ruby_libs" >&5 $as_echo "$ac_cv_ruby_libs" >&6; } - SWIG_RB_LIBS="` + SWIG_RB_LIBS="` input_flags="$ac_cv_ruby_libs" output_flags="" filtered_dirs="/lib /lib64 /usr/lib /usr/lib64" @@ -24070,11 +24632,11 @@ $as_echo "$ac_cv_ruby_libs" >&6; } fi `" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rb_errinfo" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rb_errinfo" >&5 $as_echo_n "checking for rb_errinfo... " >&6; } - old_CFLAGS="$CFLAGS" - old_LIBS="$LIBS" - CFLAGS="$CFLAGS $svn_cv_ruby_includes" + old_CFLAGS="$CFLAGS" + old_LIBS="$LIBS" + CFLAGS="$CFLAGS $svn_cv_ruby_includes" CFLAGS=`echo "$CFLAGS" | $SED -e 's/-ansi//'` @@ -24084,8 +24646,8 @@ $as_echo_n "checking for rb_errinfo... " >&6; } CFLAGS=`echo "$CFLAGS" | $SED -e 's/-std=c90//'` - LIBS="$SWIG_RB_LIBS" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + LIBS="$SWIG_RB_LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include @@ -24099,24 +24661,24 @@ else fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - if test "$have_rb_errinfo" = "yes"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 + if test "$have_rb_errinfo" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_RB_ERRINFO 1" >>confdefs.h - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - fi - CFLAGS="$old_CFLAGS" - LIBS="$old_LIBS" + fi + CFLAGS="$old_CFLAGS" + LIBS="$old_LIBS" - if ${svn_cv_ruby_sitedir+:} false; then : + if ${svn_cv_ruby_sitedir+:} false; then : $as_echo_n "(cached) " >&6 else - svn_cv_ruby_sitedir="$rbconfig_sitedir" + svn_cv_ruby_sitedir="$rbconfig_sitedir" fi @@ -24129,43 +24691,43 @@ else fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to install Ruby scripts" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to install Ruby scripts" >&5 $as_echo_n "checking where to install Ruby scripts... " >&6; } - if ${svn_cv_ruby_sitedir_libsuffix+:} false; then : + if ${svn_cv_ruby_sitedir_libsuffix+:} false; then : $as_echo_n "(cached) " >&6 else - svn_cv_ruby_sitedir_libsuffix="`echo "$rbconfig_sitelibdir" | \ - $SED -e "s,^$rbconfig_sitedir,,"`" + svn_cv_ruby_sitedir_libsuffix="`echo "$rbconfig_sitelibdir" | \ + $SED -e "s,^$rbconfig_sitedir,,"`" fi - SWIG_RB_SITE_LIB_DIR="${svn_ruby_installdir}${svn_cv_ruby_sitedir_libsuffix}" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG_RB_SITE_LIB_DIR" >&5 + SWIG_RB_SITE_LIB_DIR="${svn_ruby_installdir}${svn_cv_ruby_sitedir_libsuffix}" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG_RB_SITE_LIB_DIR" >&5 $as_echo "$SWIG_RB_SITE_LIB_DIR" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to install Ruby extensions" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to install Ruby extensions" >&5 $as_echo_n "checking where to install Ruby extensions... " >&6; } - if ${svn_cv_ruby_sitedir_archsuffix+:} false; then : + if ${svn_cv_ruby_sitedir_archsuffix+:} false; then : $as_echo_n "(cached) " >&6 else - svn_cv_ruby_sitedir_archsuffix="`echo "$rbconfig_sitearchdir" | \ - $SED -e "s,^$rbconfig_sitedir,,"`" + svn_cv_ruby_sitedir_archsuffix="`echo "$rbconfig_sitearchdir" | \ + $SED -e "s,^$rbconfig_sitedir,,"`" fi - SWIG_RB_SITE_ARCH_DIR="${svn_ruby_installdir}${svn_cv_ruby_sitedir_archsuffix}" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG_RB_SITE_ARCH_DIR" >&5 + SWIG_RB_SITE_ARCH_DIR="${svn_ruby_installdir}${svn_cv_ruby_sitedir_archsuffix}" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG_RB_SITE_ARCH_DIR" >&5 $as_echo "$SWIG_RB_SITE_ARCH_DIR" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to use output level for Ruby bindings tests" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to use output level for Ruby bindings tests" >&5 $as_echo_n "checking how to use output level for Ruby bindings tests... " >&6; } - if ${svn_cv_ruby_test_verbose+:} false; then : + if ${svn_cv_ruby_test_verbose+:} false; then : $as_echo_n "(cached) " >&6 else - svn_cv_ruby_test_verbose="normal" + svn_cv_ruby_test_verbose="normal" fi @@ -24177,9 +24739,10 @@ else svn_ruby_test_verbose="$svn_cv_ruby_test_verbose" fi - SWIG_RB_TEST_VERBOSE="$svn_ruby_test_verbose" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG_RB_TEST_VERBOSE" >&5 + SWIG_RB_TEST_VERBOSE="$svn_ruby_test_verbose" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG_RB_TEST_VERBOSE" >&5 $as_echo "$SWIG_RB_TEST_VERBOSE" >&6; } + fi fi @@ -24195,14 +24758,15 @@ $as_echo "$SWIG_RB_TEST_VERBOSE" >&6; } + ;; "yes") - where=check + where=required if test $where = no; then SWIG=none - elif test $where = check; then + elif test $where = required || test $where = check; then # Extract the first word of "swig", so it can be a program name with args. set dummy swig; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 @@ -24244,6 +24808,9 @@ $as_echo "no" >&6; } fi + if test "$SWIG" = "none" && test $where = required; then + as_fn_error $? "SWIG required, but not found" "$LINENO" 5 + fi else if test -f "$where"; then SWIG="$where" @@ -24276,10 +24843,6 @@ $as_echo_n "checking swig version... " >&6; } $as_echo "$SWIG_VERSION_RAW" >&6; } # If you change the required swig version number, don't forget to update: # subversion/bindings/swig/INSTALL - # packages/rpm/redhat-8+/subversion.spec - # packages/rpm/redhat-7.x/subversion.spec - # packages/rpm/rhel-3/subversion.spec - # packages/rpm/rhel-4/subversion.spec if test -n "$SWIG_VERSION" && test "$SWIG_VERSION" -ge "103024"; then SWIG_SUITABLE=yes else @@ -24289,70 +24852,69 @@ $as_echo "$as_me: WARNING: Detected SWIG version $SWIG_VERSION_RAW" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Subversion requires SWIG >= 1.3.24" >&5 $as_echo "$as_me: WARNING: Subversion requires SWIG >= 1.3.24" >&2;} fi - fi - SWIG_PY_COMPILE="none" - SWIG_PY_LINK="none" - if test "$PYTHON" != "none"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Configuring python swig binding" >&5 + SWIG_PY_COMPILE="none" + SWIG_PY_LINK="none" + if test "$PYTHON" != "none"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Configuring python swig binding" >&5 $as_echo "$as_me: Configuring python swig binding" >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python includes" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python includes" >&5 $as_echo_n "checking for Python includes... " >&6; } if ${ac_cv_python_includes+:} false; then : $as_echo_n "(cached) " >&6 else - ac_cv_python_includes="`$PYTHON ${abs_srcdir}/build/get-py-info.py --includes`" + ac_cv_python_includes="`$PYTHON ${abs_srcdir}/build/get-py-info.py --includes`" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_python_includes" >&5 $as_echo "$ac_cv_python_includes" >&6; } - SWIG_PY_INCLUDES="\$(SWIG_INCLUDES) $ac_cv_python_includes" + SWIG_PY_INCLUDES="\$(SWIG_INCLUDES) $ac_cv_python_includes" - if test "$ac_cv_python_includes" = "none"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: python bindings cannot be built without distutils module" >&5 + if test "$ac_cv_python_includes" = "none"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: python bindings cannot be built without distutils module" >&5 $as_echo "$as_me: WARNING: python bindings cannot be built without distutils module" >&2;} - fi + fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for compiling Python extensions" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for compiling Python extensions" >&5 $as_echo_n "checking for compiling Python extensions... " >&6; } if ${ac_cv_python_compile+:} false; then : $as_echo_n "(cached) " >&6 else - ac_cv_python_compile="`$PYTHON ${abs_srcdir}/build/get-py-info.py --compile`" + ac_cv_python_compile="`$PYTHON ${abs_srcdir}/build/get-py-info.py --compile`" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_python_compile" >&5 $as_echo "$ac_cv_python_compile" >&6; } - SWIG_PY_COMPILE="$ac_cv_python_compile $CFLAGS" + SWIG_PY_COMPILE="$ac_cv_python_compile $CFLAGS" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linking Python extensions" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linking Python extensions" >&5 $as_echo_n "checking for linking Python extensions... " >&6; } if ${ac_cv_python_link+:} false; then : $as_echo_n "(cached) " >&6 else - ac_cv_python_link="`$PYTHON ${abs_srcdir}/build/get-py-info.py --link`" + ac_cv_python_link="`$PYTHON ${abs_srcdir}/build/get-py-info.py --link`" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_python_link" >&5 $as_echo "$ac_cv_python_link" >&6; } - SWIG_PY_LINK="$ac_cv_python_link" + SWIG_PY_LINK="$ac_cv_python_link" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linking Python libraries" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linking Python libraries" >&5 $as_echo_n "checking for linking Python libraries... " >&6; } if ${ac_cv_python_libs+:} false; then : $as_echo_n "(cached) " >&6 else - ac_cv_python_libs="`$PYTHON ${abs_srcdir}/build/get-py-info.py --libs`" + ac_cv_python_libs="`$PYTHON ${abs_srcdir}/build/get-py-info.py --libs`" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_python_libs" >&5 $as_echo "$ac_cv_python_libs" >&6; } - SWIG_PY_LIBS="` + SWIG_PY_LIBS="` input_flags="$ac_cv_python_libs" output_flags="" filtered_dirs="/lib /lib64 /usr/lib /usr/lib64" @@ -24373,19 +24935,19 @@ $as_echo "$ac_cv_python_libs" >&6; } fi `" - SVN_PYCFMT_SAVE_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $SVN_APR_INCLUDES" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for apr_int64_t Python/C API format string" >&5 + SVN_PYCFMT_SAVE_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $SVN_APR_INCLUDES" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for apr_int64_t Python/C API format string" >&5 $as_echo_n "checking for apr_int64_t Python/C API format string... " >&6; } if ${svn_cv_pycfmt_apr_int64_t+:} false; then : $as_echo_n "(cached) " >&6 else - if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include - MaTcHtHiS APR_INT64_T_FMT EnDeNd + MaTcHtHiS APR_INT64_T_FMT EnDeNd _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "MaTcHtHiS +\"lld\" +EnDeNd" >/dev/null 2>&1; then : @@ -24393,13 +24955,13 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | fi rm -f conftest* - fi - if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + fi + if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ r - #include - MaTcHtHiS APR_INT64_T_FMT EnDeNd + #include + MaTcHtHiS APR_INT64_T_FMT EnDeNd _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "MaTcHtHiS +\"ld\" +EnDeNd" >/dev/null 2>&1; then : @@ -24407,12 +24969,12 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | fi rm -f conftest* - fi - if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + fi + if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include - MaTcHtHiS APR_INT64_T_FMT EnDeNd + MaTcHtHiS APR_INT64_T_FMT EnDeNd _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "MaTcHtHiS +\"d\" +EnDeNd" >/dev/null 2>&1; then : @@ -24420,85 +24982,106 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | fi rm -f conftest* - fi + fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $svn_cv_pycfmt_apr_int64_t" >&5 $as_echo "$svn_cv_pycfmt_apr_int64_t" >&6; } - CPPFLAGS="$SVN_PYCFMT_SAVE_CPPFLAGS" - if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then - as_fn_error $? "failed to recognize APR_INT64_T_FMT on this platform" "$LINENO" 5 - fi + CPPFLAGS="$SVN_PYCFMT_SAVE_CPPFLAGS" + if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then + as_fn_error $? "failed to recognize APR_INT64_T_FMT on this platform" "$LINENO" 5 + fi cat >>confdefs.h <<_ACEOF #define SVN_APR_INT64_T_PYCFMT "$svn_cv_pycfmt_apr_int64_t" _ACEOF - fi - - if test "$PERL" != "none"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking perl version" >&5 -$as_echo_n "checking perl version... " >&6; } - PERL_VERSION="`$PERL -e 'q([); print $] * 1000000,$/;'`" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL_VERSION" >&5 -$as_echo "$PERL_VERSION" >&6; } - if test "$PERL_VERSION" -ge "5008000"; then - SWIG_PL_INCLUDES="\$(SWIG_INCLUDES) `$PERL -MExtUtils::Embed -e ccopts`" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: perl bindings require perl 5.8.0 or newer." >&5 -$as_echo "$as_me: WARNING: perl bindings require perl 5.8.0 or newer." >&2;} fi - fi - SWIG_RB_COMPILE="none" - SWIG_RB_LINK="none" - if test "$RUBY" != "none"; then - rbconfig="$RUBY -rrbconfig -e " - - for var_name in arch archdir CC LDSHARED DLEXT LIBS LIBRUBYARG \ - rubyhdrdir rubyarchhdrdir sitedir sitelibdir sitearchdir libdir - do - rbconfig_tmp=`$rbconfig "print RbConfig::CONFIG['$var_name']"` - eval "rbconfig_$var_name=\"$rbconfig_tmp\"" + if test "$PERL" != "none"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking perl version" >&5 +$as_echo_n "checking perl version... " >&6; } + PERL_VERSION="`$PERL -e 'q([); print $] * 1000000,$/;'`" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL_VERSION" >&5 +$as_echo "$PERL_VERSION" >&6; } + if test "$PERL_VERSION" -ge "5008000"; then + SWIG_PL_INCLUDES="\$(SWIG_INCLUDES) `$PERL -MExtUtils::Embed -e ccopts`" + SWIG_PL_LINK="`$PERL -MExtUtils::Embed -e ldopts`" + SWIG_PL_LINK="` + input_flags="$SWIG_PL_LINK" + output_flags="" + filtered_dirs="/lib /lib64 /usr/lib /usr/lib64" + for flag in $input_flags; do + filter="no" + for dir in $filtered_dirs; do + if test "$flag" = "-L$dir" || test "$flag" = "-L$dir/"; then + filter="yes" + break + fi done + if test "$filter" = "no"; then + output_flags="$output_flags $flag" + fi + done + if test -n "$output_flags"; then + printf "%s" "${output_flags# }" + fi +`" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: perl bindings require perl 5.8.0 or newer." >&5 +$as_echo "$as_me: WARNING: perl bindings require perl 5.8.0 or newer." >&2;} + fi + fi - { $as_echo "$as_me:${as_lineno-$LINENO}: Configuring Ruby SWIG binding" >&5 + SWIG_RB_COMPILE="none" + SWIG_RB_LINK="none" + if test "$RUBY" != "none"; then + rbconfig="$RUBY -rrbconfig -e " + + for var_name in arch archdir CC LDSHARED DLEXT LIBS LIBRUBYARG \ + rubyhdrdir rubyarchhdrdir sitedir sitelibdir sitearchdir libdir + do + rbconfig_tmp=`$rbconfig "print RbConfig::CONFIG['$var_name']"` + eval "rbconfig_$var_name=\"$rbconfig_tmp\"" + done + + { $as_echo "$as_me:${as_lineno-$LINENO}: Configuring Ruby SWIG binding" >&5 $as_echo "$as_me: Configuring Ruby SWIG binding" >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Ruby include path" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Ruby include path" >&5 $as_echo_n "checking for Ruby include path... " >&6; } if ${svn_cv_ruby_includes+:} false; then : $as_echo_n "(cached) " >&6 else - if test -d "$rbconfig_rubyhdrdir"; then - svn_cv_ruby_includes="-I. -I$rbconfig_rubyhdrdir -I$rbconfig_rubyhdrdir/ruby -I$rbconfig_rubyhdrdir/ruby/backward" - if test -d "$rbconfig_rubyarchhdrdir"; then - svn_cv_ruby_includes="$svn_cv_ruby_includes -I$rbconfig_rubyarchhdrdir" + if test -d "$rbconfig_rubyhdrdir"; then + svn_cv_ruby_includes="-I. -I$rbconfig_rubyhdrdir -I$rbconfig_rubyhdrdir/ruby -I$rbconfig_rubyhdrdir/ruby/backward" + if test -d "$rbconfig_rubyarchhdrdir"; then + svn_cv_ruby_includes="$svn_cv_ruby_includes -I$rbconfig_rubyarchhdrdir" + else + svn_cv_ruby_includes="$svn_cv_ruby_includes -I$rbconfig_rubyhdrdir/$rbconfig_arch" + fi else - svn_cv_ruby_includes="$svn_cv_ruby_includes -I$rbconfig_rubyhdrdir/$rbconfig_arch" + svn_cv_ruby_includes="-I. -I$rbconfig_archdir" fi - else - svn_cv_ruby_includes="-I. -I$rbconfig_archdir" - fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $svn_cv_ruby_includes" >&5 $as_echo "$svn_cv_ruby_includes" >&6; } - SWIG_RB_INCLUDES="\$(SWIG_INCLUDES) $svn_cv_ruby_includes" + SWIG_RB_INCLUDES="\$(SWIG_INCLUDES) $svn_cv_ruby_includes" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to compile Ruby extensions" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to compile Ruby extensions" >&5 $as_echo_n "checking how to compile Ruby extensions... " >&6; } if ${svn_cv_ruby_compile+:} false; then : $as_echo_n "(cached) " >&6 else - svn_cv_ruby_compile="$rbconfig_CC $CFLAGS" + svn_cv_ruby_compile="$rbconfig_CC $CFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $svn_cv_ruby_compile" >&5 $as_echo "$svn_cv_ruby_compile" >&6; } - SWIG_RB_COMPILE="$svn_cv_ruby_compile" + SWIG_RB_COMPILE="$svn_cv_ruby_compile" SWIG_RB_COMPILE=`echo "$SWIG_RB_COMPILE" | $SED -e 's/-ansi//'` @@ -24508,36 +25091,36 @@ $as_echo "$svn_cv_ruby_compile" >&6; } SWIG_RB_COMPILE=`echo "$SWIG_RB_COMPILE" | $SED -e 's/-std=c90//'` - SWIG_RB_COMPILE="$SWIG_RB_COMPILE -Wno-int-to-pointer-cast" + SWIG_RB_COMPILE="$SWIG_RB_COMPILE -Wno-int-to-pointer-cast" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link Ruby extensions" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link Ruby extensions" >&5 $as_echo_n "checking how to link Ruby extensions... " >&6; } if ${svn_cv_ruby_link+:} false; then : $as_echo_n "(cached) " >&6 else - svn_cv_ruby_link="`$RUBY -e 'ARGV.shift; print ARGV.join(%q( ))' \ - $rbconfig_LDSHARED`" - svn_cv_ruby_link="$rbconfig_CC $svn_cv_ruby_link" - svn_cv_ruby_link="$svn_cv_ruby_link -shrext .$rbconfig_DLEXT" + svn_cv_ruby_link="`$RUBY -e 'ARGV.shift; print ARGV.join(%q( ))' \ + $rbconfig_LDSHARED`" + svn_cv_ruby_link="$rbconfig_CC $svn_cv_ruby_link" + svn_cv_ruby_link="$svn_cv_ruby_link -shrext .$rbconfig_DLEXT" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $svn_cv_ruby_link" >&5 $as_echo "$svn_cv_ruby_link" >&6; } - SWIG_RB_LINK="$svn_cv_ruby_link" + SWIG_RB_LINK="$svn_cv_ruby_link" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link Ruby libraries" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link Ruby libraries" >&5 $as_echo_n "checking how to link Ruby libraries... " >&6; } if ${ac_cv_ruby_libs+:} false; then : $as_echo_n "(cached) " >&6 else - ac_cv_ruby_libs="$rbconfig_LIBRUBYARG $rbconfig_LIBS" + ac_cv_ruby_libs="$rbconfig_LIBRUBYARG $rbconfig_LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_ruby_libs" >&5 $as_echo "$ac_cv_ruby_libs" >&6; } - SWIG_RB_LIBS="` + SWIG_RB_LIBS="` input_flags="$ac_cv_ruby_libs" output_flags="" filtered_dirs="/lib /lib64 /usr/lib /usr/lib64" @@ -24558,11 +25141,11 @@ $as_echo "$ac_cv_ruby_libs" >&6; } fi `" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rb_errinfo" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rb_errinfo" >&5 $as_echo_n "checking for rb_errinfo... " >&6; } - old_CFLAGS="$CFLAGS" - old_LIBS="$LIBS" - CFLAGS="$CFLAGS $svn_cv_ruby_includes" + old_CFLAGS="$CFLAGS" + old_LIBS="$LIBS" + CFLAGS="$CFLAGS $svn_cv_ruby_includes" CFLAGS=`echo "$CFLAGS" | $SED -e 's/-ansi//'` @@ -24572,8 +25155,8 @@ $as_echo_n "checking for rb_errinfo... " >&6; } CFLAGS=`echo "$CFLAGS" | $SED -e 's/-std=c90//'` - LIBS="$SWIG_RB_LIBS" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + LIBS="$SWIG_RB_LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include @@ -24587,24 +25170,24 @@ else fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - if test "$have_rb_errinfo" = "yes"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 + if test "$have_rb_errinfo" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_RB_ERRINFO 1" >>confdefs.h - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - fi - CFLAGS="$old_CFLAGS" - LIBS="$old_LIBS" + fi + CFLAGS="$old_CFLAGS" + LIBS="$old_LIBS" - if ${svn_cv_ruby_sitedir+:} false; then : + if ${svn_cv_ruby_sitedir+:} false; then : $as_echo_n "(cached) " >&6 else - svn_cv_ruby_sitedir="$rbconfig_sitedir" + svn_cv_ruby_sitedir="$rbconfig_sitedir" fi @@ -24617,43 +25200,43 @@ else fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to install Ruby scripts" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to install Ruby scripts" >&5 $as_echo_n "checking where to install Ruby scripts... " >&6; } - if ${svn_cv_ruby_sitedir_libsuffix+:} false; then : + if ${svn_cv_ruby_sitedir_libsuffix+:} false; then : $as_echo_n "(cached) " >&6 else - svn_cv_ruby_sitedir_libsuffix="`echo "$rbconfig_sitelibdir" | \ - $SED -e "s,^$rbconfig_sitedir,,"`" + svn_cv_ruby_sitedir_libsuffix="`echo "$rbconfig_sitelibdir" | \ + $SED -e "s,^$rbconfig_sitedir,,"`" fi - SWIG_RB_SITE_LIB_DIR="${svn_ruby_installdir}${svn_cv_ruby_sitedir_libsuffix}" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG_RB_SITE_LIB_DIR" >&5 + SWIG_RB_SITE_LIB_DIR="${svn_ruby_installdir}${svn_cv_ruby_sitedir_libsuffix}" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG_RB_SITE_LIB_DIR" >&5 $as_echo "$SWIG_RB_SITE_LIB_DIR" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to install Ruby extensions" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to install Ruby extensions" >&5 $as_echo_n "checking where to install Ruby extensions... " >&6; } - if ${svn_cv_ruby_sitedir_archsuffix+:} false; then : + if ${svn_cv_ruby_sitedir_archsuffix+:} false; then : $as_echo_n "(cached) " >&6 else - svn_cv_ruby_sitedir_archsuffix="`echo "$rbconfig_sitearchdir" | \ - $SED -e "s,^$rbconfig_sitedir,,"`" + svn_cv_ruby_sitedir_archsuffix="`echo "$rbconfig_sitearchdir" | \ + $SED -e "s,^$rbconfig_sitedir,,"`" fi - SWIG_RB_SITE_ARCH_DIR="${svn_ruby_installdir}${svn_cv_ruby_sitedir_archsuffix}" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG_RB_SITE_ARCH_DIR" >&5 + SWIG_RB_SITE_ARCH_DIR="${svn_ruby_installdir}${svn_cv_ruby_sitedir_archsuffix}" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG_RB_SITE_ARCH_DIR" >&5 $as_echo "$SWIG_RB_SITE_ARCH_DIR" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to use output level for Ruby bindings tests" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to use output level for Ruby bindings tests" >&5 $as_echo_n "checking how to use output level for Ruby bindings tests... " >&6; } - if ${svn_cv_ruby_test_verbose+:} false; then : + if ${svn_cv_ruby_test_verbose+:} false; then : $as_echo_n "(cached) " >&6 else - svn_cv_ruby_test_verbose="normal" + svn_cv_ruby_test_verbose="normal" fi @@ -24665,9 +25248,10 @@ else svn_ruby_test_verbose="$svn_cv_ruby_test_verbose" fi - SWIG_RB_TEST_VERBOSE="$svn_ruby_test_verbose" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG_RB_TEST_VERBOSE" >&5 + SWIG_RB_TEST_VERBOSE="$svn_ruby_test_verbose" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG_RB_TEST_VERBOSE" >&5 $as_echo "$SWIG_RB_TEST_VERBOSE" >&6; } + fi fi @@ -24683,6 +25267,7 @@ $as_echo "$SWIG_RB_TEST_VERBOSE" >&6; } + ;; *) @@ -24690,7 +25275,7 @@ $as_echo "$SWIG_RB_TEST_VERBOSE" >&6; } if test $where = no; then SWIG=none - elif test $where = check; then + elif test $where = required || test $where = check; then # Extract the first word of "swig", so it can be a program name with args. set dummy swig; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 @@ -24732,6 +25317,9 @@ $as_echo "no" >&6; } fi + if test "$SWIG" = "none" && test $where = required; then + as_fn_error $? "SWIG required, but not found" "$LINENO" 5 + fi else if test -f "$where"; then SWIG="$where" @@ -24764,10 +25352,6 @@ $as_echo_n "checking swig version... " >&6; } $as_echo "$SWIG_VERSION_RAW" >&6; } # If you change the required swig version number, don't forget to update: # subversion/bindings/swig/INSTALL - # packages/rpm/redhat-8+/subversion.spec - # packages/rpm/redhat-7.x/subversion.spec - # packages/rpm/rhel-3/subversion.spec - # packages/rpm/rhel-4/subversion.spec if test -n "$SWIG_VERSION" && test "$SWIG_VERSION" -ge "103024"; then SWIG_SUITABLE=yes else @@ -24777,70 +25361,69 @@ $as_echo "$as_me: WARNING: Detected SWIG version $SWIG_VERSION_RAW" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Subversion requires SWIG >= 1.3.24" >&5 $as_echo "$as_me: WARNING: Subversion requires SWIG >= 1.3.24" >&2;} fi - fi - SWIG_PY_COMPILE="none" - SWIG_PY_LINK="none" - if test "$PYTHON" != "none"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Configuring python swig binding" >&5 + SWIG_PY_COMPILE="none" + SWIG_PY_LINK="none" + if test "$PYTHON" != "none"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Configuring python swig binding" >&5 $as_echo "$as_me: Configuring python swig binding" >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python includes" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python includes" >&5 $as_echo_n "checking for Python includes... " >&6; } if ${ac_cv_python_includes+:} false; then : $as_echo_n "(cached) " >&6 else - ac_cv_python_includes="`$PYTHON ${abs_srcdir}/build/get-py-info.py --includes`" + ac_cv_python_includes="`$PYTHON ${abs_srcdir}/build/get-py-info.py --includes`" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_python_includes" >&5 $as_echo "$ac_cv_python_includes" >&6; } - SWIG_PY_INCLUDES="\$(SWIG_INCLUDES) $ac_cv_python_includes" + SWIG_PY_INCLUDES="\$(SWIG_INCLUDES) $ac_cv_python_includes" - if test "$ac_cv_python_includes" = "none"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: python bindings cannot be built without distutils module" >&5 + if test "$ac_cv_python_includes" = "none"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: python bindings cannot be built without distutils module" >&5 $as_echo "$as_me: WARNING: python bindings cannot be built without distutils module" >&2;} - fi + fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for compiling Python extensions" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for compiling Python extensions" >&5 $as_echo_n "checking for compiling Python extensions... " >&6; } if ${ac_cv_python_compile+:} false; then : $as_echo_n "(cached) " >&6 else - ac_cv_python_compile="`$PYTHON ${abs_srcdir}/build/get-py-info.py --compile`" + ac_cv_python_compile="`$PYTHON ${abs_srcdir}/build/get-py-info.py --compile`" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_python_compile" >&5 $as_echo "$ac_cv_python_compile" >&6; } - SWIG_PY_COMPILE="$ac_cv_python_compile $CFLAGS" + SWIG_PY_COMPILE="$ac_cv_python_compile $CFLAGS" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linking Python extensions" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linking Python extensions" >&5 $as_echo_n "checking for linking Python extensions... " >&6; } if ${ac_cv_python_link+:} false; then : $as_echo_n "(cached) " >&6 else - ac_cv_python_link="`$PYTHON ${abs_srcdir}/build/get-py-info.py --link`" + ac_cv_python_link="`$PYTHON ${abs_srcdir}/build/get-py-info.py --link`" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_python_link" >&5 $as_echo "$ac_cv_python_link" >&6; } - SWIG_PY_LINK="$ac_cv_python_link" + SWIG_PY_LINK="$ac_cv_python_link" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linking Python libraries" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linking Python libraries" >&5 $as_echo_n "checking for linking Python libraries... " >&6; } if ${ac_cv_python_libs+:} false; then : $as_echo_n "(cached) " >&6 else - ac_cv_python_libs="`$PYTHON ${abs_srcdir}/build/get-py-info.py --libs`" + ac_cv_python_libs="`$PYTHON ${abs_srcdir}/build/get-py-info.py --libs`" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_python_libs" >&5 $as_echo "$ac_cv_python_libs" >&6; } - SWIG_PY_LIBS="` + SWIG_PY_LIBS="` input_flags="$ac_cv_python_libs" output_flags="" filtered_dirs="/lib /lib64 /usr/lib /usr/lib64" @@ -24861,19 +25444,19 @@ $as_echo "$ac_cv_python_libs" >&6; } fi `" - SVN_PYCFMT_SAVE_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $SVN_APR_INCLUDES" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for apr_int64_t Python/C API format string" >&5 + SVN_PYCFMT_SAVE_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $SVN_APR_INCLUDES" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for apr_int64_t Python/C API format string" >&5 $as_echo_n "checking for apr_int64_t Python/C API format string... " >&6; } if ${svn_cv_pycfmt_apr_int64_t+:} false; then : $as_echo_n "(cached) " >&6 else - if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include - MaTcHtHiS APR_INT64_T_FMT EnDeNd + MaTcHtHiS APR_INT64_T_FMT EnDeNd _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "MaTcHtHiS +\"lld\" +EnDeNd" >/dev/null 2>&1; then : @@ -24881,13 +25464,13 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | fi rm -f conftest* - fi - if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + fi + if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ r - #include - MaTcHtHiS APR_INT64_T_FMT EnDeNd + #include + MaTcHtHiS APR_INT64_T_FMT EnDeNd _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "MaTcHtHiS +\"ld\" +EnDeNd" >/dev/null 2>&1; then : @@ -24895,12 +25478,12 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | fi rm -f conftest* - fi - if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + fi + if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include - MaTcHtHiS APR_INT64_T_FMT EnDeNd + MaTcHtHiS APR_INT64_T_FMT EnDeNd _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "MaTcHtHiS +\"d\" +EnDeNd" >/dev/null 2>&1; then : @@ -24908,85 +25491,106 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | fi rm -f conftest* - fi + fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $svn_cv_pycfmt_apr_int64_t" >&5 $as_echo "$svn_cv_pycfmt_apr_int64_t" >&6; } - CPPFLAGS="$SVN_PYCFMT_SAVE_CPPFLAGS" - if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then - as_fn_error $? "failed to recognize APR_INT64_T_FMT on this platform" "$LINENO" 5 - fi + CPPFLAGS="$SVN_PYCFMT_SAVE_CPPFLAGS" + if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then + as_fn_error $? "failed to recognize APR_INT64_T_FMT on this platform" "$LINENO" 5 + fi cat >>confdefs.h <<_ACEOF #define SVN_APR_INT64_T_PYCFMT "$svn_cv_pycfmt_apr_int64_t" _ACEOF - fi - - if test "$PERL" != "none"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking perl version" >&5 -$as_echo_n "checking perl version... " >&6; } - PERL_VERSION="`$PERL -e 'q([); print $] * 1000000,$/;'`" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL_VERSION" >&5 -$as_echo "$PERL_VERSION" >&6; } - if test "$PERL_VERSION" -ge "5008000"; then - SWIG_PL_INCLUDES="\$(SWIG_INCLUDES) `$PERL -MExtUtils::Embed -e ccopts`" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: perl bindings require perl 5.8.0 or newer." >&5 -$as_echo "$as_me: WARNING: perl bindings require perl 5.8.0 or newer." >&2;} fi - fi - SWIG_RB_COMPILE="none" - SWIG_RB_LINK="none" - if test "$RUBY" != "none"; then - rbconfig="$RUBY -rrbconfig -e " - - for var_name in arch archdir CC LDSHARED DLEXT LIBS LIBRUBYARG \ - rubyhdrdir rubyarchhdrdir sitedir sitelibdir sitearchdir libdir - do - rbconfig_tmp=`$rbconfig "print RbConfig::CONFIG['$var_name']"` - eval "rbconfig_$var_name=\"$rbconfig_tmp\"" + if test "$PERL" != "none"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking perl version" >&5 +$as_echo_n "checking perl version... " >&6; } + PERL_VERSION="`$PERL -e 'q([); print $] * 1000000,$/;'`" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL_VERSION" >&5 +$as_echo "$PERL_VERSION" >&6; } + if test "$PERL_VERSION" -ge "5008000"; then + SWIG_PL_INCLUDES="\$(SWIG_INCLUDES) `$PERL -MExtUtils::Embed -e ccopts`" + SWIG_PL_LINK="`$PERL -MExtUtils::Embed -e ldopts`" + SWIG_PL_LINK="` + input_flags="$SWIG_PL_LINK" + output_flags="" + filtered_dirs="/lib /lib64 /usr/lib /usr/lib64" + for flag in $input_flags; do + filter="no" + for dir in $filtered_dirs; do + if test "$flag" = "-L$dir" || test "$flag" = "-L$dir/"; then + filter="yes" + break + fi done + if test "$filter" = "no"; then + output_flags="$output_flags $flag" + fi + done + if test -n "$output_flags"; then + printf "%s" "${output_flags# }" + fi +`" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: perl bindings require perl 5.8.0 or newer." >&5 +$as_echo "$as_me: WARNING: perl bindings require perl 5.8.0 or newer." >&2;} + fi + fi - { $as_echo "$as_me:${as_lineno-$LINENO}: Configuring Ruby SWIG binding" >&5 + SWIG_RB_COMPILE="none" + SWIG_RB_LINK="none" + if test "$RUBY" != "none"; then + rbconfig="$RUBY -rrbconfig -e " + + for var_name in arch archdir CC LDSHARED DLEXT LIBS LIBRUBYARG \ + rubyhdrdir rubyarchhdrdir sitedir sitelibdir sitearchdir libdir + do + rbconfig_tmp=`$rbconfig "print RbConfig::CONFIG['$var_name']"` + eval "rbconfig_$var_name=\"$rbconfig_tmp\"" + done + + { $as_echo "$as_me:${as_lineno-$LINENO}: Configuring Ruby SWIG binding" >&5 $as_echo "$as_me: Configuring Ruby SWIG binding" >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Ruby include path" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Ruby include path" >&5 $as_echo_n "checking for Ruby include path... " >&6; } if ${svn_cv_ruby_includes+:} false; then : $as_echo_n "(cached) " >&6 else - if test -d "$rbconfig_rubyhdrdir"; then - svn_cv_ruby_includes="-I. -I$rbconfig_rubyhdrdir -I$rbconfig_rubyhdrdir/ruby -I$rbconfig_rubyhdrdir/ruby/backward" - if test -d "$rbconfig_rubyarchhdrdir"; then - svn_cv_ruby_includes="$svn_cv_ruby_includes -I$rbconfig_rubyarchhdrdir" + if test -d "$rbconfig_rubyhdrdir"; then + svn_cv_ruby_includes="-I. -I$rbconfig_rubyhdrdir -I$rbconfig_rubyhdrdir/ruby -I$rbconfig_rubyhdrdir/ruby/backward" + if test -d "$rbconfig_rubyarchhdrdir"; then + svn_cv_ruby_includes="$svn_cv_ruby_includes -I$rbconfig_rubyarchhdrdir" + else + svn_cv_ruby_includes="$svn_cv_ruby_includes -I$rbconfig_rubyhdrdir/$rbconfig_arch" + fi else - svn_cv_ruby_includes="$svn_cv_ruby_includes -I$rbconfig_rubyhdrdir/$rbconfig_arch" + svn_cv_ruby_includes="-I. -I$rbconfig_archdir" fi - else - svn_cv_ruby_includes="-I. -I$rbconfig_archdir" - fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $svn_cv_ruby_includes" >&5 $as_echo "$svn_cv_ruby_includes" >&6; } - SWIG_RB_INCLUDES="\$(SWIG_INCLUDES) $svn_cv_ruby_includes" + SWIG_RB_INCLUDES="\$(SWIG_INCLUDES) $svn_cv_ruby_includes" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to compile Ruby extensions" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to compile Ruby extensions" >&5 $as_echo_n "checking how to compile Ruby extensions... " >&6; } if ${svn_cv_ruby_compile+:} false; then : $as_echo_n "(cached) " >&6 else - svn_cv_ruby_compile="$rbconfig_CC $CFLAGS" + svn_cv_ruby_compile="$rbconfig_CC $CFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $svn_cv_ruby_compile" >&5 $as_echo "$svn_cv_ruby_compile" >&6; } - SWIG_RB_COMPILE="$svn_cv_ruby_compile" + SWIG_RB_COMPILE="$svn_cv_ruby_compile" SWIG_RB_COMPILE=`echo "$SWIG_RB_COMPILE" | $SED -e 's/-ansi//'` @@ -24996,36 +25600,36 @@ $as_echo "$svn_cv_ruby_compile" >&6; } SWIG_RB_COMPILE=`echo "$SWIG_RB_COMPILE" | $SED -e 's/-std=c90//'` - SWIG_RB_COMPILE="$SWIG_RB_COMPILE -Wno-int-to-pointer-cast" + SWIG_RB_COMPILE="$SWIG_RB_COMPILE -Wno-int-to-pointer-cast" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link Ruby extensions" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link Ruby extensions" >&5 $as_echo_n "checking how to link Ruby extensions... " >&6; } if ${svn_cv_ruby_link+:} false; then : $as_echo_n "(cached) " >&6 else - svn_cv_ruby_link="`$RUBY -e 'ARGV.shift; print ARGV.join(%q( ))' \ - $rbconfig_LDSHARED`" - svn_cv_ruby_link="$rbconfig_CC $svn_cv_ruby_link" - svn_cv_ruby_link="$svn_cv_ruby_link -shrext .$rbconfig_DLEXT" + svn_cv_ruby_link="`$RUBY -e 'ARGV.shift; print ARGV.join(%q( ))' \ + $rbconfig_LDSHARED`" + svn_cv_ruby_link="$rbconfig_CC $svn_cv_ruby_link" + svn_cv_ruby_link="$svn_cv_ruby_link -shrext .$rbconfig_DLEXT" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $svn_cv_ruby_link" >&5 $as_echo "$svn_cv_ruby_link" >&6; } - SWIG_RB_LINK="$svn_cv_ruby_link" + SWIG_RB_LINK="$svn_cv_ruby_link" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link Ruby libraries" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link Ruby libraries" >&5 $as_echo_n "checking how to link Ruby libraries... " >&6; } if ${ac_cv_ruby_libs+:} false; then : $as_echo_n "(cached) " >&6 else - ac_cv_ruby_libs="$rbconfig_LIBRUBYARG $rbconfig_LIBS" + ac_cv_ruby_libs="$rbconfig_LIBRUBYARG $rbconfig_LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_ruby_libs" >&5 $as_echo "$ac_cv_ruby_libs" >&6; } - SWIG_RB_LIBS="` + SWIG_RB_LIBS="` input_flags="$ac_cv_ruby_libs" output_flags="" filtered_dirs="/lib /lib64 /usr/lib /usr/lib64" @@ -25046,11 +25650,11 @@ $as_echo "$ac_cv_ruby_libs" >&6; } fi `" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rb_errinfo" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rb_errinfo" >&5 $as_echo_n "checking for rb_errinfo... " >&6; } - old_CFLAGS="$CFLAGS" - old_LIBS="$LIBS" - CFLAGS="$CFLAGS $svn_cv_ruby_includes" + old_CFLAGS="$CFLAGS" + old_LIBS="$LIBS" + CFLAGS="$CFLAGS $svn_cv_ruby_includes" CFLAGS=`echo "$CFLAGS" | $SED -e 's/-ansi//'` @@ -25060,8 +25664,8 @@ $as_echo_n "checking for rb_errinfo... " >&6; } CFLAGS=`echo "$CFLAGS" | $SED -e 's/-std=c90//'` - LIBS="$SWIG_RB_LIBS" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + LIBS="$SWIG_RB_LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include @@ -25075,24 +25679,24 @@ else fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - if test "$have_rb_errinfo" = "yes"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 + if test "$have_rb_errinfo" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_RB_ERRINFO 1" >>confdefs.h - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - fi - CFLAGS="$old_CFLAGS" - LIBS="$old_LIBS" + fi + CFLAGS="$old_CFLAGS" + LIBS="$old_LIBS" - if ${svn_cv_ruby_sitedir+:} false; then : + if ${svn_cv_ruby_sitedir+:} false; then : $as_echo_n "(cached) " >&6 else - svn_cv_ruby_sitedir="$rbconfig_sitedir" + svn_cv_ruby_sitedir="$rbconfig_sitedir" fi @@ -25105,43 +25709,43 @@ else fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to install Ruby scripts" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to install Ruby scripts" >&5 $as_echo_n "checking where to install Ruby scripts... " >&6; } - if ${svn_cv_ruby_sitedir_libsuffix+:} false; then : + if ${svn_cv_ruby_sitedir_libsuffix+:} false; then : $as_echo_n "(cached) " >&6 else - svn_cv_ruby_sitedir_libsuffix="`echo "$rbconfig_sitelibdir" | \ - $SED -e "s,^$rbconfig_sitedir,,"`" + svn_cv_ruby_sitedir_libsuffix="`echo "$rbconfig_sitelibdir" | \ + $SED -e "s,^$rbconfig_sitedir,,"`" fi - SWIG_RB_SITE_LIB_DIR="${svn_ruby_installdir}${svn_cv_ruby_sitedir_libsuffix}" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG_RB_SITE_LIB_DIR" >&5 + SWIG_RB_SITE_LIB_DIR="${svn_ruby_installdir}${svn_cv_ruby_sitedir_libsuffix}" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG_RB_SITE_LIB_DIR" >&5 $as_echo "$SWIG_RB_SITE_LIB_DIR" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to install Ruby extensions" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to install Ruby extensions" >&5 $as_echo_n "checking where to install Ruby extensions... " >&6; } - if ${svn_cv_ruby_sitedir_archsuffix+:} false; then : + if ${svn_cv_ruby_sitedir_archsuffix+:} false; then : $as_echo_n "(cached) " >&6 else - svn_cv_ruby_sitedir_archsuffix="`echo "$rbconfig_sitearchdir" | \ - $SED -e "s,^$rbconfig_sitedir,,"`" + svn_cv_ruby_sitedir_archsuffix="`echo "$rbconfig_sitearchdir" | \ + $SED -e "s,^$rbconfig_sitedir,,"`" fi - SWIG_RB_SITE_ARCH_DIR="${svn_ruby_installdir}${svn_cv_ruby_sitedir_archsuffix}" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG_RB_SITE_ARCH_DIR" >&5 + SWIG_RB_SITE_ARCH_DIR="${svn_ruby_installdir}${svn_cv_ruby_sitedir_archsuffix}" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG_RB_SITE_ARCH_DIR" >&5 $as_echo "$SWIG_RB_SITE_ARCH_DIR" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to use output level for Ruby bindings tests" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to use output level for Ruby bindings tests" >&5 $as_echo_n "checking how to use output level for Ruby bindings tests... " >&6; } - if ${svn_cv_ruby_test_verbose+:} false; then : + if ${svn_cv_ruby_test_verbose+:} false; then : $as_echo_n "(cached) " >&6 else - svn_cv_ruby_test_verbose="normal" + svn_cv_ruby_test_verbose="normal" fi @@ -25153,9 +25757,10 @@ else svn_ruby_test_verbose="$svn_cv_ruby_test_verbose" fi - SWIG_RB_TEST_VERBOSE="$svn_ruby_test_verbose" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG_RB_TEST_VERBOSE" >&5 + SWIG_RB_TEST_VERBOSE="$svn_ruby_test_verbose" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG_RB_TEST_VERBOSE" >&5 $as_echo "$SWIG_RB_TEST_VERBOSE" >&6; } + fi fi @@ -25171,6 +25776,7 @@ $as_echo "$SWIG_RB_TEST_VERBOSE" >&6; } + ;; esac @@ -25181,7 +25787,7 @@ else if test $where = no; then SWIG=none - elif test $where = check; then + elif test $where = required || test $where = check; then # Extract the first word of "swig", so it can be a program name with args. set dummy swig; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 @@ -25223,6 +25829,9 @@ $as_echo "no" >&6; } fi + if test "$SWIG" = "none" && test $where = required; then + as_fn_error $? "SWIG required, but not found" "$LINENO" 5 + fi else if test -f "$where"; then SWIG="$where" @@ -25255,10 +25864,6 @@ $as_echo_n "checking swig version... " >&6; } $as_echo "$SWIG_VERSION_RAW" >&6; } # If you change the required swig version number, don't forget to update: # subversion/bindings/swig/INSTALL - # packages/rpm/redhat-8+/subversion.spec - # packages/rpm/redhat-7.x/subversion.spec - # packages/rpm/rhel-3/subversion.spec - # packages/rpm/rhel-4/subversion.spec if test -n "$SWIG_VERSION" && test "$SWIG_VERSION" -ge "103024"; then SWIG_SUITABLE=yes else @@ -25268,70 +25873,69 @@ $as_echo "$as_me: WARNING: Detected SWIG version $SWIG_VERSION_RAW" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Subversion requires SWIG >= 1.3.24" >&5 $as_echo "$as_me: WARNING: Subversion requires SWIG >= 1.3.24" >&2;} fi - fi - SWIG_PY_COMPILE="none" - SWIG_PY_LINK="none" - if test "$PYTHON" != "none"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Configuring python swig binding" >&5 + SWIG_PY_COMPILE="none" + SWIG_PY_LINK="none" + if test "$PYTHON" != "none"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Configuring python swig binding" >&5 $as_echo "$as_me: Configuring python swig binding" >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python includes" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python includes" >&5 $as_echo_n "checking for Python includes... " >&6; } if ${ac_cv_python_includes+:} false; then : $as_echo_n "(cached) " >&6 else - ac_cv_python_includes="`$PYTHON ${abs_srcdir}/build/get-py-info.py --includes`" + ac_cv_python_includes="`$PYTHON ${abs_srcdir}/build/get-py-info.py --includes`" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_python_includes" >&5 $as_echo "$ac_cv_python_includes" >&6; } - SWIG_PY_INCLUDES="\$(SWIG_INCLUDES) $ac_cv_python_includes" + SWIG_PY_INCLUDES="\$(SWIG_INCLUDES) $ac_cv_python_includes" - if test "$ac_cv_python_includes" = "none"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: python bindings cannot be built without distutils module" >&5 + if test "$ac_cv_python_includes" = "none"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: python bindings cannot be built without distutils module" >&5 $as_echo "$as_me: WARNING: python bindings cannot be built without distutils module" >&2;} - fi + fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for compiling Python extensions" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for compiling Python extensions" >&5 $as_echo_n "checking for compiling Python extensions... " >&6; } if ${ac_cv_python_compile+:} false; then : $as_echo_n "(cached) " >&6 else - ac_cv_python_compile="`$PYTHON ${abs_srcdir}/build/get-py-info.py --compile`" + ac_cv_python_compile="`$PYTHON ${abs_srcdir}/build/get-py-info.py --compile`" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_python_compile" >&5 $as_echo "$ac_cv_python_compile" >&6; } - SWIG_PY_COMPILE="$ac_cv_python_compile $CFLAGS" + SWIG_PY_COMPILE="$ac_cv_python_compile $CFLAGS" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linking Python extensions" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linking Python extensions" >&5 $as_echo_n "checking for linking Python extensions... " >&6; } if ${ac_cv_python_link+:} false; then : $as_echo_n "(cached) " >&6 else - ac_cv_python_link="`$PYTHON ${abs_srcdir}/build/get-py-info.py --link`" + ac_cv_python_link="`$PYTHON ${abs_srcdir}/build/get-py-info.py --link`" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_python_link" >&5 $as_echo "$ac_cv_python_link" >&6; } - SWIG_PY_LINK="$ac_cv_python_link" + SWIG_PY_LINK="$ac_cv_python_link" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linking Python libraries" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linking Python libraries" >&5 $as_echo_n "checking for linking Python libraries... " >&6; } if ${ac_cv_python_libs+:} false; then : $as_echo_n "(cached) " >&6 else - ac_cv_python_libs="`$PYTHON ${abs_srcdir}/build/get-py-info.py --libs`" + ac_cv_python_libs="`$PYTHON ${abs_srcdir}/build/get-py-info.py --libs`" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_python_libs" >&5 $as_echo "$ac_cv_python_libs" >&6; } - SWIG_PY_LIBS="` + SWIG_PY_LIBS="` input_flags="$ac_cv_python_libs" output_flags="" filtered_dirs="/lib /lib64 /usr/lib /usr/lib64" @@ -25352,19 +25956,19 @@ $as_echo "$ac_cv_python_libs" >&6; } fi `" - SVN_PYCFMT_SAVE_CPPFLAGS="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $SVN_APR_INCLUDES" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for apr_int64_t Python/C API format string" >&5 + SVN_PYCFMT_SAVE_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $SVN_APR_INCLUDES" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for apr_int64_t Python/C API format string" >&5 $as_echo_n "checking for apr_int64_t Python/C API format string... " >&6; } if ${svn_cv_pycfmt_apr_int64_t+:} false; then : $as_echo_n "(cached) " >&6 else - if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include - MaTcHtHiS APR_INT64_T_FMT EnDeNd + MaTcHtHiS APR_INT64_T_FMT EnDeNd _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "MaTcHtHiS +\"lld\" +EnDeNd" >/dev/null 2>&1; then : @@ -25372,13 +25976,13 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | fi rm -f conftest* - fi - if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + fi + if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ r - #include - MaTcHtHiS APR_INT64_T_FMT EnDeNd + #include + MaTcHtHiS APR_INT64_T_FMT EnDeNd _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "MaTcHtHiS +\"ld\" +EnDeNd" >/dev/null 2>&1; then : @@ -25386,12 +25990,12 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | fi rm -f conftest* - fi - if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + fi + if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include - MaTcHtHiS APR_INT64_T_FMT EnDeNd + MaTcHtHiS APR_INT64_T_FMT EnDeNd _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "MaTcHtHiS +\"d\" +EnDeNd" >/dev/null 2>&1; then : @@ -25399,85 +26003,106 @@ if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | fi rm -f conftest* - fi + fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $svn_cv_pycfmt_apr_int64_t" >&5 $as_echo "$svn_cv_pycfmt_apr_int64_t" >&6; } - CPPFLAGS="$SVN_PYCFMT_SAVE_CPPFLAGS" - if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then - as_fn_error $? "failed to recognize APR_INT64_T_FMT on this platform" "$LINENO" 5 - fi + CPPFLAGS="$SVN_PYCFMT_SAVE_CPPFLAGS" + if test "x$svn_cv_pycfmt_apr_int64_t" = "x"; then + as_fn_error $? "failed to recognize APR_INT64_T_FMT on this platform" "$LINENO" 5 + fi cat >>confdefs.h <<_ACEOF #define SVN_APR_INT64_T_PYCFMT "$svn_cv_pycfmt_apr_int64_t" _ACEOF - fi - - if test "$PERL" != "none"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking perl version" >&5 -$as_echo_n "checking perl version... " >&6; } - PERL_VERSION="`$PERL -e 'q([); print $] * 1000000,$/;'`" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL_VERSION" >&5 -$as_echo "$PERL_VERSION" >&6; } - if test "$PERL_VERSION" -ge "5008000"; then - SWIG_PL_INCLUDES="\$(SWIG_INCLUDES) `$PERL -MExtUtils::Embed -e ccopts`" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: perl bindings require perl 5.8.0 or newer." >&5 -$as_echo "$as_me: WARNING: perl bindings require perl 5.8.0 or newer." >&2;} fi - fi - SWIG_RB_COMPILE="none" - SWIG_RB_LINK="none" - if test "$RUBY" != "none"; then - rbconfig="$RUBY -rrbconfig -e " - - for var_name in arch archdir CC LDSHARED DLEXT LIBS LIBRUBYARG \ - rubyhdrdir rubyarchhdrdir sitedir sitelibdir sitearchdir libdir - do - rbconfig_tmp=`$rbconfig "print RbConfig::CONFIG['$var_name']"` - eval "rbconfig_$var_name=\"$rbconfig_tmp\"" + if test "$PERL" != "none"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking perl version" >&5 +$as_echo_n "checking perl version... " >&6; } + PERL_VERSION="`$PERL -e 'q([); print $] * 1000000,$/;'`" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL_VERSION" >&5 +$as_echo "$PERL_VERSION" >&6; } + if test "$PERL_VERSION" -ge "5008000"; then + SWIG_PL_INCLUDES="\$(SWIG_INCLUDES) `$PERL -MExtUtils::Embed -e ccopts`" + SWIG_PL_LINK="`$PERL -MExtUtils::Embed -e ldopts`" + SWIG_PL_LINK="` + input_flags="$SWIG_PL_LINK" + output_flags="" + filtered_dirs="/lib /lib64 /usr/lib /usr/lib64" + for flag in $input_flags; do + filter="no" + for dir in $filtered_dirs; do + if test "$flag" = "-L$dir" || test "$flag" = "-L$dir/"; then + filter="yes" + break + fi done + if test "$filter" = "no"; then + output_flags="$output_flags $flag" + fi + done + if test -n "$output_flags"; then + printf "%s" "${output_flags# }" + fi +`" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: perl bindings require perl 5.8.0 or newer." >&5 +$as_echo "$as_me: WARNING: perl bindings require perl 5.8.0 or newer." >&2;} + fi + fi - { $as_echo "$as_me:${as_lineno-$LINENO}: Configuring Ruby SWIG binding" >&5 + SWIG_RB_COMPILE="none" + SWIG_RB_LINK="none" + if test "$RUBY" != "none"; then + rbconfig="$RUBY -rrbconfig -e " + + for var_name in arch archdir CC LDSHARED DLEXT LIBS LIBRUBYARG \ + rubyhdrdir rubyarchhdrdir sitedir sitelibdir sitearchdir libdir + do + rbconfig_tmp=`$rbconfig "print RbConfig::CONFIG['$var_name']"` + eval "rbconfig_$var_name=\"$rbconfig_tmp\"" + done + + { $as_echo "$as_me:${as_lineno-$LINENO}: Configuring Ruby SWIG binding" >&5 $as_echo "$as_me: Configuring Ruby SWIG binding" >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Ruby include path" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Ruby include path" >&5 $as_echo_n "checking for Ruby include path... " >&6; } if ${svn_cv_ruby_includes+:} false; then : $as_echo_n "(cached) " >&6 else - if test -d "$rbconfig_rubyhdrdir"; then - svn_cv_ruby_includes="-I. -I$rbconfig_rubyhdrdir -I$rbconfig_rubyhdrdir/ruby -I$rbconfig_rubyhdrdir/ruby/backward" - if test -d "$rbconfig_rubyarchhdrdir"; then - svn_cv_ruby_includes="$svn_cv_ruby_includes -I$rbconfig_rubyarchhdrdir" + if test -d "$rbconfig_rubyhdrdir"; then + svn_cv_ruby_includes="-I. -I$rbconfig_rubyhdrdir -I$rbconfig_rubyhdrdir/ruby -I$rbconfig_rubyhdrdir/ruby/backward" + if test -d "$rbconfig_rubyarchhdrdir"; then + svn_cv_ruby_includes="$svn_cv_ruby_includes -I$rbconfig_rubyarchhdrdir" + else + svn_cv_ruby_includes="$svn_cv_ruby_includes -I$rbconfig_rubyhdrdir/$rbconfig_arch" + fi else - svn_cv_ruby_includes="$svn_cv_ruby_includes -I$rbconfig_rubyhdrdir/$rbconfig_arch" + svn_cv_ruby_includes="-I. -I$rbconfig_archdir" fi - else - svn_cv_ruby_includes="-I. -I$rbconfig_archdir" - fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $svn_cv_ruby_includes" >&5 $as_echo "$svn_cv_ruby_includes" >&6; } - SWIG_RB_INCLUDES="\$(SWIG_INCLUDES) $svn_cv_ruby_includes" + SWIG_RB_INCLUDES="\$(SWIG_INCLUDES) $svn_cv_ruby_includes" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to compile Ruby extensions" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to compile Ruby extensions" >&5 $as_echo_n "checking how to compile Ruby extensions... " >&6; } if ${svn_cv_ruby_compile+:} false; then : $as_echo_n "(cached) " >&6 else - svn_cv_ruby_compile="$rbconfig_CC $CFLAGS" + svn_cv_ruby_compile="$rbconfig_CC $CFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $svn_cv_ruby_compile" >&5 $as_echo "$svn_cv_ruby_compile" >&6; } - SWIG_RB_COMPILE="$svn_cv_ruby_compile" + SWIG_RB_COMPILE="$svn_cv_ruby_compile" SWIG_RB_COMPILE=`echo "$SWIG_RB_COMPILE" | $SED -e 's/-ansi//'` @@ -25487,36 +26112,36 @@ $as_echo "$svn_cv_ruby_compile" >&6; } SWIG_RB_COMPILE=`echo "$SWIG_RB_COMPILE" | $SED -e 's/-std=c90//'` - SWIG_RB_COMPILE="$SWIG_RB_COMPILE -Wno-int-to-pointer-cast" + SWIG_RB_COMPILE="$SWIG_RB_COMPILE -Wno-int-to-pointer-cast" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link Ruby extensions" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link Ruby extensions" >&5 $as_echo_n "checking how to link Ruby extensions... " >&6; } if ${svn_cv_ruby_link+:} false; then : $as_echo_n "(cached) " >&6 else - svn_cv_ruby_link="`$RUBY -e 'ARGV.shift; print ARGV.join(%q( ))' \ - $rbconfig_LDSHARED`" - svn_cv_ruby_link="$rbconfig_CC $svn_cv_ruby_link" - svn_cv_ruby_link="$svn_cv_ruby_link -shrext .$rbconfig_DLEXT" + svn_cv_ruby_link="`$RUBY -e 'ARGV.shift; print ARGV.join(%q( ))' \ + $rbconfig_LDSHARED`" + svn_cv_ruby_link="$rbconfig_CC $svn_cv_ruby_link" + svn_cv_ruby_link="$svn_cv_ruby_link -shrext .$rbconfig_DLEXT" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $svn_cv_ruby_link" >&5 $as_echo "$svn_cv_ruby_link" >&6; } - SWIG_RB_LINK="$svn_cv_ruby_link" + SWIG_RB_LINK="$svn_cv_ruby_link" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link Ruby libraries" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link Ruby libraries" >&5 $as_echo_n "checking how to link Ruby libraries... " >&6; } if ${ac_cv_ruby_libs+:} false; then : $as_echo_n "(cached) " >&6 else - ac_cv_ruby_libs="$rbconfig_LIBRUBYARG $rbconfig_LIBS" + ac_cv_ruby_libs="$rbconfig_LIBRUBYARG $rbconfig_LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_ruby_libs" >&5 $as_echo "$ac_cv_ruby_libs" >&6; } - SWIG_RB_LIBS="` + SWIG_RB_LIBS="` input_flags="$ac_cv_ruby_libs" output_flags="" filtered_dirs="/lib /lib64 /usr/lib /usr/lib64" @@ -25537,11 +26162,11 @@ $as_echo "$ac_cv_ruby_libs" >&6; } fi `" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rb_errinfo" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for rb_errinfo" >&5 $as_echo_n "checking for rb_errinfo... " >&6; } - old_CFLAGS="$CFLAGS" - old_LIBS="$LIBS" - CFLAGS="$CFLAGS $svn_cv_ruby_includes" + old_CFLAGS="$CFLAGS" + old_LIBS="$LIBS" + CFLAGS="$CFLAGS $svn_cv_ruby_includes" CFLAGS=`echo "$CFLAGS" | $SED -e 's/-ansi//'` @@ -25551,8 +26176,8 @@ $as_echo_n "checking for rb_errinfo... " >&6; } CFLAGS=`echo "$CFLAGS" | $SED -e 's/-std=c90//'` - LIBS="$SWIG_RB_LIBS" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + LIBS="$SWIG_RB_LIBS" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include @@ -25566,24 +26191,24 @@ else fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - if test "$have_rb_errinfo" = "yes"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 + if test "$have_rb_errinfo" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_RB_ERRINFO 1" >>confdefs.h - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - fi - CFLAGS="$old_CFLAGS" - LIBS="$old_LIBS" + fi + CFLAGS="$old_CFLAGS" + LIBS="$old_LIBS" - if ${svn_cv_ruby_sitedir+:} false; then : + if ${svn_cv_ruby_sitedir+:} false; then : $as_echo_n "(cached) " >&6 else - svn_cv_ruby_sitedir="$rbconfig_sitedir" + svn_cv_ruby_sitedir="$rbconfig_sitedir" fi @@ -25596,43 +26221,43 @@ else fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to install Ruby scripts" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to install Ruby scripts" >&5 $as_echo_n "checking where to install Ruby scripts... " >&6; } - if ${svn_cv_ruby_sitedir_libsuffix+:} false; then : + if ${svn_cv_ruby_sitedir_libsuffix+:} false; then : $as_echo_n "(cached) " >&6 else - svn_cv_ruby_sitedir_libsuffix="`echo "$rbconfig_sitelibdir" | \ - $SED -e "s,^$rbconfig_sitedir,,"`" + svn_cv_ruby_sitedir_libsuffix="`echo "$rbconfig_sitelibdir" | \ + $SED -e "s,^$rbconfig_sitedir,,"`" fi - SWIG_RB_SITE_LIB_DIR="${svn_ruby_installdir}${svn_cv_ruby_sitedir_libsuffix}" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG_RB_SITE_LIB_DIR" >&5 + SWIG_RB_SITE_LIB_DIR="${svn_ruby_installdir}${svn_cv_ruby_sitedir_libsuffix}" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG_RB_SITE_LIB_DIR" >&5 $as_echo "$SWIG_RB_SITE_LIB_DIR" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to install Ruby extensions" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to install Ruby extensions" >&5 $as_echo_n "checking where to install Ruby extensions... " >&6; } - if ${svn_cv_ruby_sitedir_archsuffix+:} false; then : + if ${svn_cv_ruby_sitedir_archsuffix+:} false; then : $as_echo_n "(cached) " >&6 else - svn_cv_ruby_sitedir_archsuffix="`echo "$rbconfig_sitearchdir" | \ - $SED -e "s,^$rbconfig_sitedir,,"`" + svn_cv_ruby_sitedir_archsuffix="`echo "$rbconfig_sitearchdir" | \ + $SED -e "s,^$rbconfig_sitedir,,"`" fi - SWIG_RB_SITE_ARCH_DIR="${svn_ruby_installdir}${svn_cv_ruby_sitedir_archsuffix}" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG_RB_SITE_ARCH_DIR" >&5 + SWIG_RB_SITE_ARCH_DIR="${svn_ruby_installdir}${svn_cv_ruby_sitedir_archsuffix}" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG_RB_SITE_ARCH_DIR" >&5 $as_echo "$SWIG_RB_SITE_ARCH_DIR" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to use output level for Ruby bindings tests" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to use output level for Ruby bindings tests" >&5 $as_echo_n "checking how to use output level for Ruby bindings tests... " >&6; } - if ${svn_cv_ruby_test_verbose+:} false; then : + if ${svn_cv_ruby_test_verbose+:} false; then : $as_echo_n "(cached) " >&6 else - svn_cv_ruby_test_verbose="normal" + svn_cv_ruby_test_verbose="normal" fi @@ -25644,9 +26269,10 @@ else svn_ruby_test_verbose="$svn_cv_ruby_test_verbose" fi - SWIG_RB_TEST_VERBOSE="$svn_ruby_test_verbose" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG_RB_TEST_VERBOSE" >&5 + SWIG_RB_TEST_VERBOSE="$svn_ruby_test_verbose" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG_RB_TEST_VERBOSE" >&5 $as_echo "$SWIG_RB_TEST_VERBOSE" >&6; } + fi fi @@ -25663,12 +26289,17 @@ $as_echo "$SWIG_RB_TEST_VERBOSE" >&6; } + fi + + + + # Check whether --with-ctypesgen was given. if test "${with_ctypesgen+set}" = set; then : withval=$with_ctypesgen; @@ -25979,6 +26610,19 @@ if test "${enable_runtime_module_search+set}" = set; then : $as_echo "#define SVN_USE_DSO 1" >>confdefs.h + + case "$host" in + *-*-darwin*) + +$as_echo "#define SVN_DSO_SUFFIX_FMT \"%d.%d.dylib\"" >>confdefs.h + + ;; + *) + +$as_echo "#define SVN_DSO_SUFFIX_FMT \"%d.so.%d\"" >>confdefs.h + + ;; + esac fi fi @@ -25986,21 +26630,21 @@ fi if test "$svn_enable_shared" = "no" || test "$use_dso" != "yes"; then -$as_echo "#define SVN_LIBSVN_CLIENT_LINKS_RA_LOCAL 1" >>confdefs.h +$as_echo "#define SVN_LIBSVN_RA_LINKS_RA_LOCAL 1" >>confdefs.h svn_ra_lib_deps="\$(RA_LOCAL_DEPS)" svn_ra_lib_install_deps="install-ramod-lib" svn_ra_lib_link="\$(RA_LOCAL_LINK)" -$as_echo "#define SVN_LIBSVN_CLIENT_LINKS_RA_SVN 1" >>confdefs.h +$as_echo "#define SVN_LIBSVN_RA_LINKS_RA_SVN 1" >>confdefs.h svn_ra_lib_deps="$svn_ra_lib_deps \$(RA_SVN_DEPS)" svn_ra_lib_link="$svn_ra_lib_link \$(RA_SVN_LINK)" if test "$svn_lib_serf" = "yes"; then -$as_echo "#define SVN_LIBSVN_CLIENT_LINKS_RA_SERF 1" >>confdefs.h +$as_echo "#define SVN_LIBSVN_RA_LINKS_RA_SERF 1" >>confdefs.h svn_ra_lib_deps="$svn_ra_lib_deps \$(RA_SERF_DEPS)" svn_ra_lib_install_deps="$svn_ra_lib_install_deps install-serf-lib" @@ -26127,7 +26771,7 @@ fi # ==== Miscellaneous bits ==================================================== -for ac_header in stdbool.h inttypes.h +for ac_header in stdbool.h stdint.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" @@ -26149,16 +26793,6 @@ if test "$CC" = "clang"; then fi -# Need to strip '-no-cpp-precomp' from CPPFLAGS for SWIG as well. -SWIG_CPPFLAGS="$CPPFLAGS" - - SWIG_CPPFLAGS=`echo "$SWIG_CPPFLAGS" | $SED -e 's/-no-cpp-precomp //'` - - - SWIG_CPPFLAGS=`echo "$SWIG_CPPFLAGS" | $SED -e 's/-Wdate-time //'` - - - cat >>confdefs.h <<_ACEOF #define SVN_PATH_LOCAL_SEPARATOR '/' @@ -26756,7 +27390,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by subversion $as_me 1.9.7, which was +This file was extended by subversion $as_me 1.10.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -26822,7 +27456,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -subversion config.status 1.9.7 +subversion config.status 1.10.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 1fe041478d17..9374d656d503 100644 --- a/configure.ac +++ b/configure.ac @@ -136,16 +136,27 @@ if test "$svn_lib_apr_memcache" = "yes"; then [Defined if apr_memcache (standalone or in apr-util) is present]) fi +AC_ARG_ENABLE(apache-whitelist, + AS_HELP_STRING([--enable-apache-whitelist=VER], + [Whitelist a particular Apache version number, + typically used to enable the use of a old version + patched by a distribution.]), + [apache_whitelist_ver=$enableval], + [apache_whitelist_ver=no]) +HTTPD_WHITELIST="$apache_whitelist_ver" +AC_SUBST(HTTPD_WHITELIST) dnl Find Apache with a recent-enough magic module number -SVN_FIND_APACHE(20051115) +SVN_FIND_APACHE(20051115, $apache_whitelist_ver) dnl Search for SQLite. If you change SQLITE_URL from a .zip to dnl something else also update build/ac-macros/sqlite.m4 to reflect dnl the correct command to unpack the downloaded file. -SQLITE_MINIMUM_VER="3.7.12" -SQLITE_RECOMMENDED_VER="3.7.15.1" -SQLITE_URL="http://www.sqlite.org/sqlite-amalgamation-$(printf %d%02d%02d%02d $(echo ${SQLITE_RECOMMENDED_VER} | sed -e 's/\./ /g')).zip" +SQLITE_MINIMUM_VER="3.8.2" +SQLITE_RECOMMENDED_VER="3.8.11.1" +dnl Used to construct the SQLite download URL. +SQLITE_RECOMMENDED_VER_REL_YEAR="2015" +SQLITE_URL="https://www.sqlite.org/$SQLITE_RECOMMENDED_VER_REL_YEAR/sqlite-amalgamation-$(printf %d%02d%02d%02d $(echo ${SQLITE_RECOMMENDED_VER} | sed -e 's/\./ /g')).zip" SVN_LIB_SQLITE(${SQLITE_MINIMUM_VER}, ${SQLITE_RECOMMENDED_VER}, ${SQLITE_URL}) @@ -546,22 +557,22 @@ AC_SUBST(SVN_HAVE_GPG_AGENT) dnl GNOME Keyring ------------------- -AC_ARG_WITH(gnome_keyring, - AS_HELP_STRING([--with-gnome-keyring], - [Enable use of GNOME Keyring for auth credentials (enabled by default if found)]), - [with_gnome_keyring="$withval"], - [with_gnome_keyring=auto]) +AC_ARG_WITH(old_gnome_keyring, + AS_HELP_STRING([--with-old-gnome-keyring], + [Enable old GNOME Keyring for auth credentials (prefer --with-gnome-keyring)]), + [with_old_gnome_keyring="$withval"], + [with_old_gnome_keyring=no]) -found_gnome_keyring=no -AC_MSG_CHECKING([whether to look for GNOME Keyring]) -if test "$with_gnome_keyring" != "no"; then +found_old_gnome_keyring=no +AC_MSG_CHECKING([whether to look for old GNOME Keyring]) +if test "$with_old_gnome_keyring" != "no"; then AC_MSG_RESULT([yes]) case "$host" in *-*-darwin*) - if test "$with_gnome_keyring" = "yes"; then - AC_MSG_ERROR([--with-gnome-keyring is not supported on Mac OS X.]) + if test "$with_old_gnome_keyring" = "yes"; then + AC_MSG_ERROR([--with-old-gnome-keyring is not supported on Mac OS X.]) else - with_gnome_keyring=no + with_old_gnome_keyring=no fi ;; *) @@ -574,9 +585,9 @@ if test "$with_gnome_keyring" != "no"; then old_CPPFLAGS="$CPPFLAGS" SVN_GNOME_KEYRING_INCLUDES="`$PKG_CONFIG --cflags glib-2.0 gnome-keyring-1`" CPPFLAGS="$CPPFLAGS $SVN_GNOME_KEYRING_INCLUDES" - AC_CHECK_HEADER(gnome-keyring.h, found_gnome_keyring=yes, found_gnome_keyring=no) + AC_CHECK_HEADER(gnome-keyring.h, found_old_gnome_keyring=yes, found_old_gnome_keyring=no) AC_MSG_CHECKING([for GNOME Keyring]) - if test "$found_gnome_keyring" = "yes"; then + if test "$found_old_gnome_keyring" = "yes"; then AC_MSG_RESULT([yes]) AC_DEFINE([SVN_HAVE_GNOME_KEYRING], [1], [Is GNOME Keyring support enabled?]) @@ -584,37 +595,37 @@ if test "$with_gnome_keyring" != "no"; then SVN_GNOME_KEYRING_LIBS="`$PKG_CONFIG --libs glib-2.0 gnome-keyring-1`" else AC_MSG_RESULT([no]) - if test "$with_gnome_keyring" = "yes"; then + if test "$with_old_gnome_keyring" = "yes"; then AC_MSG_ERROR([cannot find GNOME Keyring]) fi fi else AC_MSG_RESULT([no]) - if test "$with_gnome_keyring" = "yes"; then + if test "$with_old_gnome_keyring" = "yes"; then AC_MSG_ERROR([cannot find GLib and GNOME Keyring .pc files.]) else - with_gnome_keyring=no + with_old_gnome_keyring=no fi fi else - if test "$with_gnome_keyring" = "yes"; then + if test "$with_old_gnome_keyring" = "yes"; then AC_MSG_ERROR([cannot find pkg-config. GNOME Keyring requires this.]) else - with_gnome_keyring=no + with_old_gnome_keyring=no fi fi else - if test "$with_gnome_keyring" = "yes"; then + if test "$with_old_gnome_keyring" = "yes"; then AC_MSG_ERROR([APR does not have support for DSOs. GNOME Keyring requires this.]) else - with_gnome_keyring=no + with_old_gnome_keyring=no fi fi else - if test "$with_gnome_keyring" = "yes"; then - AC_MSG_ERROR([--with-gnome-keyring conflicts with --disable-shared]) + if test "$with_old_gnome_keyring" = "yes"; then + AC_MSG_ERROR([--with-old-gnome-keyring conflicts with --disable-shared]) else - with_gnome_keyring=no + with_old_gnome_keyring=no fi fi ;; @@ -625,28 +636,31 @@ fi AC_SUBST(SVN_GNOME_KEYRING_INCLUDES) AC_SUBST(SVN_GNOME_KEYRING_LIBS) +dnl LibSecret ------------------- +SVN_LIB_SECRET + dnl Googlemock ----------------- -AC_ARG_ENABLE([gmock], - AS_HELP_STRING([--disable-gmock], +AC_ARG_ENABLE([googlemock], + AS_HELP_STRING([--disable-googlemock], [Do not use the Googlemock testing framework]), [], - [enable_gmock=yes]) + [enable_googlemock=yes]) -AC_SUBST([GMOCK_SRCDIR], [$abs_srcdir/gmock-fused]) +AC_SUBST([GOOGLEMOCK_SRCDIR], [$abs_srcdir/googlemock]) AC_MSG_CHECKING([whether use Googlemock]) -if test "$enable_gmock" != "no"; then - if test -d "$GMOCK_SRCDIR"; then +if test "$enable_googlemock" != "no"; then + if test -d "$GOOGLEMOCK_SRCDIR"; then AC_MSG_RESULT([yes]) - SVN_USE_GMOCK=true + SVN_USE_GOOGLEMOCK=true else AC_MSG_RESULT([no]) - SVN_USE_GMOCK=false + SVN_USE_GOOGLEMOCK=false fi else AC_MSG_RESULT([no]) - SVN_USE_GMOCK_SOURCES=false + SVN_USE_GOOGLEMOCK=false fi -AC_SUBST([SVN_USE_GMOCK]) +AC_SUBST([SVN_USE_GOOGLEMOCK]) dnl Ev2 experimental features ---------------------- dnl Note: The Ev2 implementations will be built unconditionally, but by @@ -892,7 +906,7 @@ if test "$svn_lib_kwallet" = "yes"; then INSTALL_STATIC_RULES="$INSTALL_STATIC_RULES install-kwallet-lib" fi -if test "$found_gnome_keyring" = "yes"; then +if test "$found_old_gnome_keyring" = "yes" || test "$found_gnome_keyring" = "yes"; then BUILD_RULES="$BUILD_RULES gnome-keyring-lib" INSTALL_RULES="`echo $INSTALL_RULES | $SED 's/install-lib/install-lib install-gnome-keyring-lib/'`" INSTALL_STATIC_RULES="$INSTALL_STATIC_RULES install-gnome-keyring-lib" @@ -993,6 +1007,7 @@ if test "$enable_disallowing_of_undefined_references" != "no"; then for library_dir in "$abs_srcdir/subversion/libsvn_"*; do eval "`basename $library_dir`_LDFLAGS=-Wl,--no-undefined" done + shared_only_LDFLAGS="-Wl,--no-undefined" else AC_MSG_RESULT([no]) if test "$enable_disallowing_of_undefined_references" = "yes"; then @@ -1000,8 +1015,6 @@ if test "$enable_disallowing_of_undefined_references" != "no"; then fi fi fi -AC_SUBST([libsvn_auth_gnome_keyring_LDFLAGS]) -AC_SUBST([libsvn_auth_kwallet_LDFLAGS]) AC_SUBST([libsvn_client_LDFLAGS]) AC_SUBST([libsvn_delta_LDFLAGS]) AC_SUBST([libsvn_diff_LDFLAGS]) @@ -1016,6 +1029,7 @@ AC_SUBST([libsvn_ra_svn_LDFLAGS]) AC_SUBST([libsvn_repos_LDFLAGS]) AC_SUBST([libsvn_subr_LDFLAGS]) AC_SUBST([libsvn_wc_LDFLAGS]) +AC_SUBST([shared_only_LDFLAGS]) AC_ARG_ENABLE(maintainer-mode, @@ -1052,12 +1066,13 @@ AS_HELP_STRING([--enable-maintainer-mode], SVN_CFLAGS_ADD_IFELSE([-Wno-system-headers]) SVN_CFLAGS_ADD_IFELSE([-Wno-format-nonliteral]) SVN_CFLAGS_ADD_IFELSE([-Wmissing-variable-declarations]) + SVN_CFLAGS_ADD_IFELSE([-Wno-unused-const-variable]) CMAINTAINERFLAGS="$CFLAGS" CFLAGS="$CFLAGS_KEEP" dnl Add flags that all versions of GCC (should) support - CMAINTAINERFLAGS="-Wall -Wpointer-arith -Wwrite-strings -Wshadow -Wformat=2 -Wunused -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wno-multichar -Wredundant-decls -Wnested-externs -Winline -Wno-long-long -Wbad-function-cast $CMAINTAINERFLAGS" + CMAINTAINERFLAGS="-Wall -Wpointer-arith -Wwrite-strings -Wshadow -Wformat=2 -Wunused -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wno-multichar -Wredundant-decls -Wnested-externs -Winline -Wno-long-long -Wbad-function-cast $CMAINTAINERFLAGS" fi if test "$GXX" = "yes"; then AC_MSG_NOTICE([maintainer-mode: adding G++ warning flags]) @@ -1203,6 +1218,10 @@ AS_HELP_STRING([--with-editor=PATH], SVN_LIB_Z +SVN_LZ4 + +SVN_UTF8PROC + MOD_ACTIVATION="" AC_ARG_ENABLE(mod-activation, AS_HELP_STRING([--enable-mod-activation], @@ -1295,7 +1314,7 @@ AC_PATH_PROG(PERL, perl, none) if test -n "$RUBY"; then AC_PATH_PROG(RUBY, "$RUBY", none) else - AC_PATH_PROGS(RUBY, ruby ruby1.8 ruby18 ruby1.9 ruby1 ruby1.9.3 ruby193 ruby2.0 ruby2.1, none) + AC_PATH_PROGS(RUBY, ruby ruby1 ruby1.8 ruby18 ruby1.9 ruby19 ruby1.9.3 ruby193 ruby2 ruby2.0 ruby20 ruby2.1 ruby21 ruby2.2 ruby22 ruby2.3 ruby23 ruby2.4 ruby24, none) fi if test "$RUBY" != "none"; then AC_MSG_CHECKING([rb_hash_foreach]) @@ -1304,7 +1323,7 @@ if test "$RUBY" != "none"; then if test -n "$RDOC"; then AC_PATH_PROG(RDOC, "$RDOC", none) else - AC_PATH_PROGS(RDOC, rdoc rdoc1.8 rdoc18 rdoc1.9 rdoc19 rdoc1.9.3 rdoc193 rdoc2.0 rdoc2.1, none) + AC_PATH_PROGS(RUBY, rdoc rdoc1 rdoc1.8 rdoc18 rdoc1.9 rdoc19 rdoc1.9.3 rdoc193 rdoc2 rdoc2.0 rdoc20 rdoc2.1 rdoc21 rdoc2.2 rdoc22 rdoc2.3 rdoc23 rdoc2.4 rdoc24, none) fi AC_CACHE_CHECK([for Ruby major version], [svn_cv_ruby_major],[ svn_cv_ruby_major="`$RUBY -rrbconfig -e 'print RbConfig::CONFIG.fetch(%q(MAJOR))'`" @@ -1328,7 +1347,7 @@ if test "$RUBY" != "none"; then # Disallow Ruby between 1.8.7 and 1.9.3 RUBY="none" AC_MSG_WARN([The detected Ruby is between 1.9 and 1.9.3]) - AC_MSG_WARN([Only 1.8.x and 1.9.3 releases are supported at this time]) + AC_MSG_WARN([Only 1.8.x and 1.9.3 or later are supported at this time]) fi else AC_MSG_RESULT([no]) @@ -1341,6 +1360,10 @@ if test "$RUBY" != "none"; then fi SVN_CHECK_SWIG +AC_ARG_VAR(SWIG_FEATURES, [SWIG feature flags common to all bindings]) +AC_ARG_VAR(SWIG_RB_FEATURES, [SWIG feature flags specific to Ruby bindings]) +AC_ARG_VAR(SWIG_PL_FEATURES, [SWIG feature flags specific to Perl bindings]) +AC_ARG_VAR(SWIG_PY_FEATURES, [SWIG feature flags specific to Python bindings]) SVN_CHECK_CTYPESGEN @@ -1357,24 +1380,37 @@ AS_HELP_STRING([--enable-runtime-module-search], fi AC_DEFINE(SVN_USE_DSO, 1, [Defined if svn should try to load DSOs]) + + dnl Mac OS X uses libname.MAJOR.SOVERSION.dylib + dnl Most other unixes use libname.MAJOR.so.SOVERSION + case "$host" in + *-*-darwin*) + AC_DEFINE(SVN_DSO_SUFFIX_FMT, ["%d.%d.dylib"], + [Shared library file name suffix format]) + ;; + *) + AC_DEFINE(SVN_DSO_SUFFIX_FMT, ["%d.so.%d"], + [Shared library file name suffix format]) + ;; + esac fi ]) if test "$svn_enable_shared" = "no" || test "$use_dso" != "yes"; then - AC_DEFINE(SVN_LIBSVN_CLIENT_LINKS_RA_LOCAL, 1, - [Defined if libsvn_client should link against libsvn_ra_local]) + AC_DEFINE(SVN_LIBSVN_RA_LINKS_RA_LOCAL, 1, + [Defined if libsvn_ra should link against libsvn_ra_local]) svn_ra_lib_deps="\$(RA_LOCAL_DEPS)" svn_ra_lib_install_deps="install-ramod-lib" svn_ra_lib_link="\$(RA_LOCAL_LINK)" - AC_DEFINE(SVN_LIBSVN_CLIENT_LINKS_RA_SVN, 1, - [Defined if libsvn_client should link against libsvn_ra_svn]) + AC_DEFINE(SVN_LIBSVN_RA_LINKS_RA_SVN, 1, + [Defined if libsvn_ra should link against libsvn_ra_svn]) svn_ra_lib_deps="$svn_ra_lib_deps \$(RA_SVN_DEPS)" svn_ra_lib_link="$svn_ra_lib_link \$(RA_SVN_LINK)" if test "$svn_lib_serf" = "yes"; then - AC_DEFINE(SVN_LIBSVN_CLIENT_LINKS_RA_SERF, 1, - [Defined if libsvn_client should link against libsvn_ra_serf]) + AC_DEFINE(SVN_LIBSVN_RA_LINKS_RA_SERF, 1, + [Defined if libsvn_ra should link against libsvn_ra_serf]) svn_ra_lib_deps="$svn_ra_lib_deps \$(RA_SERF_DEPS)" svn_ra_lib_install_deps="$svn_ra_lib_install_deps install-serf-lib" svn_ra_lib_link="$svn_ra_lib_link \$(RA_SERF_LINK)" @@ -1496,7 +1532,7 @@ AC_SUBST(JAVAHL_COMPAT_TESTS_TARGET) # ==== Miscellaneous bits ==================================================== -AC_CHECK_HEADERS([stdbool.h inttypes.h]) +AC_CHECK_HEADERS([stdbool.h stdint.h]) # Strip '-no-cpp-precomp' from CPPFLAGS for the clang compiler ### I think we get this flag from APR, so the fix probably belongs there @@ -1504,12 +1540,6 @@ if test "$CC" = "clang"; then SVN_STRIP_FLAG(CPPFLAGS, [-no-cpp-precomp ]) fi -# Need to strip '-no-cpp-precomp' from CPPFLAGS for SWIG as well. -SWIG_CPPFLAGS="$CPPFLAGS" -SVN_STRIP_FLAG(SWIG_CPPFLAGS, [-no-cpp-precomp ]) -SVN_STRIP_FLAG(SWIG_CPPFLAGS, [-Wdate-time ]) -AC_SUBST([SWIG_CPPFLAGS]) - dnl Since this is used only on Unix-y systems, define the path separator as '/' AC_DEFINE_UNQUOTED(SVN_PATH_LOCAL_SEPARATOR, '/', [Defined to be the path separator used on your local filesystem]) diff --git a/doc/doxygen.conf b/doc/doxygen.conf index 6c17d1be4be7..adb7efbda693 100644 --- a/doc/doxygen.conf +++ b/doc/doxygen.conf @@ -33,6 +33,13 @@ PROJECT_NAME = Subversion PROJECT_NUMBER = +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = doc/svn-square.jpg + # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location diff --git a/gen-make.py b/gen-make.py index 2e5557bea850..9e410c43bd11 100755 --- a/gen-make.py +++ b/gen-make.py @@ -206,9 +206,8 @@ def _usage_exit(err=None): print(" Use static openssl") print("") print(" --vsnet-version=VER") - print(" generate for VS.NET version VER (2002, 2003, 2005, 2008,") - print(" 2010, 2012, 2013 or 2015)") - print(" [only valid in combination with '-t vcproj']") + print(" generate for VS.NET version VER (2005-2017 or 9.0-15.0)") + print(" [implies '-t vcproj']") print("") print(" -D NAME[=value]") print(" define NAME macro during compilation") @@ -304,6 +303,8 @@ if __name__ == '__main__': skip = 1 elif opt == '-t': gentype = val + elif opt == '--vsnet-version': + gentype = 'vcproj' else: if opt == '--with-httpd': rest.add('--with-apr', os.path.join(val, 'srclib', 'apr'), diff --git a/get-deps.sh b/get-deps.sh index 1a6f09d9f9d5..f41d37fdeee2 100755 --- a/get-deps.sh +++ b/get-deps.sh @@ -35,8 +35,11 @@ APR_VERSION=${APR_VERSION:-"1.4.6"} APU_VERSION=${APU_VERSION:-"1.5.1"} SERF_VERSION=${SERF_VERSION:-"1.3.8"} ZLIB_VERSION=${ZLIB_VERSION:-"1.2.8"} -SQLITE_VERSION=${SQLITE_VERSION:-"3.7.15.1"} -GMOCK_VERSION=${GMOCK_VERSION:-"1.6.0"} +SQLITE_VERSION=${SQLITE_VERSION:-"3.8.11.1"} +# Used to construct the SQLite download URL. +SQLITE_VERSION_REL_YEAR=2015 +GTEST_VERSION=${GMOCK_VERSION:-"1.7.0"} +GMOCK_VERSION=${GMOCK_VERSION:-"1.7.0"} HTTPD_VERSION=${HTTPD_VERSION:-"2.4.10"} APR_ICONV_VERSION=${APR_ICONV_VERSION:-"1.2.1"} @@ -46,8 +49,10 @@ SERF=serf-${SERF_VERSION} ZLIB=zlib-${ZLIB_VERSION} SQLITE_VERSION_LIST=`echo $SQLITE_VERSION | sed -e 's/\./ /g'` SQLITE=sqlite-amalgamation-`printf %d%02d%02d%02d $SQLITE_VERSION_LIST` -GMOCK=gmock-${GMOCK_VERSION} -GMOCK_URL=https://googlemock.googlecode.com/files/ +GTEST=release-${GTEST_VERSION} +GTEST_URL=https://github.com/google/googletest/archive +GMOCK=release-${GMOCK_VERSION} +GMOCK_URL=https://github.com/google/googlemock/archive HTTPD=httpd-${HTTPD_VERSION} APR_ICONV=apr-iconv-${APR_ICONV_VERSION} @@ -67,7 +72,7 @@ APACHE_MIRROR=http://archive.apache.org/dist # helpers usage() { echo "Usage: $0" - echo "Usage: $0 [ apr | serf | zlib | sqlite | gmock ] ..." + echo "Usage: $0 [ apr | serf | zlib | sqlite | googlemock ] ..." exit $1 } @@ -113,7 +118,7 @@ get_sqlite() { test -d $BASEDIR/sqlite-amalgamation && return cd $TEMPDIR - $HTTP_FETCH http://www.sqlite.org/$SQLITE.zip + $HTTP_FETCH https://www.sqlite.org/$SQLITE_VERSION_REL_YEAR/$SQLITE.zip cd $BASEDIR unzip -q $TEMPDIR/$SQLITE.zip @@ -122,17 +127,22 @@ get_sqlite() { } -get_gmock() { - test -d $BASEDIR/gmock-fused && return +get_googlemock() { + test -d $BASEDIR/googlemock && return cd $TEMPDIR + $HTTP_FETCH ${GTEST_URL}/${GTEST}.zip + unzip -q ${GTEST}.zip + rm -f ${GTEST}.zip + $HTTP_FETCH ${GMOCK_URL}/${GMOCK}.zip + unzip -q ${GMOCK}.zip + rm -f ${GMOCK}.zip + cd $BASEDIR - - unzip -q $TEMPDIR/$GMOCK.zip - - mv $GMOCK/fused-src gmock-fused - rm -fr $GMOCK + mkdir googlemock + mv $TEMPDIR/googletest-release-${GTEST_VERSION} googlemock/googletest + mv $TEMPDIR/googlemock-release-${GMOCK_VERSION} googlemock/googlemock } # main() diff --git a/subversion/include/private/ra_svn_sasl.h b/subversion/include/private/ra_svn_sasl.h index 428e20e8033c..e8284517a83a 100644 --- a/subversion/include/private/ra_svn_sasl.h +++ b/subversion/include/private/ra_svn_sasl.h @@ -27,14 +27,8 @@ #ifndef RA_SVN_SASL_H #define RA_SVN_SASL_H -#ifdef WIN32 -/* This prevents sasl.h from redefining iovec, which is always defined by APR - on win32. */ -#define STRUCT_IOVEC_DEFINED -#include -#else -#include -#endif +/* Keep this include statement at the top of this file. */ +#include "private/ra_svn_wrapped_sasl.h" #include #include diff --git a/subversion/include/private/ra_svn_wrapped_sasl.h b/subversion/include/private/ra_svn_wrapped_sasl.h new file mode 100644 index 000000000000..266a4f8279de --- /dev/null +++ b/subversion/include/private/ra_svn_wrapped_sasl.h @@ -0,0 +1,131 @@ +/* + * svn_wrapped_sasl.h : wrapped SASL API + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#ifndef RA_SVN_WRAPPED_SASL_H +#define RA_SVN_WRAPPED_SASL_H + +#include + +#ifdef WIN32 +# define APR_WANT_IOVEC +# include + /* This prevents sasl.h from redefining iovec, + which is always defined by APR on win32. */ +# define STRUCT_IOVEC_DEFINED +# include +#else +# include +#endif + +/* Apple deprecated the SASL API on Mac OS X 10.11, causing a + moderately huge number of deprecation warnings to be emitted during + compilation. Consequently, we wrap the parts of the SASL API that + we use in a set of private functions and disable the deprecation + warnings for this header and the implementation file. */ +#ifdef __APPLE__ +# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +# endif +#endif /* __APPLE__ */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +void +svn_sasl__set_mutex(sasl_mutex_alloc_t *, sasl_mutex_lock_t *, + sasl_mutex_unlock_t *, sasl_mutex_free_t *); + +void +svn_sasl__done(void); + +void +svn_sasl__dispose(sasl_conn_t **); + +const char * +svn_sasl__errstring(int, const char *, const char **); + +const char * +svn_sasl__errdetail(sasl_conn_t *); + +int +svn_sasl__getprop(sasl_conn_t *, int, const void **); + +int +svn_sasl__setprop(sasl_conn_t *, int, const void *); + +int +svn_sasl__client_init(const sasl_callback_t *); + +int +svn_sasl__client_new(const char *, const char *, const char *, const char *, + const sasl_callback_t *, unsigned, sasl_conn_t **); + +int +svn_sasl__client_start(sasl_conn_t *, const char *, sasl_interact_t **, + const char **, unsigned *, const char **); + +int +svn_sasl__client_step(sasl_conn_t *, const char *, unsigned, + sasl_interact_t **, const char **, unsigned *); + +int +svn_sasl__server_init(const sasl_callback_t *, const char *); + +int +svn_sasl__server_new(const char *, const char *, const char *, + const char *, const char *, const sasl_callback_t *, + unsigned, sasl_conn_t **); + +int +svn_sasl__listmech(sasl_conn_t *, const char *, const char *, const char *, + const char *, const char **, unsigned *, int *); + +int +svn_sasl__server_start(sasl_conn_t *, const char *, const char *, unsigned, + const char **, unsigned *); + +int +svn_sasl__server_step(sasl_conn_t *, const char *, unsigned, + const char **, unsigned *); + +int +svn_sasl__encode(sasl_conn_t *, const char *, unsigned, + const char **, unsigned *); + +int +svn_sasl__decode(sasl_conn_t *, const char *, unsigned, + const char **, unsigned *); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#ifdef __APPLE__ +# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2) +# pragma GCC diagnostic pop +# endif +#endif /* __APPLE__ */ + +#endif /* RA_SVN_WRAPPED_SASL_H */ diff --git a/subversion/include/private/svn_atomic.h b/subversion/include/private/svn_atomic.h index 6a6b2dca6be1..f86a39ec68c6 100644 --- a/subversion/include/private/svn_atomic.h +++ b/subversion/include/private/svn_atomic.h @@ -75,22 +75,82 @@ extern "C" { apr_atomic_cas32((mem), (with), (cmp)) /** @} */ +/** + * @name Single-threaded atomic initialization + * @{ + */ + +/** + * Callback for svn_atomic__init_once(). + * @return an #svn_error_t if the initialization fails. + * @since New in 1.10 + */ +typedef svn_error_t *(*svn_atomic__err_init_func_t)(void *baton, + apr_pool_t *pool); + +/** + * Callback for svn_atomic__init_no_error(). + * @return a string containing an error message if the initialization fails. + * @since New in 1.10 + */ +typedef const char *(*svn_atomic__str_init_func_t)(void *baton); + /** * Call an initialization function in a thread-safe manner. * * @a global_status must be a pointer to a global, zero-initialized - * #svn_atomic_t. @a init_func is a pointer to the function that performs - * the actual initialization. @a baton and and @a pool are passed on to the - * init_func for its use. + * #svn_atomic_t. @a err_init_func is a pointer to the function that + * performs the actual initialization. @a baton and and @a pool are + * passed on to @a err_init_func for its use. + * + * @return the error returned by @a err_init_func. * * @since New in 1.5. */ svn_error_t * svn_atomic__init_once(volatile svn_atomic_t *global_status, - svn_error_t *(*init_func)(void*,apr_pool_t*), + svn_atomic__err_init_func_t err_init_func, void *baton, apr_pool_t* pool); +/** + * Call an initialization function in a thread-safe manner. + * + * Unlike svn_atomic__init_once(), this function does not need a pool + * and does not create an #svn_error_t, and neither should the + * @a str_init_func implementation. + * + * @a global_status must be a pointer to a global, zero-initialized + * #svn_atomic_t. @a str_init_func is a pointer to the function that + * performs the actual initialization. @a baton is passed on to + * @a str_init_func for its use. + * + * @return the error string returned by @a str_init_func. + * + * @since New in 1.10. + */ +const char * +svn_atomic__init_once_no_error(volatile svn_atomic_t *global_status, + svn_atomic__str_init_func_t str_init_func, + void *baton); + + +/** + * Query and increment the global counter and set @a value to the new + * counter value. + * + * This function is thread-safe and you should call it whenever you need + * a number that is unique within the current process. The values are > 0. + * + * @return the error object in case of a synchronization failure. + * + * @since New in 1.10. + */ +svn_error_t * +svn_atomic__unique_counter(apr_uint64_t* value); + +/** @} */ + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/subversion/include/private/svn_branch.h b/subversion/include/private/svn_branch.h new file mode 100644 index 000000000000..3fbaeb7ef77c --- /dev/null +++ b/subversion/include/private/svn_branch.h @@ -0,0 +1,679 @@ +/** + * @copyright + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * @endcopyright + * + * @file svn_branch.h + * @brief Operating on a branched version history + * + * @since New in ???. + */ + +/* Transactions + * + * A 'txn' contains a set of changes to the branches/elements. + * + * To make changes you say, for example, "for element 5: I want the parent + * element to be 3 now, and its name to be 'bar', and its content to be + * {props=... text=...}". That sets up a move and/or rename and/or + * content-change (or possibly a no-op for all three aspects) for element 5. + * + * Before or after (or at the same time, if we make a parallelizable + * implementation) we can make edits to the other elements, including + * element 3. + * + * So at the time of the edit method 'change e5: let its parent be e3' + * we might or might not have even created e3, if that happens to be an + * element that we wish to create rather than one that already existed. + * + * We allow this non-ordering because we want the changes to different + * elements to be totally independent. + * + * So at any given 'moment' in time during specifying the changes to a + * txn, the txn state is not necessarily one that maps directly to a + * flat tree (single-rooted, no cycles, no clashes of paths, etc.). + * + * Once we've finished specifying the edits, then the txn state will be + * converted to a flat tree, and that's the final result. But we can't + * query an arbitrary txn (potentially in the middle of making changes + * to it) by path, because the paths are not fully defined yet. + * + * So there are three kinds of operations: + * + * - query involving paths + * => requires a flat tree state to query, not an in-progress txn + * + * - query, not involving paths + * => accepts a txn-in-progress or a flat tree + * + * - modify (not involving paths) + * => requires a txn + * + * Currently, a txn is represented by 'svn_branch__txn_t', with + * 'svn_branch__state_t' for the individual branches in it. A flat tree is + * represented by 'svn_branch__subtree_t'. But there is currently not a + * clean separation; there is some overlap and some warts such as the + * 'svn_branch__txn_sequence_point' method. + */ + + +#ifndef SVN_BRANCH_H +#define SVN_BRANCH_H + +#include + +#include "svn_types.h" +#include "svn_error.h" +#include "svn_io.h" /* for svn_stream_t */ +#include "svn_delta.h" + +#include "private/svn_element.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/* ### */ +#define SVN_BRANCH__ERR 123456 + +/** Element Identifier (EID). + * + * An element may appear in any or all branches, and its EID is the same in + * each branch in which the element appears. + * + * By definition, an element keeps the same EID for its whole lifetime, even + * if deleted from all branches and later 'resurrected'. + * + * In principle, an EID is an arbitrary token and has no intrinsic + * relationships (except equality) to other EIDs. The current implementation + * uses integers and allocates them sequentially from a central counter, but + * the implementation may be changed. + * + * ### In most places the code currently says 'int', verbatim. + */ +typedef int svn_branch__eid_t; + +typedef struct svn_branch__el_rev_id_t svn_branch__el_rev_id_t; + +typedef struct svn_branch__rev_bid_eid_t svn_branch__rev_bid_eid_t; + +typedef struct svn_branch__rev_bid_t svn_branch__rev_bid_t; + +typedef struct svn_branch__state_t svn_branch__state_t; + +/* Per-repository branching info. + */ +typedef struct svn_branch__repos_t svn_branch__repos_t; + +/* Methods (conceptually public, but called indirectly) for a transaction. + */ +typedef struct svn_branch__txn_vtable_t svn_branch__txn_vtable_t; + +/* Private data for a transaction. + */ +typedef struct svn_branch__txn_priv_t svn_branch__txn_priv_t; + +/* A container for all the branching metadata for a specific revision (or + * an uncommitted transaction). + */ +typedef struct svn_branch__txn_t +{ + /* Methods (conceptually public, but called indirectly). */ + svn_branch__txn_vtable_t *vtable; + + /* Private data. */ + svn_branch__txn_priv_t *priv; + + /* Public data. */ + + /* The repository in which this revision exists. */ + svn_branch__repos_t *repos; + + /* If committed, the revision number; else SVN_INVALID_REVNUM. */ + svn_revnum_t rev; + + /* If committed, the previous revision number, else the revision number + on which this transaction is based. */ + svn_revnum_t base_rev; + +} svn_branch__txn_t; + +/* Create a new branch txn object. + */ +svn_branch__txn_t * +svn_branch__txn_create(const svn_branch__txn_vtable_t *vtable, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *result_pool); + +/* Return all the branches in TXN. + * + * These branches are available for reading. (Some of them may also be + * mutable.) + * + * ### Rename to 'list_branches' & return only their ids? + * + * Return an empty array if there are none. + */ +apr_array_header_t * +svn_branch__txn_get_branches(const svn_branch__txn_t *txn, + apr_pool_t *result_pool); + +/* Return the branch whose id is BRANCH_ID in TXN. + * + * Return NULL if not found. + * + * Note: a branch id is, in behavioural terms, an arbitrary token. In the + * current implementation it is constructed from the hierarchy of subbranch + * root EIDs leading to the branch, but that may be changed in future. + * + * See also: svn_branch__get_id(). + */ +svn_branch__state_t * +svn_branch__txn_get_branch_by_id(const svn_branch__txn_t *txn, + const char *branch_id, + apr_pool_t *scratch_pool); + +svn_error_t * +svn_branch__txn_get_num_new_eids(const svn_branch__txn_t *txn, + int *num_new_eids_p, + apr_pool_t *scratch_pool); + +/* Assign a new txn-scope element id in TXN. + */ +svn_error_t * +svn_branch__txn_new_eid(svn_branch__txn_t *txn, + int *new_eid_p, + apr_pool_t *scratch_pool); + +/** Open for writing, either a new branch or an existing branch. + * + * When creating a new branch, declare its root element id to be ROOT_EID. Do + * not instantiate the root element, nor any other elements. + * + * TREE_REF specifies the initial tree content, by reference to a committed + * tree. It overwrites any existing tree, even if the branch was already + * mutable in the txn. + * + * If TREE_REF is null, then the initial tree is empty for a new branch + * (not already present in the txn), or the branch's current tree if the + * branch was already present (readable or mutable) in the txn. + * + * ### TODO: Take a 'history' parameter; 'none' is a valid option. + * + * We use a common 'open subbranch' method for both 'find' and 'add' + * cases, according to the principle that 'editing' a txn should dictate + * the new state without reference to the old state. + * + * This method returns a mutable 'branch state' object which is a part of + * the txn. + * + * ### When opening ('finding') an existing branch, ROOT_EID should match + * it. (Should we check, and throw an error if not?) + */ +svn_error_t * +svn_branch__txn_open_branch(svn_branch__txn_t *txn, + svn_branch__state_t **new_branch_p, + const char *branch_id, + int root_eid, + svn_branch__rev_bid_eid_t *tree_ref, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/** Register a sequence point. + * + * At a sequence point, elements are arranged in a tree hierarchy: each + * element has exactly one parent element, except the root, and so on. + * Translation between paths and element addressing is defined only at + * a sequence point. + * + * The other edit operations -- add, alter, delete, etc. -- result in a + * state that is not a sequence point. + * + * The new transaction begins at a sequence point. Completion of editing + * (svn_branch__txn_complete()) also creates a sequence point. + */ +svn_error_t * +svn_branch__txn_sequence_point(svn_branch__txn_t *txn, + apr_pool_t *scratch_pool); + +/** Finalize this transaction. + * + * Notify that the edit has been completed successfully. + */ +svn_error_t * +svn_branch__txn_complete(svn_branch__txn_t *txn, + apr_pool_t *scratch_pool); + +/** Abandon this transaction. + * + * Notify that editing this transaction was not successful. + */ +svn_error_t * +svn_branch__txn_abort(svn_branch__txn_t *txn, + apr_pool_t *scratch_pool); + +/* Change txn-local EIDs (negative integers) in TXN to revision EIDs, by + * assigning a new revision-EID (positive integer) for each one. + * + * Rewrite TXN->first_eid and TXN->next_eid accordingly. + */ +svn_error_t * +svn_branch__txn_finalize_eids(svn_branch__txn_t *txn, + apr_pool_t *scratch_pool); + +/* Often, branches have the same root element. For example, + * branching /trunk to /branches/br1 results in: + * + * branch 1: (root-EID=100) + * EID 100 => /trunk + * ... + * branch 2: (root-EID=100) + * EID 100 => /branches/br1 + * ... + * + * However, the root element of one branch may correspond to a non-root + * element of another branch. + * + * Continuing the same example, branching from the trunk subtree + * /trunk/D (which is not itself a branch root) results in: + * + * branch 3: (root-EID=104) + * EID 100 => (nil) + * ... + * EID 104 => /branches/branch-of-trunk-subtree-D + * ... + */ + +/* Methods (conceptually public, but called indirectly) for a branch state. + */ +typedef struct svn_branch__state_vtable_t svn_branch__state_vtable_t; + +/* Private data for a branch state. + */ +typedef struct svn_branch__state_priv_t svn_branch__state_priv_t; + +/* A branch state. + * + * A branch state object describes one version of one branch. + */ +struct svn_branch__state_t +{ + /* Methods (conceptually public, but called indirectly). */ + svn_branch__state_vtable_t *vtable; + + /* Private data. */ + svn_branch__state_priv_t *priv; + + /* Public data. */ + + /* The branch identifier (starting with 'B') */ + const char *bid; + + /* The revision to which this branch state belongs */ + /* ### Later we should remove this and let a single state be sharable + by multiple txns. */ + svn_branch__txn_t *txn; + +}; + +/* Create a new branch state object. + */ +svn_branch__state_t * +svn_branch__state_create(const svn_branch__state_vtable_t *vtable, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *result_pool); + +/* Get the full id of branch BRANCH. + * + * Branch id format: + * B[.<1st-level-eid>[.<2nd-level-eid>[...]]] + * + * Note: a branch id is, in behavioural terms, an arbitrary token. In the + * current implementation it is constructed from the hierarchy of subbranch + * root EIDs leading to the branch, but that may be changed in future. + * + * See also: svn_branch__txn_get_branch_by_id(). + */ +const char * +svn_branch__get_id(const svn_branch__state_t *branch, + apr_pool_t *result_pool); + +/* Return the element id of the root element of BRANCH. + */ +int +svn_branch__root_eid(const svn_branch__state_t *branch); + +/* Return the id of the branch nested in OUTER_BID at element OUTER_EID. + * + * For a top-level branch, OUTER_BID is null and OUTER_EID is the + * top-level branch number. + * + * (Such branches need not exist. This works purely with ids, making use + * of the fact that nested branch ids are predictable based on the nesting + * element id.) + */ +const char * +svn_branch__id_nest(const char *outer_bid, + int outer_eid, + apr_pool_t *result_pool); + +/* Given a nested branch id BID, set *OUTER_BID to the outer branch's id + * and *OUTER_EID to the nesting element in the outer branch. + * + * For a top-level branch, set *OUTER_BID to NULL and *OUTER_EID to the + * top-level branch number. + * + * (Such branches need not exist. This works purely with ids, making use + * of the fact that nested branch ids are predictable based on the nesting + * element id.) + */ +void +svn_branch__id_unnest(const char **outer_bid, + int *outer_eid, + const char *bid, + apr_pool_t *result_pool); + +/* Remove the branch with id BID from the list of branches in TXN. + */ +svn_error_t * +svn_branch__txn_delete_branch(svn_branch__txn_t *txn, + const char *bid, + apr_pool_t *scratch_pool); + +/* Branch-Element-Revision */ +struct svn_branch__el_rev_id_t +{ + /* The branch state that applies to REV. */ + svn_branch__state_t *branch; + /* Element. */ + int eid; + /* Revision. SVN_INVALID_REVNUM means 'in this transaction', not 'head'. + ### Do we need this if BRANCH refers to a particular branch-revision? */ + svn_revnum_t rev; + +}; + +/* Revision-branch-element id. */ +struct svn_branch__rev_bid_eid_t +{ + /* Revision. SVN_INVALID_REVNUM means 'in this transaction', not 'head'. */ + svn_revnum_t rev; + /* The branch id in revision REV. */ + const char *bid; + /* Element id. */ + int eid; + +}; + +/* Revision-branch id. */ +struct svn_branch__rev_bid_t +{ + /* Revision. SVN_INVALID_REVNUM means 'in this transaction', not 'head'. */ + svn_revnum_t rev; + /* The branch id in revision REV. */ + const char *bid; + +}; + +/* Return a new el_rev_id object constructed with *shallow* copies of BRANCH, + * EID and REV, allocated in RESULT_POOL. + */ +svn_branch__el_rev_id_t * +svn_branch__el_rev_id_create(svn_branch__state_t *branch, + int eid, + svn_revnum_t rev, + apr_pool_t *result_pool); + +/* Return a new id object constructed with a deep copy of OLD_ID, + * allocated in RESULT_POOL. */ +svn_branch__el_rev_id_t * +svn_branch__el_rev_id_dup(const svn_branch__el_rev_id_t *old_id, + apr_pool_t *result_pool); + +/* Return a new id object constructed with deep copies of REV, BRANCH_ID + * and EID, allocated in RESULT_POOL. + */ +svn_branch__rev_bid_eid_t * +svn_branch__rev_bid_eid_create(svn_revnum_t rev, + const char *branch_id, + int eid, + apr_pool_t *result_pool); +svn_branch__rev_bid_t * +svn_branch__rev_bid_create(svn_revnum_t rev, + const char *branch_id, + apr_pool_t *result_pool); + +/* Return a new id object constructed with a deep copy of OLD_ID, + * allocated in RESULT_POOL. */ +svn_branch__rev_bid_eid_t * +svn_branch__rev_bid_eid_dup(const svn_branch__rev_bid_eid_t *old_id, + apr_pool_t *result_pool); +svn_branch__rev_bid_t * +svn_branch__rev_bid_dup(const svn_branch__rev_bid_t *old_id, + apr_pool_t *result_pool); + +svn_boolean_t +svn_branch__rev_bid_equal(const svn_branch__rev_bid_t *id1, + const svn_branch__rev_bid_t *id2); + +typedef struct svn_branch__history_t +{ + /* The immediate parents of this state in the branch/merge graph. + Hash of (BID -> svn_branch__rev_bid_t). */ + apr_hash_t *parents; +} svn_branch__history_t; + +svn_branch__history_t * +svn_branch__history_create_empty(apr_pool_t *result_pool); + +svn_branch__history_t * +svn_branch__history_create(apr_hash_t *parents, + apr_pool_t *result_pool); + +svn_branch__history_t * +svn_branch__history_dup(const svn_branch__history_t *old, + apr_pool_t *result_pool); + +/* Return the mapping of elements in branch BRANCH. + */ +svn_error_t * +svn_branch__state_get_elements(const svn_branch__state_t *branch, + svn_element__tree_t **element_tree_p, + apr_pool_t *result_pool); + +/* In BRANCH, get element EID (parent, name, payload). + * + * If element EID is not present, return null. + */ +svn_error_t * +svn_branch__state_get_element(const svn_branch__state_t *branch, + svn_element__content_t **element_p, + int eid, + apr_pool_t *result_pool); + +/** Equivalent to + * alter_one(..., element->parent_eid, element->name, element->payload), + * or, if @a element is null, to + * delete_one(...). + */ +svn_error_t * +svn_branch__state_set_element(svn_branch__state_t *branch, + int eid, + const svn_element__content_t *element, + apr_pool_t *result_pool); + +/** Specify that the element of @a branch identified by @a eid shall not + * be present. + * + * The delete is not explicitly recursive. However, as an effect of the + * final 'flattening' of a branch state into a single tree, each element + * in the final state that still has this element as its parent will also + * be deleted, recursively. + * + * The element @a eid must not be the root element of @a branch. + * + * ### Options for Out-Of-Date Checking on Rebase + * + * We may want to specify what kind of OOD check takes place. The + * following two options differ in what happens to an element that is + * added, on the other side, as a child of this deleted element. + * + * Rebase option 1: The rebase checks for changes in the whole subtree, + * excluding any portions of the subtree for which an explicit delete or + * move-away has been issued. The check includes checking that the other + * side has not added any child. In other words, the deletion is + * interpreted as an action affecting a subtree (dynamically rooted at + * this element), rather than as an action affecting a single element or + * a fixed set of elements that was explicitly or implicitly specified + * by the sender. + * + * To delete a mixed-rev subtree, the client sends an explicit delete for + * each subtree that has a different base revision from its parent. + * + * Rebase option 2: The rebase checks for changes to this element only. + * The sender can send an explicit delete for each existing child element + * that it requires to be checked as well. However, there is no way for + * the sender to specify whether a child element added by the other side + * should be considered an out-of-date error or silently deleted. + * + * It would also be possible to let the caller specify, at some suitable + * granularity, which option to use. + */ +svn_error_t * +svn_branch__state_delete_one(svn_branch__state_t *branch, + svn_branch__eid_t eid, + apr_pool_t *scratch_pool); + +/** Specify the tree position and payload of the element of @a branch + * identified by @a eid. + * + * Set the element's parent EID, name and payload to @a new_parent_eid, + * @a new_name and @a new_payload respectively. + * + * This may create a new element or alter an existing element. + * + * If the element ... we can describe the effect as ... + * + * exists in the branch => altering it; + * previously existed in the branch => resurrecting it; + * only existed in other branches => branching it; + * never existed anywhere => creating or adding it. + * + * However, these are imprecise descriptions and not mutually exclusive. + * For example, if it existed previously in this branch and another, then + * we may describe the result as 'resurrecting' and/or as 'branching'. + * + * Duplicate @a new_name and @a new_payload into the branch's pool. + */ +svn_error_t * +svn_branch__state_alter_one(svn_branch__state_t *branch, + svn_branch__eid_t eid, + svn_branch__eid_t new_parent_eid, + const char *new_name, + const svn_element__payload_t *new_payload, + apr_pool_t *scratch_pool); + +svn_error_t * +svn_branch__state_copy_tree(svn_branch__state_t *branch, + const svn_branch__rev_bid_eid_t *src_el_rev, + svn_branch__eid_t new_parent_eid, + const char *new_name, + apr_pool_t *scratch_pool); + +/* Purge orphaned elements in BRANCH. + */ +svn_error_t * +svn_branch__state_purge(svn_branch__state_t *branch, + apr_pool_t *scratch_pool); + +/* Get the merge history of BRANCH. + */ +svn_error_t * +svn_branch__state_get_history(svn_branch__state_t *branch, + svn_branch__history_t **merge_history_p, + apr_pool_t *result_pool); + +/* Set the merge history of BRANCH. + */ +svn_error_t * +svn_branch__state_set_history(svn_branch__state_t *branch, + const svn_branch__history_t *merge_history, + apr_pool_t *scratch_pool); + +/* Return the branch-relative path of element EID in BRANCH. + * + * If the element EID does not currently exist in BRANCH, return NULL. + * + * ### TODO: Clarify sequencing requirements. + */ +const char * +svn_branch__get_path_by_eid(const svn_branch__state_t *branch, + int eid, + apr_pool_t *result_pool); + +/* Return the EID for the branch-relative path PATH in BRANCH. + * + * If no element of BRANCH is at this path, return -1. + * + * ### TODO: Clarify sequencing requirements. + */ +int +svn_branch__get_eid_by_path(const svn_branch__state_t *branch, + const char *path, + apr_pool_t *scratch_pool); + +/* Get the default branching metadata for r0 of a new repository. + */ +svn_string_t * +svn_branch__get_default_r0_metadata(apr_pool_t *result_pool); + +/* Create a new txn object *TXN_P, initialized with info + * parsed from STREAM, allocated in RESULT_POOL. + */ +svn_error_t * +svn_branch__txn_parse(svn_branch__txn_t **txn_p, + svn_branch__repos_t *repos, + svn_stream_t *stream, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/* Write to STREAM a parseable representation of TXN. + */ +svn_error_t * +svn_branch__txn_serialize(svn_branch__txn_t *txn, + svn_stream_t *stream, + apr_pool_t *scratch_pool); + +/* Write to STREAM a parseable representation of BRANCH. + */ +svn_error_t * +svn_branch__state_serialize(svn_stream_t *stream, + svn_branch__state_t *branch, + apr_pool_t *scratch_pool); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SVN_BRANCH_H */ diff --git a/subversion/include/private/svn_branch_compat.h b/subversion/include/private/svn_branch_compat.h new file mode 100644 index 000000000000..8c7d0b2a04dc --- /dev/null +++ b/subversion/include/private/svn_branch_compat.h @@ -0,0 +1,273 @@ +/** + * @copyright + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * @endcopyright + * + * @file svn_branch_compat.h + * @brief Compatibility with svn_delta_editor_t etc. + * + * @since New in ???. + */ + +#ifndef SVN_BRANCH_COMPAT_H +#define SVN_BRANCH_COMPAT_H + +#include + +#include "svn_types.h" +#include "svn_error.h" +#include "svn_delta.h" +#include "svn_ra.h" +#include "private/svn_branch.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/** Callback to retrieve a node's kind and content. This is + * needed by the various editor shims in order to effect backwards + * compatibility. + * + * Implementations should set @a *kind to the node kind of @a repos_relpath + * in @a revision. + * + * Implementations should set @a *props to the hash of properties + * associated with @a repos_relpath in @a revision, allocating that hash + * and its contents in @a result_pool. Only the 'regular' props should be + * included, not special props such as 'entry props'. + * + * Implementations should set @a *filename to the name of a file + * suitable for use as a delta base for @a repos_relpath in @a revision + * (allocating @a *filename from @a result_pool), or to @c NULL if the + * base stream is empty. + * + * Any output argument may be NULL if the output is not wanted. + * + * @a baton is an implementation-specific closure. + * @a repos_relpath is relative to the repository root. + * The implementation should ensure that @a new_content, including any + * file therein, lives at least for the life time of @a result_pool. + * @a scratch_pool is provided for temporary allocations. + */ +typedef svn_error_t *(*svn_branch__compat_fetch_func_t)( + svn_node_kind_t *kind, + apr_hash_t **props, + svn_stringbuf_t **file_text, + apr_hash_t **children_names, + void *baton, + const char *repos_relpath, + svn_revnum_t revision, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool + ); + +/* + */ +svn_error_t * +svn_branch__compat_fetch(svn_element__payload_t **payload_p, + svn_branch__txn_t *txn, + svn_element__branch_ref_t branch_ref, + svn_branch__compat_fetch_func_t fetch_func, + void *fetch_baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/* An object for communicating out-of-band details between an Ev1-to-Ev3 + * shim and an Ev3-to-Ev1 shim. */ +typedef struct svn_branch__compat_shim_connector_t svn_branch__compat_shim_connector_t; + +/* Return an Ev3 editor in *EDITOR_P which will drive the Ev1 delta + * editor DEDITOR/DEDIT_BATON. + * + * This editor buffers all the changes and then drives the Ev1 when the + * returned editor's "close" method is called. + * + * This editor converts moves into copy-and-delete. It presently makes a + * one-way (lossy) conversion. + * + * TODO: Option to pass the 'move' information through as some sort of + * metadata so that it can be preserved in an Ev3-Ev1-Ev3 round-trip + * conversion. + * - Use 'entry-props'? + * - Send copy-and-delete with copy-from-rev = -1? + * + * This editor implements the "independent per-element changes" variant + * of the Ev3 commit editor interface. + * + * Use *BRANCHING_TXN as the branching state info ... + * + * SHIM_CONNECTOR can be used to enable a more exact round-trip conversion + * from an Ev1 drive to Ev3 and back to Ev1. The caller should pass the + * returned *SHIM_CONNECTOR value to svn_delta__delta_from_ev3_for_commit(). + * SHIM_CONNECTOR may be null if not wanted. + * + * REPOS_ROOT_URL is the repository root URL. + * + * FETCH_FUNC/FETCH_BATON is a callback by which the shim may retrieve the + * original or copy-from kind/properties/text for a path being committed. + * + * CANCEL_FUNC / CANCEL_BATON: The usual cancellation callback; folded + * into the produced editor. May be NULL/NULL if not wanted. + * + * Allocate the new editor in RESULT_POOL, which may become large and must + * live for the lifetime of the edit. Use SCRATCH_POOL for temporary + * allocations. + */ +svn_error_t * +svn_branch__compat_txn_from_delta_for_commit( + svn_branch__txn_t **txn_p, + svn_branch__compat_shim_connector_t **shim_connector, + const svn_delta_editor_t *deditor, + void *dedit_baton, + svn_branch__txn_t *branching_txn, + const char *repos_root_url, + svn_branch__compat_fetch_func_t fetch_func, + void *fetch_baton, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/* Return a delta editor in DEDITOR/DEDITOR_BATON which will drive EDITOR. + * + * REPOS_ROOT_URL is the repository root URL, and BASE_RELPATH is the + * relative path within the repository of the root directory of the edit. + * (An Ev1 edit must be rooted at a directory, not at a file.) + * + * FETCH_FUNC/FETCH_BATON is a callback by which the shim may retrieve the + * original or copy-from kind/properties/text for a path being committed. + * + * SHIM_CONNECTOR can be used to enable a more exact round-trip conversion + * from an Ev1 drive to Ev3 and back to Ev1. It must live for the lifetime + * of the edit. It may be null if not wanted. + * + * Allocate the new editor in RESULT_POOL, which may become large and must + * live for the lifetime of the edit. Use SCRATCH_POOL for temporary + * allocations. + */ +svn_error_t * +svn_branch__compat_delta_from_txn_for_commit( + const svn_delta_editor_t **deditor, + void **dedit_baton, + svn_branch__txn_t *edit_txn, + const char *repos_root_url, + const char *base_relpath, + svn_branch__compat_fetch_func_t fetch_func, + void *fetch_baton, + const svn_branch__compat_shim_connector_t *shim_connector, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/* Return in NEW_DEDITOR/NEW_DETIT_BATON a delta editor that wraps + * OLD_DEDITOR/OLD_DEDIT_BATON, inserting a pair of shims that convert + * Ev1 to Ev3 and back to Ev1. + * + * REPOS_ROOT_URL is the repository root URL, and BASE_RELPATH is the + * relative path within the repository of the root directory of the edit. + * + * FETCH_FUNC/FETCH_BATON is a callback by which the shim may retrieve the + * original or copy-from kind/properties/text for a path being committed. + */ +svn_error_t * +svn_branch__compat_insert_shims( + const svn_delta_editor_t **new_deditor, + void **new_dedit_baton, + const svn_delta_editor_t *old_deditor, + void *old_dedit_baton, + const char *repos_root, + const char *base_relpath, + svn_branch__compat_fetch_func_t fetch_func, + void *fetch_baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/* A callback for declaring the target revision of an update or switch. + */ +typedef svn_error_t *(*svn_branch__compat_set_target_revision_func_t)( + void *baton, + svn_revnum_t target_revision, + apr_pool_t *scratch_pool); + +/* An update (or switch) editor. + * + * This consists of a plain Ev3 editor and the additional methods or + * resources needed for use as an update or switch editor. + */ +typedef struct svn_branch__compat_update_editor3_t { + /* The txn we're driving. */ + svn_branch__txn_t *edit_txn; + + /* A method to communicate the target revision of the update (or switch), + * to be called before driving the editor. It has its own baton, rather + * than using the editor's baton, so that the editor can be replaced (by + * a wrapper editor, typically) without having to wrap this callback. */ + svn_branch__compat_set_target_revision_func_t set_target_revision_func; + void *set_target_revision_baton; +} svn_branch__compat_update_editor3_t; + +/* Like svn_delta__ev3_from_delta_for_commit() but for an update editor. + */ +svn_error_t * +svn_branch__compat_txn_from_delta_for_update( + svn_branch__compat_update_editor3_t **editor_p, + const svn_delta_editor_t *deditor, + void *dedit_baton, + svn_branch__txn_t *branching_txn, + const char *repos_root_url, + const char *base_repos_relpath, + svn_branch__compat_fetch_func_t fetch_func, + void *fetch_baton, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/* Like svn_delta__delta_from_ev3_for_commit() but for an update editor. + */ +svn_error_t * +svn_branch__compat_delta_from_txn_for_update( + const svn_delta_editor_t **deditor, + void **dedit_baton, + svn_branch__compat_update_editor3_t *update_editor, + const char *repos_root_url, + const char *base_repos_relpath, + svn_branch__compat_fetch_func_t fetch_func, + void *fetch_baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/* An Ev1 editor that drives (heuristically) a move-tracking editor. + */ +svn_error_t * +svn_branch__compat_get_migration_editor( + const svn_delta_editor_t **old_editor, + void **old_edit_baton, + svn_branch__txn_t *edit_txn, + svn_ra_session_t *from_session, + svn_revnum_t revision, + apr_pool_t *result_pool); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SVN_BRANCH_COMPAT_H */ diff --git a/subversion/include/private/svn_branch_impl.h b/subversion/include/private/svn_branch_impl.h new file mode 100644 index 000000000000..ad4df3b1b12d --- /dev/null +++ b/subversion/include/private/svn_branch_impl.h @@ -0,0 +1,197 @@ +/** + * @copyright + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * @endcopyright + * + * @file svn_branch_impl.h + * @brief Declarations needed by implementators of branch classes + * + * @since New in ???. + */ + +#ifndef SVN_BRANCH_IMPL_H +#define SVN_BRANCH_IMPL_H + +#include "private/svn_branch.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Common aspects od a txn/branch 'editor' class (derived from Ev2) */ +typedef struct svn_branch__vtable_priv_t +{ + /* Standard cancellation function. Called before each callback. */ + svn_cancel_func_t cancel_func; + void *cancel_baton; + +#ifdef ENABLE_ORDERING_CHECK + svn_boolean_t within_callback; + svn_boolean_t finished; + apr_pool_t *state_pool; +#endif + +} svn_branch__vtable_priv_t; + +/* The methods of svn_branch__txn_t. + * See the corresponding public API functions for details. + */ + +typedef apr_array_header_t *(*svn_branch__txn_v_get_branches_t)( + const svn_branch__txn_t *txn, + apr_pool_t *result_pool); + +typedef svn_error_t *(*svn_branch__txn_v_delete_branch_t)( + svn_branch__txn_t *txn, + const char *bid, + apr_pool_t *scratch_pool); + +typedef svn_error_t *(*svn_branch__txn_v_get_num_new_eids_t)( + const svn_branch__txn_t *txn, + int *num_new_eids_p, + apr_pool_t *scratch_pool); + +typedef svn_error_t *(*svn_branch__txn_v_new_eid_t)( + svn_branch__txn_t *txn, + svn_branch__eid_t *eid_p, + apr_pool_t *scratch_pool); + +typedef svn_error_t *(*svn_branch__txn_v_open_branch_t)( + svn_branch__txn_t *txn, + svn_branch__state_t **new_branch_p, + const char *new_branch_id, + int root_eid, + svn_branch__rev_bid_eid_t *from, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +typedef svn_error_t *(*svn_branch__txn_v_finalize_eids_t)( + svn_branch__txn_t *txn, + apr_pool_t *scratch_pool); + +typedef svn_error_t *(*svn_branch__txn_v_serialize_t)( + svn_branch__txn_t *txn, + svn_stream_t *stream, + apr_pool_t *scratch_pool); + +typedef svn_error_t *(*svn_branch__txn_v_sequence_point_t)( + svn_branch__txn_t *txn, + apr_pool_t *scratch_pool); + +typedef svn_error_t *(*svn_branch__txn_v_complete_t)( + svn_branch__txn_t *txn, + apr_pool_t *scratch_pool); + +typedef svn_error_t *(*svn_branch__txn_v_abort_t)( + svn_branch__txn_t *txn, + apr_pool_t *scratch_pool); + +struct svn_branch__txn_vtable_t +{ + svn_branch__vtable_priv_t vpriv; + + /* Methods. */ + svn_branch__txn_v_get_branches_t get_branches; + svn_branch__txn_v_delete_branch_t delete_branch; + svn_branch__txn_v_get_num_new_eids_t get_num_new_eids; + svn_branch__txn_v_new_eid_t new_eid; + svn_branch__txn_v_open_branch_t open_branch; + svn_branch__txn_v_finalize_eids_t finalize_eids; + svn_branch__txn_v_serialize_t serialize; + svn_branch__txn_v_sequence_point_t sequence_point; + svn_branch__txn_v_complete_t complete; + svn_branch__txn_v_complete_t abort; + +}; + +/* The methods of svn_branch__state_t. + * See the corresponding public API functions for details. + */ + +typedef svn_error_t *(*svn_branch__state_v_get_elements_t)( + const svn_branch__state_t *branch, + svn_element__tree_t **element_tree_p, + apr_pool_t *result_pool); + +typedef svn_error_t *(*svn_branch__state_v_get_element_t)( + const svn_branch__state_t *branch, + svn_element__content_t **element_p, + int eid, + apr_pool_t *result_pool); + +typedef svn_error_t *(*svn_branch__state_v_set_element_t)( + svn_branch__state_t *branch, + svn_branch__eid_t eid, + const svn_element__content_t *element, + apr_pool_t *scratch_pool); + +typedef svn_error_t *(*svn_branch__state_v_copy_one_t)( + svn_branch__state_t *branch, + const svn_branch__rev_bid_eid_t *src_el_rev, + svn_branch__eid_t local_eid, + svn_branch__eid_t new_parent_eid, + const char *new_name, + const svn_element__payload_t *new_payload, + apr_pool_t *scratch_pool); + +typedef svn_error_t *(*svn_branch__state_v_copy_tree_t)( + svn_branch__state_t *branch, + const svn_branch__rev_bid_eid_t *src_el_rev, + svn_branch__eid_t new_parent_eid, + const char *new_name, + apr_pool_t *scratch_pool); + +typedef svn_error_t *(*svn_branch__state_v_purge_t)( + svn_branch__state_t *branch, + apr_pool_t *scratch_pool); + +typedef svn_error_t *(*svn_branch__state_v_get_history_t)( + svn_branch__state_t *branch, + svn_branch__history_t **history_p, + apr_pool_t *scratch_pool); + +typedef svn_error_t *(*svn_branch__state_v_set_history_t)( + svn_branch__state_t *branch, + const svn_branch__history_t *history, + apr_pool_t *scratch_pool); + +struct svn_branch__state_vtable_t +{ + svn_branch__vtable_priv_t vpriv; + + svn_branch__state_v_get_elements_t get_elements; + svn_branch__state_v_get_element_t get_element; + svn_branch__state_v_set_element_t set_element; + svn_branch__state_v_copy_one_t copy_one; + svn_branch__state_v_copy_tree_t copy_tree; + svn_branch__state_v_purge_t purge; + svn_branch__state_v_get_history_t get_history; + svn_branch__state_v_set_history_t set_history; + +}; + + +#ifdef __cplusplus +} +#endif + +#endif /* SVN_BRANCH_IMPL_H */ + diff --git a/subversion/include/private/svn_branch_nested.h b/subversion/include/private/svn_branch_nested.h new file mode 100644 index 000000000000..5f262739b092 --- /dev/null +++ b/subversion/include/private/svn_branch_nested.h @@ -0,0 +1,216 @@ +/** + * @copyright + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * @endcopyright + * + * @file svn_branch_nested.h + * @brief Nested branches and subbranch-root elements + * + * @since New in ???. + */ + +#ifndef SVN_BRANCH_NESTED_H +#define SVN_BRANCH_NESTED_H + +#include + +#include "svn_types.h" + +#include "private/svn_branch.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/* + */ +void +svn_branch__get_outer_branch_and_eid(svn_branch__state_t **outer_branch_p, + int *outer_eid_p, + const svn_branch__state_t *branch, + apr_pool_t *scratch_pool); + +/* Return the root repos-relpath of BRANCH. + * + * ### TODO: Clarify sequencing requirements. + */ +const char * +svn_branch__get_root_rrpath(const svn_branch__state_t *branch, + apr_pool_t *result_pool); + +/* Return the repos-relpath of element EID in BRANCH. + * + * If the element EID does not currently exist in BRANCH, return NULL. + * + * ### TODO: Clarify sequencing requirements. + */ +const char * +svn_branch__get_rrpath_by_eid(const svn_branch__state_t *branch, + int eid, + apr_pool_t *result_pool); + +/* Return the EID for the repos-relpath RRPATH in BRANCH. + * + * If no element of BRANCH is at this path, return -1. + * + * ### TODO: Clarify sequencing requirements. + */ +/*int*/ +/*svn_branch__get_eid_by_rrpath(svn_branch__state_t *branch,*/ +/* const char *rrpath,*/ +/* apr_pool_t *scratch_pool);*/ + +/* Find the (deepest) branch of which the path RELPATH is either the root + * path or a normal, non-sub-branch path. An element need not exist at + * RELPATH. + * + * Set *BRANCH_P to the deepest branch within ROOT_BRANCH (recursively, + * including itself) that contains the path RELPATH. + * + * If EID_P is not null then set *EID_P to the element id of RELPATH in + * *BRANCH_P, or to -1 if no element exists at RELPATH in that branch. + * + * If RELPATH is not within any branch in ROOT_BRANCH, set *BRANCH_P to + * NULL and (if EID_P is not null) *EID_P to -1. + * + * ### TODO: Clarify sequencing requirements. + */ +svn_error_t * +svn_branch__find_nested_branch_element_by_relpath( + svn_branch__state_t **branch_p, + int *eid_p, + svn_branch__state_t *root_branch, + const char *relpath, + apr_pool_t *scratch_pool); + +/* Set *EL_REV_P to the el-rev-id of the element at relative path RELPATH + * anywhere in or under branch BRANCH_ID in revision REVNUM in REPOS. + * + * If there is no element there, set *EL_REV_P to point to an id in which + * the BRANCH field is the nearest enclosing branch of RRPATH and the EID + * field is -1. + * + * Allocate *EL_REV_P (but not the branch object that it refers to) in + * RESULT_POOL. + * + * ### TODO: Clarify sequencing requirements. + */ +svn_error_t * +svn_branch__repos_find_el_rev_by_path_rev(svn_branch__el_rev_id_t **el_rev_p, + const svn_branch__repos_t *repos, + svn_revnum_t revnum, + const char *branch_id, + const char *relpath, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/* Set *SUBBRANCHES_P an array of pointers to the branches that are immediate + * sub-branches of BRANCH. + */ +svn_error_t * +svn_branch__get_immediate_subbranches(svn_branch__state_t *branch, + apr_array_header_t **subbranches_p, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/* Return the subbranch rooted at BRANCH:EID, or NULL if that is + * not a subbranch root. + */ +svn_error_t * +svn_branch__get_subbranch_at_eid(svn_branch__state_t *branch, + svn_branch__state_t **subbranch_p, + int eid, + apr_pool_t *scratch_pool); + +/* A subtree of a branch, including any nested branches. + */ +typedef struct svn_branch__subtree_t +{ + svn_branch__rev_bid_t *predecessor; + + /* EID -> svn_element__content_t mapping. */ + svn_element__tree_t *tree; + + /* Subbranches to be included: each subbranch-root element in E_MAP + should be mapped here. + + A mapping of (int)EID -> (svn_branch__subtree_t *). */ + apr_hash_t *subbranches; +} svn_branch__subtree_t; + +/* Create an empty subtree (no elements populated, not even ROOT_EID). + * + * The result contains a *shallow* copy of E_MAP, or a new empty mapping + * if E_MAP is null. + */ +svn_branch__subtree_t * +svn_branch__subtree_create(apr_hash_t *e_map, + int root_eid, + apr_pool_t *result_pool); + +/* Return the subtree of BRANCH rooted at EID. + * Recursive: includes subbranches. + * + * The result is limited by the lifetime of BRANCH. It includes a shallow + * copy of the element maps in BRANCH and its subbranches: the hash tables + * are duplicated but the keys and values (element content data) are not. + * It assumes that modifications on a svn_branch__state_t treat element + * map keys and values as immutable -- which they do. + */ +svn_error_t * +svn_branch__get_subtree(svn_branch__state_t *branch, + svn_branch__subtree_t **subtree_p, + int eid, + apr_pool_t *result_pool); + +/* Return the subbranch rooted at SUBTREE:EID, or NULL if that is + * not a subbranch root. */ +svn_branch__subtree_t * +svn_branch__subtree_get_subbranch_at_eid(svn_branch__subtree_t *subtree, + int eid, + apr_pool_t *result_pool); + +/* Instantiate elements in a branch. + * + * In TO_BRANCH, instantiate (or alter, if existing) each element of + * ELEMENTS, each with its given tree structure (parent, name) and payload. + * + * Also branch the subbranches in ELEMENTS, creating corresponding new + * subbranches in TO_BRANCH, recursively. + */ +svn_error_t * +svn_branch__instantiate_elements_r(svn_branch__state_t *to_branch, + svn_branch__subtree_t elements, + apr_pool_t *scratch_pool); + +/* Create a branch txn object that implements nesting, and wraps a plain + * branch txn (that doesn't support nesting) WRAPPED_TXN. + */ +svn_branch__txn_t * +svn_branch__nested_txn_create(svn_branch__txn_t *wrapped_txn, + apr_pool_t *result_pool); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SVN_BRANCH_NESTED_H */ diff --git a/subversion/include/private/svn_branch_repos.h b/subversion/include/private/svn_branch_repos.h new file mode 100644 index 000000000000..663d017ebf36 --- /dev/null +++ b/subversion/include/private/svn_branch_repos.h @@ -0,0 +1,104 @@ +/** + * @copyright + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * @endcopyright + * + * @file svn_branch_repos.h + * @brief Operating on a repository + * + * @since New in ???. + */ + + +#ifndef SVN_BRANCH_REPOS_H +#define SVN_BRANCH_REPOS_H + +#include + +#include "svn_types.h" + +#include "private/svn_branch.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/* Create a new branching metadata object */ +svn_branch__repos_t * +svn_branch__repos_create(apr_pool_t *result_pool); + +/* Add REV_ROOT as the next revision in the repository REPOS. + * + * (This does not change the REV and BASE_REV fields of REV_ROOT. The + * caller should set those, before or after this call.) + */ +svn_error_t * +svn_branch__repos_add_revision(svn_branch__repos_t *repos, + svn_branch__txn_t *rev_root); + +/* Return a pointer to revision REVNUM of the repository REPOS. + */ +struct svn_branch__txn_t * +svn_branch__repos_get_revision(const svn_branch__repos_t *repos, + svn_revnum_t revnum); + +/* Return the revision root that represents the base revision (or, + * potentially, txn) of the revision or txn REV_ROOT. + */ +svn_branch__txn_t * +svn_branch__repos_get_base_revision_root(svn_branch__txn_t *rev_root); + +/* Set *BRANCH_P to the branch found in REPOS : REVNUM : BRANCH_ID. + * + * Return an error if REVNUM or BRANCH_ID is not found. + */ +svn_error_t * +svn_branch__repos_get_branch_by_id(svn_branch__state_t **branch_p, + const svn_branch__repos_t *repos, + svn_revnum_t revnum, + const char *branch_id, + apr_pool_t *scratch_pool); + +/* Set *EL_REV_P to the el-rev-id of the element at branch id BRANCH_ID, + * element id EID, in revision REVNUM in REPOS. + * + * If there is no element there, set *EL_REV_P to point to an id in which + * the BRANCH field is the nearest enclosing branch of RRPATH and the EID + * field is -1. + * + * Allocate *EL_REV_P (but not the branch object that it refers to) in + * RESULT_POOL. + */ +svn_error_t * +svn_branch__repos_find_el_rev_by_id(svn_branch__el_rev_id_t **el_rev_p, + const svn_branch__repos_t *repos, + svn_revnum_t revnum, + const char *branch_id, + int eid, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SVN_BRANCH_REPOS_H */ diff --git a/subversion/include/private/svn_cache.h b/subversion/include/private/svn_cache.h index 166295d6ce90..bedd0a8bfaf0 100644 --- a/subversion/include/private/svn_cache.h +++ b/subversion/include/private/svn_cache.h @@ -356,7 +356,12 @@ svn_cache__membuffer_cache_create(svn_membuffer_t **cache, * * If @a thread_safe is true, and APR is compiled with threads, all * accesses to the cache will be protected with a mutex, if the shared - * @a memcache has also been created with thread_safe flag set. + * @a membuffer has also been created with thread_safe flag set. + * + * If @a short_lived is set, assume that the data stored through this + * cache will probably only be needed for a short period of time. + * Typically, some UUID is used as part of the prefix in that scenario. + * This flag is a mere hint and does not affect functionality. * * These caches do not support svn_cache__iter. */ @@ -369,9 +374,23 @@ svn_cache__create_membuffer_cache(svn_cache__t **cache_p, const char *prefix, apr_uint32_t priority, svn_boolean_t thread_safe, + svn_boolean_t short_lived, apr_pool_t *result_pool, apr_pool_t *scratch_pool); +/** + * Creates a null-cache instance in @a *cache_p, allocated from + * @a result_pool. The given @c id is the only data stored in it and can + * be retrieved through svn_cache__get_info(). + * + * The cache object will immediately evict (reject) any data being added + * to it and will always report as empty. + */ +svn_error_t * +svn_cache__create_null(svn_cache__t **cache_p, + const char *id, + apr_pool_t *result_pool); + /** * Sets @a handler to be @a cache's error handling routine. If any * error is returned from a call to svn_cache__get or svn_cache__set, @a diff --git a/subversion/include/private/svn_cmdline_private.h b/subversion/include/private/svn_cmdline_private.h index f21a5d2e911b..ac5fb7b07924 100644 --- a/subversion/include/private/svn_cmdline_private.h +++ b/subversion/include/private/svn_cmdline_private.h @@ -63,6 +63,7 @@ svn_cmdline__print_xml_prop(svn_stringbuf_t **outstr, * Expects a @c svn_cmdline_prompt_baton2_t to be passed as @a baton. * * @since New in 1.6. + * @deprecated Only used by old libgome-keyring implementation. */ svn_error_t * svn_cmdline__auth_gnome_keyring_unlock_prompt(char **keyring_password, @@ -88,7 +89,7 @@ typedef struct svn_cmdline__config_argument_t * containing svn_cmdline__config_argument_t* elements, allocating the option * data in @a pool * - * [Since 1.9/1.10:] If the file, section, or option value is not recognized, + * [Since 1.9:] If the file, section, or option value is not recognized, * warn to @c stderr, using @a prefix as in svn_handle_warning2(). * * @since New in 1.7. @@ -213,6 +214,18 @@ svn_cmdline__getopt_init(apr_getopt_t **os, const char *argv[], apr_pool_t *pool); +/* */ +svn_boolean_t +svn_cmdline__stdin_is_a_terminal(void); + +/* */ +svn_boolean_t +svn_cmdline__stdout_is_a_terminal(void); + +/* */ +svn_boolean_t +svn_cmdline__stderr_is_a_terminal(void); + /* Determine whether interactive mode should be enabled, based on whether * the user passed the --non-interactive or --force-interactive options. * If neither option was passed, interactivity is enabled if standard @@ -239,6 +252,32 @@ svn_cmdline__parse_trust_options( const char *opt_arg, apr_pool_t *scratch_pool); +/* Setup signal handlers for signals such as SIGINT and return a + cancellation handler function. This also sets some other signals + to be ignored. */ +svn_cancel_func_t +svn_cmdline__setup_cancellation_handler(void); + +/* Set the handlers for signals such as SIGINT back to default. */ +void +svn_cmdline__disable_cancellation_handler(void); + +/* Exit this process with a status that indicates the cancellation + signal, or return without exiting if there is no signal. This + allows the shell to use WIFSIGNALED and WTERMSIG to detect the + signal. See http://www.cons.org/cracauer/sigint.html */ +void +svn_cmdline__cancellation_exit(void); + +/** Reads a string from stdin until a newline or EOF is found + * + * @since New in 1.10. + */ +svn_error_t * +svn_cmdline__stdin_readline(const char **result, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/subversion/include/private/svn_config_private.h b/subversion/include/private/svn_config_private.h new file mode 100644 index 000000000000..95cca27b20f9 --- /dev/null +++ b/subversion/include/private/svn_config_private.h @@ -0,0 +1,129 @@ +/** + * @copyright + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * @endcopyright + * + * @file svn_config_private.h + * @brief Private config file parsing API. + */ + +#ifndef SVN_CONFIG_PRIVATE_H +#define SVN_CONFIG_PRIVATE_H + +#include + +#include "svn_error.h" +#include "svn_io.h" +#include "svn_string.h" +#include "svn_config.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* + * Description of a constructor for in-memory config file + * representations. + */ +typedef struct svn_config__constructor_t svn_config__constructor_t; + +/* + * Constructor callback: called when the parsing of a new SECTION + * begins. If the implementation stores the value of SECTION, it + * must copy it into a permanent pool. + * + * May return SVN_ERR_CEASE_INVOCATION to stop further parsing. + */ +typedef svn_error_t *(*svn_config__open_section_fn)( + void *baton, svn_stringbuf_t *section); + +/* + * Constructor callback: called when the parsing of SECTION ends. If + * the implementation stores the value of SECTION, it must copy it + * into a permanent pool. + * + * May return SVN_ERR_CEASE_INVOCATION to stop further parsing. + */ +typedef svn_error_t *(*svn_config__close_section_fn)( + void *baton, svn_stringbuf_t *section); + +/* + * Constructor callback: called OPTION with VALUE in SECTION was + * parsed. If the implementation stores the values of SECTION, OPTION + * or VALUE, it must copy them into a permanent pool. + * + * May return SVN_ERR_CEASE_INVOCATION to stop further parsing. + */ +typedef svn_error_t *(*svn_config__add_value_fn)( + void *baton, svn_stringbuf_t *section, + svn_stringbuf_t *option, svn_stringbuf_t *value); + + +/* + * Create a new constuctor allocated from RESULT_POOL. + * Any of the callback functions may be NULL. + * The constructor implementation is responsible for implementing any + * case-insensitivity, value expansion, or other features on top of + * the basic parser. + */ +svn_config__constructor_t * +svn_config__constructor_create( + svn_config__open_section_fn open_section_callback, + svn_config__close_section_fn close_section_callback, + svn_config__add_value_fn add_value_callback, + apr_pool_t *result_pool); + +/* + * Parse the configuration from STREAM, using CONSTRUCTOR to build the + * in-memory representation of the parsed configuration. + * CONSTRUCTOR_BATON is passed unchanged to the constructor + * callbacks. The parser guarantees that sections and options will be + * passed to the callback in the same order as they're defined in + * STREAM. + * + * The lifetome of section names, option names and values passed to + * the constructor does not extend past the invocation of each + * callback; see calback docs, above. + * + * The parser will use SCRATCH_POOL for its own allocations. + */ +svn_error_t * +svn_config__parse_stream(svn_stream_t *stream, + svn_config__constructor_t *constructor, + void *constructor_baton, + apr_pool_t *scratch_pool); + +/* + * Write the configuration CFG to STREAM, using SCRATCH_POOL for + * temporary allocations. + * + * Note that option values will not be expanded and that the order + * of sections as well as the options within them is undefined. + */ +svn_error_t * +svn_config__write(svn_stream_t *stream, + const svn_config_t *cfg, + apr_pool_t *scratch_pool); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SVN_CONFIG_PRIVATE_H */ diff --git a/subversion/include/private/svn_delta_private.h b/subversion/include/private/svn_delta_private.h index 260327c43c69..fbf66e1be7b7 100644 --- a/subversion/include/private/svn_delta_private.h +++ b/subversion/include/private/svn_delta_private.h @@ -108,6 +108,25 @@ svn_txdelta__read_raw_window_len(apr_size_t *window_len, svn_stream_t *stream, apr_pool_t *pool); +/* Return a debug editor that wraps @a wrapped_editor. + * + * The debug editor simply prints an indication of what callbacks are being + * called to @c stdout, and is only intended for use in debugging subversion + * editors. + * + * @a prefix, if non-null, is printed between "DBG: " and each indication. + * + * Note: Our test suite generally ignores stdout lines starting with "DBG:". + */ +svn_error_t * +svn_delta__get_debug_editor(const svn_delta_editor_t **editor, + void **edit_baton, + const svn_delta_editor_t *wrapped_editor, + void *wrapped_baton, + const char *prefix, + apr_pool_t *pool); + + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/subversion/include/private/svn_dep_compat.h b/subversion/include/private/svn_dep_compat.h index 729cf7e4df11..6b381d2ce81c 100644 --- a/subversion/include/private/svn_dep_compat.h +++ b/subversion/include/private/svn_dep_compat.h @@ -74,6 +74,27 @@ extern "C" { #define SVN_LOCK_IS_BUSY(x) APR_STATUS_IS_EBUSY(x) #endif +/** + * Indicate whether we are running on a POSIX platform. This has + * implications on the way e.g. fsync() works. + * + * For details on this check, see + * http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system#POSIX + * + * @since New in 1.10. + */ +#ifndef SVN_ON_POSIX +#if !defined(_WIN32) \ + && ( defined(__unix__) \ + || defined(__unix) \ + || (defined(__APPLE__) && defined(__MACH__))) /* UNIX-style OS? */ +# include +# if defined(_POSIX_VERSION) +# define SVN_ON_POSIX +# endif +#endif +#endif + /** * APR keeps a few interesting defines hidden away in its private * headers apr_arch_file_io.h, so we redefined them here. @@ -93,6 +114,28 @@ extern "C" { #endif #endif +/** + * APR 1 has volatile qualifier bugs in some atomic prototypes that + * are fixed in APR 2: + * https://issues.apache.org/bugzilla/show_bug.cgi?id=50731 + * Subversion code should put the volatile qualifier in the correct + * place when declaring variables which means that casting at the call + * site is necessary when using APR 1. No casts should be used with + * APR 2 as this allows the compiler to check that the variable has + * the correct volatile qualifier. + */ +#if APR_VERSION_AT_LEAST(2,0,0) +#define svn_atomic_casptr(mem, with, cmp) \ + apr_atomic_casptr((mem), (with), (cmp)) +#define svn_atomic_xchgptr(mem, val) \ + apr_atomic_xchgptr((mem), (val)) +#else +#define svn_atomic_casptr(mem, with, cmp) \ + apr_atomic_casptr((void volatile **)(mem), (with), (cmp)) +#define svn_atomic_xchgptr(mem, val) \ + apr_atomic_xchgptr((void volatile **)(mem), (val)) +#endif + /** * Check at compile time if the Serf version is at least a certain * level. diff --git a/subversion/include/private/svn_diff_private.h b/subversion/include/private/svn_diff_private.h index 48b4d5266200..bf7f490d37e9 100644 --- a/subversion/include/private/svn_diff_private.h +++ b/subversion/include/private/svn_diff_private.h @@ -113,6 +113,40 @@ svn_diff__display_prop_diffs(svn_stream_t *outstream, void *cancel_baton, apr_pool_t *scratch_pool); +/** Create a hunk object that adds a single line without newline. Return the + * new object in @a *hunk. + * + * @a line is the added text, without a trailing newline. + * + * The hunk will be associated with @a patch. + */ +svn_error_t * +svn_diff_hunk__create_adds_single_line(svn_diff_hunk_t **hunk, + const char *line, + const svn_patch_t *patch, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/** Create a hunk object that deletes a single line without newline. Return + * the new object in @a *hunk. + * + * @a line is the deleted text, without a trailing newline. + * + * The hunk will be associated with @a patch. + */ +svn_error_t * +svn_diff_hunk__create_deletes_single_line(svn_diff_hunk_t **hunk, + const char *line, + const svn_patch_t *patch, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/** Fetches the penalty fuzz of the diff hunk. The patch file parser applies + * an additional penalty on some cases of bad patch files. These cases may + * include errors as headers that aren't consistent with bodies, etc. + */ +svn_linenum_t +svn_diff_hunk__get_fuzz_penalty(const svn_diff_hunk_t *hunk); #ifdef __cplusplus } diff --git a/subversion/include/private/svn_diff_tree.h b/subversion/include/private/svn_diff_tree.h index 4554da2b47c9..713644d08c4e 100644 --- a/subversion/include/private/svn_diff_tree.h +++ b/subversion/include/private/svn_diff_tree.h @@ -114,12 +114,24 @@ extern "C" { * ### How come many users don't set the 'repos_relpath' field? */ typedef struct svn_diff_source_t { - /* Always available */ + /* Always available + In case of copyfrom: the revision copied from + */ svn_revnum_t revision; - /* Depending on the driver available for copyfrom */ - /* ### What? */ + /* In case of copyfrom: the repository relative path copied from. + + NULL if the node wasn't copied or moved, or when the driver doesn't + have this information */ const char *repos_relpath; + + /* In case of copyfrom: the relative path of source location before the + move. This path is relative WITHIN THE DIFF. The repository path is + typically in repos_relpath + + NULL if the node wasn't moved or if the driver doesn't have this + information. */ + const char *moved_from_relpath; } svn_diff_source_t; /** diff --git a/subversion/include/private/svn_element.h b/subversion/include/private/svn_element.h new file mode 100644 index 000000000000..c467175c748e --- /dev/null +++ b/subversion/include/private/svn_element.h @@ -0,0 +1,399 @@ +/** + * @copyright + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * @endcopyright + * + * @file svn_element.h + * @brief Tree elements + * + * @since New in ???. + */ + +#ifndef SVN_BRANCH_ELEMENT_H +#define SVN_BRANCH_ELEMENT_H + +#include +#include + +#include "svn_types.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/* ====================================================================== */ + +/** Like apr_hash_get() but the hash key is an integer. */ +void * +svn_eid__hash_get(apr_hash_t *ht, + int key); + +/** Like apr_hash_set() but the hash key is an integer. */ +void +svn_eid__hash_set(apr_hash_t *ht, + int key, + const void *val); + +/** Like apr_hash_this_key() but the hash key is an integer. */ +int +svn_eid__hash_this_key(apr_hash_index_t *hi); + +struct svn_sort__item_t; + +/** A hash iterator for iterating over an array or a hash table in + * its natural order or in sorted order. + * + * For an array, the @a i and @a val members provide the index and value + * of the current item. + */ +typedef struct svn_eid__hash_iter_t +{ + /* private: an array of (svn_sort__item_t) hash items for sorted iteration */ + const apr_array_header_t *array; + + /* current element: iteration order index */ + int i; + /* current element: key */ + int eid; + /* current element: value */ + void *val; +} svn_eid__hash_iter_t; + +svn_eid__hash_iter_t * +svn_eid__hash_sorted_first(apr_pool_t *pool, + apr_hash_t *ht, + int (*comparison_func)(const struct svn_sort__item_t *, + const struct svn_sort__item_t *)); + +svn_eid__hash_iter_t * +svn_eid__hash_sorted_next(svn_eid__hash_iter_t *hi); + +/** A sort ordering callback function that returns an indication whether + * A sorts before or after or equal to B, by comparing their keys as EIDs. + */ +int +svn_eid__hash_sort_compare_items_by_eid(const struct svn_sort__item_t *a, + const struct svn_sort__item_t *b); + +#define SVN_EID__HASH_ITER_SORTED(i, ht, comparison_func, pool) \ + i = (void *)svn_eid__hash_sorted_first(pool, ht, comparison_func); \ + i; \ + i = (void *)svn_eid__hash_sorted_next((void *)i) + +#define SVN_EID__HASH_ITER_SORTED_BY_EID(i, ht, pool) \ + SVN_EID__HASH_ITER_SORTED(i, ht, svn_eid__hash_sort_compare_items_by_eid, pool) + + +/* ====================================================================== */ + +/** + */ +typedef struct svn_element__branch_ref_t +{ + svn_revnum_t rev; + const char *branch_id; + int eid; +} svn_element__branch_ref_t; + +/** Versioned payload of an element, excluding tree structure information. + * + * This specifies the properties and the text of a file or target of a + * symlink, directly, or by reference to an existing committed element, or + * by a delta against such a reference payload. + * + * ### An idea: If the sender and receiver agree, the payload for an element + * may be specified as "null" to designate that the payload is not + * available. For example, when a client performing a WC update has + * no read authorization for a given path, the server may send null + * payload and the client may record an 'absent' WC node. (This + * would not make sense in a commit.) + */ +typedef struct svn_element__payload_t svn_element__payload_t; + +/* + * ======================================================================== + * Element Payload Interface + * ======================================================================== + * + * @defgroup svn_element_payload Element payload interface + * @{ + */ + +/** Versioned payload of a node, excluding tree structure information. + * + * Payload is described by setting fields in one of the following ways. + * Other fields SHOULD be null (or equivalent). + * + * by reference: (kind=unknown, ref) + * dir: (kind=dir, props) + * file: (kind=file, props, text) + * symlink: (kind=symlink, props, target) + * + * ### Idea for the future: Specify payload as an (optional) reference + * plus (optional) overrides or deltas against the reference? + */ +struct svn_element__payload_t +{ + /* Is this a subbranch-root element, in other words a link to a nested + * branch? If so, all other fields are irrelevant. */ + svn_boolean_t is_subbranch_root; + + /* The node kind for this payload: dir, file, symlink, or unknown. */ + svn_node_kind_t kind; + + /* Reference an existing, committed payload. (Use with kind=unknown if + * there is no content in props/text/targe fields.) + * The 'null' value is (SVN_INVALID_REVNUM, NULL, *). */ + svn_element__branch_ref_t branch_ref; + + /* The pool in which the payload's content is allocated. Used when + * resolving (populating the props/text/target in) a payload that was + * originally defined by reference. */ + apr_pool_t *pool; + + /* Properties (for kind != unknown). + * Maps (const char *) name -> (svn_string_t) value. + * An empty hash means no properties. (SHOULD NOT be NULL.) + * ### Presently NULL means 'no change' in some contexts. */ + apr_hash_t *props; + + /* File text (for kind=file; otherwise SHOULD be NULL). */ + svn_stringbuf_t *text; + + /* Symlink target (for kind=symlink; otherwise SHOULD be NULL). */ + const char *target; + +}; + +/* Return true iff PAYLOAD satisfies all its invariants. + */ +svn_boolean_t +svn_element__payload_invariants(const svn_element__payload_t *payload); + +/** Duplicate a node-payload @a old into @a result_pool. + */ +svn_element__payload_t * +svn_element__payload_dup(const svn_element__payload_t *old, + apr_pool_t *result_pool); + +/* Return true iff the payload of LEFT is identical to that of RIGHT. + * References are not supported. Node kind 'unknown' is not supported. + */ +svn_boolean_t +svn_element__payload_equal(const svn_element__payload_t *left, + const svn_element__payload_t *right, + apr_pool_t *scratch_pool); + +/** Create a new node-payload object for a subbranch-root (link to a + * nested branch). + * + * Allocate the result in @a result_pool. + */ +svn_element__payload_t * +svn_element__payload_create_subbranch(apr_pool_t *result_pool); + +/** Create a new node-payload object by reference to an existing payload. + * + * Set the node kind to 'unknown'. + * + * Allocate the result in @a result_pool. + */ +svn_element__payload_t * +svn_element__payload_create_ref(svn_revnum_t rev, + const char *branch_id, + int eid, + apr_pool_t *result_pool); + +/** Create a new node-payload object for a directory node. + * + * Allocate the result in @a result_pool. + */ +svn_element__payload_t * +svn_element__payload_create_dir(apr_hash_t *props, + apr_pool_t *result_pool); + +/** Create a new node-payload object for a file node. + * + * Allocate the result in @a result_pool. + */ +svn_element__payload_t * +svn_element__payload_create_file(apr_hash_t *props, + svn_stringbuf_t *text, + apr_pool_t *result_pool); + +/** Create a new node-payload object for a symlink node. + * + * Allocate the result in @a result_pool. + */ +svn_element__payload_t * +svn_element__payload_create_symlink(apr_hash_t *props, + const char *target, + apr_pool_t *result_pool); + +/** @} */ + + +/* + * ======================================================================== + * Element-Revision Content + * ======================================================================== + * + * @defgroup svn_el_rev_content Element-Revision Content + * @{ + */ + +/* The content (parent, name and payload) of an element-revision. + * In other words, an el-rev node in a (mixed-rev) directory-tree. + */ +typedef struct svn_element__content_t +{ + /* eid of the parent element, or -1 if this is the root element */ + int parent_eid; + /* element name, or "" for root element; never null */ + const char *name; + /* payload (kind, props, text, ...) */ + svn_element__payload_t *payload; + +} svn_element__content_t; + +/* Return a new content object constructed with deep copies of PARENT_EID, + * NAME and PAYLOAD, allocated in RESULT_POOL. + */ +svn_element__content_t * +svn_element__content_create(int parent_eid, + const char *name, + const svn_element__payload_t *payload, + apr_pool_t *result_pool); + +/* Return a deep copy of OLD, allocated in RESULT_POOL. + */ +svn_element__content_t * +svn_element__content_dup(const svn_element__content_t *old, + apr_pool_t *result_pool); + +/* Return TRUE iff CONTENT_LEFT is the same as CONTENT_RIGHT. */ +svn_boolean_t +svn_element__content_equal(const svn_element__content_t *content_left, + const svn_element__content_t *content_right, + apr_pool_t *scratch_pool); + +/** @} */ + + +/* + * ======================================================================== + * Element Tree + * ======================================================================== + * + * The elements in an Element Tree do not necessarily form a single, + * complete tree at all times. + * + * @defgroup svn_element_tree Element Tree + * @{ + */ + +/* A (sub)tree of elements. + * + * An element tree is described by the content of element ROOT_EID in E_MAP, + * and its children (as determined by their parent links) and their names + * and their content recursively. For the element ROOT_EID itself, only + * its content is relevant; its parent and name are to be ignored. + * + * E_MAP may also contain entries that are not part of the subtree. Thus, + * to select a sub-subtree, it is only necessary to change ROOT_EID. + * + * The EIDs used in here may be considered either as global EIDs (known to + * the repo), or as local stand-alone EIDs (in their own local name-space), + * according to the context. + */ +typedef struct svn_element__tree_t +{ + /* EID -> svn_element__content_t mapping. */ + apr_hash_t *e_map; + + /* Subtree root EID. (ROOT_EID must be an existing key in E_MAP.) */ + int root_eid; + +} svn_element__tree_t; + +/* Create an element tree object. + * + * The result contains a *shallow* copy of E_MAP, or a new empty mapping + * if E_MAP is null. + */ +svn_element__tree_t * +svn_element__tree_create(apr_hash_t *e_map, + int root_eid, + apr_pool_t *result_pool); + +svn_element__content_t * +svn_element__tree_get(const svn_element__tree_t *tree, + int eid); + +svn_error_t * +svn_element__tree_set(svn_element__tree_t *tree, + int eid, + const svn_element__content_t *element); + +/* Purge entries from E_MAP that don't connect, via parent directory hierarchy, + * to ROOT_EID. In other words, remove elements that have been implicitly + * deleted. + * + * ROOT_EID must be present in E_MAP. + * + * ### Does not detect cycles: current implementation will not purge a cycle + * that is disconnected from ROOT_EID. This could be a problem. + */ +void +svn_element__tree_purge_orphans(apr_hash_t *e_map, + int root_eid, + apr_pool_t *scratch_pool); + +/* Return the subtree-relative path of element EID in TREE. + * + * If the element EID does not currently exist in TREE, return NULL. + * + * ### TODO: Clarify sequencing requirements. + */ +const char * +svn_element__tree_get_path_by_eid(const svn_element__tree_t *tree, + int eid, + apr_pool_t *result_pool); + +/* Return the subtree rooted at EID within ELEMENT_TREE. + * + * The result is limited by the lifetime of ELEMENT_TREE. It includes a + * shallow copy of the mapping in ELEMENT_TREE: the hash table is + * duplicated but the keys and values (element content data) are not. + */ +svn_element__tree_t * +svn_element__tree_get_subtree_at_eid(svn_element__tree_t *element_tree, + int eid, + apr_pool_t *result_pool); + +/** @} */ + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SVN_BRANCH_ELEMENT_H */ diff --git a/subversion/include/private/svn_fs_fs_private.h b/subversion/include/private/svn_fs_fs_private.h index 59aede1c7a62..d2573d447c9d 100644 --- a/subversion/include/private/svn_fs_fs_private.h +++ b/subversion/include/private/svn_fs_fs_private.h @@ -53,7 +53,8 @@ typedef struct svn_fs_fs__large_change_info_t /* size of the (deltified) representation */ apr_uint64_t size; - /* Revision of the representation. SVN_INVALID_REVNUM for unused entries. */ + /* Revision of the representation. SVN_INVALID_REVNUM for unused entries. + */ svn_revnum_t revision; /* node path. "" for unused instances */ @@ -151,6 +152,9 @@ typedef struct svn_fs_fs__representation_stats_t /* sum of ref_count * expanded_size, * i.e. total plaintext content if there was no rep sharing */ apr_uint64_t expanded_size; + + /* sum of all representation delta chain lengths */ + apr_uint64_t chain_len; } svn_fs_fs__representation_stats_t; /* Basic statistics we collect over a given set of noderevs. @@ -267,19 +271,20 @@ svn_fs_fs__get_stats(svn_fs_fs__stats_t **stats, apr_pool_t *result_pool, apr_pool_t *scratch_pool); -/* Node-revision IDs in FSFS consist of 3 of sub-IDs ("parts") that consist +/* A node-revision ID in FSFS consists of 3 sub-IDs ("parts") that consist * of a creation REVISION number and some revision- / transaction-local * counter value (NUMBER). Old-style ID parts use global counter values. * * The parts are: node_id, copy_id and txn_id for in-txn IDs as well as - * node_id, copy_id and rev_offset for in-revision IDs. This struct the + * node_id, copy_id and rev_item for in-revision IDs. This struct is the * data structure used for each of those parts. */ typedef struct svn_fs_fs__id_part_t { - /* SVN_INVALID_REVNUM for txns -> not a txn, COUNTER must be 0. - SVN_INVALID_REVNUM for others -> not assigned to a revision, yet. - 0 for others -> old-style ID or the root in rev 0. */ + /* SVN_INVALID_REVNUM for txn_id part -> not a txn, NUMBER must be 0. + SVN_INVALID_REVNUM for other parts -> not assigned to a revision, yet. + 0 for other parts -> old-style ID or the root in rev 0. + */ svn_revnum_t revision; /* sub-id value relative to REVISION. Its interpretation depends on diff --git a/subversion/include/private/svn_fs_private.h b/subversion/include/private/svn_fs_private.h index 5bd89c0280c0..4bd0a5052731 100644 --- a/subversion/include/private/svn_fs_private.h +++ b/subversion/include/private/svn_fs_private.h @@ -183,7 +183,7 @@ svn_fs__editor_commit(svn_revnum_t *revision, * * If there is no mergeinfo, set @a *mergeinfo to NULL. * - * See svn_fs_get_mergeinfo2() but for the meanings of @a inherit and + * See svn_fs_get_mergeinfo3() but for the meanings of @a inherit and * @a adjust_inheritable_mergeinfo and other details. */ svn_error_t * @@ -195,6 +195,22 @@ svn_fs__get_mergeinfo_for_path(svn_mergeinfo_t *mergeinfo, apr_pool_t *result_pool, apr_pool_t *scratch_pool); +/** Determine the previous location of @a path under @a root and return it + * as @a *node_path under @a *node_root. This may be called for arbitrary + * nodes but is intended for nodes that got deleted in @a root, i.e. when + * standard navigation fails. It also works if @a root is transaction root. + * + * Allocate @a *node_path and @a *node_root in @a result_pool while using + * @a scratch_pool for temporaries. + */ +svn_error_t * +svn_fs__get_deleted_node(svn_fs_root_t **node_root, + const char **node_path, + svn_fs_root_t *root, + const char *path, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + /** @} */ diff --git a/subversion/include/private/svn_fs_util.h b/subversion/include/private/svn_fs_util.h index c9f74a126858..fc548ed15ee0 100644 --- a/subversion/include/private/svn_fs_util.h +++ b/subversion/include/private/svn_fs_util.h @@ -206,6 +206,15 @@ svn_fs__path_change_create_internal(const svn_fs_id_t *node_rev_id, svn_fs_path_change_kind_t change_kind, apr_pool_t *pool); +/* Allocate an svn_fs_path_change3_t structure in RESULT_POOL, initialize + and return it. + + Set the change_kind to CHANGE_KIND. Set all other fields to their + _unknown, NULL or invalid value, respectively. */ +svn_fs_path_change3_t * +svn_fs__path_change_create_internal2(svn_fs_path_change_kind_t change_kind, + apr_pool_t *result_pool); + /* Append REL_PATH (which may contain slashes) to each path that exists in the mergeinfo INPUT, and return a new mergeinfo in *OUTPUT. Deep copies the values. Perform all allocations in POOL. */ diff --git a/subversion/include/private/svn_io_private.h b/subversion/include/private/svn_io_private.h index 814c27aea422..2c9028a9c31d 100644 --- a/subversion/include/private/svn_io_private.h +++ b/subversion/include/private/svn_io_private.h @@ -85,32 +85,6 @@ svn_io__file_lock_autocreate(const char *lock_file, apr_pool_t *pool); -/** Buffer test handler function for a generic stream. @see svn_stream_t - * and svn_stream__is_buffered(). - * - * @since New in 1.7. - */ -typedef svn_boolean_t (*svn_stream__is_buffered_fn_t)(void *baton); - -/** Set @a stream's buffer test function to @a is_buffered_fn - * - * @since New in 1.7. - */ -void -svn_stream__set_is_buffered(svn_stream_t *stream, - svn_stream__is_buffered_fn_t is_buffered_fn); - -/** Return whether this generic @a stream uses internal buffering. - * This may be used to work around subtle differences between buffered - * and non-buffered APR files. A lazy-open stream cannot report the - * true buffering state until after the lazy open: a stream that - * initially reports as non-buffered may report as buffered later. - * - * @since New in 1.7. - */ -svn_boolean_t -svn_stream__is_buffered(svn_stream_t *stream); - /** Return the underlying file, if any, associated with the stream, or * NULL if not available. Accessing the file bypasses the stream. */ @@ -153,6 +127,13 @@ svn_stream__install_get_info(apr_finfo_t *finfo, apr_int32_t wanted, apr_pool_t *scratch_pool); +/* Internal version of svn_stream_from_aprfile2() supporting the + additional TRUNCATE_ON_SEEK argument. */ +svn_stream_t * +svn_stream__from_aprfile(apr_file_t *file, + svn_boolean_t disown, + svn_boolean_t truncate_on_seek, + apr_pool_t *pool); #if defined(WIN32) diff --git a/subversion/include/private/svn_log.h b/subversion/include/private/svn_log.h index 1ad8d559b9df..c2da89d173c1 100644 --- a/subversion/include/private/svn_log.h +++ b/subversion/include/private/svn_log.h @@ -93,7 +93,7 @@ svn_log__get_file(const char *path, svn_revnum_t rev, const char * svn_log__get_dir(const char *path, svn_revnum_t rev, svn_boolean_t want_contents, svn_boolean_t want_props, - apr_uint64_t dirent_fields, + apr_uint32_t dirent_fields, apr_pool_t *pool); /** @@ -253,6 +253,17 @@ const char * svn_log__get_inherited_props(const char *path, svn_revnum_t rev, apr_pool_t *pool); + +/** + * Return a log string for a list action. + * + * @since New in 1.10. + */ +const char * +svn_log__list(const char *path, svn_revnum_t revision, + apr_array_header_t *patterns, svn_depth_t depth, + apr_uint32_t dirent_fields, apr_pool_t *pool); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/subversion/include/private/svn_mergeinfo_private.h b/subversion/include/private/svn_mergeinfo_private.h index 716d0c9f90e2..a34cb39ce3da 100644 --- a/subversion/include/private/svn_mergeinfo_private.h +++ b/subversion/include/private/svn_mergeinfo_private.h @@ -52,18 +52,21 @@ svn_rangelist__set_inheritance(svn_rangelist_t *rangelist, * Unlike svn_mergeinfo_parse(), this does not sort the ranges into order * or combine adjacent and overlapping ranges. * - * The compaction can be done with svn_rangelist__combine_adjacent_ranges(). + * The compaction can be done with svn_rangelist__canonicalize(). */ svn_error_t * svn_rangelist__parse(svn_rangelist_t **rangelist, const char *str, apr_pool_t *result_pool); -/* In-place combines adjacent ranges in a rangelist. - SCRATCH_POOL is just used for providing error messages. */ -svn_error_t * -svn_rangelist__combine_adjacent_ranges(svn_rangelist_t *rangelist, - apr_pool_t *scratch_pool); +/* Return TRUE, if all ranges in RANGELIST are in ascending order and do +* not overlap and are not adjacent. +* +* If this returns FALSE, you probaly want to call +* svn_rangelist__canonicalize(). +*/ +svn_boolean_t +svn_rangelist__is_canonical(const svn_rangelist_t *rangelist); /** Canonicalize the @a rangelist: sort the ranges, and combine adjacent or * overlapping ranges into single ranges where possible. diff --git a/subversion/include/private/svn_mutex.h b/subversion/include/private/svn_mutex.h index c04820bacbbb..0b779474c350 100644 --- a/subversion/include/private/svn_mutex.h +++ b/subversion/include/private/svn_mutex.h @@ -27,8 +27,6 @@ #ifndef SVN_MUTEX_H #define SVN_MUTEX_H -#include - #include "svn_error.h" #ifdef __cplusplus @@ -106,6 +104,17 @@ do { \ SVN_ERR(svn_mutex__unlock(svn_mutex__m, (expr))); \ } while (0) +#if APR_HAS_THREADS + +/** Return the APR mutex encapsulated in @a mutex. + * + * @note This function should only be called by APR wrapper code. + */ +apr_thread_mutex_t * +svn_mutex__get(svn_mutex__t *mutex); + +#endif + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/subversion/include/private/svn_object_pool.h b/subversion/include/private/svn_object_pool.h index 7a9383e5f625..767a48bc6a12 100644 --- a/subversion/include/private/svn_object_pool.h +++ b/subversion/include/private/svn_object_pool.h @@ -65,80 +65,46 @@ /* The opaque object container type. */ typedef struct svn_object_pool__t svn_object_pool__t; -/* Extract the actual object from the WRAPPER using optional information - * from BATON (provided through #svn_object_pool__lookup) and return it. - * The result will be used with POOL and must remain valid throughout - * POOL's lifetime. - * - * It is legal to return a copy, allocated in POOL, of the wrapped object. - */ -typedef void * (* svn_object_pool__getter_t)(void *wrapper, - void *baton, - apr_pool_t *pool); - -/* Copy the information from the SOURCE object wrapper into the already - * existing *TARGET object wrapper using POOL for allocations and BATON - * for optional context (provided through #svn_object_pool__insert). - */ -typedef svn_error_t * (* svn_object_pool__setter_t)(void **target, - void *source, - void *baton, - apr_pool_t *pool); - /* Create a new object pool in POOL and return it in *OBJECT_POOL. - * Objects will be extracted using GETTER and updated using SETTER. Either - * one (or both) may be NULL and the default implementation assumes that - * wrapper == object and updating is a no-op. + * Objects are reference-counted and stored as opaque pointers. Each + * must be allocated in a separate pool ceated by + * svn_object_pool__new_item_pool. Unused objects get destroyed at + * the object pool's discretion. * * If THREAD_SAFE is not set, neither the object pool nor the object * references returned from it may be accessed from multiple threads. * * It is not legal to call any API on the object pool after POOL got - * cleared or destroyed. However, existing object references handed out - * from the object pool remain valid and will keep the internal pool data - * structures alive for as long as such object references exist. + * cleared or destroyed nor to use any objects from this object pool. */ svn_error_t * svn_object_pool__create(svn_object_pool__t **object_pool, - svn_object_pool__getter_t getter, - svn_object_pool__setter_t setter, svn_boolean_t thread_safe, apr_pool_t *pool); -/* Return the root pool containing the OBJECT_POOL and all sub-structures. +/* Return a pool to allocate the new object. */ apr_pool_t * -svn_object_pool__new_wrapper_pool(svn_object_pool__t *object_pool); - -/* Return the mutex used to serialize all OBJECT_POOL access. - */ -svn_mutex__t * -svn_object_pool__mutex(svn_object_pool__t *object_pool); - -/* Return the number of object instances (used or unused) in OBJECT_POOL. - */ -unsigned -svn_object_pool__count(svn_object_pool__t *object_pool); +svn_object_pool__new_item_pool(svn_object_pool__t *object_pool); /* In OBJECT_POOL, look for an available object by KEY and return a * reference to it in *OBJECT. If none can be found, *OBJECT will be NULL. - * BATON will be passed to OBJECT_POOL's getter function. The reference - * will be returned when *RESULT_POOL gets cleaned up or destroyed. + * + * The reference will be returned when *RESULT_POOL and may be destroyed + * or recycled by OBJECT_POOL. */ svn_error_t * svn_object_pool__lookup(void **object, svn_object_pool__t *object_pool, svn_membuf_t *key, - void *baton, apr_pool_t *result_pool); -/* Store the wrapped object WRAPPER under KEY in OBJECT_POOL and return - * a reference to the object in *OBJECT (just like lookup). +/* Store the object ITEM under KEY in OBJECT_POOL and return a reference + * to the object in *OBJECT (just like lookup). * - * The object must have been created in WRAPPER_POOL and the latter must - * be a sub-pool of OBJECT_POOL's root POOL (see #svn_object_pool__pool). + * The object must have been created in ITEM_POOL and the latter must + * have been created by svn_object_pool__new_item_pool. * - * BATON will be passed to OBJECT_POOL's setter and getter functions. * The reference will be returned when *RESULT_POOL gets cleaned up or * destroyed. */ @@ -146,9 +112,8 @@ svn_error_t * svn_object_pool__insert(void **object, svn_object_pool__t *object_pool, const svn_membuf_t *key, - void *wrapper, - void *baton, - apr_pool_t *wrapper_pool, + void *item, + apr_pool_t *item_pool, apr_pool_t *result_pool); #endif /* SVN_OBJECT_POOL_H */ diff --git a/subversion/include/private/svn_packed_data.h b/subversion/include/private/svn_packed_data.h index 6faf0dd0e116..841be3a0cebb 100644 --- a/subversion/include/private/svn_packed_data.h +++ b/subversion/include/private/svn_packed_data.h @@ -218,6 +218,11 @@ svn_packed__int_count(svn_packed__int_stream_t *stream); apr_size_t svn_packed__byte_count(svn_packed__byte_stream_t *stream); +/* Return the number of entries left to read from STREAM. + */ +apr_size_t +svn_packed__byte_block_count(svn_packed__byte_stream_t *stream); + /* Return the next number from STREAM as unsigned integer. Returns 0 when * reading beyond the end of the stream. */ diff --git a/subversion/include/private/svn_ra_svn_private.h b/subversion/include/private/svn_ra_svn_private.h index bc2fa4533f31..42fd31ee060c 100644 --- a/subversion/include/private/svn_ra_svn_private.h +++ b/subversion/include/private/svn_ra_svn_private.h @@ -34,6 +34,104 @@ extern "C" { #endif /* __cplusplus */ +/** Memory representation of an on-the-wire data item. */ +typedef struct svn_ra_svn__item_t svn_ra_svn__item_t; + +/* A list of svn_ra_svn__item_t objects. */ +typedef struct svn_ra_svn__list_t +{ + /* List contents (array). May be NULL if NELTS is 0. */ + struct svn_ra_svn__item_t *items; + + /* Number of elements in ITEMS. */ + int nelts; +} svn_ra_svn__list_t; + +/* List element access macro. */ +#define SVN_RA_SVN__LIST_ITEM(list, idx) (list)->items[idx] + +/** Memory representation of an on-the-wire data item. */ +struct svn_ra_svn__item_t +{ + /** Variant indicator. */ + svn_ra_svn_item_kind_t kind; + + /** Variant data. */ + union { + apr_uint64_t number; + svn_string_t string; + svn_string_t word; + svn_ra_svn__list_t list; + } u; +}; + +/** Command handler, used by svn_ra_svn__handle_commands(). */ +typedef svn_error_t *(*svn_ra_svn__command_handler)(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton); + +/** Command table, used by svn_ra_svn_handle_commands(). + */ +typedef struct svn_ra_svn__cmd_entry_t +{ + /** Name of the command */ + const char *cmdname; + + /** Handler for the command */ + svn_ra_svn__command_handler handler; + + /** Only set when used through a deprecated API. + * HANDLER is NULL in that case. */ + svn_ra_svn_command_handler deprecated_handler; + + /** Termination flag. If set, command-handling will cease after + * command is processed. */ + svn_boolean_t terminate; +} svn_ra_svn__cmd_entry_t; + + +/* Return a deep copy of the SOURCE array containing private API + * svn_ra_svn__item_t SOURCE to public API *TARGET, allocating + * sub-structures in RESULT_POOL. */ +apr_array_header_t * +svn_ra_svn__to_public_array(const svn_ra_svn__list_t *source, + apr_pool_t *result_pool); + +/* Deep copy contents from private API *SOURCE to public API *TARGET, + * allocating sub-structures in RESULT_POOL. */ +void +svn_ra_svn__to_public_item(svn_ra_svn_item_t *target, + const svn_ra_svn__item_t *source, + apr_pool_t *result_pool); + +svn_ra_svn__list_t * +svn_ra_svn__to_private_array(const apr_array_header_t *source, + apr_pool_t *result_pool); + +/* Deep copy contents from public API *SOURCE to private API *TARGET, + * allocating sub-structures in RESULT_POOL. */ +void +svn_ra_svn__to_private_item(svn_ra_svn__item_t *target, + const svn_ra_svn_item_t *source, + apr_pool_t *result_pool); + +/** Add the capabilities in @a list to @a conn's capabilities. + * @a list contains svn_ra_svn__item_t entries (which should be of type + * SVN_RA_SVN_WORD; a malformed data error will result if any are not). + * + * This is idempotent: if a given capability was already set for + * @a conn, it remains set. + */ +svn_error_t * +svn_ra_svn__set_capabilities(svn_ra_svn_conn_t *conn, + const svn_ra_svn__list_t *list); + +/** Returns the preferred svndiff version to be used with connection @a conn. + */ +int +svn_ra_svn__svndiff_version(svn_ra_svn_conn_t *conn); + /** * Set the shim callbacks to be used by @a conn to @a shim_callbacks. @@ -161,10 +259,10 @@ svn_ra_svn__flush(svn_ra_svn_conn_t *conn, * to transmit an array or other unusual data. For example, to write * a tuple containing a revision, an array of words, and a boolean: * @code - SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "r(!", rev)); + SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "r(!", rev)); for (i = 0; i < n; i++) - SVN_ERR(svn_ra_svn_write_word(conn, pool, words[i])); - SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!)b", flag)); @endcode + SVN_ERR(svn_ra_svn__write_word(conn, pool, words[i])); + SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "!)b", flag)); @endcode */ svn_error_t * svn_ra_svn__write_tuple(svn_ra_svn_conn_t *conn, @@ -175,7 +273,7 @@ svn_ra_svn__write_tuple(svn_ra_svn_conn_t *conn, svn_error_t * svn_ra_svn__read_item(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - svn_ra_svn_item_t **item); + svn_ra_svn__item_t **item); /** Scan data on @a conn until we find something which looks like the * beginning of an svn server greeting (an open paren followed by a @@ -221,13 +319,12 @@ svn_ra_svn__skip_leading_garbage(svn_ra_svn_conn_t *conn, * * If an optional part of a tuple contains no data, 'r' values will be * set to @c SVN_INVALID_REVNUM; 'n' and 'B' values will be set to - * #SVN_RA_SVN_UNSPECIFIED_NUMBER; 's', 'c', 'w', and 'l' values - * will be set to @c NULL; and '3' values will be set to #svn_tristate_unknown - * 'b' may not appear inside an optional tuple specification; use '3' instead. + * #SVN_RA_SVN_UNSPECIFIED_NUMBER; 's', 'c', 'w', and 'l' values will + * be set to @c NULL; '3' values will be set to #svn_tristate_unknown; + * and 'b' values will be set to @c FALSE. */ svn_error_t * -svn_ra_svn__parse_tuple(const apr_array_header_t *list, - apr_pool_t *pool, +svn_ra_svn__parse_tuple(const svn_ra_svn__list_t *list, const char *fmt, ...); /** Read a tuple from the network and parse it as a tuple, using the @@ -238,13 +335,13 @@ svn_ra_svn__read_tuple(svn_ra_svn_conn_t *conn, apr_pool_t *pool, const char *fmt, ...); -/** Parse an array of @c svn_ra_svn_item_t structures as a list of +/** Parse an array of @c svn_ra_svn__item_t structures as a list of * properties, storing the properties in a hash table. * * @since New in 1.5. */ svn_error_t * -svn_ra_svn__parse_proplist(const apr_array_header_t *list, +svn_ra_svn__parse_proplist(const svn_ra_svn__list_t *list, apr_pool_t *pool, apr_hash_t **props); @@ -300,7 +397,7 @@ svn_ra_svn__handle_command(svn_boolean_t *terminate, svn_error_t * svn_ra_svn__handle_commands2(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - const svn_ra_svn_cmd_entry_t *commands, + const svn_ra_svn__cmd_entry_t *commands, void *baton, svn_boolean_t error_on_disconnect); @@ -347,7 +444,7 @@ svn_error_t * svn_ra_svn__write_cmd_open_root(svn_ra_svn_conn_t *conn, apr_pool_t *pool, svn_revnum_t rev, - const char *token); + const svn_string_t *token); /** Send a "delete-entry" command over connection @a conn. Delete the * @a path at optional revision @a rev below @a parent_token. @@ -358,7 +455,7 @@ svn_ra_svn__write_cmd_delete_entry(svn_ra_svn_conn_t *conn, apr_pool_t *pool, const char *path, svn_revnum_t rev, - const char *parent_token); + const svn_string_t *parent_token); /** Send a "add-dir" command over connection @a conn. Add a new directory * node named @a path under the directory identified by @a parent_token. @@ -370,8 +467,8 @@ svn_error_t * svn_ra_svn__write_cmd_add_dir(svn_ra_svn_conn_t *conn, apr_pool_t *pool, const char *path, - const char *parent_token, - const char *token, + const svn_string_t *parent_token, + const svn_string_t *token, const char *copy_path, svn_revnum_t copy_rev); @@ -384,8 +481,8 @@ svn_error_t * svn_ra_svn__write_cmd_open_dir(svn_ra_svn_conn_t *conn, apr_pool_t *pool, const char *path, - const char *parent_token, - const char *token, + const svn_string_t *parent_token, + const svn_string_t *token, svn_revnum_t rev); /** Send a "change-dir-prop" command over connection @a conn. Set the @@ -395,7 +492,7 @@ svn_ra_svn__write_cmd_open_dir(svn_ra_svn_conn_t *conn, svn_error_t * svn_ra_svn__write_cmd_change_dir_prop(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - const char *token, + const svn_string_t *token, const char *name, const svn_string_t *value); @@ -406,7 +503,7 @@ svn_ra_svn__write_cmd_change_dir_prop(svn_ra_svn_conn_t *conn, svn_error_t * svn_ra_svn__write_cmd_close_dir(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - const char *token); + const svn_string_t *token); /** Send a "absent-dir" command over connection @a conn. Directory node * named @a path under the directory identified by @a parent_token is @@ -416,7 +513,7 @@ svn_error_t * svn_ra_svn__write_cmd_absent_dir(svn_ra_svn_conn_t *conn, apr_pool_t *pool, const char *path, - const char *parent_token); + const svn_string_t *parent_token); /** Send a "add-file" command over connection @a conn. Add a new file * node named @a path under the directory identified by @a parent_token. @@ -428,8 +525,8 @@ svn_error_t * svn_ra_svn__write_cmd_add_file(svn_ra_svn_conn_t *conn, apr_pool_t *pool, const char *path, - const char *parent_token, - const char *token, + const svn_string_t *parent_token, + const svn_string_t *token, const char *copy_path, svn_revnum_t copy_rev); @@ -442,8 +539,8 @@ svn_error_t * svn_ra_svn__write_cmd_open_file(svn_ra_svn_conn_t *conn, apr_pool_t *pool, const char *path, - const char *parent_token, - const char *token, + const svn_string_t *parent_token, + const svn_string_t *token, svn_revnum_t rev); /** Send a "change-file-prop" command over connection @a conn. Set the @@ -453,7 +550,7 @@ svn_ra_svn__write_cmd_open_file(svn_ra_svn_conn_t *conn, svn_error_t * svn_ra_svn__write_cmd_change_file_prop(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - const char *token, + const svn_string_t *token, const char *name, const svn_string_t *value); @@ -465,7 +562,7 @@ svn_ra_svn__write_cmd_change_file_prop(svn_ra_svn_conn_t *conn, svn_error_t * svn_ra_svn__write_cmd_close_file(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - const char *token, + const svn_string_t *token, const char *text_checksum); /** Send a "absent-file" command over connection @a conn. File node @@ -476,7 +573,7 @@ svn_error_t * svn_ra_svn__write_cmd_absent_file(svn_ra_svn_conn_t *conn, apr_pool_t *pool, const char *path, - const char *parent_token); + const svn_string_t *parent_token); /** Send a "apply-textdelta" command over connection @a conn. Starts a * series of text deltas to be applied to the file identified by @a token. @@ -486,7 +583,7 @@ svn_ra_svn__write_cmd_absent_file(svn_ra_svn_conn_t *conn, svn_error_t * svn_ra_svn__write_cmd_apply_textdelta(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - const char *token, + const svn_string_t *token, const char *base_checksum); /** Send a "textdelta-chunk" command over connection @a conn. Apply @@ -496,7 +593,7 @@ svn_ra_svn__write_cmd_apply_textdelta(svn_ra_svn_conn_t *conn, svn_error_t * svn_ra_svn__write_cmd_textdelta_chunk(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - const char *token, + const svn_string_t *token, const svn_string_t *chunk); /** Send a "textdelta-end" command over connection @a conn. Ends the @@ -506,7 +603,7 @@ svn_ra_svn__write_cmd_textdelta_chunk(svn_ra_svn_conn_t *conn, svn_error_t * svn_ra_svn__write_cmd_textdelta_end(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - const char *token); + const svn_string_t *token); /** Send a "close-edit" command over connection @a conn. Ends the editor * drive (successfully). Use @a pool for allocations. @@ -790,7 +887,7 @@ svn_error_t * svn_ra_svn__write_cmd_unlock(svn_ra_svn_conn_t *conn, apr_pool_t *pool, const char *path, - const char *token, + const svn_string_t *token, svn_boolean_t break_lock); /** Send a "get-lock" command over connection @a conn. @@ -886,7 +983,7 @@ svn_ra_svn__write_cmd_finish_replay(svn_ra_svn_conn_t *conn, svn_error_t * svn_ra_svn__write_data_log_changed_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - const char *path, + const svn_string_t *path, char action, const char *copyfrom_path, svn_revnum_t copyfrom_rev, @@ -916,6 +1013,19 @@ svn_ra_svn__write_data_log_entry(svn_ra_svn_conn_t *conn, svn_boolean_t invalid_revnum, unsigned revprop_count); +/** Send a directory entry @a dirent for @a path over connection @a conn. + * Use @a pool for allocations. + * + * Depending on the flags in @a dirent_fields, only selected elements will + * be transmitted. + */ +svn_error_t * +svn_ra_svn__write_dirent(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + const char *path, + svn_dirent_t *dirent, + apr_uint32_t dirent_fields); + /** * @} */ @@ -931,7 +1041,7 @@ svn_ra_svn__write_data_log_entry(svn_ra_svn_conn_t *conn, * @see svn_log_changed_path2_t for a description of the output parameters. */ svn_error_t * -svn_ra_svn__read_data_log_changed_entry(const apr_array_header_t *items, +svn_ra_svn__read_data_log_changed_entry(const svn_ra_svn__list_t *items, svn_string_t **cpath, const char **action, const char **copy_path, diff --git a/subversion/include/private/svn_repos_private.h b/subversion/include/private/svn_repos_private.h index c5a232f29b55..c65b73fc1e69 100644 --- a/subversion/include/private/svn_repos_private.h +++ b/subversion/include/private/svn_repos_private.h @@ -34,6 +34,7 @@ #include "svn_editor.h" #include "svn_config.h" +#include "private/svn_object_pool.h" #include "private/svn_string_private.h" #ifdef __cplusplus @@ -74,6 +75,30 @@ svn_repos__validate_prop(const char *name, const svn_string_t *value, apr_pool_t *pool); +/* Attempt to normalize a Subversion property if it "needs translation" + * (according to svn_prop_needs_translation(), currently all svn:* props). + * + * At this time, the only performed normalization is translation of + * the line endings of the property value so that it would only contain + * LF (\n) characters. "\r" characters found mid-line are replaced with "\n". + * "\r\n" sequences are replaced with "\n". + * + * NAME is used to check that VALUE should be normalized, and if this + * is the case, VALUE is then normalized, allocated from RESULT_POOL. + * If no normalization is required, VALUE will be copied to RESULT_POOL + * unchanged. If NORMALIZED_P is not NULL, and the normalization + * happened, set *NORMALIZED_P to non-zero. If the property is returned + * unchanged and NORMALIZED_P is not NULL, then *NORMALIZED_P will be + * set to zero. SCRATCH_POOL will be used for temporary allocations. + */ +svn_error_t * +svn_repos__normalize_prop(const svn_string_t **result_p, + svn_boolean_t *normalized_p, + const char *name, + const svn_string_t *value, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + /** * Given the error @a err from svn_repos_fs_commit_txn(), return an * string containing either or both of the svn_fs_commit_txn() error @@ -127,26 +152,27 @@ svn_repos__replay_ev2(svn_fs_root_t *root, void *authz_read_baton, apr_pool_t *scratch_pool); -/* Given a PATH which might be a relative repo URL (^/), an absolute - * local repo URL (file://), an absolute path outside of the repo - * or a location in the Windows registry. +/** + * Non-deprecated alias for svn_repos_get_logs4. * - * Retrieve the configuration data that PATH points at and parse it into - * CFG_P allocated in POOL. - * - * If PATH cannot be parsed as a config file then an error is returned. The - * contents of CFG_P is then undefined. If MUST_EXIST is TRUE, a missing - * authz file is also an error. The CASE_SENSITIVE controls the lookup - * behavior for section and option names alike. - * - * REPOS_ROOT points at the root of the repos you are - * going to apply the authz against, can be NULL if you are sure that you - * don't have a repos relative URL in PATH. */ + * Since the mapping of log5 to ra_get_log is would basically duplicate the + * log5->log4 adapter, we provide this log4 wrapper that does not create a + * deprecation warning. + */ svn_error_t * -svn_repos__retrieve_config(svn_config_t **cfg_p, - const char *path, - svn_boolean_t must_exist, - svn_boolean_t case_sensitive, +svn_repos__get_logs_compat(svn_repos_t *repos, + const apr_array_header_t *paths, + svn_revnum_t start, + svn_revnum_t end, + int limit, + svn_boolean_t discover_changed_paths, + svn_boolean_t strict_node_history, + svn_boolean_t include_merged_revisions, + const apr_array_header_t *revprops, + svn_repos_authz_func_t authz_read_func, + void *authz_read_baton, + svn_log_entry_receiver_t receiver, + void *receiver_baton, apr_pool_t *pool); /** @@ -160,7 +186,7 @@ svn_repos__retrieve_config(svn_config_t **cfg_p, * from multiple threads. Configuration objects no longer referenced by * any user may linger for a while before being cleaned up. */ -typedef struct svn_repos__config_pool_t svn_repos__config_pool_t; +typedef svn_object_pool__t svn_repos__config_pool_t; /* Create a new configuration pool object with a lifetime determined by * POOL and return it in *CONFIG_POOL. @@ -177,11 +203,10 @@ svn_repos__config_pool_create(svn_repos__config_pool_t **config_pool, * configuration specified by PATH. If the latter is a URL, we read the * data from a local repository. CONFIG_POOL will store the configuration * and make further callers use the same instance if the content matches. - * If KEY is not NULL, *KEY will be set to a unique ID - if available. + * Section and option names will be case-insensitive. * * If MUST_EXIST is TRUE, a missing config file is also an error, *CFG - * is otherwise simply NULL. The CASE_SENSITIVE controls the lookup - * behavior for section and option names alike. + * is otherwise simply NULL. * * PREFERRED_REPOS is only used if it is not NULL and PATH is a URL. * If it matches the URL, access the repository through this object @@ -194,72 +219,14 @@ svn_repos__config_pool_create(svn_repos__config_pool_t **config_pool, */ svn_error_t * svn_repos__config_pool_get(svn_config_t **cfg, - svn_membuf_t **key, svn_repos__config_pool_t *config_pool, const char *path, svn_boolean_t must_exist, - svn_boolean_t case_sensitive, svn_repos_t *preferred_repos, apr_pool_t *pool); /** @} */ -/** - * @defgroup svn_authz_pool Authz object pool API - * @{ - */ - -/* Opaque thread-safe factory and container for authorization objects. - * - * Instances handed out are read-only and may be given to multiple callers - * from multiple threads. Authorization objects no longer referenced by - * any user may linger for a while before being cleaned up. - */ -typedef struct svn_repos__authz_pool_t svn_repos__authz_pool_t; - -/* Create a new authorization pool object with a lifetime determined by - * POOL and return it in *AUTHZ_POOL. CONFIG_POOL will be the common - * source for the configuration data underlying the authz objects and must - * remain valid at least until POOL cleanup. - * - * The THREAD_SAFE flag indicates whether the pool actually needs to be - * thread-safe and POOL must be also be thread-safe if this flag is set. - */ -svn_error_t * -svn_repos__authz_pool_create(svn_repos__authz_pool_t **authz_pool, - svn_repos__config_pool_t *config_pool, - svn_boolean_t thread_safe, - apr_pool_t *pool); - -/* Set *AUTHZ_P to a read-only reference to the current contents of the - * authorization specified by PATH and GROUPS_PATH. If these are URLs, - * we read the data from a local repository (see #svn_repos_authz_read2). - * AUTHZ_POOL will store the authz data and make further callers use the - * same instance if the content matches. - * - * If MUST_EXIST is TRUE, a missing config file is also an error, *AUTHZ_P - * is otherwise simply NULL. - * - * PREFERRED_REPOS is only used if it is not NULL and PATH is a URL. - * If it matches the URL, access the repository through this object - * instead of creating a new repo instance. Note that this might not - * return the latest content. - * - * POOL determines the minimum lifetime of *AUTHZ_P (may remain cached - * after release) but must not exceed the lifetime of the pool provided to - * svn_repos__authz_pool_create. - */ -svn_error_t * -svn_repos__authz_pool_get(svn_authz_t **authz_p, - svn_repos__authz_pool_t *authz_pool, - const char *path, - const char *groups_path, - svn_boolean_t must_exist, - svn_repos_t *preferred_repos, - apr_pool_t *pool); - -/** @} */ - /* Adjust mergeinfo paths and revisions in ways that are useful when loading * a dump stream. * diff --git a/subversion/include/private/svn_sorts_private.h b/subversion/include/private/svn_sorts_private.h index c358513e9233..2d5f1887f1b7 100644 --- a/subversion/include/private/svn_sorts_private.h +++ b/subversion/include/private/svn_sorts_private.h @@ -53,12 +53,12 @@ struct svn_sort__item_t { /** Sort @a ht according to its keys, return an @c apr_array_header_t * containing @c svn_sort__item_t structures holding those keys and values * (i.e. for each @c svn_sort__item_t @a item in the returned array, - * @a item->key and @a item->size are the hash key, and @a item->value points to + * @a item.key and @a item.size are the hash key, and @a item.value points to * the hash value). * * Storage is shared with the original hash, not copied. * - * @a comparison_func should take two @c svn_sort__item_t's and return an + * @a comparison_func should take pointers to two items and return an * integer greater than, equal to, or less than 0, according as the first item * is greater than, equal to, or less than the second. * diff --git a/subversion/include/private/svn_sqlite.h b/subversion/include/private/svn_sqlite.h index 4c6cb97cd506..cd01348ad595 100644 --- a/subversion/include/private/svn_sqlite.h +++ b/subversion/include/private/svn_sqlite.h @@ -555,8 +555,14 @@ svn_sqlite__hotcopy(const char *src_path, const char *dst_path, apr_pool_t *scratch_pool); -/* Backported version of SVN_ERR_SQLITE_ROLLBACK_FAILED. */ -#define SVN_SQLITE__ERR_ROLLBACK_FAILED (SVN_ERR_MISC_CATEGORY_START + 44) +/* Evaluate the expression EXPR. If any error is returned, close + * the connection in DB. */ +#define SVN_SQLITE__ERR_CLOSE(expr, db) do \ +{ \ + svn_error_t *svn__err = (expr); \ + if (svn__err) \ + return svn_error_compose_create(svn__err, svn_sqlite__close(db)); \ +} while (0) #ifdef __cplusplus } diff --git a/subversion/include/private/svn_string_private.h b/subversion/include/private/svn_string_private.h index 2f162733db81..25e42049db7b 100644 --- a/subversion/include/private/svn_string_private.h +++ b/subversion/include/private/svn_string_private.h @@ -131,6 +131,14 @@ svn_membuf__nzero(svn_membuf_t *membuf, apr_size_t size); svn_string_t * svn_stringbuf__morph_into_string(svn_stringbuf_t *strbuf); +/** Utility macro to define static svn_string_t objects. @a value must + * be a static string; the "" in the macro declaration tries to ensure this. + * + * Usage: + * static const svn_string_t my_string = SVN__STATIC_STRING("my text"); + */ +#define SVN__STATIC_STRING(value) { value "", sizeof(value "") - 1 } + /** Like strtoul but with a fixed base of 10 and without overflow checks. * This allows the compiler to generate massively faster (4x on 64bit LINUX) * code. Overflow checks may be added on the caller side where you might diff --git a/subversion/include/private/svn_subr_private.h b/subversion/include/private/svn_subr_private.h index 095d71c5df2c..d18c564748d0 100644 --- a/subversion/include/private/svn_subr_private.h +++ b/subversion/include/private/svn_subr_private.h @@ -112,12 +112,12 @@ svn_spillbuf__get_size(const svn_spillbuf_t *buf); svn_filesize_t svn_spillbuf__get_memory_size(const svn_spillbuf_t *buf); -/* Retrieve the name of the spill file. The returned value can be NULL - if the file has not been created yet. */ +/* Retrieve the name of the spill file. The returned value will be + NULL if the file has not been created yet. */ const char * svn_spillbuf__get_filename(const svn_spillbuf_t *buf); -/* Retrieve the handle of the spill file. The returned value can be +/* Retrieve the handle of the spill file. The returned value will be NULL if the file has not been created yet. */ apr_file_t * svn_spillbuf__get_file(const svn_spillbuf_t *buf); @@ -133,8 +133,8 @@ svn_spillbuf__write(svn_spillbuf_t *buf, /* Read a block of memory from the spill buffer. @a *data will be set to NULL if no content remains. Otherwise, @a data and @a len will point to data that must be fully-consumed by the caller. This data will remain - valid until another call to svn_spillbuf_write(), svn_spillbuf_read(), - or svn_spillbuf_process(), or if the spill buffer's pool is cleared. */ + valid until another call to svn_spillbuf__write(), svn_spillbuf__read(), + or svn_spillbuf__process(), or if the spill buffer's pool is cleared. */ svn_error_t * svn_spillbuf__read(const char **data, apr_size_t *len, @@ -143,7 +143,7 @@ svn_spillbuf__read(const char **data, /* Callback for reading content out of the spill buffer. Set @a stop if - you want to stop the processing (and will call svn_spillbuf_process + you want to stop the processing (and will call svn_spillbuf__process again, at a later time). */ typedef svn_error_t * (*svn_spillbuf_read_t)(svn_boolean_t *stop, void *baton, @@ -472,7 +472,7 @@ svn_version__parse_version_string(svn_version_t **version, * @since New in 1.8. */ svn_boolean_t -svn_version__at_least(svn_version_t *version, +svn_version__at_least(const svn_version_t *version, int major, int minor, int patch); @@ -525,6 +525,16 @@ svn_version__at_least(svn_version_t *version, unsigned char * svn__encode_uint(unsigned char *p, apr_uint64_t val); +/* Wrapper around svn__encode_uint using the LSB to store the sign: + * + * If VAL >= 0 + * UINT_VAL = 2 * VAL + * else + * UINT_VAL = (- 2 * VAL) - 1 + */ +unsigned char * +svn__encode_int(unsigned char *p, apr_int64_t val); + /* Decode an unsigned 7b/8b-encoded integer into *VAL and return a pointer to the byte after the integer. The bytes to be decoded live in the range [P..END-1]. If these bytes do not contain a whole encoded @@ -537,22 +547,49 @@ svn__decode_uint(apr_uint64_t *val, const unsigned char *p, const unsigned char *end); -/* Get the data from IN, compress it according to the specified - * COMPRESSION_METHOD and write the result to OUT. +/* Wrapper around svn__decode_uint, reversing the transformation performed + * by svn__encode_int. + */ +const unsigned char * +svn__decode_int(apr_int64_t *val, + const unsigned char *p, + const unsigned char *end); + +/* Compress the data from DATA with length LEN, it according to the + * specified COMPRESSION_METHOD and write the result to OUT. * SVN__COMPRESSION_NONE is valid for COMPRESSION_METHOD. */ svn_error_t * -svn__compress(svn_stringbuf_t *in, - svn_stringbuf_t *out, - int compression_method); +svn__compress_zlib(const void *data, apr_size_t len, + svn_stringbuf_t *out, + int compression_method); -/* Get the compressed data from IN, decompress it and write the result to - * OUT. Return an error if the decompressed size is larger than LIMIT. +/* Decompress the compressed data from DATA with length LEN and write the + * result to OUT. Return an error if the decompressed size is larger than + * LIMIT. */ svn_error_t * -svn__decompress(svn_stringbuf_t *in, - svn_stringbuf_t *out, - apr_size_t limit); +svn__decompress_zlib(const void *data, apr_size_t len, + svn_stringbuf_t *out, + apr_size_t limit); + +/* Same as svn__compress_zlib(), but use LZ4 compression. Note that + * while the declaration of this function uses apr_size_t, it expects + * blocks of size not exceeding LZ4_MAX_INPUT_SIZE. The caller should + * ensure that the proper size is passed to this function. + */ +svn_error_t * +svn__compress_lz4(const void *data, apr_size_t len, + svn_stringbuf_t *out); + +/* Same as svn__decompress_zlib(), but use LZ4 compression. The caller + * should ensure that the size and limit passed to this function do not + * exceed INT_MAX. + */ +svn_error_t * +svn__decompress_lz4(const void *data, apr_size_t len, + svn_stringbuf_t *out, + apr_size_t limit); /** @} */ @@ -701,6 +738,14 @@ const char *svn_zlib__compiled_version(void); /* Return the zlib version we run against. */ const char *svn_zlib__runtime_version(void); +/* Return the lz4 version we compiled against. */ +const char *svn_lz4__compiled_version(void); + +/* Return the lz4 version we run against as a composed value: + * major * 100 * 100 + minor * 100 + release + */ +int svn_lz4__runtime_version(void); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/subversion/include/private/svn_temp_serializer.h b/subversion/include/private/svn_temp_serializer.h index dd2e0478e21c..6d648b133338 100644 --- a/subversion/include/private/svn_temp_serializer.h +++ b/subversion/include/private/svn_temp_serializer.h @@ -206,7 +206,7 @@ svn_temp_serializer__get(svn_temp_serializer__context_t *context); * the pointer to resolve in @a ptr. */ void -svn_temp_deserializer__resolve(void *buffer, void **ptr); +svn_temp_deserializer__resolve(const void *buffer, void **ptr); /** * Similar to svn_temp_deserializer__resolve() but instead of modifying diff --git a/subversion/include/private/svn_utf_private.h b/subversion/include/private/svn_utf_private.h index 4584944fb47c..473e731141bf 100644 --- a/subversion/include/private/svn_utf_private.h +++ b/subversion/include/private/svn_utf_private.h @@ -150,6 +150,40 @@ svn_utf__normalize(const char **result, const char *str, apr_size_t len, svn_membuf_t *buf); +/* Transform the UTF-8 string to a shape suitable for comparison with + * strcmp(). The tranformation is defined by CASE_INSENSITIVE and + * ACCENT_INSENSITIVE arguments. If CASE_INSENSITIVE is non-zero, + * remove case distinctions from the string. If ACCENT_INSENSITIVE + * is non-zero, remove diacritical marks from the string. + * + * Use BUF as a temporary storage. If LEN is SVN_UTF__UNKNOWN_LENGTH, + * assume STR is null-terminated; otherwise, consider the string only + * up to the given length. Place the tranformed string in *RESULT, which + * shares storage with BUF and is valid only until the next time BUF is + * modified. + * + * A returned error may indicate that STRING contains invalid UTF-8 or + * invalid Unicode codepoints. + */ +svn_error_t * +svn_utf__xfrm(const char **result, + const char *str, apr_size_t len, + svn_boolean_t case_insensitive, + svn_boolean_t accent_insensitive, + svn_membuf_t *buf); + +/* Return TRUE if S matches any of the const char * glob patterns in + * PATTERNS. + * + * S will internally be normalized to lower-case and accents removed + * using svn_utf__xfrm. To get a match, the PATTERNS must have been + * normalized accordingly before calling this function. + */ +svn_boolean_t +svn_utf__fuzzy_glob_match(const char *str, + const apr_array_header_t *patterns, + svn_membuf_t *buf); + /* Check if STRING is a valid, NFC-normalized UTF-8 string. Note that * a FALSE return value may indicate that STRING is not valid UTF-8 at * all. @@ -176,7 +210,7 @@ svn_utf__encode_ucs4_string(svn_membuf_t *buffer, apr_size_t length, apr_size_t *result_length); -/* Pattern matching similar to the the SQLite LIKE and GLOB +/* Pattern matching similar to the SQLite LIKE and GLOB * operators. PATTERN, KEY and ESCAPE must all point to UTF-8 * strings. Furthermore, ESCAPE, if provided, must be a character from * the ASCII subset. diff --git a/subversion/include/private/svn_wc_private.h b/subversion/include/private/svn_wc_private.h index 28d22479118e..521d092be692 100644 --- a/subversion/include/private/svn_wc_private.h +++ b/subversion/include/private/svn_wc_private.h @@ -82,6 +82,8 @@ svn_wc__get_file_external_editor(const svn_delta_editor_t **editor, const char *recorded_url, const svn_opt_revision_t *recorded_peg_rev, const svn_opt_revision_t *recorded_rev, + svn_wc_conflict_resolver_func2_t conflict_func, + void *conflict_baton, svn_cancel_func_t cancel_func, void *cancel_baton, svn_wc_notify_func2_t notify_func, @@ -346,6 +348,20 @@ svn_wc__get_wcroot(const char **wcroot_abspath, apr_pool_t *result_pool, apr_pool_t *scratch_pool); +/** Set @a *dir to the abspath of the directory in which shelved patches + * are stored, which is inside the WC's administrative directory, and ensure + * the directory exists. + * + * @a local_abspath is any path in the WC, and is used to find the WC root. + */ +SVN_EXPERIMENTAL +svn_error_t * +svn_wc__get_shelves_dir(char **dir, + svn_wc_context_t *wc_ctx, + const char *local_abspath, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + /** * The following are temporary APIs to aid in the transition from wc-1 to * wc-ng. Use them for new development now, but they may be disappearing @@ -1746,6 +1762,207 @@ svn_wc__resolve_conflicts(svn_wc_context_t *wc_ctx, void *notify_baton, apr_pool_t *scratch_pool); +/** + * Resolve the text conflict at LOCAL_ABSPATH as per CHOICE, and then + * mark the conflict resolved. + * The working copy must already be locked for resolving, e.g. by calling + * svn_wc__acquire_write_lock_for_resolve() first. + * @since New in 1.10. + */ +svn_error_t * +svn_wc__conflict_text_mark_resolved(svn_wc_context_t *wc_ctx, + const char *local_abspath, + svn_wc_conflict_choice_t choice, + svn_cancel_func_t cancel_func, + void *cancel_baton, + svn_wc_notify_func2_t notify_func, + void *notify_baton, + apr_pool_t *scratch_pool); + +/** + * Resolve the conflicted property PROPNAME at LOCAL_ABSPATH as per CHOICE, + * and then mark the conflict resolved. If MERGED_VALUE is not NULL, this is + * the new merged property, used when choosing #svn_wc_conflict_choose_merged. + * + * The working copy must already be locked for resolving, e.g. by calling + * svn_wc__acquire_write_lock_for_resolve() first. + * @since New in 1.10. + */ +svn_error_t * +svn_wc__conflict_prop_mark_resolved(svn_wc_context_t *wc_ctx, + const char *local_abspath, + const char *propname, + svn_wc_conflict_choice_t choice, + const svn_string_t *merged_value, + svn_wc_notify_func2_t notify_func, + void *notify_baton, + apr_pool_t *scratch_pool); + +/* Resolve a tree conflict where the victim at LOCAL_ABSPATH is a directory + * which was locally deleted, replaced or moved away, and which received an + * arbitrary incoming change during an update or switch operation. + * + * The conflict is resolved by accepting the current working copy state and + * breaking the 'moved-here' link for any files or directories which were + * moved out of the victim directory before the update operation. + * As a result, any such files or directories become copies (rather than moves) + * of content which the victim directory contained before it was updated. + * + * The tree conflict at LOCAL_ABSPATH must have the following properties or + * SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE will be returned: + * + * operation: svn_wc_operation_update or svn_wc_operation_switch + * local change: svn_wc_conflict_reason_deleted or + * svn_wc_conflict_reason_replaced or + * svn_wc_conflict_reason_moved_away + * incoming change: any + * + * The working copy must already be locked for resolving, e.g. by calling + * svn_wc__acquire_write_lock_for_resolve() first. + * + * @since New in 1.10. + */ +svn_error_t * +svn_wc__conflict_tree_update_break_moved_away(svn_wc_context_t *wc_ctx, + const char *local_abspath, + svn_cancel_func_t cancel_func, + void *cancel_baton, + svn_wc_notify_func2_t notify_func, + void *notify_baton, + apr_pool_t *scratch_pool); + + +/* Resolve a tree conflict where the victim at LOCAL_ABSPATH is a directory + * which was locally deleted or replaced, and which received an edit (some + * change inside the directory, or a change to the direcotory's properties) + * during an update or switch operation. + * + * The conflict is resolved by keeping the victim deleted, and propagating + * its tree conflict to any children which were moved out of the directory + * before the update operation. + * As a result, any such files or directories become victims of the tree + * conflict as well and must be resolved independently. + * Additionally, LOCAL_ABSPATH itself may become the victim of a different + * tree conflict as a result of resolving the existing tree conflict. + * + * The tree conflict at LOCAL_ABSPATH must have the following properties or + * SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE will be returned: + * + * operation: svn_wc_operation_update or svn_wc_operation_switch + * local change: svn_wc_conflict_reason_deleted or + * svn_wc_conflict_reason_replaced + * incoming change: svn_wc_conflict_action_edit + * + * If this conflict cannot be resolved because the conflict cannot be + * propagated to moved-away children, this function returns + * SVN_ERR_WC_OBSTRUCTED_UPDATE or SVN_ERR_WC_FOUND_CONFLICT. + * The caller should continue by resolving other conflicts and attempt to + * resolve this conflict again later. + * + * The working copy must already be locked for resolving, e.g. by calling + * svn_wc__acquire_write_lock_for_resolve() first. + * + * @since New in 1.10. + */ +svn_error_t * +svn_wc__conflict_tree_update_raise_moved_away(svn_wc_context_t *wc_ctx, + const char *local_abspath, + svn_cancel_func_t cancel_func, + void *cancel_baton, + svn_wc_notify_func2_t notify_func, + void *notify_baton, + apr_pool_t *scratch_pool); + +/* Resolve a tree conflict where the victim at LOCAL_ABSPATH is a file or + * directory which was locally moved away, and which received an edit (some + * change inside the directory or file, or a change to properties) during an + * update or switch operation. + * + * The conflict is resolved by keeping the victim moved-away, and propagating + * the incoming edits to the victim's moved-to location. + * + * The tree conflict at LOCAL_ABSPATH must have the following properties or + * SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE will be returned: + * + * operation: svn_wc_operation_update or svn_wc_operation_switch + * local change: svn_wc_conflict_reason_moved_away + * incoming change: svn_wc_conflict_action_edit + * + * If this conflict cannot be resolved this function returns + * SVN_ERR_WC_OBSTRUCTED_UPDATE or SVN_ERR_WC_FOUND_CONFLICT. + * The caller should continue by resolving other conflicts and attempt to + * resolve this conflict again later. + * + * The working copy must already be locked for resolving, e.g. by calling + * svn_wc__acquire_write_lock_for_resolve() first. + * + * @since New in 1.10. + */ +svn_error_t * +svn_wc__conflict_tree_update_moved_away_node(svn_wc_context_t *wc_ctx, + const char *local_abspath, + svn_cancel_func_t cancel_func, + void *cancel_baton, + svn_wc_notify_func2_t notify_func, + void *notify_baton, + apr_pool_t *scratch_pool); + +/* Merge local changes from a tree conflict victim of an incoming deletion + * to the specified DEST_ABSPATH added during an update. Both LOCAL_ABSPATH + * and DEST_ABSPATH must be directories. + * + * Assuming DEST_ABSPATH is the correct move destination, this function + * allows local changes to "follow" incoming moves during updates. + * + * @since New in 1.10. */ +svn_error_t * +svn_wc__conflict_tree_update_incoming_move(svn_wc_context_t *wc_ctx, + const char *local_abspath, + const char *dest_abspath, + svn_cancel_func_t cancel_func, + void *cancel_baton, + svn_wc_notify_func2_t notify_func, + void *notify_baton, + apr_pool_t *scratch_pool); + +/* Resolve a 'local dir add vs incoming dir add' tree conflict upon update + * by merging the locally added directory with the incoming added directory. + * + * @since New in 1.10. */ +svn_error_t * +svn_wc__conflict_tree_update_local_add(svn_wc_context_t *wc_ctx, + const char *local_abspath, + svn_cancel_func_t cancel_func, + void *cancel_baton, + svn_wc_notify_func2_t notify_func, + void *notify_baton, + apr_pool_t *scratch_pool); + +/* Find nodes in the working copy which corresponds to the new location + * MOVED_TO_REPOS_RELPATH of the tree conflict victim at VICTIM_ABSPATH. + * The nodes must be of the same node kind as VICTIM_NODE_KIND. + * If no such node can be found, set *POSSIBLE_TARGETS to an empty array. + * + * The nodes should be useful for conflict resolution, e.g. it should be + * possible to merge changes into these nodes to resolve an incoming-move + * tree conflict. But the exact criteria for selecting a node are left + * to the implementation of this function. + * Note that this function may not necessarily return a node which was + * actually moved. The only hard guarantee is that the node corresponds to + * the repository relpath MOVED_TO_REPOS_RELPATH specified by the caller. + * Users should perform a sanity check on the results returned from this + * function, e.g. establish whether the MOVED_TO_REPOS_RELPATH at its + * current checked-out revision shares ancestry with the conflict victim. + */ +svn_error_t * +svn_wc__guess_incoming_move_target_nodes(apr_array_header_t **possible_targets, + svn_wc_context_t *wc_ctx, + const char *victim_abspath, + svn_node_kind_t victim_node_kind, + const char *moved_to_repos_relpath, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + /** * Move @a src_abspath to @a dst_abspath, by scheduling @a dst_abspath * for addition to the repository, remembering the history. Mark @a src_abspath @@ -1847,6 +2064,28 @@ svn_wc__diff7(const char **root_relpath, apr_pool_t *result_pool, apr_pool_t *scratch_pool); +/** + * Read all conflicts at LOCAL_ABSPATH into an array containing pointers to + * svn_wc_conflict_description2_t data structures alloated in RESULT_POOL. + */ +svn_error_t * +svn_wc__read_conflict_descriptions2_t(const apr_array_header_t **conflicts, + svn_wc_context_t *wc_ctx, + const char *local_abspath, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/* Internal version of svn_wc_translated_stream(), accepting a working + copy context. */ +svn_error_t * +svn_wc__translated_stream(svn_stream_t **stream, + svn_wc_context_t *wc_ctx, + const char *local_abspath, + const char *versioned_abspath, + apr_uint32_t flags, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/subversion/include/svn_auth.h b/subversion/include/svn_auth.h index 3a78ba6ace5f..ca3b703a4970 100644 --- a/subversion/include/svn_auth.h +++ b/subversion/include/svn_auth.h @@ -1012,11 +1012,13 @@ typedef svn_error_t *(*svn_auth_gnome_keyring_unlock_prompt_func_t)( /** @brief The pointer to function which prompts user for GNOME Keyring * password. - * The type of this pointer should be svn_auth_gnome_keyring_unlock_prompt_func_t. */ + * The type of this pointer should be svn_auth_gnome_keyring_unlock_prompt_func_t. + * @deprecated Only used by old libgnome-keyring implementation. */ #define SVN_AUTH_PARAM_GNOME_KEYRING_UNLOCK_PROMPT_FUNC "gnome-keyring-unlock-prompt-func" /** @brief The baton which is passed to - * @c *SVN_AUTH_PARAM_GNOME_KEYRING_UNLOCK_PROMPT_FUNC. */ + * @c *SVN_AUTH_PARAM_GNOME_KEYRING_UNLOCK_PROMPT_FUNC. + * @deprecated Only used by old libgnome-keyring implementation. */ #define SVN_AUTH_PARAM_GNOME_KEYRING_UNLOCK_PROMPT_BATON "gnome-keyring-unlock-prompt-baton" #if (!defined(DARWIN) && !defined(WIN32)) || defined(DOXYGEN) @@ -1037,7 +1039,7 @@ svn_auth_gnome_keyring_version(void); * This is like svn_client_get_simple_provider(), except that the * password is stored in GNOME Keyring. * - * If the GNOME Keyring is locked the provider calls + * If the GNOME Keyring is locked the old libgnome-keyring provider calls * @c *SVN_AUTH_PARAM_GNOME_KEYRING_UNLOCK_PROMPT_FUNC in order to unlock * the keyring. * diff --git a/subversion/include/svn_base64.h b/subversion/include/svn_base64.h index cc1820fb93cf..90316afba334 100644 --- a/subversion/include/svn_base64.h +++ b/subversion/include/svn_base64.h @@ -46,11 +46,26 @@ extern "C" { */ /** Return a writable generic stream which will encode binary data in - * base64 format and write the encoded data to @a output. Be sure to - * close the stream when done writing in order to squeeze out the last - * bit of encoded data. The stream is allocated in @a pool. + * base64 format and write the encoded data to @a output. If @a break_lines + * is true, newlines will be inserted periodically; otherwise the output + * stream will only consist of base64 encoding characters. Be sure to close + * the stream when done writing in order to squeeze out the last bit of + * encoded data. The stream is allocated in @a pool. + * + * @since New in 1.10. */ svn_stream_t * +svn_base64_encode2(svn_stream_t *output, + svn_boolean_t break_lines, + apr_pool_t *pool); + +/** + * Same as svn_base64_encode2, but with @a break_lines always TRUE. + * + * @deprecated Provided for backward compatibility with the 1.9 API. + */ +SVN_DEPRECATED +svn_stream_t * svn_base64_encode(svn_stream_t *output, apr_pool_t *pool); diff --git a/subversion/include/svn_checksum.h b/subversion/include/svn_checksum.h index e332e87e328d..1e58167ab068 100644 --- a/subversion/include/svn_checksum.h +++ b/subversion/include/svn_checksum.h @@ -177,6 +177,10 @@ svn_checksum_deserialize(const svn_checksum_t **checksum, * * @since New in 1.6. */ +/* ### TODO: When revving this, make it set @a *checksum to a non-NULL struct + * ### when @a hex is the all-zeroes checksum. See + * ### http://mail-archives.apache.org/mod_mbox/subversion-dev/201609.mbox/%3c00cd26ab-bdb3-67b4-ca6b-063266493874%40apache.org%3e + */ svn_error_t * svn_checksum_parse_hex(svn_checksum_t **checksum, svn_checksum_kind_t kind, @@ -218,6 +222,15 @@ svn_checksum_ctx_t * svn_checksum_ctx_create(svn_checksum_kind_t kind, apr_pool_t *pool); +/** + * Reset an existing checksum @a ctx to initial state. + * @see svn_checksum_ctx_create() + * + * @since New in 1.10. + */ +svn_error_t * +svn_checksum_ctx_reset(svn_checksum_ctx_t *ctx); + /** * Update the checksum represented by @a ctx, with @a len bytes starting at * @a data. diff --git a/subversion/include/svn_client.h b/subversion/include/svn_client.h index cb0f49d98d49..06dbbc35a7b3 100644 --- a/subversion/include/svn_client.h +++ b/subversion/include/svn_client.h @@ -1975,7 +1975,7 @@ typedef svn_error_t *(*svn_client_import_filter_func_t)( * on @a url if @a url is already under versioned control, or the nearest parents * of @a path which are already under version control if not. * - * If @a ignore_unknown_node_types is @c FALSE, ignore files of which the + * If @a ignore_unknown_node_types is @c TRUE, ignore files of which the * node type is unknown, such as device files and pipes. * * If @a filter_callback is non-NULL, call it for each node that isn't ignored @@ -4353,6 +4353,760 @@ svn_client_revert(const apr_array_header_t *paths, apr_pool_t *pool); +/** @} */ + +/** + * @defgroup Conflicts Dealing with conflicted paths. + * + * @{ + */ + +/** + * An opaque type which represents a conflicted node in the working copy. + * + * @since New in 1.10. + */ +typedef struct svn_client_conflict_t svn_client_conflict_t; + +/** + * An opaque type which represents a resolution option for a conflict. + * + * @since New in 1.10. + */ +typedef struct svn_client_conflict_option_t svn_client_conflict_option_t; + +/** + * A public enumeration of conflict option IDs. + * + * @since New in 1.10, unless noted otherwise. + */ +typedef enum svn_client_conflict_option_id_t { + + /* Options for text and property conflicts. + * These values intentionally mirror svn_wc_conflict_choice_t. */ + svn_client_conflict_option_undefined = -1, /* for private use only */ + svn_client_conflict_option_postpone = 0, + svn_client_conflict_option_base_text, + svn_client_conflict_option_incoming_text, /* "theirs-full" */ + svn_client_conflict_option_working_text, /* "mine-full" */ + svn_client_conflict_option_incoming_text_where_conflicted, + svn_client_conflict_option_working_text_where_conflicted, + svn_client_conflict_option_merged_text, + svn_client_conflict_option_unspecified, + /* Values derived from svn_wc_conflict_choice_t end here. */ + + /* Tree conflict resolution options start here. */ + + /* Accept current working copy state. */ + svn_client_conflict_option_accept_current_wc_state, + + /* Options for local move vs incoming edit on update. */ + svn_client_conflict_option_update_move_destination, + + /* Options for local delete/replace vs incoming edit on update. */ + svn_client_conflict_option_update_any_moved_away_children, + + /* Options for incoming add vs local add or obstruction. */ + svn_client_conflict_option_incoming_add_ignore, + + /* Options for incoming file add vs local file add or obstruction. */ + svn_client_conflict_option_incoming_added_file_text_merge, + svn_client_conflict_option_incoming_added_file_replace_and_merge, + + /* Options for incoming dir add vs local dir add or obstruction. */ + svn_client_conflict_option_incoming_added_dir_merge, + svn_client_conflict_option_incoming_added_dir_replace, + svn_client_conflict_option_incoming_added_dir_replace_and_merge, + + /* Options for incoming delete vs any */ + svn_client_conflict_option_incoming_delete_ignore, + svn_client_conflict_option_incoming_delete_accept, + + /* Options for incoming move vs local edit */ + svn_client_conflict_option_incoming_move_file_text_merge, + svn_client_conflict_option_incoming_move_dir_merge, + + /* Options for local move vs incoming edit on merge. */ + svn_client_conflict_option_local_move_file_text_merge +} svn_client_conflict_option_id_t; + +/** + * Set a merged property value on @a option to @a merged_propval. + * + * Setting the merged value is required before resolving the property + * conflict using an option with ID svn_client_conflict_option_merged_text. + * + * The contents of @a merged_propval are not copied, so the storage it + * points to needs to remain valid until svn_client_conflict_prop_resolve() + * has been called with @a option. + * + * @since New in 1.10. + */ +void +svn_client_conflict_option_set_merged_propval( + svn_client_conflict_option_t *option, + const svn_string_t *merged_propval); + +/** + * Get a list of possible repository paths which can be applied to the + * svn_client_conflict_option_incoming_move_file_text_merge or + * svn_client_conflict_option_incoming_move_dir_merge resolution + * @a option. (If a different option is passed in, this function will + * raise an assertion failure.) + * + * In some situations, there can be multiple possible destinations for an + * incoming move. One such situation is where a file was copied and moved + * in the same revision: svn cp a b; svn mv a c; svn commit + * When this move is merged elsewhere, both b and c will appear as valid move + * destinations to the conflict resolver. To resolve such ambiguity, the client + * may call this function to obtain a list of possible destinations the user + * may choose from. + * + * The array is allocated in @a result_pool and will have "const char *" + * elements pointing to strings also allocated in @a result_pool. + * All paths are relpaths, and relative to the repository root. + * + * @see svn_client_conflict_option_set_moved_to_repos_relpath() + * @since New in 1.10. + */ +svn_error_t * +svn_client_conflict_option_get_moved_to_repos_relpath_candidates( + apr_array_header_t **possible_moved_to_repos_relpaths, + svn_client_conflict_option_t *option, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/** + * Set the preferred moved target repository path for the + * svn_client_conflict_option_incoming_move_file_text_merge or + * svn_client_conflict_option_incoming_move_dir_merge resolution option. + * + * @a preferred_move_target_idx must be a valid index into the list returned + * by svn_client_conflict_option_get_moved_to_repos_relpath_candidates(). + * + * This function can be called multiple times. + * It affects the output of svn_client_conflict_tree_get_description() and + * svn_client_conflict_option_get_description(). Call these functions again + * to get updated descriptions containing the newly selected move target. + * + * @since New in 1.10. + */ +svn_error_t * +svn_client_conflict_option_set_moved_to_repos_relpath( + svn_client_conflict_option_t *option, + int preferred_move_target_idx, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool); + +/** + * Get a list of possible moved-to abspaths in the working copy which can be + * applied to the svn_client_conflict_option_incoming_move_file_text_merge + * or svn_client_conflict_option_incoming_move_dir_merge resolution @a option. + * (If a different option is passed in, this function will raise an assertion + * failure.) + * + * All paths in the returned list correspond to the repository path which + * is assumed to be the destination of the incoming move operation. + * To support cases where this destination path is ambiguous, the client may + * call svn_client_conflict_option_get_moved_to_repos_relpath_candidates() + * before calling this function to let the user select a repository path first. + * + * If no possible moved-to paths can be found, return an empty array. + * This doesn't mean that no move happened in the repository. It is possible + * that the move destination is outside the scope of the current working copy, + * for example, in which case the conflict must be resolved in some other way. + * + * @see svn_client_conflict_option_set_moved_to_abspath() + * @since New in 1.10. + */ +svn_error_t * +svn_client_conflict_option_get_moved_to_abspath_candidates( + apr_array_header_t **possible_moved_to_abspaths, + svn_client_conflict_option_t *option, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/** + * Set the preferred moved target abspath for the + * svn_client_conflict_option_incoming_move_file_text_merge or + * svn_client_conflict_option_incoming_move_dir_merge resolution option. + * + * @a preferred_move_target_idx must be a valid index into the list + * returned by svn_client_conflict_option_get_moved_to_abspath_candidates(). + * + * @since New in 1.10. + */ +svn_error_t * +svn_client_conflict_option_set_moved_to_abspath( + svn_client_conflict_option_t *option, + int preferred_move_target_idx, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool); + +/** + * Given an @a option_id, try to find the corresponding option in @a options, + * which is an array of svn_client_conflict_option_t * elements. + * + * Return NULL if no corresponding option can be be found. + * + * @since New in 1.10. + */ +svn_client_conflict_option_t * +svn_client_conflict_option_find_by_id( + apr_array_header_t *options, + svn_client_conflict_option_id_t option_id); + +/** + * Return a conflict for the conflicted path @a local_abspath. + * + * @since New in 1.10. + */ +svn_error_t * +svn_client_conflict_get(svn_client_conflict_t **conflict, + const char *local_abspath, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/** + * Callback for svn_client_conflict_conflict_walk(); + * + * The lifetime of @a conflict is limited. Its allocation in + * memory will not persist beyond this callback's execution. + * + * @since New in 1.10. + */ +typedef svn_error_t *(*svn_client_conflict_walk_func_t)( + void *baton, + svn_client_conflict_t *conflict, + apr_pool_t *scratch_pool); + +/** + * Walk all conflicts within the specified @a depth of @a local_abspath. + * Pass each conflict found during the walk to the @conflict_walk_func + * callback, along with @a conflict_walk_func_baton. + * Use cancellation and notification support provided by client context @a ctx. + * + * This callback may choose to resolve the conflict. If the act of resolving + * a conflict creates new conflicts within the walked working copy (as might + * be the case for some tree conflicts), the callback will be invoked for each + * such new conflict as well. + * + * @since New in 1.10. + */ +svn_error_t * +svn_client_conflict_walk(const char *local_abspath, + svn_depth_t depth, + svn_client_conflict_walk_func_t conflict_walk_func, + void *conflict_walk_func_baton, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool); + +/** +* Indicate the types of conflicts present on the working copy node +* described by @a conflict. Any output argument may be @c NULL if +* the caller is not interested in the status of a particular type. +* +* The returned @a *props_conflicted array is allocated in @a result_pool. +* It contains the names of conflicted properties. If no property conflict +* exists, the array will contain no elements. +* +* @since New in 1.10. +*/ +svn_error_t * +svn_client_conflict_get_conflicted(svn_boolean_t *text_conflicted, + apr_array_header_t **props_conflicted, + svn_boolean_t *tree_conflicted, + svn_client_conflict_t *conflict, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/** + * Return a textual human-readable description of the property conflict + * described by @a conflict, allocated in @a result_pool. The description + * is encoded in UTF-8 and may contain multiple lines separated by + * @c APR_EOL_STR. The last line is not terminated by a newline. + * + * Additionally, the description may be localized to the language used + * by the current locale. + * + * @since New in 1.10. + */ +svn_error_t * +svn_client_conflict_prop_get_description(const char **description, + svn_client_conflict_t *conflict, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/** + * Return a textual human-readable description of the tree conflict + * described by @a conflict, allocated in @a result_pool. The description + * is encoded in UTF-8 and may contain multiple lines separated by + * @c APR_EOL_STR. The last line is not terminated by a newline. + * + * Additionally, the description may be localized to the language used + * by the current locale. + * + * While client implementors are free to enhance descriptions by adding + * additional information to the text, or break up very long lines for + * formatting purposes, there is no syntax defined for descriptions, and + * implementors should not rely on any particular parts of descriptions + * to remain stable over time, apart from what is stated below. + * Descriptions may or may not form complete sentences. They may contain + * paths relative to the repository root; such paths always start with "^/", + * and end with either a peg revision (e.g. "@100") or a colon followed by + * a range of revisions (as in svn:mergeinfo, e.g. ":100-200"). + * Paths may appear on a line of their own to avoid overlong lines. + * Any revision numbers mentioned elsewhere in the description are + * prefixed with the letter 'r' (e.g. "r99"). + * + * The description has two parts: One part describes the "incoming change" + * applied by an update, merge, or switch operation. The other part + * describes the "local change" which occurred in the working copy or + * perhaps in the history of a merge target branch. + * Both parts are provided independently to allow for some flexibility + * when displaying the description. As a convention, displaying the + * "incoming change" first and the "local change" second is recommended. + * + * By default, the description is based only on information available in + * the working copy. If svn_client_conflict_tree_get_details() was already + * called for @a conflict, the description might also contain useful + * information obtained from the repository and provide for a much better + * user experience. + * + * @since New in 1.10. + */ +svn_error_t * +svn_client_conflict_tree_get_description( + const char **incoming_change_description, + const char **local_change_description, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/** + * Set @a *options to an array of pointers to svn_client_conflict_option_t + * objects applicable to text conflicts described by @a conflict. + * + * @since New in 1.10. + */ +svn_error_t * +svn_client_conflict_text_get_resolution_options(apr_array_header_t **options, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/** + * Set @a *options to an array of pointers to svn_client_conflict_option_t + * objects applicable to property conflicts described by @a conflict. + * + * @since New in 1.10. + */ +svn_error_t * +svn_client_conflict_prop_get_resolution_options(apr_array_header_t **options, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/** + * Set @a *options to an array of pointers to svn_client_conflict_option_t + * objects applicable to the tree conflict described by @a conflict. + * + * By default, the list of options is based only on information available in + * the working copy. If svn_client_conflict_tree_get_details() was already + * called for @a conflict, a more useful list of options might be returned. + * + * @since New in 1.10. + */ +svn_error_t * +svn_client_conflict_tree_get_resolution_options(apr_array_header_t **options, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/** + * Find more information about the tree conflict represented by @a conflict. + * + * A call to svn_client_conflict_tree_get_description() may yield much better + * results after this function has been called. + * + * A call to svn_client_conflict_tree_get_resolution_options() may provide + * more useful resolution options if this function has been called. + * + * This function may contact the repository. Use the authentication baton + * cached in @a ctx for authentication if contacting the repository. + * + * @since New in 1.10. + */ +svn_error_t * +svn_client_conflict_tree_get_details(svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool); + +/** + * Return an ID for @a option. This ID can be used by callers to associate + * arbitrary data with a particular conflict resolution option. + * + * The ID of a particular resolution option will never change in future + * revisions of this API. + * + * @since New in 1.10. + */ +svn_client_conflict_option_id_t +svn_client_conflict_option_get_id(svn_client_conflict_option_t *option); + +/** + * Return a textual human-readable label of @a option, allocated in + * @a result_pool. The label is encoded in UTF-8 and usually + * contains up to three words. + * + * Additionally, the label may be localized to the language used + * by the current locale. + * + * @since New in 1.10. + */ +const char * +svn_client_conflict_option_get_label(svn_client_conflict_option_t *option, + apr_pool_t *result_pool); + +/** + * Return a textual human-readable description of @a option, allocated in + * @a result_pool. The description is encoded in UTF-8 and may contain + * multiple lines separated by @c APR_EOL_STR. + * + * Additionally, the description may be localized to the language used + * by the current locale. + * + * @since New in 1.10. + */ +const char * +svn_client_conflict_option_get_description(svn_client_conflict_option_t *option, + apr_pool_t *result_pool); + +/** + * Return the ID of the recommended resolution option. If no specific option + * is recommended, return @c svn_client_conflict_option_unspecified; + * + * Client implementations which aim to avoid excessive interactive prompting + * may wish to try a recommended resolution option before falling back to + * asking the user which option to use. + * + * Conflict resolution with a recommended option is not guaranteed to succeed. + * Clients should check for errors when trying to resolve a conflict and fall + * back to other options and/or interactive prompting when the recommended + * option fails to resolve a conflict. + * + * If @a conflict is a tree conflict, svn_client_conflict_tree_get_details() + * should be called before this function to allow for useful recommendations. + * + * @since New in 1.10. + */ +svn_client_conflict_option_id_t +svn_client_conflict_get_recommended_option_id(svn_client_conflict_t *conflict); + +/** + * Return the absolute path to the conflicted working copy node described + * by @a conflict. + * + * @since New in 1.10. + */ +const char * +svn_client_conflict_get_local_abspath(svn_client_conflict_t *conflict); + +/** + * Return the operation during which the conflict described by @a + * conflict was recorded. + * + * @since New in 1.10. + */ +svn_wc_operation_t +svn_client_conflict_get_operation(svn_client_conflict_t *conflict); + +/** + * Return the action an update, switch, or merge operation attempted to + * perform on the working copy node described by @a conflict. + * + * @since New in 1.10. + */ +svn_wc_conflict_action_t +svn_client_conflict_get_incoming_change(svn_client_conflict_t *conflict); + +/** + * Return the reason why the attempted action performed by an update, switch, + * or merge operation conflicted with the state of the node in the working copy. + * + * During update and switch operations this local change is part of uncommitted + * modifications in the working copy. During merge operations it may + * additionally be part of the history of the merge target branch, anywhere + * between the common ancestor revision and the working copy revision. + * + * @since New in 1.10. + */ +svn_wc_conflict_reason_t +svn_client_conflict_get_local_change(svn_client_conflict_t *conflict); + +/** + * Return information about the repository associated with @a conflict. + * In case of a foreign-repository merge this will differ from the + * repository information associated with the merge target working copy. + * + * @since New in 1.10. + */ +svn_error_t * +svn_client_conflict_get_repos_info(const char **repos_root_url, + const char **repos_uuid, + svn_client_conflict_t *conflict, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/** + * Return the repository-relative location and the node kind of the incoming + * old version of the conflicted node described by @a conflict. + * + * If the repository-relative path is not available, the @a + * *incoming_old_repos_relpath will be set to @c NULL, + * + * If the peg revision is not available, @a *incoming_old_regrev will be + * set to SVN_INVALID_REVNUM. + * + * If the node kind is not available or if the node does not exist at the + * specified path and revision, @a *incoming_old_node_kind will be set to + * svn_node_none. + * ### Should return svn_node_unkown if not available? + * + * Any output parameter may be set to @c NULL by the caller to indicate that + * a particular piece of information should not be returned. + * + * In case of tree conflicts, this path@revision does not necessarily exist + * in the repository, and it does not necessarily represent the incoming + * change which is responsible for the occurance of the tree conflict. + * The responsible incoming change is generally located somewhere between + * the old and new incoming versions. + * + * @since New in 1.10. + */ +svn_error_t * +svn_client_conflict_get_incoming_old_repos_location( + const char **incoming_old_repos_relpath, + svn_revnum_t *incoming_old_regrev, + svn_node_kind_t *incoming_old_node_kind, + svn_client_conflict_t *conflict, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/** + * Like svn_client_conflict_get_incoming_old_repos_location(), expect this + * function returns the same data for the incoming new version. + * + * The same note about tree conflicts applies. + * + * @since New in 1.10. + */ +svn_error_t * +svn_client_conflict_get_incoming_new_repos_location( + const char **incoming_new_repos_relpath, + svn_revnum_t *incoming_new_regrev, + svn_node_kind_t *incoming_new_node_kind, + svn_client_conflict_t *conflict, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/** + * Return the node kind of the tree conflict victim described by @a conflict. + * The victim is the local node in the working copy which was affected by the + * tree conflict at the time the conflict was raised. + * + * @since New in 1.10. + */ +svn_node_kind_t +svn_client_conflict_tree_get_victim_node_kind(svn_client_conflict_t *conflict); + +/** + * Resolve a tree @a conflict using resolution option @a option. + * + * May raise an error in case the tree conflict cannot be resolved yet, for + * instance @c SVN_ERR_WC_OBSTRUCTED_UPDATE, @c SVN_ERR_WC_FOUND_CONFLICT, + * or @c SVN_ERR_WC_CONFLICT_RESOLVER_FAILUE. + * This may happen when other tree conflicts, or unversioned obstructions, + * block the resolution of this tree conflict. In such a case the other + * conflicts should be resolved first and resolution of this conflict should + * be attempted again later. + * + * @since New in 1.10. + */ +svn_error_t * +svn_client_conflict_tree_resolve(svn_client_conflict_t *conflict, + svn_client_conflict_option_t *option, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool); + +/** + * Like svn_client_conflict_tree_resolve(), except that it identifies + * the desired resolution option by ID @a option_id. + * + * If the provided @a option_id is the ID of an option which resolves + * @a conflict, try to resolve the tree conflict using that option. + * Else, return @c SVN_ERR_CLIENT_CONFLICT_OPTION_NOT_APPLICABLE. + * + * @since New in 1.10. + */ +svn_error_t * +svn_client_conflict_tree_resolve_by_id( + svn_client_conflict_t *conflict, + svn_client_conflict_option_id_t option_id, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool); + +/** + * Return the ID of the option this tree @a conflict has been resolved to. + * If the conflict has not been resolved yet, then return + * @c svn_client_conflict_option_unspecified. + * + * @since New in 1.10. + */ +svn_client_conflict_option_id_t +svn_client_conflict_tree_get_resolution(svn_client_conflict_t *conflict); + +/** + * Return the path to the legacy property conflicts reject file + * for the property conflicts represented by @a conflict. + * + * This function exists for backwards compatibility only and should not be + * used in new code. + * + * @since New in 1.10. + */ +const char * +svn_client_conflict_prop_get_reject_abspath(svn_client_conflict_t *conflict); + +/** + * Return the set of property values involved in the conflict of property + * PROPNAME described by @a conflict. If a property value is unavailable the + * corresponding output argument is set to @c NULL. + * + * A 3-way diff of these property values can be generated with + * svn_diff_mem_string_diff3(). A merged version with conflict + * markers can be generated with svn_diff_mem_string_output_merge3(). + * + * @since New in 1.10. + */ +svn_error_t * +svn_client_conflict_prop_get_propvals(const svn_string_t **base_propval, + const svn_string_t **working_propval, + const svn_string_t **incoming_old_propval, + const svn_string_t **incoming_new_propval, + svn_client_conflict_t *conflict, + const char *propname, + apr_pool_t *result_pool); + +/** + * Resolve a property @a conflict in property @a propname using resolution + * option @a option. To resolve all properties to the same option at once, + * set @a propname to the empty string "". + * + * @since New in 1.10. + */ +svn_error_t * +svn_client_conflict_prop_resolve(svn_client_conflict_t *conflict, + const char *propname, + svn_client_conflict_option_t *option, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool); +/** + * If the provided @a option_id is the ID of an option which resolves + * @a conflict, resolve the property conflict in property @a propname + * using that option. + * Else, return @c SVN_ERR_CLIENT_CONFLICT_OPTION_NOT_APPLICABLE. + * + * @since New in 1.10. + */ +svn_error_t * +svn_client_conflict_prop_resolve_by_id( + svn_client_conflict_t *conflict, + const char *propname, + svn_client_conflict_option_id_t option_id, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool); + +/** + * Return the ID of the option this property @a conflict in property + * @a propname has been resolved to. + * If the conflict has not been resolved yet, then return + * @c svn_client_conflict_option_unspecified. + * + * @since New in 1.10. + */ +svn_client_conflict_option_id_t +svn_client_conflict_prop_get_resolution(svn_client_conflict_t *conflict, + const char *propname); + +/** + * Return the MIME-type of the working version of the text-conflicted file + * described by @a conflict. + * + * ### Really needed? What about base/incoming_old/incoming_new values? + * @since: New in 1.10. + */ +const char * +svn_client_conflict_text_get_mime_type(svn_client_conflict_t *conflict); + +/** + * Return absolute paths to the versions of the text-conflicted file + * described by @a conflict. + * + * If a particular content is not available, it is set to @c NULL. + * + * ### Should this be returning svn_stream_t instead of paths? + * @since: New in 1.10. + */ +svn_error_t * +svn_client_conflict_text_get_contents(const char **base_abspath, + const char **working_abspath, + const char **incoming_old_abspath, + const char **incoming_new_abspath, + svn_client_conflict_t *conflict, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/** + * Resolve a text @a conflict using resolution option @a option. + * + * @since New in 1.10. + */ +svn_error_t * +svn_client_conflict_text_resolve(svn_client_conflict_t *conflict, + svn_client_conflict_option_t *option, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool); + +/** + * If the provided @a option_id is the ID of an option which resolves + * @a conflict, resolve the text conflict using that option. + * Else, return @c SVN_ERR_CLIENT_CONFLICT_OPTION_NOT_APPLICABLE. + * + * @since New in 1.10. + */ +svn_error_t * +svn_client_conflict_text_resolve_by_id( + svn_client_conflict_t *conflict, + svn_client_conflict_option_id_t option_id, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool); + +/** + * Return the ID of the option this text @a conflict has been resolved to. + * If the conflict has not been resolved yet, then return + * @c svn_client_conflict_option_unspecified. + * + * @since New in 1.10. + */ +svn_client_conflict_option_id_t +svn_client_conflict_text_get_resolution(svn_client_conflict_t *conflict); + /** @} */ /** @@ -4402,7 +5156,11 @@ svn_client_resolved(const char *path, * - svn_wc_conflict_choose_unspecified * invoke @a ctx->conflict_func2 with @a ctx->conflict_baton2 to obtain * a resolution decision for each conflict. This can be used to - * implement interactive conflict resolution. + * implement interactive conflict resolution but is NOT RECOMMENDED for + * new code. To perform conflict resolution based on interactive user + * input on a per-conflict basis, use svn_client_conflict_text_resolve(), + * svn_client_conflict_prop_resolve(), and + * svn_client_conflict_tree_resolve() instead of svn_client_resolve(). * * #svn_wc_conflict_choose_theirs_conflict and * #svn_wc_conflict_choose_mine_conflict are not legal for binary @@ -5493,8 +6251,7 @@ svn_client_revprop_list(apr_hash_t **props, * #svn_opt_revision_unspecified, then it defaults to #svn_opt_revision_head * for URLs or #svn_opt_revision_working for WC targets. * - * @a revision is the revision that should be exported, which is only used - * when exporting from a repository. + * @a revision is the revision that should be exported. * * @a peg_revision and @a revision must not be @c NULL. * @@ -5706,13 +6463,18 @@ typedef svn_error_t *(*svn_client_list_func_t)(void *baton, * its children. If @a path_or_url is non-existent, return * #SVN_ERR_FS_NOT_FOUND. * + * If the @a patterns array of const char * is not @c NULL, only + * report paths whose last segment matches one of the specified glob + * patterns. This does not affect the size of the tree nor the number of + * externals being covered. + * * If @a fetch_locks is TRUE, include locks when reporting directory entries. * * If @a include_externals is TRUE, also list all external items * reached by recursion. @a depth value passed to the original list target * applies for the externals also. * - * Use @a pool for temporary allocations. + * Use @a scratch_pool for temporary allocations. * * Use authentication baton cached in @a ctx to authenticate against the * repository. @@ -5728,9 +6490,30 @@ typedef svn_error_t *(*svn_client_list_func_t)(void *baton, * otherwise simply bitwise OR together the combination of @c SVN_DIRENT_ * fields you care about. * - * @since New in 1.8. + * @since New in 1.10. */ svn_error_t * +svn_client_list4(const char *path_or_url, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *revision, + const apr_array_header_t *patterns, + svn_depth_t depth, + apr_uint32_t dirent_fields, + svn_boolean_t fetch_locks, + svn_boolean_t include_externals, + svn_client_list_func2_t list_func, + void *baton, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool); + +/** Similar to svn_client_list4(), but with @a patterns set to @c NULL. + * + * @since New in 1.8. + * + * @deprecated Provided for backwards compatibility with the 1.9 API. + */ +SVN_DEPRECATED +svn_error_t * svn_client_list3(const char *path_or_url, const svn_opt_revision_t *peg_revision, const svn_opt_revision_t *revision, @@ -5747,9 +6530,9 @@ svn_client_list3(const char *path_or_url, /** Similar to svn_client_list3(), but with @a include_externals set * to FALSE, and using a #svn_client_list_func_t as callback. * - * @deprecated Provided for backwards compatibility with the 1.7 API. - * * @since New in 1.5. + * + * @deprecated Provided for backwards compatibility with the 1.7 API. */ SVN_DEPRECATED svn_error_t * @@ -5932,6 +6715,153 @@ svn_client_cat(svn_stream_t *out, +/** Shelving commands + * + * @defgroup svn_client_shelve_funcs Client Shelving Functions + * @{ + */ + +/** Shelve a change. + * + * Shelve as @a name the local modifications found by @a paths, @a depth, + * @a changelists. Revert the shelved change from the WC unless @a keep_local + * is true. + * + * If @a dry_run is true, don't actually do it. + * + * @since New in 1.10. + * @warning EXPERIMENTAL. + */ +SVN_EXPERIMENTAL +svn_error_t * +svn_client_shelve(const char *name, + const apr_array_header_t *paths, + svn_depth_t depth, + const apr_array_header_t *changelists, + svn_boolean_t keep_local, + svn_boolean_t dry_run, + svn_client_ctx_t *ctx, + apr_pool_t *pool); + +/** Unshelve the shelved change @a name. + * + * @a local_abspath is any path in the WC and is used to find the WC root. + * Rename the shelved patch to add a '.bak' extension unless @a keep is true. + * + * If @a dry_run is true, don't actually do it. + * + * @since New in 1.10. + * @warning EXPERIMENTAL. + */ +SVN_EXPERIMENTAL +svn_error_t * +svn_client_unshelve(const char *name, + const char *local_abspath, + svn_boolean_t keep, + svn_boolean_t dry_run, + svn_client_ctx_t *ctx, + apr_pool_t *pool); + +/** Delete the shelved patch @a name. + * + * @a local_abspath is any path in the WC and is used to find the WC root. + * + * If @a dry_run is true, don't actually do it. + * + * @since New in 1.10. + * @warning EXPERIMENTAL. + */ +SVN_EXPERIMENTAL +svn_error_t * +svn_client_shelves_delete(const char *name, + const char *local_abspath, + svn_boolean_t dry_run, + svn_client_ctx_t *ctx, + apr_pool_t *pool); + +/** Information about a shelved patch. + * + * @since New in 1.10. + * @warning EXPERIMENTAL. + */ +typedef struct svn_client_shelved_patch_info_t +{ + const char *message; /* first line of log message */ + const char *patch_path; /* abspath of the patch file */ + svn_io_dirent2_t *dirent; /* info about the patch file */ + apr_time_t mtime; /* a copy of dirent->mtime */ +} svn_client_shelved_patch_info_t; + +/** Set @a *shelved_patch_infos to a hash, keyed by patch name, of pointers to + * @c svn_client_shelved_patch_info_t structures. + * + * @a local_abspath is any path in the WC and is used to find the WC root. + * + * @since New in 1.10. + * @warning EXPERIMENTAL. + */ +SVN_EXPERIMENTAL +svn_error_t * +svn_client_shelves_list(apr_hash_t **shelved_patch_infos, + const char *local_abspath, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/** Set @a *any_shelved to indicate if there are any shelved changes in this WC. + * + * This shall provide the answer fast, regardless of how many changes + * are stored, unlike svn_client_shelves_list(). + * + * ### Initial implementation isn't O(1) fast -- it just calls + * svn_client_shelves_list(). + * + * @a local_abspath is any path in the WC and is used to find the WC root. + * + * @since New in 1.10. + * @warning EXPERIMENTAL. + */ +SVN_EXPERIMENTAL +svn_error_t * +svn_client_shelves_any(svn_boolean_t *any_shelved, + const char *local_abspath, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool); + +/** Set @a *affected_paths to a hash with one entry for each path affected + * by the shelf @a name. The hash key is the old path and value is + * the new path, both relative to the WC root. The key and value are the + * same except when a path is moved or copied. + * + * @since New in 1.10. + * @warning EXPERIMENTAL. + */ +SVN_EXPERIMENTAL +svn_error_t * +svn_client_shelf_get_paths(apr_hash_t **affected_paths, + const char *name, + const char *local_abspath, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/** Set @a *has_changes to indicate whether the shelf @a name + * contains any modifications, in other words if svn_client_shelf_get_paths() + * would return a non-empty set of paths. + * + * @since New in 1.10. + * @warning EXPERIMENTAL. + */ +SVN_EXPERIMENTAL +svn_error_t * +svn_client_shelf_has_changes(svn_boolean_t *has_changes, + const char *name, + const char *local_abspath, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool); + +/** @} */ + /** Changelist commands * * @defgroup svn_client_changelist_funcs Client Changelist Functions diff --git a/subversion/include/svn_cmdline.h b/subversion/include/svn_cmdline.h index 923aeee6235a..2789aa411310 100644 --- a/subversion/include/svn_cmdline.h +++ b/subversion/include/svn_cmdline.h @@ -374,6 +374,7 @@ svn_cmdline_create_auth_baton2(svn_auth_baton_t **ab, * @deprecated Provided for backward compatibility with the 1.8 API. * @since New in 1.6. */ +SVN_DEPRECATED svn_error_t * svn_cmdline_create_auth_baton(svn_auth_baton_t **ab, svn_boolean_t non_interactive, diff --git a/subversion/include/svn_config.h b/subversion/include/svn_config.h index 5ad3b0bae234..d194af09efbf 100644 --- a/subversion/include/svn_config.h +++ b/subversion/include/svn_config.h @@ -63,6 +63,12 @@ typedef struct svn_config_t svn_config_t; * @{ */ +/* If you add a new SVN_CONFIG_* category/section/option macro to this group, + * you have to re-run gen-make.py manually. + * + * ### This should be fixed in the build system; see issue #4581. + */ + /* This list of #defines is intentionally presented as a nested list that matches the in-config hierarchy. */ diff --git a/subversion/include/svn_dav.h b/subversion/include/svn_dav.h index e9092d541938..9af9bc58f7ed 100644 --- a/subversion/include/svn_dav.h +++ b/subversion/include/svn_dav.h @@ -386,6 +386,41 @@ extern "C" { #define SVN_DAV_NS_DAV_SVN_REVERSE_FILE_REVS\ SVN_DAV_PROP_NS_DAV "svn/reverse-file-revs" +/** Presence of this in a DAV header in an OPTIONS response indicates + * that the transmitter (in this case, the server) knows how to handle + * svndiff1 format encoding. + * + * @since New in 1.10. + */ +#define SVN_DAV_NS_DAV_SVN_SVNDIFF1\ + SVN_DAV_PROP_NS_DAV "svn/svndiff1" + +/** Presence of this in a DAV header in an OPTIONS response indicates + * that the transmitter (in this case, the server) knows how to handle + * 'list' requests. + * + * @since New in 1.10. + */ +#define SVN_DAV_NS_DAV_SVN_LIST\ + SVN_DAV_PROP_NS_DAV "svn/list" + +/** Presence of this in a DAV header in an OPTIONS response indicates + * that the transmitter (in this case, the server) knows how to handle + * svndiff2 format encoding. + * + * @since New in 1.10. + */ +#define SVN_DAV_NS_DAV_SVN_SVNDIFF2\ + SVN_DAV_PROP_NS_DAV "svn/svndiff2" + +/** Presence of this in a DAV header in an OPTIONS response indicates + * that the transmitter (in this case, the server) sends the result + * checksum in the response to a successful PUT request. + * + * @since New in 1.10. + */ +#define SVN_DAV_NS_DAV_SVN_PUT_RESULT_CHECKSUM\ + SVN_DAV_PROP_NS_DAV "svn/put-result-checksum" /** @} */ diff --git a/subversion/include/svn_delta.h b/subversion/include/svn_delta.h index d949ced66b8b..c15788ee4d00 100644 --- a/subversion/include/svn_delta.h +++ b/subversion/include/svn_delta.h @@ -330,6 +330,18 @@ typedef svn_error_t * typedef const unsigned char * (*svn_txdelta_md5_digest_fn_t)(void *baton); +/** A typedef for a function that opens an #svn_txdelta_stream_t object, + * allocated in @a result_pool. @a baton is provided by the caller. + * Any temporary allocations may be performed in @a scratch_pool. + * + * @since New in 1.10. + */ +typedef svn_error_t * +(*svn_txdelta_stream_open_func_t)(svn_txdelta_stream_t **txdelta_stream, + void *baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + /** Create and return a generic text delta stream with @a baton, @a * next_window and @a md5_digest. Allocate the new stream in @a * pool. @@ -508,7 +520,9 @@ svn_txdelta_apply(svn_stream_t *source, * version is @a svndiff_version. @a compression_level is the zlib * compression level from 0 (no compression) and 9 (maximum compression). * - * @since New in 1.7. + * @since New in 1.7. Since 1.10, @a svndiff_version can be 2 for the + * svndiff2 format. @a compression_level is currently ignored if + * @a svndiff_version is set to 2. */ void svn_txdelta_to_svndiff3(svn_txdelta_window_handler_t *handler, @@ -544,6 +558,20 @@ svn_txdelta_to_svndiff(svn_stream_t *output, svn_txdelta_window_handler_t *handler, void **handler_baton); +/** Return a readable generic stream which will produce svndiff-encoded + * text delta from the delta stream @a txstream. @a svndiff_version and + * @a compression_level are same as in svn_txdelta_to_svndiff3(). + * + * Allocate the stream in @a pool. + * + * @since New in 1.10. + */ +svn_stream_t * +svn_txdelta_to_svndiff_stream(svn_txdelta_stream_t *txstream, + int svndiff_version, + int compression_level, + apr_pool_t *pool); + /** Return a writable generic stream which will parse svndiff-format * data into a text delta, invoking @a handler with @a handler_baton * whenever a new window is ready. @@ -666,8 +694,10 @@ svn_txdelta_skip_svndiff_window(apr_file_t *file, * as it produces the delta. * * @note Don't try to allocate one of these yourself. Instead, always - * use svn_delta_default_editor() or some other constructor, to ensure - * that unused slots are filled in with no-op functions. + * use svn_delta_default_editor() or some other constructor, to avoid + * backwards compatibility problems if the structure is extended in + * future releases and to ensure that unused slots are filled in with + * no-op functions. * *

Function Usage

* @@ -738,10 +768,11 @@ svn_txdelta_skip_svndiff_window(apr_file_t *file, * * The @c add_file and @c open_file callbacks each return a baton * for the file being created or changed. This baton can then be - * passed to @c apply_textdelta to change the file's contents, or - * @c change_file_prop to change the file's properties. When the - * producer is finished making changes to a file, it should call - * @c close_file, to let the consumer clean up and free the baton. + * passed to @c apply_textdelta or @c apply_textdelta_stream to change + * the file's contents, or @c change_file_prop to change the file's + * properties. When the producer is finished making changes to a + * file, it should call @c close_file, to let the consumer clean up + * and free the baton. * * The @c add_file and @c add_directory functions each take arguments * @a copyfrom_path and @a copyfrom_revision. If @a copyfrom_path is @@ -783,15 +814,16 @@ svn_txdelta_skip_svndiff_window(apr_file_t *file, * 5. When the producer calls @c open_file or @c add_file, either: * * (a) The producer must follow with any changes to the file - * (@c change_file_prop and/or @c apply_textdelta, as applicable), - * followed by a @c close_file call, before issuing any other file - * or directory calls, or + * (@c change_file_prop and/or @c apply_textdelta / + * @c apply_textdelta_stream, as applicable), followed by + * a @c close_file call, before issuing any other file or + * directory calls, or * * (b) The producer must follow with a @c change_file_prop call if * it is applicable, before issuing any other file or directory * calls; later, after all directory batons including the root - * have been closed, the producer must issue @c apply_textdelta - * and @c close_file calls. + * have been closed, the producer must issue @c apply_textdelta / + * @c apply_textdelta_stream and @c close_file calls. * * 6. When the producer calls @c apply_textdelta, it must make all of * the window handler calls (including the @c NULL window at the @@ -800,7 +832,7 @@ svn_txdelta_skip_svndiff_window(apr_file_t *file, * So, the producer needs to use directory and file batons as if it * is doing a single depth-first traversal of the tree, with the * exception that the producer may keep file batons open in order to - * make @c apply_textdelta calls at the end. + * make @c apply_textdelta / @c apply_textdelta_stream calls at the end. * * *

Pool Usage

@@ -824,12 +856,13 @@ svn_txdelta_skip_svndiff_window(apr_file_t *file, * Note that close_directory can be called *before* a file in that * directory has been closed. That is, the directory's baton is * closed before the file's baton. The implication is that - * @c apply_textdelta and @c close_file should not refer to a parent - * directory baton UNLESS the editor has taken precautions to - * allocate it in a pool of the appropriate lifetime (the @a dir_pool - * passed to @c open_directory and @c add_directory definitely does not - * have the proper lifetime). In general, it is recommended to simply - * avoid keeping a parent directory baton in a file baton. + * @c apply_textdelta / @c apply_textdelta_stream and @c close_file + * should not refer to a parent directory baton UNLESS the editor has + * taken precautions to allocate it in a pool of the appropriate + * lifetime (the @a dir_pool passed to @c open_directory and + * @c add_directory definitely does not have the proper lifetime). + * In general, it is recommended to simply avoid keeping a parent + * directory baton in a file baton. * * *

Errors

@@ -977,7 +1010,8 @@ typedef struct svn_delta_editor_t /** We are going to add a new file at @a path, a child of the * directory represented by @a parent_baton. The callback can * store a baton for this new file in @a **file_baton; whatever value - * it stores there should be passed through to @c apply_textdelta. + * it stores there should be passed through to @c apply_textdelta or + * @c apply_textdelta_stream. * * If @a copyfrom_path is non-@c NULL, this add has history (i.e., is a * copy), and the origin of the copy may be recorded as @@ -1009,8 +1043,8 @@ typedef struct svn_delta_editor_t * * The callback can store a baton for this new file in @a **file_baton; * whatever value it stores there should be passed through to - * @c apply_textdelta. If a valid revnum, @a base_revision is the - * current revision of the file. + * @c apply_textdelta or @c apply_textdelta_stream. If a valid revnum, + * @a base_revision is the current revision of the file. * * Allocations for the returned @a file_baton should be performed in * @a result_pool. It is also typical to save this pool for later usage @@ -1075,11 +1109,11 @@ typedef struct svn_delta_editor_t * more, so whatever resources it refers to may now be freed. * * @a text_checksum is the hex MD5 digest for the fulltext that - * resulted from a delta application, see @c apply_textdelta. The - * checksum is ignored if NULL. If not null, it is compared to the - * checksum of the new fulltext, and the error - * SVN_ERR_CHECKSUM_MISMATCH is returned if they do not match. If - * there is no new fulltext, @a text_checksum is ignored. + * resulted from a delta application, see @c apply_textdelta and + * @c apply_textdelta_stream. The checksum is ignored if NULL. + * If not null, it is compared to the checksum of the new fulltext, + * and the error SVN_ERR_CHECKSUM_MISMATCH is returned if they do + * not match. If there is no new fulltext, @a text_checksum is ignored. * * Any temporary allocations may be performed in @a scratch_pool. */ @@ -1115,6 +1149,38 @@ typedef struct svn_delta_editor_t svn_error_t *(*abort_edit)(void *edit_baton, apr_pool_t *scratch_pool); + /** Apply a text delta stream, yielding the new revision of a file. + * This callback operates on the passed-in @a editor instance. + * + * @a file_baton indicates the file we're creating or updating, and the + * ancestor file on which it is based; it is the baton set by some + * prior @c add_file or @c open_file callback. + * + * @a open_func is a function that opens a #svn_txdelta_stream_t object. + * @a open_baton is provided by the caller. + * + * @a base_checksum is the hex MD5 digest for the base text against + * which the delta is being applied; it is ignored if NULL, and may + * be ignored even if not NULL. If it is not ignored, it must match + * the checksum of the base text against which svndiff data is being + * applied; if it does not, @c apply_textdelta_stream call which detects + * the mismatch will return the error #SVN_ERR_CHECKSUM_MISMATCH + * (if there is no base text, there may still be an error if + * @a base_checksum is neither NULL nor the hex MD5 checksum of the + * empty string). + * + * Any temporary allocations may be performed in @a scratch_pool. + * + * @since New in 1.10. + */ + svn_error_t *(*apply_textdelta_stream)( + const struct svn_delta_editor_t *editor, + void *file_baton, + const char *base_checksum, + svn_txdelta_stream_open_func_t open_func, + void *open_baton, + apr_pool_t *scratch_pool); + /* Be sure to update svn_delta_get_cancellation_editor() and * svn_delta_default_editor() if you add a new callback here. */ } svn_delta_editor_t; diff --git a/subversion/include/svn_diff.h b/subversion/include/svn_diff.h index 5b8f8d7fc9f2..bd2c97084bfb 100644 --- a/subversion/include/svn_diff.h +++ b/subversion/include/svn_diff.h @@ -1211,8 +1211,44 @@ typedef struct svn_prop_patch_t { apr_array_header_t *hunks; } svn_prop_patch_t; +/** + * A binary patch representation. This basically describes replacing one + * exact binary representation with another one. + * + * @since New in 1.10. */ +typedef struct svn_diff_binary_patch_t svn_diff_binary_patch_t; + +/** + * Creates a stream allocated in @a result_pool from which the original + * (pre-patch-application) version of the binary patched file can be read. + * + * @note Like many svn_diff_get functions over patches, this is implemented + * as reading from the backing patch file. Therefore it is recommended to + * read the whole stream before using other functions on the same patch file. + * + * @since New in 1.10 */ +svn_stream_t * +svn_diff_get_binary_diff_original_stream(const svn_diff_binary_patch_t *bpatch, + apr_pool_t *result_pool); + +/** + * Creates a stream allocated in @a result_pool from which the resulting + * (post-patch-application) version of the binary patched file can be read. + * + * @note Like many svn_diff_get functions over patches, this is implemented + * as reading from the backing patch file. Therefore it is recommended to + * read the whole stream before using other functions on the same patch file. + * + * @since New in 1.10 */ +svn_stream_t * +svn_diff_get_binary_diff_result_stream(const svn_diff_binary_patch_t *bpatch, + apr_pool_t *result_pool); + /** * Data type to manage parsing of patches. + * + * Represents a patch to one target file. + * * API users should not allocate structures of this type directly. * * @since New in 1.7. */ @@ -1239,7 +1275,9 @@ typedef struct svn_patch_t { svn_diff_operation_kind_t operation; /** - * Indicates whether the patch is being interpreted in reverse. */ + * Indicates whether the patch is being interpreted in reverse. + * ### If so, how does this affect the interpretation of other fields? + */ svn_boolean_t reverse; /** @@ -1249,6 +1287,45 @@ typedef struct svn_patch_t { * @since New in 1.9. */ svn_mergeinfo_t mergeinfo; svn_mergeinfo_t reverse_mergeinfo; + + /** + * Declares that there is a binary conflict and contains the information + * to apply it as parsed from the file. + * @since New in 1.10. */ + svn_diff_binary_patch_t *binary_patch; + + /** The old and new executability bits, as retrieved from the patch file, from + * the git-like mode headers. + * + * A patch may specify an executability change via @a old_executable_bit and + * @a new_executable_bit, via a #SVN_PROP_EXECUTABLE propchange hunk, or both + * ways. It is upto caller how to decide how conflicting information is + * handled. + * + * #svn_tristate_unknown indicates the patch does not specify the + * corresponding bit. + * + * @since New in 1.10. + */ + svn_tristate_t old_executable_bit; + svn_tristate_t new_executable_bit; + + /** The old and new symlink bits, as retrieved from the patch file, from + * the git-like mode headers. + * + * A patch may specify a symlink change via @a old_symlink_bit and + * @a new_symlink_bit, via a #SVN_PROP_SPECIAL propchange hunk, or both + * ways. It is upto caller how to decide how conflicting information is + * handled. Most implementations will currently just describe a replacement + * of the file though. + * + * #svn_tristate_unknown indicates the patch does not specify the + * corresponding bit. + * + * @since New in 1.10. + */ + svn_tristate_t old_symlink_bit; + svn_tristate_t new_symlink_bit; } svn_patch_t; /** An opaque type representing an open patch file. diff --git a/subversion/include/svn_error.h b/subversion/include/svn_error.h index 5681644fd194..290aaa2cbb22 100644 --- a/subversion/include/svn_error.h +++ b/subversion/include/svn_error.h @@ -165,18 +165,16 @@ svn_error_wrap_apr(apr_status_t status, ...) __attribute__((format(printf, 2, 3))); -/** A quick n' easy way to create a wrapped exception with your own - * message, before throwing it up the stack. (It uses all of the - * @a child's fields.) +/** If @a child is SVN_NO_ERROR, return SVN_NO_ERROR. + * Else, prepend a new error to the error chain of @a child. The new error + * uses @a new_msg as error message but all other error attributes (such + * as the error code) are copied from @a child. */ svn_error_t * svn_error_quick_wrap(svn_error_t *child, const char *new_msg); -/** A quick n' easy way to create a wrapped exception with your own - * printf-style error message produced by passing @a fmt, using - * apr_psprintf(), before throwing it up the stack. (It uses all of the - * @a child's fields.) +/** Like svn_error_quick_wrap(), but with format string support. * * @since New in 1.9. */ diff --git a/subversion/include/svn_error_codes.h b/subversion/include/svn_error_codes.h index f8348f48dec9..f95f0a0f0e84 100644 --- a/subversion/include/svn_error_codes.h +++ b/subversion/include/svn_error_codes.h @@ -240,6 +240,11 @@ SVN_ERROR_START SVN_ERR_BAD_CATEGORY_START + 16, "Invalid compression method") + /** @since New in 1.10. */ + SVN_ERRDEF(SVN_ERR_BAD_PROPERTY_VALUE_EOL, + SVN_ERR_BAD_CATEGORY_START + 17, + "Unexpected line ending in the property value") + /* xml errors */ SVN_ERRDEF(SVN_ERR_XML_ATTRIB_NOT_FOUND, @@ -868,6 +873,21 @@ SVN_ERROR_START SVN_ERR_FS_CATEGORY_START + 63, "Invalid generation number data.") + /** @since New in 1.10. */ + SVN_ERRDEF(SVN_ERR_FS_CORRUPT_REVPROP_MANIFEST, + SVN_ERR_FS_CATEGORY_START + 64, + "Revprop manifest corrupt.") + + /** @since New in 1.10. */ + SVN_ERRDEF(SVN_ERR_FS_CORRUPT_PROPLIST, + SVN_ERR_FS_CATEGORY_START + 65, + "Property list is corrupt.") + + /** @since New in 1.10. */ + SVN_ERRDEF(SVN_ERR_FS_AMBIGUOUS_CHECKSUM_REP, + SVN_ERR_FS_CATEGORY_START + 67, + "Content checksums supposedly match but content does not.") + /* repos errors */ SVN_ERRDEF(SVN_ERR_REPOS_LOCKED, @@ -1236,6 +1256,11 @@ SVN_ERROR_START SVN_ERR_CLIENT_CATEGORY_START + 23, "The operation is forbidden by the server") + /** @since New in 1.10. */ + SVN_ERRDEF(SVN_ERR_CLIENT_CONFLICT_OPTION_NOT_APPLICABLE, + SVN_ERR_CLIENT_CATEGORY_START + 24, + "The conflict resolution option is not applicable") + /* misc errors */ SVN_ERRDEF(SVN_ERR_BASE, @@ -1442,6 +1467,21 @@ SVN_ERROR_START SVN_ERR_MISC_CATEGORY_START + 43, "Parser error: invalid input") + /** @since New in 1.10. */ + SVN_ERRDEF(SVN_ERR_SQLITE_ROLLBACK_FAILED, + SVN_ERR_MISC_CATEGORY_START + 44, + "SQLite transaction rollback failed") + + /** @since New in 1.10. */ + SVN_ERRDEF(SVN_ERR_LZ4_COMPRESSION_FAILED, + SVN_ERR_MISC_CATEGORY_START + 45, + "LZ4 compression failed") + + /** @since New in 1.10. */ + SVN_ERRDEF(SVN_ERR_LZ4_DECOMPRESSION_FAILED, + SVN_ERR_MISC_CATEGORY_START + 46, + "LZ4 decompression failed") + /* command-line client errors */ SVN_ERRDEF(SVN_ERR_CL_ARG_PARSING_ERROR, @@ -1537,6 +1577,16 @@ SVN_ERROR_START SVN_ERR_RA_SVN_CATEGORY_START + 8, "Editor drive was aborted") + /** @since New in 1.10 */ + SVN_ERRDEF(SVN_ERR_RA_SVN_REQUEST_SIZE, + SVN_ERR_RA_SVN_CATEGORY_START + 9, + "Client request too long") + + /** @since New in 1.10 */ + SVN_ERRDEF(SVN_ERR_RA_SVN_RESPONSE_SIZE, + SVN_ERR_RA_SVN_CATEGORY_START + 10, + "Server response too long") + /* libsvn_auth errors */ /* this error can be used when an auth provider doesn't have @@ -1594,6 +1644,11 @@ SVN_ERROR_START SVN_ERR_DIFF_CATEGORY_START + 0, "Diff data source modified unexpectedly") + /** @since New in 1.10 */ + SVN_ERRDEF(SVN_ERR_DIFF_UNEXPECTED_DATA, + SVN_ERR_DIFF_CATEGORY_START + 1, + "Diff data unexpected") + /* libsvn_ra_serf errors */ /** @since New in 1.5. @deprecated SSPI now handled by serf rather than libsvn_ra_serf. */ @@ -1617,6 +1672,11 @@ SVN_ERROR_START SVN_ERR_RA_SERF_CATEGORY_START + 3, "While handling serf response:") + /** @since New in 1.10. */ + SVN_ERRDEF(SVN_ERR_RA_SERF_STREAM_BUCKET_READ_ERROR, + SVN_ERR_RA_SERF_CATEGORY_START + 4, + "Can't read from stream") + /* malfunctions such as assertion failures */ SVN_ERRDEF(SVN_ERR_ASSERTION_FAIL, diff --git a/subversion/include/svn_fs.h b/subversion/include/svn_fs.h index e34146d16dff..179774e16a1e 100644 --- a/subversion/include/svn_fs.h +++ b/subversion/include/svn_fs.h @@ -113,7 +113,7 @@ typedef struct svn_fs_t svn_fs_t; * * "2" is allowed, too and means "enable if efficient", * i.e. this will not create warning at runtime if there - * if no efficient support for revprop caching. + * is no efficient support for revprop caching. * * @since New in 1.8. */ @@ -134,6 +134,12 @@ typedef struct svn_fs_t svn_fs_t; */ #define SVN_FS_CONFIG_FSFS_CACHE_NS "fsfs-cache-namespace" +/** Enable / disable caching of node properties for a FSFS repository. + * + * @since New in 1.10. + */ +#define SVN_FS_CONFIG_FSFS_CACHE_NODEPROPS "fsfs-cache-nodeprops" + /** Enable / disable the FSFS format 7 "block read" feature. * * @since New in 1.9. @@ -207,6 +213,20 @@ typedef struct svn_fs_t svn_fs_t; * @since New in 1.9. */ #define SVN_FS_CONFIG_COMPATIBLE_VERSION "compatible-version" + +/** Specifies whether the filesystem should be forcing a physical write of + * the data to disk. Enabling the option allows the filesystem to return + * from the API calls without forcing the write to disk. If this option + * is disabled, the changes are always written to disk. + * + * @note Avoiding the forced write to disk usually is more efficient, but + * doesn't guarantee data integrity after a system crash or power failure + * and should be used with caution. + * + * @since New in 1.10. + */ +#define SVN_FS_CONFIG_NO_FLUSH_TO_DISK "no-flush-to-disk" + /** @} */ @@ -269,11 +289,13 @@ svn_fs_set_warning_func(svn_fs_t *fs, * @c NULL, the options it contains modify the behavior of the * filesystem. The interpretation of @a fs_config is specific to the * filesystem back-end. The new filesystem may be closed by - * destroying @a pool. + * destroying @a result_pool. + * + * Use @a scratch_pool for temporary allocations. * * @note The lifetime of @a fs_config must not be shorter than @a - * pool's. It's a good idea to allocate @a fs_config from @a pool or - * one of its ancestors. + * result_pool's. It's a good idea to allocate @a fs_config from + * @a result_pool or one of its ancestors. * * If @a fs_config contains a value for #SVN_FS_CONFIG_FS_TYPE, that * value determines the filesystem type for the new filesystem. @@ -289,8 +311,22 @@ svn_fs_set_warning_func(svn_fs_t *fs, * though the caller should not rely upon any particular default if they * wish to ensure that a filesystem of a specific type is created. * + * @since New in 1.10. + */ +svn_error_t * +svn_fs_create2(svn_fs_t **fs_p, + const char *path, + apr_hash_t *fs_config, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/** + * Like svn_fs_create2(), but without @a scratch_pool. + * + * @deprecated Provided for backward compatibility with the 1.9 API. * @since New in 1.1. */ +SVN_DEPRECATED svn_error_t * svn_fs_create(svn_fs_t **fs_p, const char *path, @@ -1060,15 +1096,12 @@ svn_fs_unparse_id(const svn_fs_id_t *id, * set. * * The Subversion filesystem will make a best effort to not reuse - * transaction names. The Berkeley DB backend generates transaction - * names using a sequence, or a counter, which is stored in the BDB + * transaction names. The BDB and FSFS backends generate transaction + * names using a sequence, or a counter, which is stored in the * database. Each new transaction increments the counter. The * current value of the counter is not serialized into a filesystem * dump file, so dumping and restoring the repository will reset the - * sequence and reuse transaction names. The FSFS backend generates a - * transaction name using the hostname, process ID and current time in - * microseconds since 00:00:00 January 1, 1970 UTC. So it is - * extremely unlikely that a transaction name will be reused. + * sequence and so may reuse transaction names. * * @defgroup svn_fs_txns Filesystem transactions * @{ @@ -1425,7 +1458,7 @@ svn_fs_revision_root_revision(svn_fs_root_t *root); * Unicode canonical decomposition and ordering. No directory entry * may be named '.', '..', or the empty string. Given a directory * entry name which fails to meet these requirements, a filesystem - * function returns an SVN_ERR_FS_PATH_SYNTAX error. + * function returns an #SVN_ERR_FS_PATH_SYNTAX error. * * A directory path is a sequence of zero or more directory entry * names, separated by slash characters (U+002f), and possibly ending @@ -1433,7 +1466,7 @@ svn_fs_revision_root_revision(svn_fs_root_t *root); * characters are treated as if they were a single slash. If a path * ends with a slash, it refers to the same node it would without the * slash, but that node must be a directory, or else the function - * returns an SVN_ERR_FS_NOT_DIRECTORY error. + * may return an #SVN_ERR_FS_NOT_DIRECTORY error. * * A path consisting of the empty string, or a string containing only * slashes, refers to the root directory. @@ -1474,7 +1507,75 @@ typedef enum svn_fs_path_change_kind_t * by the commit API; this does not mean the new value is different from * the old value. * - * @since New in 1.6. */ + * @since New in 1.10. */ +typedef struct svn_fs_path_change3_t +{ + /** path of the node that got changed. */ + svn_string_t path; + + /** kind of change */ + svn_fs_path_change_kind_t change_kind; + + /** what node kind is the path? + (Note: it is legal for this to be #svn_node_unknown.) */ + svn_node_kind_t node_kind; + + /** was the text touched? + * For node_kind=dir: always false. For node_kind=file: + * modify: true iff text touched. + * add (copy): true iff text touched. + * add (plain): always true. + * delete: always false. + * replace: as for the add/copy part of the replacement. + */ + svn_boolean_t text_mod; + + /** were the properties touched? + * modify: true iff props touched. + * add (copy): true iff props touched. + * add (plain): true iff props touched. + * delete: always false. + * replace: as for the add/copy part of the replacement. + */ + svn_boolean_t prop_mod; + + /** was the mergeinfo property touched? + * modify: } true iff svn:mergeinfo property add/del/mod + * add (copy): } and fs format supports this flag. + * add (plain): } + * delete: always false. + * replace: as for the add/copy part of the replacement. + * (Note: Pre-1.9 repositories will report #svn_tristate_unknown.) + */ + svn_tristate_t mergeinfo_mod; + + /** Copyfrom revision and path; this is only valid if copyfrom_known + * is true. */ + svn_boolean_t copyfrom_known; + svn_revnum_t copyfrom_rev; + const char *copyfrom_path; + + /* NOTE! Please update svn_fs_path_change3_create() when adding new + fields here. */ +} svn_fs_path_change3_t; + + +/** Similar to #svn_fs_path_change3_t, but with @a node_rev_id and without + * path information. + * + * @note Fields may be added to the end of this structure in future + * versions. Therefore, to preserve binary compatibility, users + * should not directly allocate structures of this type. + * + * @note The @c text_mod, @c prop_mod and @c mergeinfo_mod flags mean the + * text, properties and mergeinfo property (respectively) were "touched" + * by the commit API; this does not mean the new value is different from + * the old value. + * + * @since New in 1.6. + * + * @deprecated Provided for backwards compatibility with the 1.9 API. + */ typedef struct svn_fs_path_change2_t { /** node revision id of changed path */ @@ -1563,22 +1664,94 @@ svn_fs_path_change2_create(const svn_fs_id_t *node_rev_id, svn_fs_path_change_kind_t change_kind, apr_pool_t *pool); +/** + * Allocate an #svn_fs_path_change3_t structure in @a result_pool, + * initialize and return it. + * + * Set the @c change_kind field to @a change_kind. Set all other fields + * to their @c _unknown, @c NULL or invalid value, respectively. + * + * @since New in 1.10. + */ +svn_fs_path_change3_t * +svn_fs_path_change3_create(svn_fs_path_change_kind_t change_kind, + apr_pool_t *result_pool); + +/** + * Return a deep copy of @a *change, allocated in @a result_pool. + * + * @since New in 1.10. + */ +svn_fs_path_change3_t * +svn_fs_path_change3_dup(svn_fs_path_change3_t *change, + apr_pool_t *result_pool); + +/** + * Opaque iterator object type for a changed paths list. + * + * @since New in 1.10. + */ +typedef struct svn_fs_path_change_iterator_t svn_fs_path_change_iterator_t; + +/** + * Set @a *change to the path change that @a iterator currently points to + * and advance the @a iterator. If the change list has been exhausted, + * @a change will be set to @c NULL. + * + * You may modify @a **change but its content becomes invalid as soon as + * either @a iterator becomes invalid or you call this function again. + * + * @note The @c node_kind field in @a change may be #svn_node_unknown and + * the @c copyfrom_known fields may be FALSE. + * + * @since New in 1.10. + */ +svn_error_t * +svn_fs_path_change_get(svn_fs_path_change3_t **change, + svn_fs_path_change_iterator_t *iterator); + + /** Determine what has changed under a @a root. + * + * Set @a *iterator to an iterator object, allocated in @a result_pool, + * which will give access to the full list of changed paths under @a root. + * Each call to @a svn_fs_path_change_get will return a new unique path + * change and has amortized O(1) runtime. The iteration order is undefined + * and may change even for the same @a root. + * + * If @a root becomes invalid, @a *iterator becomes invalid, too. + * + * Use @a scratch_pool for temporary allocations. + * + * @note The @a *iterator may be a large object and bind limited system + * resources such as file handles. Be sure to clear the owning + * pool once you don't need that iterator anymore. + * + * @since New in 1.10. + */ +svn_error_t * +svn_fs_paths_changed3(svn_fs_path_change_iterator_t **iterator, + svn_fs_root_t *root, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/** Same as svn_fs_paths_changed3() but returning all changes in a single, + * large data structure and using a single pool for all allocations. * * Allocate and return a hash @a *changed_paths2_p containing descriptions * of the paths changed under @a root. The hash is keyed with * const char * paths, and has #svn_fs_path_change2_t * values. * - * Callers can assume that this function takes time proportional to - * the amount of data output, and does not need to do tree crawls; - * however, it is possible that some of the @c node_kind fields in the - * #svn_fs_path_change2_t * values will be #svn_node_unknown or - * that and some of the @c copyfrom_known fields will be FALSE. - * * Use @a pool for all allocations, including the hash and its values. * + * @note Retrieving the #node_rev_id element of #svn_fs_path_change2_t may + * be expensive in some FS backends. + * * @since New in 1.6. + * + * @deprecated Provided for backward compatibility with the 1.9 API. */ +SVN_DEPRECATED svn_error_t * svn_fs_paths_changed2(apr_hash_t **changed_paths2_p, svn_fs_root_t *root, @@ -1989,11 +2162,23 @@ svn_fs_closest_copy(svn_fs_root_t **root_p, const char *path, apr_pool_t *pool); +/** Receives parsed @a mergeinfo for the file system path @a path. + * + * The user-provided @a baton is being passed through by the retrieval + * function and @a scratch_pool will be cleared between invocations. + * + * @since New in 1.10. + */ +typedef svn_error_t * +(*svn_fs_mergeinfo_receiver_t)(const char *path, + svn_mergeinfo_t mergeinfo, + void *baton, + apr_pool_t *scratch_pool); /** Retrieve mergeinfo for multiple nodes. * - * @a *catalog is a catalog for @a paths. It will never be @c NULL, - * but may be empty. + * For each node found with mergeinfo on it, invoke @a receiver with + * the provided @a baton. * * @a root is revision root to use when looking up paths. * @@ -2003,7 +2188,7 @@ svn_fs_closest_copy(svn_fs_root_t **root_p, * explicit-or-inherited, or only inherited mergeinfo. * * If @a adjust_inherited_mergeinfo is @c TRUE, then any inherited - * mergeinfo returned in @a *catalog is normalized to represent the + * mergeinfo reported to @a *receiver is normalized to represent the * inherited mergeinfo on the path which inherits it. This adjusted * mergeinfo is keyed by the path which inherits it. If * @a adjust_inherited_mergeinfo is @c FALSE, then any inherited @@ -2018,13 +2203,31 @@ svn_fs_closest_copy(svn_fs_root_t **root_p, * the #SVN_PROP_MERGEINFO property explicitly set on it. (Note * that inheritance is only taken into account for the elements in @a * paths; descendants of the elements in @a paths which get their - * mergeinfo via inheritance are not included in @a *catalog.) + * mergeinfo via inheritance are not reported to @a receiver.) * - * Allocate @a *catalog in result_pool. Do any necessary temporary - * allocations in @a scratch_pool. + * Do any necessary temporary allocations in @a scratch_pool. + * + * @since New in 1.10. + */ +svn_error_t * +svn_fs_get_mergeinfo3(svn_fs_root_t *root, + const apr_array_header_t *paths, + svn_mergeinfo_inheritance_t inherit, + svn_boolean_t include_descendants, + svn_boolean_t adjust_inherited_mergeinfo, + svn_fs_mergeinfo_receiver_t receiver, + void *baton, + apr_pool_t *scratch_pool); + +/** + * Same as svn_fs_get_mergeinfo3(), but all mergeinfo is being collected + * and returned in @a *catalog. It will never be @c NULL, but may be empty. * * @since New in 1.8. + * + * @deprecated Provided for backward compatibility with the 1.9 API. */ +SVN_DEPRECATED svn_error_t * svn_fs_get_mergeinfo2(svn_mergeinfo_catalog_t *catalog, svn_fs_root_t *root, @@ -2545,12 +2748,71 @@ svn_fs_deltify_revision(svn_fs_t *fs, svn_revnum_t revision, apr_pool_t *pool); +/** Make sure that all completed revision property changes to the filesystem + * underlying @a fs are actually visible through @a fs. Use @a scratch_pool + * for temporary allocations. + * + * This is an explicit synchronization barrier for revprop changes made + * through different #svn_fs_t for the same underlying filesystem. Any + * revprop change through @a fs acts as an implicit barrier, i.e. that + * object will see all completed revprop changes up to an including its own. + * Only #svn_fs_revision_prop2 and #svn_fs_revision_proplist2 have an option + * to not synchronize with on-disk data and potentially return outdated data + * as old as the last barrier. + * + * The intended use of this is implementing efficient queries in upper layers + * where the result only needs to include all changes up to the start of + * that query but does not need to pick up on changes while the query is + * running: + * + * @code + SVN_ERR(svn_fs_deltify_revision(fs, pool); + for (i = 0; i < n; i++) + SVN_ERR(svn_fs_revision_prop2(&authors[i], fs, revs[i], "svn:author", + FALSE, pool, pool)); @endcode + * + * @see svn_fs_revision_prop2, svn_fs_revision_proplist2 + * + * @since New in 1.10. + */ +svn_error_t * +svn_fs_refresh_revision_props(svn_fs_t *fs, + apr_pool_t *scratch_pool); /** Set @a *value_p to the value of the property named @a propname on * revision @a rev in the filesystem @a fs. If @a rev has no property by - * that name, set @a *value_p to zero. Allocate the result in @a pool. + * that name, set @a *value_p to zero. + * + * If @a refresh is set, this call acts as a read barrier and is guaranteed + * to return the latest value. Otherwise, it may return data as old as the + * last synchronization point but can be much faster to access - in + * particular for packed repositories. + * + * Allocate the result in @a result_pool and use @a scratch_pool for + * temporary allocations. + * + * @see svn_fs_refresh_revision_props + * + * @since New in 1.10. */ svn_error_t * +svn_fs_revision_prop2(svn_string_t **value_p, + svn_fs_t *fs, + svn_revnum_t rev, + const char *propname, + svn_boolean_t refresh, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/** Like #svn_fs_revision_prop2 but using @a pool for @a scratch_pool as + * well as @a result_pool and setting @a refresh to #TRUE. + * + * @see svn_fs_refresh_revision_props + * + * @deprecated For backward compatibility with 1.9. + */ +SVN_DEPRECATED +svn_error_t * svn_fs_revision_prop(svn_string_t **value_p, svn_fs_t *fs, svn_revnum_t rev, @@ -2561,15 +2823,41 @@ svn_fs_revision_prop(svn_string_t **value_p, /** Set @a *table_p to the entire property list of revision @a rev in * filesystem @a fs, as an APR hash table allocated in @a pool. The table * maps char * property names to #svn_string_t * values; the names - * and values are allocated in @a pool. + * and values are allocated in @a result_pool. Use @a scratch_pool for + * temporary allocations. + * + * If @a refresh is set, this call acts as a read barrier and is guaranteed + * to return the latest value. Otherwise, it may return data as old as the + * last synchronization point but can be much faster to access - in + * particular for packed repositories. + * + * @see svn_fs_refresh_revision_props + * + * @since New in 1.10. + * */ svn_error_t * +svn_fs_revision_proplist2(apr_hash_t **table_p, + svn_fs_t *fs, + svn_revnum_t rev, + svn_boolean_t refresh, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/** Like svn_fs_revision_proplist2 but using @a pool for @a scratch_pool as + * well as @a result_pool and setting @a refresh to #TRUE. + * + * @see svn_fs_refresh_revision_props + * + * @deprecated For backward compatibility with 1.9. + */ +SVN_DEPRECATED +svn_error_t * svn_fs_revision_proplist(apr_hash_t **table_p, svn_fs_t *fs, svn_revnum_t rev, apr_pool_t *pool); - /** Change a revision's property's value, or add/delete a property. * * - @a fs is a filesystem, and @a rev is the revision in that filesystem @@ -2992,7 +3280,13 @@ typedef enum svn_fs_pack_notify_action_t /** packing of the shard revprops has completed @since New in 1.7. */ - svn_fs_pack_notify_end_revprop + svn_fs_pack_notify_end_revprop, + + /** pack has been a no-op for this repository. The next / future packable + shard will be given. If the shard is -1, then the repository does not + support packing at all. + @since New in 1.10. */ + svn_fs_pack_notify_noop } svn_fs_pack_notify_action_t; diff --git a/subversion/include/svn_hash.h b/subversion/include/svn_hash.h index 50ed10a4b3f8..8303f077e18e 100644 --- a/subversion/include/svn_hash.h +++ b/subversion/include/svn_hash.h @@ -239,19 +239,44 @@ svn_hash_from_cstring_keys(apr_hash_t **hash, const apr_array_header_t *keys, apr_pool_t *pool); +/* For the Subversion developers, this #define makes the svn_hash_gets and + * svn_hash_sets macros forward their parameters through functions in order to + * gain type checking for the 'key' parameter which the basic apr_hash_* APIs + * declare only as 'void *'. + */ +#ifdef SVN_DEBUG +#define SVN_HASH__GETS_SETS +#endif + +#ifdef SVN_HASH__GETS_SETS +void * +svn_hash__gets_debug(apr_hash_t *ht, const char *key); + +#define svn_hash_gets(ht, key) \ + svn_hash__gets_debug(ht, key) +#else /** Shortcut for apr_hash_get() with a const char * key. * * @since New in 1.8. */ #define svn_hash_gets(ht, key) \ apr_hash_get(ht, key, APR_HASH_KEY_STRING) +#endif +#ifdef SVN_HASH__GETS_SETS +void +svn_hash__sets_debug(apr_hash_t *ht, const char *key, const void *value); + +#define svn_hash_sets(ht, key, val) \ + svn_hash__sets_debug(ht, key, val) +#else /** Shortcut for apr_hash_set() with a const char * key. * * @since New in 1.8. */ #define svn_hash_sets(ht, key, val) \ apr_hash_set(ht, key, APR_HASH_KEY_STRING, val) +#endif /** @} */ diff --git a/subversion/include/svn_io.h b/subversion/include/svn_io.h index 42eb422bfab9..802e5caa5c12 100644 --- a/subversion/include/svn_io.h +++ b/subversion/include/svn_io.h @@ -918,6 +918,17 @@ typedef svn_error_t *(*svn_stream_seek_fn_t)(void *baton, typedef svn_error_t *(*svn_stream_data_available_fn_t)(void *baton, svn_boolean_t *data_available); +/** Readline handler function for a generic stream. @see svn_stream_t and + * svn_stream_readline(). + * + * @since New in 1.10. + */ +typedef svn_error_t *(*svn_stream_readline_fn_t)(void *baton, + svn_stringbuf_t **stringbuf, + const char *eol, + svn_boolean_t *eof, + apr_pool_t *pool); + /** Create a generic stream. @see svn_stream_t. */ svn_stream_t * svn_stream_create(void *baton, @@ -992,6 +1003,14 @@ void svn_stream_set_data_available(svn_stream_t *stream, svn_stream_data_available_fn_t data_available); +/** Set @a stream's readline function to @a readline_fn + * + * @since New in 1.10. + */ +void +svn_stream_set_readline(svn_stream_t *stream, + svn_stream_readline_fn_t readline_fn); + /** Create a stream that is empty for reading and infinite for writing. */ svn_stream_t * svn_stream_empty(apr_pool_t *pool); @@ -1102,11 +1121,29 @@ svn_stream_from_aprfile(apr_file_t *file, apr_pool_t *pool); /** Set @a *in to a generic stream connected to stdin, allocated in - * @a pool. The stream and its underlying APR handle will be closed - * when @a pool is cleared or destroyed. + * @a pool. If @a buffered is set, APR buffering will be enabled. + * The stream and its underlying APR handle will be closed when @a pool + * is cleared or destroyed. + * + * @note APR buffering will try to fill the whole internal buffer before + * serving read requests. This may be inappropriate for interactive + * applications where stdin will not deliver any more data unless + * the application processed the data already received. + * + * @since New in 1.10. + */ +svn_error_t * +svn_stream_for_stdin2(svn_stream_t **in, + svn_boolean_t buffered, + apr_pool_t *pool); + +/** Similar to svn_stream_for_stdin2(), but with buffering being disabled. * * @since New in 1.7. + * + * @deprecated Provided for backward compatibility with the 1.9 API. */ +SVN_DEPRECATED svn_error_t * svn_stream_for_stdin(svn_stream_t **in, apr_pool_t *pool); @@ -1129,16 +1166,27 @@ svn_error_t * svn_stream_for_stdout(svn_stream_t **out, apr_pool_t *pool); -/** Set @a *str to a string buffer allocated in @a result_pool that contains - * all data from the current position in @a stream to its end. @a len_hint - * specifies the initial capacity of the string buffer and may be 0. The - * buffer gets automatically resized to fit the actual amount of data being - * read from @a stream. +/** Read the contents of @a stream into memory, from its current position + * to its end, returning the data in @a *result. This function does not + * close the @a stream upon completion. + * + * @a len_hint gives a hint about the expected length, in bytes, of the + * actual data that will be read from the stream. It may be 0, meaning no + * hint is being provided. Efficiency in time and/or in space may be + * better (and in general will not be worse) when the actual data length + * is equal or approximately equal to the length hint. + * + * The returned memory is allocated in @a result_pool. + * + * @note The present implementation is efficient when @a len_hint is big + * enough (but not vastly bigger than necessary), and also for actual + * lengths up to 64 bytes when @a len_hint is 0. Otherwise it can incur + * significant time and space overheads. See source code for details. * * @since New in 1.9. */ svn_error_t * -svn_stringbuf_from_stream(svn_stringbuf_t **str, +svn_stringbuf_from_stream(svn_stringbuf_t **result, svn_stream_t *stream, apr_size_t len_hint, apr_pool_t *result_pool); @@ -1200,7 +1248,8 @@ svn_stream_compressed(svn_stream_t *stream, * The @a stream passed into this function is closed when the created * stream is closed. * - * @since New in 1.6. + * @since New in 1.6. Since 1.10, the resulting stream supports reset + * via stream_stream_reset(). */ svn_stream_t * svn_stream_checksummed2(svn_stream_t *stream, @@ -1225,6 +1274,24 @@ svn_stream_checksummed(svn_stream_t *stream, svn_boolean_t read_all, apr_pool_t *pool); +/** Read the contents of the readable stream @a stream and return its + * checksum of type @a kind in @a *checksum. + * + * The stream will be closed before this function returns (regardless + * of the result, or any possible error). + * + * Use @a scratch_pool for temporary allocations and @a result_pool + * to allocate @a *checksum. + * + * @since New in 1.10. + */ +svn_error_t * +svn_stream_contents_checksum(svn_checksum_t **checksum, + svn_stream_t *stream, + svn_checksum_kind_t kind, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + /** Read from a generic stream until @a buffer is filled upto @a *len or * until EOF is reached. @see svn_stream_t * @@ -1318,6 +1385,14 @@ svn_stream_reset(svn_stream_t *stream); svn_boolean_t svn_stream_supports_mark(svn_stream_t *stream); +/** Returns @c TRUE if the generic @a stream supports svn_stream_reset(). + * + * @see svn_stream_reset() + * @since New in 1.10. + */ +svn_boolean_t +svn_stream_supports_reset(svn_stream_t *stream); + /** Set a @a mark at the current position of a generic @a stream, * which can later be sought back to using svn_stream_seek(). * The @a mark is allocated in @a pool. @@ -1502,25 +1577,44 @@ svn_stream_contents_same(svn_boolean_t *same, apr_pool_t *pool); -/** Read the contents of @a stream into memory, returning the data in - * @a result. The stream will be closed when it has been successfully and - * completely read. +/** Read the contents of @a stream into memory, from its current position + * to its end, returning the data in @a *result. The stream will be closed + * when it has been successfully and completely read. + * + * @a len_hint gives a hint about the expected length, in bytes, of the + * actual data that will be read from the stream. It may be 0, meaning no + * hint is being provided. Efficiency in time and/or in space may be + * better (and in general will not be worse) when the actual data length + * is equal or approximately equal to the length hint. * * The returned memory is allocated in @a result_pool, and any temporary - * allocations are performed in @a scratch_pool. + * allocations may be performed in @a scratch_pool. * - * @note due to memory pseudo-reallocation behavior (due to pools), this - * can be a memory-intensive operation for large files. + * @note The present implementation is efficient when @a len_hint is big + * enough (but not vastly bigger than necessary), and also for actual + * lengths up to 64 bytes when @a len_hint is 0. Otherwise it can incur + * significant time and space overheads. See source code for details. * - * @since New in 1.6 + * @since New in 1.10 */ svn_error_t * +svn_string_from_stream2(svn_string_t **result, + svn_stream_t *stream, + apr_size_t len_hint, + apr_pool_t *result_pool); + +/** Similar to svn_string_from_stream2(), but always passes 0 for + * @a len_hint. + * + * @deprecated Provided for backwards compatibility with the 1.9 API. + */ +SVN_DEPRECATED +svn_error_t * svn_string_from_stream(svn_string_t **result, svn_stream_t *stream, apr_pool_t *result_pool, apr_pool_t *scratch_pool); - /** A function type provided for use as a callback from * @c svn_stream_lazyopen_create(). * @@ -2175,6 +2269,28 @@ svn_io_file_info_get(apr_finfo_t *finfo, apr_pool_t *pool); +/** Set @a *filesize_p to the size of @a file. Use @a pool for temporary + * allocations. + * + * @note Use svn_io_file_info_get() to get more information about + * apr_file_t. + * + * @since New in 1.10 + */ +svn_error_t * +svn_io_file_size_get(svn_filesize_t *filesize_p, apr_file_t *file, + apr_pool_t *pool); + +/** Fetch the current offset of @a file into @a *offset_p. Use @a pool for + * temporary allocations. + * + * @since New in 1.10 + */ +svn_error_t * +svn_io_file_get_offset(apr_off_t *offset_p, + apr_file_t *file, + apr_pool_t *pool); + /** Wrapper for apr_file_read(). */ svn_error_t * svn_io_file_read(apr_file_t *file, @@ -2276,13 +2392,31 @@ svn_io_file_write_full(apr_file_t *file, * If @a copy_perms_path is not NULL, copy the permissions applied on @a * @a copy_perms_path on the temporary file before renaming. * - * @note This function uses advanced file control operations to flush buffers - * to disk that aren't always accessible and can be very expensive. Avoid - * using this function in cases where the file should just work on any - * network filesystem. + * If @a flush_to_disk is non-zero, do not return until the node has + * actually been written on the disk. + * + * @note The flush to disk operation can be very expensive on systems + * that implement flushing on all IO layers, like Windows. Please use + * @a flush_to_disk flag only for critical data. + * + * @since New in 1.10. + */ +svn_error_t * +svn_io_write_atomic2(const char *final_path, + const void *buf, + apr_size_t nbytes, + const char *copy_perms_path, + svn_boolean_t flush_to_disk, + apr_pool_t *scratch_pool); + +/** Similar to svn_io_write_atomic2(), but with @a flush_to_disk set + * to @c TRUE. * * @since New in 1.9. + * + * @deprecated Provided for backward compatibility with the 1.9 API */ +SVN_DEPRECATED svn_error_t * svn_io_write_atomic(const char *final_path, const void *buf, @@ -2332,10 +2466,27 @@ svn_io_stat(apr_finfo_t *finfo, * @a from_path to a new path @a to_path within the same filesystem. * In some cases, an existing node at @a to_path will be overwritten. * - * A wrapper for apr_file_rename(). @a from_path and @a to_path are - * utf8-encoded. + * @a from_path and @a to_path are utf8-encoded. If @a flush_to_disk + * is non-zero, do not return until the node has actually been moved on + * the disk. + * + * @note The flush to disk operation can be very expensive on systems + * that implement flushing on all IO layers, like Windows. Please use + * @a flush_to_disk flag only for critical data. + * + * @since New in 1.10. */ svn_error_t * +svn_io_file_rename2(const char *from_path, const char *to_path, + svn_boolean_t flush_to_disk, apr_pool_t *pool); + +/** Similar to svn_io_file_rename2(), but with @a flush_to_disk set + * to @c FALSE. + * + * @deprecated Provided for backward compatibility with the 1.9 API + */ +SVN_DEPRECATED +svn_error_t * svn_io_file_rename(const char *from_path, const char *to_path, apr_pool_t *pool); diff --git a/subversion/include/svn_props.h b/subversion/include/svn_props.h index e920b03dee6d..7ea8bba0c048 100644 --- a/subversion/include/svn_props.h +++ b/subversion/include/svn_props.h @@ -475,22 +475,42 @@ svn_prop_name_is_valid(const char *prop_name); /** The files' last modification time. * This is stored as string in the form @c "2008-08-07T07:38:51.008782Z", to * be converted by the functions @c svn_time_to_cstring() and - * @c svn_time_from_cstring(). */ + * @c svn_time_from_cstring(). + * + * @note This property name is reserved for future usage, but currently unused. + * + * @since New in 1.6. + */ #define SVN_PROP_TEXT_TIME SVN_PROP_PREFIX "text-time" /** The files' owner. * Stored as numeric ID, optionally followed by whitespace and the string: * @c "1000 pmarek". Parsers @b should accept any number of whitespace, - * and writers @b should put exactly a single space. */ + * and writers @b should put exactly a single space. + * + * @note This property name is reserved for future usage, but currently unused. + * + * @since New in 1.6. + */ #define SVN_PROP_OWNER SVN_PROP_PREFIX "owner" /** The files' group. - * The same format as for @c SVN_PROP_OWNER, the owner-property. */ + * The same format as for @c SVN_PROP_OWNER, the owner-property. + * + * @note This property name is reserved for future usage, but currently unused. + * + * @since New in 1.6. + */ #define SVN_PROP_GROUP SVN_PROP_PREFIX "group" /** The files' unix-mode. * Stored in octal, with a leading @c 0; may have 5 digits if any of @c setuid, - * @c setgid or @c sticky are set; an example is @c "0644". */ + * @c setgid or @c sticky are set; an example is @c "0644". + * + * @note This property name is reserved for future usage, but currently unused. + * + * @since New in 1.6. + */ #define SVN_PROP_UNIX_MODE SVN_PROP_PREFIX "unix-mode" /** @} */ /* Meta-data properties */ diff --git a/subversion/include/svn_ra.h b/subversion/include/svn_ra.h index a3ab672dda92..030458d0e16a 100644 --- a/subversion/include/svn_ra.h +++ b/subversion/include/svn_ra.h @@ -1089,7 +1089,7 @@ svn_ra_get_file(svn_ra_session_t *session, * @a path is interpreted relative to the URL in @a session. * * If @a revision is @c SVN_INVALID_REVNUM (meaning 'head') and - * @a *fetched_rev is not @c NULL, then this function will set + * @a fetched_rev is not @c NULL, then this function will set * @a *fetched_rev to the actual revision that was retrieved. (Some * callers want to know, and some don't.) * @@ -1129,6 +1129,63 @@ svn_ra_get_dir(svn_ra_session_t *session, apr_hash_t **props, apr_pool_t *pool); +/** + * Callback type to be used with svn_ra_list(). It will be invoked for + * every directory entry found. + * + * The full path of the entry is given in @a rel_path and @a dirent contains + * various additional information. Only the elements of @a dirent specified + * by the @a dirent_fields argument to svn_ra_list() will be valid. + * + * @a baton is the user-provided receiver baton. @a scratch_pool may be + * used for temporary allocations. + * + * @since New in 1.10. + */ +typedef svn_error_t *(* svn_ra_dirent_receiver_t)(const char *rel_path, + svn_dirent_t *dirent, + void *baton, + apr_pool_t *scratch_pool); + +/** + * Efficiently list everything within a sub-tree. Specify a glob pattern + * to search for specific files and folders. + * + * In @a session, walk the sub-tree starting at @a path at @a revision down + * to the given @a depth. For each directory entry found, @a receiver will + * be called with @a receiver_baton. The starting @a path will be reported + * as well. Because retrieving elements of a #svn_dirent_t can be + * expensive, you need to select them individually via flags set in + * @a dirent_fields. + * + * @a patterns is an optional array of const char *. If it is + * not @c NULL, only those directory entries will be reported whose last + * path segment matches at least one of these patterns. This feature uses + * apr_fnmatch() for glob matching and requiring '.' to matched by dots + * in the path. + * + * @a path must point to a directory and @a depth must be at least + * #svn_depth_empty. + * + * If the server doesn't support the 'list' command, return + * #SVN_ERR_UNSUPPORTED_FEATURE in preference to any other error that + * might otherwise be returned. + * + * Use @a scratch_pool for temporary memory allocation. + * + * @since New in 1.10. + */ +svn_error_t * +svn_ra_list(svn_ra_session_t *session, + const char *path, + svn_revnum_t revision, + const apr_array_header_t *patterns, + svn_depth_t depth, + apr_uint32_t dirent_fields, + svn_ra_dirent_receiver_t receiver, + void *receiver_baton, + apr_pool_t *scratch_pool); + /** * Set @a *catalog to a mergeinfo catalog for the paths in @a paths. * If no mergeinfo is available, set @a *catalog to @c NULL. The @@ -1550,7 +1607,7 @@ svn_ra_do_diff(svn_ra_session_t *session, * revisions in which at least one of @a paths was changed (i.e., if * file, text or props changed; if dir, props changed or an entry * was added or deleted). Each path is an const char *, relative - * to the @a session's common parent. + * to the repository root of @a session. * * If @a limit is greater than zero only invoke @a receiver on the first * @a limit logs. @@ -1717,9 +1774,10 @@ svn_ra_get_repos_root(svn_ra_session_t *session, /** * Set @a *locations to the locations (at the repository revisions * @a location_revisions) of the file identified by @a path in - * @a peg_revision. @a path is relative to the URL to which - * @a session was opened. @a location_revisions is an array of - * @c svn_revnum_t's. @a *locations will be a mapping from the revisions to + * @a peg_revision (passing @c SVN_INVALID_REVNUM is an error). + * @a path is relative to the URL to which @a session was opened. + * @a location_revisions is an array of @c svn_revnum_t's. + * @a *locations will be a mapping from the revisions to * their appropriate absolute paths. If the file doesn't exist in a * location_revision, that revision will be ignored. * @@ -1966,7 +2024,7 @@ svn_ra_get_locks(svn_ra_session_t *session, /** * Replay the changes from a range of revisions between @a start_revision - * and @a end_revision. + * and @a end_revision (inclusive). * * When receiving information for one revision, a callback @a revstart_func is * called; this callback will provide an editor and baton through which the @@ -2174,6 +2232,13 @@ svn_ra_has_capability(svn_ra_session_t *session, */ #define SVN_RA_CAPABILITY_GET_FILE_REVS_REVERSE "get-file-revs-reversed" +/** + * The capability of a server to understand the list command. + * + * @since New in 1.10. + */ +#define SVN_RA_CAPABILITY_LIST "list" + /* *** PLEASE READ THIS IF YOU ADD A NEW CAPABILITY *** * diff --git a/subversion/include/svn_ra_svn.h b/subversion/include/svn_ra_svn.h index c968e400805f..6293255daba9 100644 --- a/subversion/include/svn_ra_svn.h +++ b/subversion/include/svn_ra_svn.h @@ -49,6 +49,7 @@ extern "C" { /** Currently-defined capabilities. */ #define SVN_RA_SVN_CAP_EDIT_PIPELINE "edit-pipeline" #define SVN_RA_SVN_CAP_SVNDIFF1 "svndiff1" +#define SVN_RA_SVN_CAP_SVNDIFF2_ACCEPTED "accepts-svndiff2" #define SVN_RA_SVN_CAP_ABSENT_ENTRIES "absent-entries" /* maps to SVN_RA_CAPABILITY_COMMIT_REVPROPS: */ #define SVN_RA_SVN_CAP_COMMIT_REVPROPS "commit-revprops" @@ -68,6 +69,8 @@ extern "C" { #define SVN_RA_SVN_CAP_EPHEMERAL_TXNPROPS "ephemeral-txnprops" /* maps to SVN_RA_CAPABILITY_GET_FILE_REVS_REVERSE */ #define SVN_RA_SVN_CAP_GET_FILE_REVS_REVERSE "file-revs-reverse" +/* maps to SVN_RA_CAPABILITY_LIST */ +#define SVN_RA_SVN_CAP_LIST "list" /** ra_svn passes @c svn_dirent_t fields over the wire as a list of @@ -141,16 +144,23 @@ typedef struct svn_ra_svn_cmd_entry_t svn_boolean_t terminate; } svn_ra_svn_cmd_entry_t; +/** Data types defined by the svn:// protocol. + * + * @since The typedef name is new in 1.10; the enumerators are not. */ +typedef enum +{ + SVN_RA_SVN_NUMBER, + SVN_RA_SVN_STRING, + SVN_RA_SVN_WORD, + SVN_RA_SVN_LIST +} svn_ra_svn_item_kind_t; + /** Memory representation of an on-the-wire data item. */ typedef struct svn_ra_svn_item_t { /** Variant indicator. */ - enum { - SVN_RA_SVN_NUMBER, - SVN_RA_SVN_STRING, - SVN_RA_SVN_WORD, - SVN_RA_SVN_LIST - } kind; + svn_ra_svn_item_kind_t kind; + /** Variant data. */ union { apr_uint64_t number; @@ -169,7 +179,9 @@ typedef svn_error_t *(*svn_ra_svn_edit_callback)(void *baton); * * Either @a sock or @a in_stream/@a out_stream must be set, not both. * @a compression_level specifies the desired network data compression - * level (zlib) from 0 (no compression) to 9 (best but slowest). + * level from 0 (no compression) to 9 (best but slowest). The effect + * of the parameter depends on the compression algorithm; for example, + * it is used verbatim by zlib/deflate but ignored by LZ4. * * If @a zero_copy_limit is not 0, cached file contents smaller than the * given limit may be sent directly to the network socket. Otherwise, @@ -184,13 +196,38 @@ typedef svn_error_t *(*svn_ra_svn_edit_callback)(void *baton); * It defines the number of bytes that must have been sent since the last * check before the next check will be made. * + * If @a max_in is not 0, error out and close the connection whenever more + * than @a max_in bytes are received for a command (e.g. a client request). + * If @a max_out is not 0, error out and close the connection whenever more + * than @a max_out bytes have been send as response to some command. + * + * @note The limits enforced may vary slightly by +/- the I/O buffer size. + * * @note If @a out_stream is an wrapped apr_file_t* the backing file will be * used for some operations. * * Allocate the result in @a pool. * - * @since New in 1.9 + * @since New in 1.10 */ +svn_ra_svn_conn_t *svn_ra_svn_create_conn5(apr_socket_t *sock, + svn_stream_t *in_stream, + svn_stream_t *out_stream, + int compression_level, + apr_size_t zero_copy_limit, + apr_size_t error_check_interval, + apr_uint64_t max_in, + apr_uint64_t max_out, + apr_pool_t *result_pool); + + +/** Similar to svn_ra_svn_create_conn5() but with @a max_in and @a max_out + * set to 0. + * + * @since New in 1.9 + * @deprecated Provided for backward compatibility with the 1.9 API. + */ +SVN_DEPRECATED svn_ra_svn_conn_t *svn_ra_svn_create_conn4(apr_socket_t *sock, svn_stream_t *in_stream, svn_stream_t *out_stream, diff --git a/subversion/include/svn_repos.h b/subversion/include/svn_repos.h index 45b7a8fe579b..9bb462abbb3c 100644 --- a/subversion/include/svn_repos.h +++ b/subversion/include/svn_repos.h @@ -244,7 +244,13 @@ typedef enum svn_repos_notify_action_t svn_repos_notify_format_bumped, /** A revision range was copied. @since New in 1.9. */ - svn_repos_notify_hotcopy_rev_range + svn_repos_notify_hotcopy_rev_range, + + /** The repository pack did not do anything. @since New in 1.10. */ + svn_repos_notify_pack_noop, + + /** The revision properties got set. @since New in 1.10. */ + svn_repos_notify_load_revprop_set } svn_repos_notify_action_t; /** The type of warning occurring. @@ -369,6 +375,24 @@ typedef void (*svn_repos_notify_func_t)(void *baton, const svn_repos_notify_t *notify, apr_pool_t *scratch_pool); +/** Callback for filtering repository contents during dump. + * + * Set @a *include to TRUE to indicate that node, identified by path + * @a path in @a root should be included in dump, or set it to @c FALSE + * to indicate that node should be excluded (presumably according to state + * stored in @a baton). + * + * Do not assume @a scratch_pool has any lifetime beyond this call. + * + * @since New in 1.10. + */ +typedef svn_error_t * (*svn_repos_dump_filter_func_t)( + svn_boolean_t *include, + svn_fs_root_t *root, + const char *path, + void *baton, + apr_pool_t *scratch_pool); + /** * Allocate an #svn_repos_notify_t structure in @a result_pool, initialize * and return it. @@ -1701,6 +1725,68 @@ svn_repos_stat(svn_dirent_t **dirent, const char *path, apr_pool_t *pool); +/** + * Callback type to be used with svn_repos_list(). It will be invoked for + * every directory entry found. + * + * The full path of the entry is given in @a path and @a dirent contains + * various additional information. If svn_repos_list() has been called + * with @a path_info_only set, only the @a kind element of this struct + * will be valid. + * + * @a baton is the user-provided receiver baton. @a scratch_pool may be + * used for temporary allocations. + * + * @since New in 1.10. + */ +typedef svn_error_t *(* svn_repos_dirent_receiver_t)(const char *path, + svn_dirent_t *dirent, + void *baton, + apr_pool_t *scratch_pool); + +/** + * Efficiently list everything within a sub-tree. Specify glob patterns + * to search for specific files and folders. + * + * Walk the sub-tree starting at @a path under @a root up to the given + * @a depth. For each directory entry found, @a receiver will be called + * with @a receiver_baton. The starting @a path will be reported as well. + * Because retrieving all elements of a #svn_dirent_t can be expensive, + * you may set @a path_info_only to receive only the path name and the node + * kind. The entries will be reported ordered by their path. + * + * @a patterns is an optional array of const char *. If it is + * not @c NULL, only those directory entries will be reported whose last + * path segment matches at least one of these patterns. This feature uses + * apr_fnmatch() for glob matching and requiring '.' to matched by dots + * in the path. + * + * If @a authz_read_func is not @c NULL, this function will neither report + * entries nor recurse into directories that the user has no access to. + * + * Cancellation support is provided in the usual way through the optional + * @a cancel_func and @a cancel_baton. + * + * @a path must point to a directory and @a depth must be at least + * #svn_depth_empty. + * + * Use @a scratch_pool for temporary memory allocation. + * + * @since New in 1.10. + */ +svn_error_t * +svn_repos_list(svn_fs_root_t *root, + const char *path, + const apr_array_header_t *patterns, + svn_depth_t depth, + svn_boolean_t path_info_only, + svn_repos_authz_func_t authz_read_func, + void *authz_read_baton, + svn_repos_dirent_receiver_t receiver, + void *receiver_baton, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *scratch_pool); /** * Given @a path which exists at revision @a start in @a fs, set @@ -1864,13 +1950,181 @@ svn_repos_node_location_segments(svn_repos_t *repos, /* Retrieving log messages. */ +/** Path change descriptor. + * + * @note Identical to #svn_fs_path_change3_t but with all information + * known, i.e. @a node_kind is never #svn_node_unknown and + * @a copyfrom_known is always @c TRUE. + * + * @note To allow for extending this structure in future releases, + * always use svn_repos_path_change_create() to allocate the stucture. + * + * @see svn_fs_path_change3_t + * + * @since New in 1.10. + */ +typedef svn_fs_path_change3_t svn_repos_path_change_t; /** - * Invoke @a receiver with @a receiver_baton on each log message from - * @a start to @a end in @a repos's filesystem. @a start may be greater - * or less than @a end; this just controls whether the log messages are + * Return an #svn_repos_path_change_t structure, allocated in @a result_pool, + * with all fields initialized to their respective null/none/empty/invalid + * values. + * + * @note To allow for extending the #svn_repos_path_change_t structure in + * future releases, this function should always be used to allocate it. + * + * @since New in 1.10. + */ +svn_repos_path_change_t * +svn_repos_path_change_create(apr_pool_t *result_pool); + +/** + * Return a deep copy of @a change, allocated in @a result_pool. + * + * @since New in 1.10. + */ +svn_repos_path_change_t * +svn_repos_path_change_dup(svn_repos_path_change_t *change, + apr_pool_t *result_pool); + +/** The callback invoked by log message loopers, such as + * svn_repos_get_logs5(). + * + * This function is invoked once on each changed path, in a potentially + * random order that may even change between invocations for the same + * revisions. + * + * @a baton is what you think it is, and @a change contains relevant + * information for the changed path. Please note that @a change may be + * modified within this callback but it will become invalid as soon as + * the callback returns. + * + * Use @a scratch_pool for temporary allocation. The caller may clear it + * between or after invocations. + * + * @since New in 1.10. + */ +typedef svn_error_t *(*svn_repos_path_change_receiver_t)( + void *baton, + svn_repos_path_change_t *change, + apr_pool_t *scratch_pool); + + +/** + * A structure to represent all the information about a particular log entry. + * + * @note To allow for extending this structure in future releases, + * always use svn_repos_log_entry_create() to allocate the stucture. + * + * @since New in 1.10. + */ +typedef struct svn_repos_log_entry_t +{ + /** The revision of the commit. */ + svn_revnum_t revision; + + /** The hash of requested revision properties, which may be NULL if it + * would contain no revprops. Maps (const char *) property name to + * (svn_string_t *) property value. */ + apr_hash_t *revprops; + + /** + * Whether or not this message has children. + * + * When a log operation requests additional merge information, extra log + * entries may be returned as a result of this entry. The new entries, are + * considered children of the original entry, and will follow it. When + * the HAS_CHILDREN flag is set, the receiver should increment its stack + * depth, and wait until an entry is provided with SVN_INVALID_REVNUM which + * indicates the end of the children. + * + * For log operations which do not request additional merge information, the + * HAS_CHILDREN flag is always FALSE. + * + * For more information see: + * https://svn.apache.org/repos/asf/subversion/trunk/notes/merge-tracking/design.html#commutative-reporting + */ + svn_boolean_t has_children; + + /** + * Whether @a revision should be interpreted as non-inheritable in the + * same sense of #svn_merge_range_t. + * + * Currently always FALSE. + */ + svn_boolean_t non_inheritable; + + /** + * Whether @a revision is a merged revision resulting from a reverse merge. + */ + svn_boolean_t subtractive_merge; + + /* NOTE: Add new fields at the end to preserve binary compatibility. */ +} svn_repos_log_entry_t; + +/** + * Return an #svn_repos_log_entry_t, allocated in @a result_pool, + * with all fields initialized to their respective null/none/empty/invalid + * values. + * + * @note To allow for extending the #svn_repos_log_entry_t structure in + * future releases, this function should always be used to allocate it. + * + * @since New in 1.10. + */ +svn_repos_log_entry_t * +svn_repos_log_entry_create(apr_pool_t *result_pool); + +/** Return a deep copy of @a log_entry, allocated in @a result_pool. + * + * @since New in 1.10. + */ +svn_repos_log_entry_t * +svn_repos_log_entry_dup(const svn_repos_log_entry_t *log_entry, + apr_pool_t *result_pool); + + +/** The callback invoked by log message loopers, such as + * svn_repos_get_logs5(). + * + * This function is invoked once on each log message, in the order + * determined by the caller (see above-mentioned functions). + * + * @a baton is what you think it is, and @a log_entry contains relevant + * information for the log message. + * + * If @a log_entry->has_children is @c TRUE, the message will be followed + * immediately by any number of merged revisions (child messages), which are + * terminated by an invocation with SVN_INVALID_REVNUM. This usage may + * be recursive. + * + * Use @a scratch_pool for temporary allocation. The caller may clear it + * between or after invocations. + * + * @since New in 1.10. + */ +typedef svn_error_t *(*svn_repos_log_entry_receiver_t)( + void *baton, + svn_repos_log_entry_t *log_entry, + apr_pool_t *scratch_pool); + + +/** + * Invoke @a revision_receiver with @a revision_receiver_baton on each + * revision from @a start to @a end in @a repos's filesystem. @a start may + * be greater or less than @a end; this just controls whether the log is * processed in descending or ascending revision number order. * + * If not @c NULL, @a path_change_receiver will be invoked with + * @a path_change_receiver_baton for each changed path in the respective + * revision. These changes will be reported before the @a revision_receiver + * is invoked for that revision. So, for each revision in the log, there + * is a number of calls to @a path_change_receiver followed by a single + * invocation of @a revision_receiver, implicitly marking the end of the + * changes list for that revision. If a revision does not contain any + * changes (or if none are visible due to @a authz_read_func), + * @a path_change_receiver will not be called for that revision. + * * If @a start or @a end is #SVN_INVALID_REVNUM, it defaults to youngest. * * If @a paths is non-NULL and has one or more elements, then only show @@ -1881,13 +2135,8 @@ svn_repos_node_location_segments(svn_repos_t *repos, * show all revisions regardless of what paths were changed in those * revisions. * - * If @a limit is greater than zero then only invoke @a receiver on the first - * @a limit logs. - * - * If @a discover_changed_paths, then each call to @a receiver passes a - * hash mapping paths committed in that revision to information about them - * as the receiver's @a changed_paths argument. - * Otherwise, each call to @a receiver passes NULL for @a changed_paths. + * If @a limit is greater than zero then only invoke @a revision_receiver + * on the first @a limit logs. * * If @a strict_node_history is set, copy history (if any exists) will * not be traversed while harvesting revision logs for each path. @@ -1902,28 +2151,64 @@ svn_repos_node_location_segments(svn_repos_t *repos, * only the revision properties named by the (const char *) array elements * (i.e. retrieve none if the array is empty). * - * If any invocation of @a receiver returns error, return that error - * immediately and without wrapping it. + * If any invocation of @a revision_receiver or @a path_change_receiver + * returnn an error, return that error immediately and without wrapping it. * * If @a start or @a end is a non-existent revision, return the error - * #SVN_ERR_FS_NO_SUCH_REVISION, without ever invoking @a receiver. + * #SVN_ERR_FS_NO_SUCH_REVISION, without ever invoking @a revision_receiver. * * If optional @a authz_read_func is non-NULL, then use this function * (along with optional @a authz_read_baton) to check the readability * of each changed-path in each revision about to be "pushed" at - * @a receiver. If a revision has some changed-paths readable and - * others unreadable, unreadable paths are omitted from the - * changed_paths field and only svn:author and svn:date will be - * available in the revprops field. If a revision has no - * changed-paths readable at all, then all paths are omitted and no - * revprops are available. + * @a path_change_receiver. If a revision has some changed-paths readable + * and others unreadable, unreadable paths are omitted from the + * @a path_change_receiver invocations and only svn:author and svn:date + * will be available in the revprops field in the @a revision_receiver + * callback. If a revision has no changed-paths readable at all, then all + * paths are omitted and no revprops are available. If + * @a path_change_receiver is @c NULL, the same filtering is performed + * just without reporting any path changes. * - * See also the documentation for #svn_log_entry_receiver_t. + * Use @a scratch_pool for temporary allocations. * - * Use @a pool for temporary allocations. + * @see svn_repos_path_change_receiver_t, svn_repos_log_entry_receiver_t + * + * @since New in 1.10. + */ +svn_error_t * +svn_repos_get_logs5(svn_repos_t *repos, + const apr_array_header_t *paths, + svn_revnum_t start, + svn_revnum_t end, + int limit, + svn_boolean_t strict_node_history, + svn_boolean_t include_merged_revisions, + const apr_array_header_t *revprops, + svn_repos_authz_func_t authz_read_func, + void *authz_read_baton, + svn_repos_path_change_receiver_t path_change_receiver, + void *path_change_receiver_baton, + svn_repos_log_entry_receiver_t revision_receiver, + void *revision_receiver_baton, + apr_pool_t *scratch_pool); + +/** + * Similar to svn_repos_get_logs5 but using a #svn_log_entry_receiver_t + * @a receiver to receive revision properties and changed paths through a + * single callback and the @a discover_changed_paths flag to control it. + * + * If @a discover_changed_paths, then each call to @a receiver passes a + * hash mapping paths committed in that revision to information about them + * as the receiver's @a changed_paths argument. + * Otherwise, each call to @a receiver passes NULL for @a changed_paths. + * + * @see svn_log_entry_receiver_t * * @since New in 1.5. + * + * @deprecated Provided for backward compatibility with the 1.9 API. */ +SVN_DEPRECATED svn_error_t * svn_repos_get_logs4(svn_repos_t *repos, const apr_array_header_t *paths, @@ -2009,12 +2294,20 @@ svn_repos_get_logs(svn_repos_t *repos, /* Retrieving mergeinfo. */ -/** - * Fetch the mergeinfo for @a paths at @a revision in @a repos, and - * set @a *catalog to a catalog of this mergeinfo. @a *catalog will - * never be @c NULL but may be empty. +/** Receives parsed @a mergeinfo for the file system path @a path. * - * The paths in @a paths, and the keys of @a catalog, start with '/'. + * The user-provided @a baton is being passed through by the retrieval + * function and @a scratch_pool will be cleared between invocations. + * + * @since New in 1.10. + */ +typedef svn_fs_mergeinfo_receiver_t svn_repos_mergeinfo_receiver_t; + +/** + * For each node found with mergeinfo on it, invoke @a receiver with + * the provided @a receiver_baton. + * + * The paths in @a paths start with '/'. * * @a inherit indicates whether explicit, explicit or inherited, or * only inherited mergeinfo for @a paths is fetched. @@ -2026,17 +2319,38 @@ svn_repos_get_logs(svn_repos_t *repos, * the #SVN_PROP_MERGEINFO property explicitly set on it. (Note * that inheritance is only taken into account for the elements in @a * paths; descendants of the elements in @a paths which get their - * mergeinfo via inheritance are not included in @a *catalog.) + * mergeinfo via inheritance are not reported to @a receiver.) * * If optional @a authz_read_func is non-NULL, then use this function * (along with optional @a authz_read_baton) to check the readability * of each path which mergeinfo was requested for (from @a paths). * Silently omit unreadable paths from the request for mergeinfo. * - * Use @a pool for all allocations. + * Use @a scratch_pool for temporary allocations. + * + * @since New in 1.10. + */ +svn_error_t * +svn_repos_fs_get_mergeinfo2(svn_repos_t *repos, + const apr_array_header_t *paths, + svn_revnum_t revision, + svn_mergeinfo_inheritance_t inherit, + svn_boolean_t include_descendants, + svn_repos_authz_func_t authz_read_func, + void *authz_read_baton, + svn_repos_mergeinfo_receiver_t receiver, + void *receiver_baton, + apr_pool_t *scratch_pool); + +/** + * Same as svn_repos_fs_get_mergeinfo2(), but all mergeinfo is being collected + * and returned in @a *catalog. It will never be @c NULL, but may be empty. * * @since New in 1.5. + * + * @deprecated Provided for backward compatibility with the 1.9 API. */ +SVN_DEPRECATED svn_error_t * svn_repos_fs_get_mergeinfo(svn_mergeinfo_catalog_t *catalog, svn_repos_t *repos, @@ -2983,6 +3297,12 @@ svn_repos_verify_fs(svn_repos_t *repos, * be done with full plain text. A dump with @a use_deltas set cannot * be loaded by Subversion 1.0.x. * + * If @a include_revprops is @c TRUE, output the revision properties as + * well, otherwise omit them. + * + * If @a include_changes is @c TRUE, output the revision contents, i.e. + * tree and node changes. + * * If @a notify_func is not null, then call it with @a notify_baton and * with a notification structure in which the fields are set as follows. * (For a warning or error notification that does not apply to a specific @@ -3008,15 +3328,44 @@ svn_repos_verify_fs(svn_repos_t *repos, * reiterating the existence of previous warnings * ### This is a presentation issue. Caller could do this itself. * + * If @a filter_func is not @c NULL, it is called for each node being + * dumped, allowing the caller to exclude it from dump. + * * If @a cancel_func is not @c NULL, it is called periodically with * @a cancel_baton as argument to see if the client wishes to cancel * the dump. * * Use @a scratch_pool for temporary allocation. * - * @since New in 1.7. + * @since New in 1.10. */ svn_error_t * +svn_repos_dump_fs4(svn_repos_t *repos, + svn_stream_t *stream, + svn_revnum_t start_rev, + svn_revnum_t end_rev, + svn_boolean_t incremental, + svn_boolean_t use_deltas, + svn_boolean_t include_revprops, + svn_boolean_t include_changes, + svn_repos_notify_func_t notify_func, + void *notify_baton, + svn_repos_dump_filter_func_t filter_func, + void *filter_baton, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *pool); + +/** + * Similar to svn_repos_dump_fs4(), but with @a include_revprops and + * @a include_changes both set to @c TRUE and @a filter_func and + * @a filter_baton set to @c NULL. + * + * @since New in 1.7. + * @deprecated Provided for backward compatibility with the 1.9 API. + */ +SVN_DEPRECATED +svn_error_t * svn_repos_dump_fs3(svn_repos_t *repos, svn_stream_t *dumpstream, svn_revnum_t start_rev, @@ -3111,6 +3460,15 @@ svn_repos_dump_fs(svn_repos_t *repos, * to be stamped as if they were newly created via the normal commit * process. * + * If @a normalize_props is set, attempt to normalize invalid Subversion + * revision and node properties (those in the svn: namespace) so that + * their values would follow the established rules for them. For example, + * for such properties, typically the value must be in UTF-8 with LF + * line endings. + * + * @note The details or the performed normalizations are deliberately + * left unspecified and may change in the future. + * * If non-NULL, use @a notify_func and @a notify_baton to send notification * of events to the caller. * @@ -3118,9 +3476,35 @@ svn_repos_dump_fs(svn_repos_t *repos, * @a cancel_baton as argument to see if the client wishes to cancel * the load. * - * @since New in 1.9. + * @since New in 1.10. */ svn_error_t * +svn_repos_load_fs6(svn_repos_t *repos, + svn_stream_t *dumpstream, + svn_revnum_t start_rev, + svn_revnum_t end_rev, + enum svn_repos_load_uuid uuid_action, + const char *parent_dir, + svn_boolean_t use_pre_commit_hook, + svn_boolean_t use_post_commit_hook, + svn_boolean_t validate_props, + svn_boolean_t ignore_dates, + svn_boolean_t normalize_props, + svn_repos_notify_func_t notify_func, + void *notify_baton, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *pool); + +/** + * Similar to svn_repos_load_fs6(), but with the @a normalize_props + * parameter always set to @c FALSE. + * + * @since New in 1.9. + * @deprecated Provided for backward compatibility with the 1.9 API. + */ +SVN_DEPRECATED +svn_error_t * svn_repos_load_fs5(svn_repos_t *repos, svn_stream_t *dumpstream, svn_revnum_t start_rev, @@ -3219,6 +3603,62 @@ svn_repos_load_fs(svn_repos_t *repos, void *cancel_baton, apr_pool_t *pool); +/** + * Read and parse dumpfile-formatted @a dumpstream, extracting the + * revision properties from it and apply them to the already-open + * @a repos. Use @a scratch_pool for temporary allocations. + * + * If, after filtering by the @a start_rev and @a end_rev, the dumpstream + * contains revisions missing in @a repos, an error will be thrown. + * + * @a start_rev and @a end_rev act as filters, the lower and upper + * (inclusive) range values of revisions in @a dumpstream which will + * be loaded. Either both of these values are #SVN_INVALID_REVNUM (in + * which case no revision-based filtering occurs at all), or both are + * valid revisions (where @a start_rev is older than or equivalent to + * @a end_rev). + * + * If @a validate_props is set, then validate Subversion revision + * properties (those in the svn: namespace) against established + * rules for those things. + * + * If @a ignore_dates is set, ignore any revision datestamps found in + * @a dumpstream, keeping whatever timestamps the revisions currently + * have. + * + * If @a normalize_props is set, attempt to normalize invalid Subversion + * revision and node properties (those in the svn: namespace) so that + * their values would follow the established rules for them. For example, + * for such properties, typically the value must be in UTF-8 with LF + * line endings. + * + * @note The details or the performed normalizations are deliberately + * left unspecified and may change in the future. + * + * If non-NULL, use @a notify_func and @a notify_baton to send notification + * of events to the caller. + * + * If @a cancel_func is not @c NULL, it is called periodically with + * @a cancel_baton as argument to see if the client wishes to cancel + * the load. + * + * @remark No repository hooks will be triggered. + * + * @since New in 1.10. + */ +svn_error_t * +svn_repos_load_fs_revprops(svn_repos_t *repos, + svn_stream_t *dumpstream, + svn_revnum_t start_rev, + svn_revnum_t end_rev, + svn_boolean_t validate_props, + svn_boolean_t ignore_dates, + svn_boolean_t normalize_props, + svn_repos_notify_func_t notify_func, + void *notify_baton, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *scratch_pool); /** * A vtable that is driven by svn_repos_parse_dumpstream3(). @@ -3362,6 +3802,9 @@ typedef struct svn_repos_parse_fns3_t * could stop reading entirely after the youngest required rev. * * @since New in 1.8. + + * @since Starting in 1.10, @a parse_fns may contain #NULL pointers for + * those callbacks that the caller is not interested in. */ svn_error_t * svn_repos_parse_dumpstream3(svn_stream_t *stream, @@ -3414,13 +3857,48 @@ svn_repos_parse_dumpstream3(svn_stream_t *stream, * to be stamped as if they were newly created via the normal commit * process. * + * If @a normalize_props is set, attempt to normalize invalid Subversion + * revision and node properties (those in the svn: namespace) so that + * their values would follow the established rules for them. For example, + * for such properties, typically the value must be in UTF-8 with LF + * line endings. + * + * @note The details or the performed normalizations are deliberately + * left unspecified and may change in the future. + * * If @a parent_dir is not NULL, then the parser will reparent all the * loaded nodes, from root to @a parent_dir. The directory @a parent_dir * must be an existing directory in the repository. * - * @since New in 1.9. + * @since New in 1.10. */ svn_error_t * +svn_repos_get_fs_build_parser6(const svn_repos_parse_fns3_t **parser, + void **parse_baton, + svn_repos_t *repos, + svn_revnum_t start_rev, + svn_revnum_t end_rev, + svn_boolean_t use_history, + svn_boolean_t validate_props, + enum svn_repos_load_uuid uuid_action, + const char *parent_dir, + svn_boolean_t use_pre_commit_hook, + svn_boolean_t use_post_commit_hook, + svn_boolean_t ignore_dates, + svn_boolean_t normalize_props, + svn_repos_notify_func_t notify_func, + void *notify_baton, + apr_pool_t *pool); + +/** + * Similar to svn_repos_get_fs_build_parser6(), but with the + * @a normalize_props parameter always set to @c FALSE. + * + * @since New in 1.9. + * @deprecated Provided for backward compatibility with the 1.9 API. + */ +SVN_DEPRECATED +svn_error_t * svn_repos_get_fs_build_parser5(const svn_repos_parse_fns3_t **parser, void **parse_baton, svn_repos_t *repos, @@ -3654,6 +4132,17 @@ svn_repos_get_fs_build_parser(const svn_repos_parser_fns_t **parser, */ typedef struct svn_authz_t svn_authz_t; +/** + * This should be called before any other authz function. + * + * @a pool must support multi-threaded access if the application will use + * authz from multiple threads. + * + * @since New in 1.10. + */ +svn_error_t * +svn_repos_authz_initialize(apr_pool_t *pool); + /** * Read authz configuration data from @a path (a dirent, an absolute file url * or a registry path) into @a *authz_p, allocated in @a pool. @@ -3667,9 +4156,30 @@ typedef struct svn_authz_t svn_authz_t; * is also an error other than #SVN_ERR_AUTHZ_INVALID_CONFIG (exact error * depends on the access type). * - * @since New in 1.8. + * For efficient access of in-repository authz, you may provide @a repos_hint + * which will be tried first and may remove the need to open a temporary + * repository instance. Otherwise, set it to NULL and the repositories will + * be opened as needed. + * + * @since New in 1.10. */ svn_error_t * +svn_repos_authz_read3(svn_authz_t **authz_p, + const char *path, + const char *groups_path, + svn_boolean_t must_exist, + svn_repos_t *repos_hint, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/** + * Similar to svn_repos_authz_read3(), but with @a repos_hint set to @c NULL. + * + * @since New in 1.8. + * @deprecated Provided for backward compatibility with the 1.9 API. + */ +SVN_DEPRECATED +svn_error_t * svn_repos_authz_read2(svn_authz_t **authz_p, const char *path, const char *groups_path, diff --git a/subversion/include/svn_string.h b/subversion/include/svn_string.h index 82c6fd693e20..9b0cf5cf7f8f 100644 --- a/subversion/include/svn_string.h +++ b/subversion/include/svn_string.h @@ -294,6 +294,14 @@ svn_stringbuf_isempty(const svn_stringbuf_t *str); void svn_stringbuf_chop(svn_stringbuf_t *str, apr_size_t nbytes); +/** + * Chop @a nbytes bytes off the start of @a str, but not more than @a str->len. + * + * @since New in 1.10. + */ +void +svn_stringbuf_leftchop(svn_stringbuf_t *str, apr_size_t nbytes); + /** Fill @a str with character @a c. */ void svn_stringbuf_fillchar(svn_stringbuf_t *str, unsigned char c); @@ -404,6 +412,16 @@ svn_stringbuf_replace(svn_stringbuf_t *str, const char *bytes, apr_size_t new_count); +/** Replace all occurrences of @a to_find in @a str with @a replacement. + * Return the number of replacements made. + * + * @since New in 1.10. + */ +apr_size_t +svn_stringbuf_replace_all(svn_stringbuf_t *str, + const char *to_find, + const char *replacement); + /** Return a duplicate of @a original_string. */ svn_stringbuf_t * svn_stringbuf_dup(const svn_stringbuf_t *original_string, apr_pool_t *pool); @@ -512,12 +530,27 @@ svn_cstring_count_newlines(const char *msg); /** * Return a cstring which is the concatenation of @a strings (an array - * of char *) each followed by @a separator (that is, @a separator - * will also end the resulting string). Allocate the result in @a pool. + * of char *) joined by @a separator. Allocate the result in @a pool. * If @a strings is empty, then return the empty string. + * If @a trailing_separator is non-zero, also append the separator + * after the last joined element. + * + * @since New in 1.10. + */ +char * +svn_cstring_join2(const apr_array_header_t *strings, + const char *separator, + svn_boolean_t trailing_separator, + apr_pool_t *pool); + +/** + * Similar to svn_cstring_join2(), but always includes the trailing + * separator. * * @since New in 1.2. + * @deprecated Provided for backwards compatibility with the 1.9 API. */ +SVN_DEPRECATED char * svn_cstring_join(const apr_array_header_t *strings, const char *separator, @@ -541,7 +574,17 @@ svn_cstring_casecmp(const char *str1, const char *str2); * Assume that the number is represented in base @a base. * Raise an error if conversion fails (e.g. due to overflow), or if the * converted number is smaller than @a minval or larger than @a maxval. + * * Leading whitespace in @a str is skipped in a locale-dependent way. + * After that, the string may contain an optional '+' (positive, default) + * or '-' (negative) character, followed by an optional '0x' prefix if + * @a base is 0 or 16, followed by numeric digits appropriate for the base. + * If there are any more characters after the numeric digits, an error is + * returned. + * + * If @a base is zero, then a leading '0x' or '0X' prefix means hexadecimal, + * else a leading '0' means octal (implemented, though not documented, in + * apr_strtoi64() in APR 0.9.0 through 1.5.0), else use base ten. * * @since New in 1.7. */ @@ -554,7 +597,8 @@ svn_cstring_strtoi64(apr_int64_t *n, const char *str, * Parse the C string @a str into a 64 bit number, and return it in @a *n. * Assume that the number is represented in base 10. * Raise an error if conversion fails (e.g. due to overflow). - * Leading whitespace in @a str is skipped in a locale-dependent way. + * + * The behaviour otherwise is as described for svn_cstring_strtoi64(). * * @since New in 1.7. */ @@ -565,7 +609,8 @@ svn_cstring_atoi64(apr_int64_t *n, const char *str); * Parse the C string @a str into a 32 bit number, and return it in @a *n. * Assume that the number is represented in base 10. * Raise an error if conversion fails (e.g. due to overflow). - * Leading whitespace in @a str is skipped in a locale-dependent way. + * + * The behaviour otherwise is as described for svn_cstring_strtoi64(). * * @since New in 1.7. */ @@ -577,7 +622,21 @@ svn_cstring_atoi(int *n, const char *str); * it in @a *n. Assume that the number is represented in base @a base. * Raise an error if conversion fails (e.g. due to overflow), or if the * converted number is smaller than @a minval or larger than @a maxval. + * * Leading whitespace in @a str is skipped in a locale-dependent way. + * After that, the string may contain an optional '+' (positive, default) + * or '-' (negative) character, followed by an optional '0x' prefix if + * @a base is 0 or 16, followed by numeric digits appropriate for the base. + * If there are any more characters after the numeric digits, an error is + * returned. + * + * If @a base is zero, then a leading '0x' or '0X' prefix means hexadecimal, + * else a leading '0' means octal (implemented, though not documented, in + * apr_strtoi64() in APR 0.9.0 through 1.5.0), else use base ten. + * + * @warning The implementation used since version 1.7 returns an error + * if the parsed number is greater than APR_INT64_MAX, even if it is not + * greater than @a maxval. * * @since New in 1.7. */ @@ -590,7 +649,9 @@ svn_cstring_strtoui64(apr_uint64_t *n, const char *str, * Parse the C string @a str into an unsigned 64 bit number, and return * it in @a *n. Assume that the number is represented in base 10. * Raise an error if conversion fails (e.g. due to overflow). - * Leading whitespace in @a str is skipped in a locale-dependent way. + * + * The behaviour otherwise is as described for svn_cstring_strtoui64(), + * including the upper limit of APR_INT64_MAX. * * @since New in 1.7. */ @@ -601,7 +662,9 @@ svn_cstring_atoui64(apr_uint64_t *n, const char *str); * Parse the C string @a str into an unsigned 32 bit number, and return * it in @a *n. Assume that the number is represented in base 10. * Raise an error if conversion fails (e.g. due to overflow). - * Leading whitespace in @a str is skipped in a locale-dependent way. + * + * The behaviour otherwise is as described for svn_cstring_strtoui64(), + * including the upper limit of APR_INT64_MAX. * * @since New in 1.7. */ diff --git a/subversion/include/svn_types.h b/subversion/include/svn_types.h index f1a0850bcf8a..394eda866937 100644 --- a/subversion/include/svn_types.h +++ b/subversion/include/svn_types.h @@ -416,7 +416,7 @@ svn_tristate__from_word(const char * word); * 2. Creating a new textual name similar to * SVN_SUBST__SPECIAL_LINK_STR in libsvn_subr/subst.c. * 3. Handling the translation/detranslation case for the new type in - * create_special_file and detranslate_special_file, using the + * create_special_file_from_stream and detranslate_special_file, using the * routines from 1. */ @@ -652,7 +652,7 @@ typedef struct svn_dirent_t /** node kind */ svn_node_kind_t kind; - /** length of file text, or 0 for directories */ + /** length of file text, otherwise SVN_INVALID_FILESIZE */ svn_filesize_t size; /** does the node have props? */ @@ -1078,6 +1078,11 @@ typedef svn_error_t *(*svn_log_message_receiver_t)( * @a commit_info, along with the @a baton closure. * @a pool can be used for temporary allocations. * + * @note Implementers of this callback that pass this callback to + * svn_ra_get_commit_editor3() should be careful with returning errors + * as these might be returned as commit errors. See the documentation + * of svn_ra_get_commit_editor3() for more details. + * * @since New in 1.4. */ typedef svn_error_t *(*svn_commit_callback2_t)( diff --git a/subversion/include/svn_user.h b/subversion/include/svn_user.h index 65e28200b6d0..922fdcf0a175 100644 --- a/subversion/include/svn_user.h +++ b/subversion/include/svn_user.h @@ -45,6 +45,9 @@ svn_user_get_name(apr_pool_t *pool); * any necessary allocation, returning NULL on error. * * @since New in 1.4. + * @since 1.10 returns a canonical path. Earlier versions returned a + * non-canonical path if the operating system reported a non-canonical + * path such as "/home/user/" or "//home/user". */ const char * svn_user_get_homedir(apr_pool_t *pool); diff --git a/subversion/include/svn_version.h b/subversion/include/svn_version.h index 39f7154847e5..9c88b5b2f71d 100644 --- a/subversion/include/svn_version.h +++ b/subversion/include/svn_version.h @@ -61,7 +61,7 @@ extern "C" { * Modify when new functionality is added or new interfaces are * defined, but all changes are backward compatible. */ -#define SVN_VER_MINOR 9 +#define SVN_VER_MINOR 10 /** * Patch number. @@ -70,7 +70,7 @@ extern "C" { * * @since New in 1.1. */ -#define SVN_VER_PATCH 7 +#define SVN_VER_PATCH 0 /** @deprecated Provided for backward compatibility with the 1.0 API. */ @@ -93,7 +93,7 @@ extern "C" { * * Always change this at the same time as SVN_VER_NUMTAG. */ -#define SVN_VER_TAG " (r1800392)" +#define SVN_VER_TAG " (r1827917)" /** Number tag: a string describing the version. @@ -117,7 +117,7 @@ extern "C" { * file version. Its value remains 0 in the repository except in release * tags where it is the revision from which the tag was created. */ -#define SVN_VER_REVISION 1800392 +#define SVN_VER_REVISION 1827917 /* Version strings composed from the above definitions. */ diff --git a/subversion/include/svn_wc.h b/subversion/include/svn_wc.h index 010597bd6eeb..e632673e0ae4 100644 --- a/subversion/include/svn_wc.h +++ b/subversion/include/svn_wc.h @@ -998,7 +998,10 @@ typedef enum svn_wc_notify_action_t /** A revert operation has failed. */ svn_wc_notify_failed_revert, - /** Resolving a conflict. */ + /** All conflicts on a path were marked as resolved. + * @note As of 1.10, separate notifications are sent for individually + * resolved text, property, and tree conflicts. This notification is used + * only if all conflicts on a path were marked resolved at once. */ svn_wc_notify_resolved, /** Skipping a path. */ @@ -1274,7 +1277,34 @@ typedef enum svn_wc_notify_action_t /** Finalizing commit. * @since New in 1.9. */ - svn_wc_notify_commit_finalizing + svn_wc_notify_commit_finalizing, + + /** All text conflicts in a file were marked as resolved. + * @since New in 1.10. */ + svn_wc_notify_resolved_text, + + /** A property conflict on a path was marked as resolved. + * The name of the property is specified in #svn_wc_notify_t.prop_name. + * @since New in 1.10. */ + svn_wc_notify_resolved_prop, + + /** A tree conflict on a path was marked as resolved. + * @since New in 1.10. */ + svn_wc_notify_resolved_tree, + + /** Starting to search the repository for details about a tree conflict. + * @since New in 1.10. */ + svn_wc_notify_begin_search_tree_conflict_details, + + /** Progressing in search of repository for details about a tree conflict. + * The revision being searched is specified in #svn_wc_notify_t.revision. + * @since New in 1.10. */ + svn_wc_notify_tree_conflict_details_progress, + + /** Done searching the repository for details about a conflict. + * @since New in 1.10. */ + svn_wc_notify_end_search_tree_conflict_details + } svn_wc_notify_action_t; @@ -1911,8 +1941,9 @@ typedef struct svn_wc_conflict_description_t /** The path that is in conflict (for a tree conflict, it is the victim) */ const char *path; - /** The node type of the path being operated on (for a tree conflict, - * ### which version?) */ + /** The local node type of the path being operated on (for a tree conflict, + * this specifies the local node kind, which may be (and typically is) + * different than the left and right kind) */ svn_node_kind_t node_kind; /** What sort of conflict are we describing? */ @@ -2063,7 +2094,7 @@ svn_wc_conflict_description_create_prop(const char *path, * * Set the @c local_abspath field of the created struct to @a local_abspath * (which must be an absolute path), the @c kind field to - * #svn_wc_conflict_kind_tree, the @c local_node_kind to @a local_node_kind, + * #svn_wc_conflict_kind_tree, the @c node_kind to @a node_kind, * the @c operation to @a operation, the @c src_left_version field to * @a src_left_version, and the @c src_right_version field to * @a src_right_version. @@ -2131,8 +2162,11 @@ svn_wc__conflict_description2_dup( */ typedef enum svn_wc_conflict_choice_t { - /** Undefined; for internal use only. - This value is never returned in svn_wc_conflict_result_t. + /** Undefined; for private use only. + This value must never be returned in svn_wc_conflict_result_t, + but a separate value, unequal to all other pre-defined values may + be useful in conflict resolver implementations to signal that no + choice is made yet. * @since New in 1.9 */ svn_wc_conflict_choose_undefined = -1, @@ -4544,7 +4578,7 @@ svn_wc_move(svn_wc_context_t *wc_ctx, * and everything below @a local_abspath. * * If @a keep_local is FALSE, this function immediately deletes all files, - * modified and unmodified, versioned and of @a delete_unversioned is TRUE, + * modified and unmodified, versioned and if @a delete_unversioned is TRUE, * unversioned from the working copy. * It also immediately deletes unversioned directories and directories that * are scheduled to be added below @a local_abspath. Only versioned may @@ -5050,7 +5084,11 @@ svn_wc_remove_from_revision_control(svn_wc_adm_access_t *adm_access, * Temporary allocations will be performed in @a scratch_pool. * * @since New in 1.7. + * @deprecated Provided for backward compatibility with the 1.9 API. + * Use svn_client_conflict_text_resolve(), svn_client_conflict_prop_resolve(), + * and svn_client_conflict_tree_resolve() instead. */ +SVN_DEPRECATED svn_error_t * svn_wc_resolved_conflict5(svn_wc_context_t *wc_ctx, const char *local_abspath, diff --git a/subversion/include/svn_x509.h b/subversion/include/svn_x509.h index eabe3ed46c8b..e3cb7941d357 100644 --- a/subversion/include/svn_x509.h +++ b/subversion/include/svn_x509.h @@ -166,7 +166,7 @@ svn_x509_certinfo_get_valid_from(const svn_x509_certinfo_t *certinfo); * * @since New in 1.9. */ -const apr_time_t +apr_time_t svn_x509_certinfo_get_valid_to(const svn_x509_certinfo_t *certinfo); /** @@ -188,7 +188,7 @@ svn_x509_certinfo_get_hostnames(const svn_x509_certinfo_t *certinfo); * Given an @a oid return a null-terminated C string representation. * For example an OID with the bytes "\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01" * would be converted to the string "1.2.840.113549.1.9.1". Returns - * NULL if the @oid can't be represented as a string. + * NULL if the @a oid can't be represented as a string. * * @since New in 1.9. */ const char * diff --git a/subversion/include/svn_xml.h b/subversion/include/svn_xml.h index 8791b143750c..1a52166feaea 100644 --- a/subversion/include/svn_xml.h +++ b/subversion/include/svn_xml.h @@ -169,7 +169,15 @@ typedef void (*svn_xml_char_data)(void *baton, apr_size_t len); -/** Create a general Subversion XML parser */ +/** Create a general Subversion XML parser. + * + * The @c svn_xml_parser_t object itself will be allocated from @a pool, + * but some internal structures may be allocated out of pool. Use + * svn_xml_free_parser() to free all memory used by the parser. + * + * @since Since Subversion 1.10 parser will be freed automatically on pool + * cleanup or by svn_xml_free_parser() call. + */ svn_xml_parser_t * svn_xml_make_parser(void *baton, svn_xml_start_elem start_handler, diff --git a/subversion/libsvn_auth_gnome_keyring/gnome_keyring.c b/subversion/libsvn_auth_gnome_keyring/gnome_keyring.c index 030023a72b47..0e77586e051e 100644 --- a/subversion/libsvn_auth_gnome_keyring/gnome_keyring.c +++ b/subversion/libsvn_auth_gnome_keyring/gnome_keyring.c @@ -23,31 +23,169 @@ /* ==================================================================== */ - /*** Includes. ***/ - #include #include -#include -#include - #include "svn_auth.h" -#include "svn_config.h" -#include "svn_error.h" #include "svn_hash.h" -#include "svn_pools.h" - +#include "svn_version.h" #include "private/svn_auth_private.h" - #include "svn_private_config.h" +#ifdef SVN_HAVE_LIBSECRET - -/*-----------------------------------------------------------------------*/ -/* GNOME Keyring simple provider, puts passwords in GNOME Keyring */ -/*-----------------------------------------------------------------------*/ +#include +/* Return TRUE if the default collection is available and FALSE + otherwise. In interactive mode the collection only has to exist to + be available, it can be locked or unlocked. The default collection + will be created if necessary. + + In non-interactive mode the collection is only available if it + already exists and is unlocked. Such an available collection can + be used without prompting. Strictly this is racy: nothing ensures + the collection remains unlocked. A similar issue affects the + KWallet and original GNOME Keyring providers. + + As a non-racy alternative one could override prompt_async in the + _SecretServiceClass vtable, the get/set would still fail but there + would be no prompt and no race. This "works" but it is not clear + to me whether it is legitimate since the SecretService is a + singleton and the effect would be application-wide. + */ +static svn_boolean_t +available_collection(svn_boolean_t non_interactive, + apr_pool_t *pool) +{ + GError *gerror = NULL; + SecretService *service = NULL; + SecretCollection *collection = NULL; + + service = secret_service_get_sync(SECRET_SERVICE_NONE, NULL, &gerror); + if (gerror || !service) + goto error_return; + + collection = secret_collection_for_alias_sync(service, + SECRET_COLLECTION_DEFAULT, + SECRET_COLLECTION_NONE, + NULL, &gerror); + if (gerror) + goto error_return; + + if (!collection) + { + if (non_interactive) + goto error_return; + + /* "Default" is the label used by the old libgnome-keyring. */ + collection = secret_collection_create_sync(service, "Default", + SECRET_COLLECTION_DEFAULT, + 0, NULL, &gerror); + if (gerror || !collection) + goto error_return; + } + + if (non_interactive && secret_collection_get_locked(collection)) + goto error_return; + + g_object_unref(collection); + g_object_unref(service); + + return TRUE; + + error_return: + if (gerror) + g_error_free(gerror); + if (collection) + g_object_unref(collection); + if (service) + g_object_unref(service); + return FALSE; +} + +/* Implementation of svn_auth__password_get_t that retrieves the password + using libsecret. */ +static svn_error_t * +password_get_gnome_keyring(svn_boolean_t *done, + const char **password, + apr_hash_t *creds, + const char *realmstring, + const char *username, + apr_hash_t *parameters, + svn_boolean_t non_interactive, + apr_pool_t *pool) +{ + GError *gerror = NULL; + gchar *gpassword; + + if (!available_collection(non_interactive, pool)) + return SVN_NO_ERROR; + + gpassword = secret_password_lookup_sync(SECRET_SCHEMA_COMPAT_NETWORK, NULL, + &gerror, + "domain", realmstring, + "user", username, + NULL); + if (gerror) + { + g_error_free(gerror); + } + else if (gpassword) + { + *password = apr_pstrdup(pool, gpassword); + g_free(gpassword); + *done = TRUE; + } + + return SVN_NO_ERROR; +} + +/* Implementation of svn_auth__password_set_t that stores the password + using libsecret. */ +static svn_error_t * +password_set_gnome_keyring(svn_boolean_t *done, + apr_hash_t *creds, + const char *realmstring, + const char *username, + const char *password, + apr_hash_t *parameters, + svn_boolean_t non_interactive, + apr_pool_t *pool) +{ + GError *gerror = NULL; + gboolean gstatus; + + if (!available_collection(non_interactive, pool)) + return SVN_NO_ERROR; + + /* "network password" is the label used by the old libgnome-keyring. */ + gstatus = secret_password_store_sync(SECRET_SCHEMA_COMPAT_NETWORK, + SECRET_COLLECTION_DEFAULT, + "network password", + password, + NULL, &gerror, + "domain", realmstring, + "user", username, + NULL); + if (gerror) + { + g_error_free(gerror); + } + else if (gstatus) + { + *done = TRUE; + } + + return SVN_NO_ERROR; +} + +#endif /* SVN_HAVE_LIBSECRET */ + +#ifdef SVN_HAVE_GNOME_KEYRING + +#include +#include /* Returns the default keyring name, allocated in RESULT_POOL. */ static char* @@ -252,6 +390,41 @@ password_set_gnome_keyring(svn_boolean_t *done, return SVN_NO_ERROR; } +#if GLIB_CHECK_VERSION(2,6,0) +static void +log_noop(const gchar *log_domain, GLogLevelFlags log_level, + const gchar *message, gpointer user_data) +{ + /* do nothing */ +} +#endif + +static void +init_gnome_keyring(void) +{ + const char *application_name = NULL; + application_name = g_get_application_name(); + if (!application_name) + g_set_application_name("Subversion"); + + /* Ideally we call g_log_set_handler() with a log_domain specific to + libgnome-keyring. Unfortunately, at least as of gnome-keyring + 2.22.3, it doesn't have its own log_domain. As a result, we + suppress stderr spam for not only libgnome-keyring, but for + anything else the app is linked to that uses glib logging and + doesn't specify a log_domain. */ +#if GLIB_CHECK_VERSION(2,6,0) + g_log_set_default_handler(log_noop, NULL); +#endif +} + +#endif /* SVN_HAVE_GNOME_KEYRING */ + + +/*-----------------------------------------------------------------------*/ +/* GNOME Keyring simple provider, puts passwords in GNOME Keyring */ +/*-----------------------------------------------------------------------*/ + /* Get cached encrypted credentials from the simple provider's cache. */ static svn_error_t * simple_gnome_keyring_first_creds(void **credentials, @@ -286,34 +459,6 @@ simple_gnome_keyring_save_creds(svn_boolean_t *saved, pool); } -#if GLIB_CHECK_VERSION(2,6,0) -static void -log_noop(const gchar *log_domain, GLogLevelFlags log_level, - const gchar *message, gpointer user_data) -{ - /* do nothing */ -} -#endif - -static void -init_gnome_keyring(void) -{ - const char *application_name = NULL; - application_name = g_get_application_name(); - if (!application_name) - g_set_application_name("Subversion"); - - /* Ideally we call g_log_set_handler() with a log_domain specific to - libgnome-keyring. Unfortunately, at least as of gnome-keyring - 2.22.3, it doesn't have its own log_domain. As a result, we - suppress stderr spam for not only libgnome-keyring, but for - anything else the app is linked to that uses glib logging and - doesn't specify a log_domain. */ -#if GLIB_CHECK_VERSION(2,6,0) - g_log_set_default_handler(log_noop, NULL); -#endif -} - static const svn_auth_provider_t gnome_keyring_simple_provider = { SVN_AUTH_CRED_SIMPLE, simple_gnome_keyring_first_creds, @@ -332,9 +477,12 @@ svn_auth_get_gnome_keyring_simple_provider po->vtable = &gnome_keyring_simple_provider; *provider = po; +#ifdef SVN_HAVE_GNOME_KEYRING init_gnome_keyring(); +#endif } + /*-----------------------------------------------------------------------*/ /* GNOME Keyring SSL client certificate passphrase provider, */ @@ -391,5 +539,7 @@ svn_auth_get_gnome_keyring_ssl_client_cert_pw_provider po->vtable = &gnome_keyring_ssl_client_cert_pw_provider; *provider = po; +#ifdef SVN_HAVE_GNOME_KEYRING init_gnome_keyring(); +#endif } diff --git a/subversion/libsvn_auth_kwallet/kwallet.cpp b/subversion/libsvn_auth_kwallet/kwallet.cpp index 74e4eaf846ff..f59e04778b3c 100644 --- a/subversion/libsvn_auth_kwallet/kwallet.cpp +++ b/subversion/libsvn_auth_kwallet/kwallet.cpp @@ -39,8 +39,6 @@ #include #include -#include -#include #include #include @@ -57,6 +55,10 @@ #include "svn_private_config.h" +#ifndef SVN_HAVE_KF5 +#include +#include +#endif /*-----------------------------------------------------------------------*/ /* KWallet simple provider, puts passwords in KWallet */ @@ -221,6 +223,16 @@ kwallet_password_get(svn_boolean_t *done, app = new QCoreApplication(argc, q_argv); } +#if SVN_HAVE_KF5 + KLocalizedString::setApplicationDomain("subversion"); /* translation domain */ + + /* componentName appears in KDE GUI prompts */ + KAboutData aboutData(QStringLiteral("subversion"), /* componentName */ + i18n(get_application_name(parameters, + pool)), /* displayName */ + QStringLiteral(SVN_VER_NUMBER)); + KAboutData::setApplicationData(aboutData); +#else KCmdLineArgs::init(q_argc, q_argv, get_application_name(parameters, pool), "subversion", @@ -229,6 +241,8 @@ kwallet_password_get(svn_boolean_t *done, ki18n("Version control system"), KCmdLineArgs::CmdLineArgKDE); KComponentData component_data(KCmdLineArgs::aboutData()); +#endif + QString folder = QString::fromUtf8("Subversion"); QString key = QString::fromUtf8(username) + "@" + QString::fromUtf8(realmstring); @@ -291,6 +305,16 @@ kwallet_password_set(svn_boolean_t *done, app = new QCoreApplication(argc, q_argv); } +#if SVN_HAVE_KF5 + KLocalizedString::setApplicationDomain("subversion"); /* translation domain */ + + /* componentName appears in KDE GUI prompts */ + KAboutData aboutData(QStringLiteral("subversion"), /* componentName */ + i18n(get_application_name(parameters, + pool)), /* displayName */ + QStringLiteral(SVN_VER_NUMBER)); + KAboutData::setApplicationData(aboutData); +#else KCmdLineArgs::init(q_argc, q_argv, get_application_name(parameters, pool), "subversion", @@ -299,6 +323,8 @@ kwallet_password_set(svn_boolean_t *done, ki18n("Version control system"), KCmdLineArgs::CmdLineArgKDE); KComponentData component_data(KCmdLineArgs::aboutData()); +#endif + QString q_password = QString::fromUtf8(password); QString folder = QString::fromUtf8("Subversion"); KWallet::Wallet *wallet = get_wallet(wallet_name, parameters); diff --git a/subversion/libsvn_client/checkout.c b/subversion/libsvn_client/checkout.c index 0d20e24e117a..b9138b0b6606 100644 --- a/subversion/libsvn_client/checkout.c +++ b/subversion/libsvn_client/checkout.c @@ -81,6 +81,7 @@ svn_client__checkout_internal(svn_revnum_t *result_rev, { svn_node_kind_t kind; svn_client__pathrev_t *pathrev; + svn_opt_revision_t resolved_rev = { svn_opt_revision_number }; /* Sanity check. Without these, the checkout is meaningless. */ SVN_ERR_ASSERT(local_abspath != NULL); @@ -125,6 +126,7 @@ svn_client__checkout_internal(svn_revnum_t *result_rev, } SVN_ERR(svn_ra_check_path(ra_session, "", pathrev->rev, &kind, scratch_pool)); + resolved_rev.value.number = pathrev->rev; if (kind == svn_node_none) return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL, @@ -185,8 +187,8 @@ svn_client__checkout_internal(svn_revnum_t *result_rev, /* Have update fix the incompleteness. */ SVN_ERR(svn_client__update_internal(result_rev, timestamp_sleep, - local_abspath, revision, depth, TRUE, - ignore_externals, + local_abspath, &resolved_rev, depth, + TRUE, ignore_externals, allow_unver_obstructions, TRUE /* adds_as_modification */, FALSE, FALSE, ra_session, diff --git a/subversion/libsvn_client/client.h b/subversion/libsvn_client/client.h index 58354cf9b2c4..c0a794712f3f 100644 --- a/subversion/libsvn_client/client.h +++ b/subversion/libsvn_client/client.h @@ -1072,9 +1072,13 @@ svn_client__ensure_revprop_table(apr_hash_t **revprop_table_out, EXPAND_KEYWORDS operates as per the EXPAND argument to svn_subst_stream_translated, which see. If NORMALIZE_EOLS is TRUE and LOCAL_ABSPATH requires translation, then normalize the line endings in - *NORMAL_STREAM. + *NORMAL_STREAM to "\n" if the stream has svn:eol-style set. - Uses SCRATCH_POOL for temporary allocations. */ + Note that this IS NOT the repository normal form of the stream as that + would use "\r\n" if set to CRLF and "\r" if set to CR. + + The stream is allocated in RESULT_POOL and temporary SCRATCH_POOL is + used for temporary allocations. */ svn_error_t * svn_client__get_normalized_stream(svn_stream_t **normal_stream, svn_wc_context_t *wc_ctx, @@ -1181,6 +1185,88 @@ svn_client__remote_propget(apr_hash_t *props, apr_pool_t *result_pool, apr_pool_t *scratch_pool); +/* */ +typedef struct merge_source_t +{ + /* "left" side URL and revision (inclusive iff youngest) */ + const svn_client__pathrev_t *loc1; + + /* "right" side URL and revision (inclusive iff youngest) */ + const svn_client__pathrev_t *loc2; + + /* True iff LOC1 is an ancestor of LOC2 or vice-versa (history-wise). */ + svn_boolean_t ancestral; +} merge_source_t; + +/* Description of the merge target root node (a WC working node) */ +typedef struct merge_target_t +{ + /* Absolute path to the WC node */ + const char *abspath; + + /* The repository location of the base node of the target WC. If the node + * is locally added, then URL & REV are NULL & SVN_INVALID_REVNUM. + * REPOS_ROOT_URL and REPOS_UUID are always valid. */ + svn_client__pathrev_t loc; + +} merge_target_t; + +/* + * Similar API to svn_client_merge_peg5(). + */ +svn_error_t * +svn_client__merge_elements(svn_boolean_t *use_sleep, + apr_array_header_t *merge_sources, + merge_target_t *target, + svn_ra_session_t *ra_session, + svn_boolean_t diff_ignore_ancestry, + svn_boolean_t force_delete, + svn_boolean_t dry_run, + const apr_array_header_t *merge_options, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/* Data for reporting when a merge aborted because of raising conflicts. + * + * ### TODO: More info, including the ranges (or other parameters) the user + * needs to complete the merge. + */ +typedef struct svn_client__conflict_report_t +{ + const char *target_abspath; + /* The revision range during which conflicts were raised */ + const merge_source_t *conflicted_range; + /* Was the conflicted range the last range in the whole requested merge? */ + svn_boolean_t was_last_range; +} svn_client__conflict_report_t; + +/* Create and return an error structure appropriate for the unmerged + revisions range(s). */ +svn_error_t * +svn_client__make_merge_conflict_error(svn_client__conflict_report_t *report, + apr_pool_t *scratch_pool); + +/* The body of svn_client_merge5(), which see for details. */ +svn_error_t * +svn_client__merge_locked(svn_client__conflict_report_t **conflict_report, + const char *source1, + const svn_opt_revision_t *revision1, + const char *source2, + const svn_opt_revision_t *revision2, + const char *target_abspath, + svn_depth_t depth, + svn_boolean_t ignore_mergeinfo, + svn_boolean_t diff_ignore_ancestry, + svn_boolean_t force_delete, + svn_boolean_t record_only, + svn_boolean_t dry_run, + svn_boolean_t allow_mixed_rev, + const apr_array_header_t *merge_options, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/subversion/libsvn_client/conflicts.c b/subversion/libsvn_client/conflicts.c new file mode 100644 index 000000000000..0fd9a2bbec5e --- /dev/null +++ b/subversion/libsvn_client/conflicts.c @@ -0,0 +1,11207 @@ +/* + * conflicts.c: conflict resolver implementation + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +/* ==================================================================== */ + + + +/*** Includes. ***/ + +#include "svn_types.h" +#include "svn_wc.h" +#include "svn_client.h" +#include "svn_error.h" +#include "svn_dirent_uri.h" +#include "svn_path.h" +#include "svn_pools.h" +#include "svn_props.h" +#include "svn_hash.h" +#include "svn_sorts.h" +#include "svn_subst.h" +#include "client.h" + +#include "private/svn_diff_tree.h" +#include "private/svn_ra_private.h" +#include "private/svn_sorts_private.h" +#include "private/svn_token.h" +#include "private/svn_wc_private.h" + +#include "svn_private_config.h" + +#define ARRAY_LEN(ary) ((sizeof (ary)) / (sizeof ((ary)[0]))) + + +/*** Dealing with conflicts. ***/ + +/* Describe a tree conflict. */ +typedef svn_error_t *(*tree_conflict_get_description_func_t)( + const char **change_description, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/* Get more information about a tree conflict. + * This function may contact the repository. */ +typedef svn_error_t *(*tree_conflict_get_details_func_t)( + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool); + +struct svn_client_conflict_t +{ + const char *local_abspath; + apr_hash_t *prop_conflicts; + + /* Indicate which options were chosen to resolve a text or tree conflict + * on the conflicted node. */ + svn_client_conflict_option_id_t resolution_text; + svn_client_conflict_option_id_t resolution_tree; + + /* A mapping from const char* property name to pointers to + * svn_client_conflict_option_t for all properties which had their + * conflicts resolved. Indicates which options were chosen to resolve + * the property conflicts. */ + apr_hash_t *resolved_props; + + /* Ask a tree conflict to describe itself. */ + tree_conflict_get_description_func_t + tree_conflict_get_incoming_description_func; + tree_conflict_get_description_func_t + tree_conflict_get_local_description_func; + + /* Ask a tree conflict to find out more information about itself + * by contacting the repository. */ + tree_conflict_get_details_func_t tree_conflict_get_incoming_details_func; + tree_conflict_get_details_func_t tree_conflict_get_local_details_func; + + /* Any additional information found can be stored here and may be used + * when describing a tree conflict. */ + void *tree_conflict_incoming_details; + void *tree_conflict_local_details; + + /* The pool this conflict was allocated from. */ + apr_pool_t *pool; + + /* Conflict data provided by libsvn_wc. */ + const svn_wc_conflict_description2_t *legacy_text_conflict; + const char *legacy_prop_conflict_propname; + const svn_wc_conflict_description2_t *legacy_tree_conflict; + + /* The recommended resolution option's ID. */ + svn_client_conflict_option_id_t recommended_option_id; +}; + +/* Resolves conflict to OPTION and sets CONFLICT->RESOLUTION accordingly. + * + * May raise an error in case the conflict could not be resolved. A common + * case would be a tree conflict the resolution of which depends on other + * tree conflicts to be resolved first. */ +typedef svn_error_t *(*conflict_option_resolve_func_t)( + svn_client_conflict_option_t *option, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool); + +struct svn_client_conflict_option_t +{ + svn_client_conflict_option_id_t id; + const char *label; + const char *description; + + svn_client_conflict_t *conflict; + conflict_option_resolve_func_t do_resolve_func; + + /* The pool this option was allocated from. */ + apr_pool_t *pool; + + /* Data which is specific to particular conflicts and options. */ + union { + struct { + /* Indicates the property to resolve in case of a property conflict. + * If set to "", all properties are resolved to this option. */ + const char *propname; + + /* A merged property value, if supplied by the API user, else NULL. */ + const svn_string_t *merged_propval; + } prop; + } type_data; + +}; + +/* + * Return a legacy conflict choice corresponding to OPTION_ID. + * Return svn_wc_conflict_choose_undefined if no corresponding + * legacy conflict choice exists. + */ +static svn_wc_conflict_choice_t +conflict_option_id_to_wc_conflict_choice( + svn_client_conflict_option_id_t option_id) +{ + + switch (option_id) + { + case svn_client_conflict_option_undefined: + return svn_wc_conflict_choose_undefined; + + case svn_client_conflict_option_postpone: + return svn_wc_conflict_choose_postpone; + + case svn_client_conflict_option_base_text: + return svn_wc_conflict_choose_base; + + case svn_client_conflict_option_incoming_text: + return svn_wc_conflict_choose_theirs_full; + + case svn_client_conflict_option_working_text: + return svn_wc_conflict_choose_mine_full; + + case svn_client_conflict_option_incoming_text_where_conflicted: + return svn_wc_conflict_choose_theirs_conflict; + + case svn_client_conflict_option_working_text_where_conflicted: + return svn_wc_conflict_choose_mine_conflict; + + case svn_client_conflict_option_merged_text: + return svn_wc_conflict_choose_merged; + + case svn_client_conflict_option_unspecified: + return svn_wc_conflict_choose_unspecified; + + default: + break; + } + + return svn_wc_conflict_choose_undefined; +} + +static void +add_legacy_desc_to_conflict(const svn_wc_conflict_description2_t *desc, + svn_client_conflict_t *conflict, + apr_pool_t *result_pool) +{ + switch (desc->kind) + { + case svn_wc_conflict_kind_text: + conflict->legacy_text_conflict = desc; + break; + + case svn_wc_conflict_kind_property: + if (conflict->prop_conflicts == NULL) + conflict->prop_conflicts = apr_hash_make(result_pool); + svn_hash_sets(conflict->prop_conflicts, desc->property_name, desc); + conflict->legacy_prop_conflict_propname = desc->property_name; + break; + + case svn_wc_conflict_kind_tree: + conflict->legacy_tree_conflict = desc; + break; + + default: + SVN_ERR_ASSERT_NO_RETURN(FALSE); /* unknown kind of conflict */ + } +} + +/* A map for svn_wc_conflict_action_t values to strings */ +static const svn_token_map_t map_conflict_action[] = +{ + { "edit", svn_wc_conflict_action_edit }, + { "delete", svn_wc_conflict_action_delete }, + { "add", svn_wc_conflict_action_add }, + { "replace", svn_wc_conflict_action_replace }, + { NULL, 0 } +}; + +/* A map for svn_wc_conflict_reason_t values to strings */ +static const svn_token_map_t map_conflict_reason[] = +{ + { "edit", svn_wc_conflict_reason_edited }, + { "delete", svn_wc_conflict_reason_deleted }, + { "missing", svn_wc_conflict_reason_missing }, + { "obstruction", svn_wc_conflict_reason_obstructed }, + { "add", svn_wc_conflict_reason_added }, + { "replace", svn_wc_conflict_reason_replaced }, + { "unversioned", svn_wc_conflict_reason_unversioned }, + { "moved-away", svn_wc_conflict_reason_moved_away }, + { "moved-here", svn_wc_conflict_reason_moved_here }, + { NULL, 0 } +}; + +/* Describes a server-side move (really a copy+delete within the same + * revision) which was identified by scanning the revision log. + * This structure can represent one or more "chains" of moves, i.e. + * multiple move operations which occurred across a range of revisions. */ +struct repos_move_info { + /* The revision in which this move was committed. */ + svn_revnum_t rev; + + /* The author who commited the revision in which this move was committed. */ + const char *rev_author; + + /* The repository relpath the node was moved from in this revision. */ + const char *moved_from_repos_relpath; + + /* The repository relpath the node was moved to in this revision. */ + const char *moved_to_repos_relpath; + + /* The copyfrom revision of the moved-to path. */ + svn_revnum_t copyfrom_rev; + + /* The node kind of the item being moved. */ + svn_node_kind_t node_kind; + + /* Prev pointer. NULL if no prior move exists in the chain. */ + struct repos_move_info *prev; + + /* An array of struct repos_move_info * elements, each representing + * a possible way forward in the move chain. NULL if no next move + * exists in this chain. If the deleted node was copied only once in + * this revision, then this array has only one element and the move + * chain does not fork. But if this revision contains multiple copies of + * the deleted node, each of these copies appears as an element of this + * array, and each element represents a different path the next move + * might have taken. */ + apr_array_header_t *next; +}; + +static svn_revnum_t +rev_below(svn_revnum_t rev) +{ + SVN_ERR_ASSERT_NO_RETURN(rev != SVN_INVALID_REVNUM); + SVN_ERR_ASSERT_NO_RETURN(rev > 0); + + return rev == 1 ? 1 : rev - 1; +} + +/* Set *RELATED to true if the deleted node DELETED_REPOS_RELPATH@DELETED_REV + * is an ancestor of the copied node COPYFROM_PATH@COPYFROM_REV. + * If CHECK_LAST_CHANGED_REV is non-zero, also ensure that the copied node + * is a copy of the deleted node's last-changed revision's content, rather + * than a copy of some older content. If it's not, set *RELATED to false. */ +static svn_error_t * +check_move_ancestry(svn_boolean_t *related, + svn_ra_session_t *ra_session, + const char *repos_root_url, + const char *deleted_repos_relpath, + svn_revnum_t deleted_rev, + const char *copyfrom_path, + svn_revnum_t copyfrom_rev, + svn_boolean_t check_last_changed_rev, + apr_pool_t *scratch_pool) +{ + apr_hash_t *locations; + const char *deleted_url; + const char *deleted_location; + apr_array_header_t *location_revisions; + const char *old_session_url; + + location_revisions = apr_array_make(scratch_pool, 1, sizeof(svn_revnum_t)); + APR_ARRAY_PUSH(location_revisions, svn_revnum_t) = copyfrom_rev; + deleted_url = svn_uri_canonicalize(apr_pstrcat(scratch_pool, + repos_root_url, "/", + deleted_repos_relpath, + NULL), + scratch_pool); + SVN_ERR(svn_client__ensure_ra_session_url(&old_session_url, ra_session, + deleted_url, scratch_pool)); + SVN_ERR(svn_ra_get_locations(ra_session, &locations, "", + rev_below(deleted_rev), location_revisions, + scratch_pool)); + + deleted_location = apr_hash_get(locations, ©from_rev, + sizeof(svn_revnum_t)); + if (deleted_location) + { + if (deleted_location[0] == '/') + deleted_location++; + if (strcmp(deleted_location, copyfrom_path) != 0) + { + *related = FALSE; + return SVN_NO_ERROR; + } + } + else + { + *related = FALSE; + return SVN_NO_ERROR; + } + + if (check_last_changed_rev) + { + svn_dirent_t *dirent; + + /* Verify that copyfrom_rev >= last-changed revision of the + * deleted node. */ + SVN_ERR(svn_ra_stat(ra_session, "", rev_below(deleted_rev), &dirent, + scratch_pool)); + if (dirent == NULL || copyfrom_rev < dirent->created_rev) + { + *related = FALSE; + return SVN_NO_ERROR; + } + } + + *related = TRUE; + return SVN_NO_ERROR; +} + +struct copy_info { + const char *copyto_path; + const char *copyfrom_path; + svn_revnum_t copyfrom_rev; + svn_node_kind_t node_kind; +}; + +/* Allocate and return a NEW_MOVE, and update MOVED_PATHS with this new move. */ +static svn_error_t * +add_new_move(struct repos_move_info **new_move, + const char *deleted_repos_relpath, + const char *copyto_path, + svn_revnum_t copyfrom_rev, + svn_node_kind_t node_kind, + svn_revnum_t revision, + const char *author, + apr_hash_t *moved_paths, + svn_ra_session_t *ra_session, + const char *repos_root_url, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + struct repos_move_info *move; + struct repos_move_info *next_move; + + move = apr_pcalloc(result_pool, sizeof(*move)); + move->moved_from_repos_relpath = apr_pstrdup(result_pool, + deleted_repos_relpath); + move->moved_to_repos_relpath = apr_pstrdup(result_pool, copyto_path); + move->rev = revision; + move->rev_author = apr_pstrdup(result_pool, author); + move->copyfrom_rev = copyfrom_rev; + move->node_kind = node_kind; + + /* Link together multiple moves of the same node. + * Note that we're traversing history backwards, so moves already + * present in the list happened in younger revisions. */ + next_move = svn_hash_gets(moved_paths, move->moved_to_repos_relpath); + if (next_move) + { + svn_boolean_t related; + + /* Tracing back history of the delete-half of the next move + * to the copyfrom-revision of the prior move we must end up + * at the delete-half of the prior move. */ + SVN_ERR(check_move_ancestry(&related, ra_session, repos_root_url, + next_move->moved_from_repos_relpath, + next_move->rev, + move->moved_from_repos_relpath, + move->copyfrom_rev, + FALSE, scratch_pool)); + if (related) + { + SVN_ERR_ASSERT(move->rev < next_move->rev); + + /* Prepend this move to the linked list. */ + if (move->next == NULL) + move->next = apr_array_make(result_pool, 1, + sizeof (struct repos_move_info *)); + APR_ARRAY_PUSH(move->next, struct repos_move_info *) = next_move; + next_move->prev = move; + } + } + + /* Make this move the head of our next-move linking map. */ + svn_hash_sets(moved_paths, move->moved_from_repos_relpath, move); + + *new_move = move; + return SVN_NO_ERROR; +} + +/* Push a MOVE into the MOVES_TABLE. */ +static void +push_move(struct repos_move_info *move, apr_hash_t *moves_table, + apr_pool_t *result_pool) +{ + apr_array_header_t *moves; + + /* Add this move to the list of moves in the revision. */ + moves = apr_hash_get(moves_table, &move->rev, sizeof(svn_revnum_t)); + if (moves == NULL) + { + /* It is the first move in this revision. Create the list. */ + moves = apr_array_make(result_pool, 1, sizeof(struct repos_move_info *)); + apr_hash_set(moves_table, &move->rev, sizeof(svn_revnum_t), moves); + } + APR_ARRAY_PUSH(moves, struct repos_move_info *) = move; +} + +/* Find the youngest common ancestor of REPOS_RELPATH1@PEG_REV1 and + * REPOS_RELPATH2@PEG_REV2. Return the result in *YCA_LOC. + * Set *YCA_LOC to NULL if no common ancestor exists. */ +static svn_error_t * +find_yca(svn_client__pathrev_t **yca_loc, + const char *repos_relpath1, + svn_revnum_t peg_rev1, + const char *repos_relpath2, + svn_revnum_t peg_rev2, + const char *repos_root_url, + const char *repos_uuid, + svn_ra_session_t *ra_session, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_client__pathrev_t *loc1; + svn_client__pathrev_t *loc2; + + *yca_loc = NULL; + + loc1 = svn_client__pathrev_create_with_relpath(repos_root_url, repos_uuid, + peg_rev1, repos_relpath1, + scratch_pool); + loc2 = svn_client__pathrev_create_with_relpath(repos_root_url, repos_uuid, + peg_rev2, repos_relpath2, + scratch_pool); + SVN_ERR(svn_client__get_youngest_common_ancestor(yca_loc, loc1, loc2, + ra_session, ctx, + result_pool, scratch_pool)); + + return SVN_NO_ERROR; +} + +/* Like find_yca, expect that a YCA could also be found via a brute-force + * search of parents of REPOS_RELPATH1 and REPOS_RELPATH2, if no "direct" + * YCA exists. An implicit assumption is that some parent of REPOS_RELPATH1 + * is a branch of some parent of REPOS_RELPATH2. + * + * This function can guess a "good enough" YCA for 'missing nodes' which do + * not exist in the working copy, e.g. when a file edit is merged to a path + * which does not exist in the working copy. + */ +static svn_error_t * +find_nearest_yca(svn_client__pathrev_t **yca_locp, + const char *repos_relpath1, + svn_revnum_t peg_rev1, + const char *repos_relpath2, + svn_revnum_t peg_rev2, + const char *repos_root_url, + const char *repos_uuid, + svn_ra_session_t *ra_session, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_client__pathrev_t *yca_loc; + svn_error_t *err; + apr_pool_t *iterpool; + const char *p1, *p2; + apr_size_t c1, c2; + + *yca_locp = NULL; + + iterpool = svn_pool_create(scratch_pool); + + p1 = repos_relpath1; + c1 = svn_path_component_count(repos_relpath1); + while (c1--) + { + svn_pool_clear(iterpool); + + p2 = repos_relpath2; + c2 = svn_path_component_count(repos_relpath2); + while (c2--) + { + err = find_yca(&yca_loc, p1, peg_rev1, p2, peg_rev2, + repos_root_url, repos_uuid, ra_session, ctx, + result_pool, iterpool); + if (err) + { + if (err->apr_err == SVN_ERR_FS_NOT_FOUND) + { + svn_error_clear(err); + yca_loc = NULL; + } + else + return svn_error_trace(err); + } + + if (yca_loc) + { + *yca_locp = yca_loc; + svn_pool_destroy(iterpool); + return SVN_NO_ERROR; + } + + p2 = svn_relpath_dirname(p2, scratch_pool); + } + + p1 = svn_relpath_dirname(p1, scratch_pool); + } + + svn_pool_destroy(iterpool); + + return SVN_NO_ERROR; +} + +/* Check if the copied node described by COPY and the DELETED_PATH@DELETED_REV + * share a common ancestor. If so, return new repos_move_info in *MOVE which + * describes a move from the deleted path to that copy's destination. */ +static svn_error_t * +find_related_move(struct repos_move_info **move, + struct copy_info *copy, + const char *deleted_repos_relpath, + svn_revnum_t deleted_rev, + const char *author, + apr_hash_t *moved_paths, + const char *repos_root_url, + const char *repos_uuid, + svn_client_ctx_t *ctx, + svn_ra_session_t *ra_session, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_client__pathrev_t *yca_loc; + svn_error_t *err; + + *move = NULL; + err = find_yca(&yca_loc, copy->copyfrom_path, copy->copyfrom_rev, + deleted_repos_relpath, rev_below(deleted_rev), + repos_root_url, repos_uuid, ra_session, ctx, + scratch_pool, scratch_pool); + if (err) + { + if (err->apr_err == SVN_ERR_FS_NOT_FOUND) + { + svn_error_clear(err); + yca_loc = NULL; + } + else + return svn_error_trace(err); + } + + if (yca_loc) + SVN_ERR(add_new_move(move, deleted_repos_relpath, + copy->copyto_path, copy->copyfrom_rev, + copy->node_kind, deleted_rev, author, + moved_paths, ra_session, repos_root_url, + result_pool, scratch_pool)); + + return SVN_NO_ERROR; +} + +/* Detect moves by matching DELETED_REPOS_RELPATH@DELETED_REV to the copies + * in COPIES. Add any moves found to MOVES_TABLE and update MOVED_PATHS. */ +static svn_error_t * +match_copies_to_deletion(const char *deleted_repos_relpath, + svn_revnum_t deleted_rev, + const char *author, + apr_hash_t *copies, + apr_hash_t *moves_table, + apr_hash_t *moved_paths, + const char *repos_root_url, + const char *repos_uuid, + svn_ra_session_t *ra_session, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + apr_hash_index_t *hi; + apr_pool_t *iterpool; + + iterpool = svn_pool_create(scratch_pool); + for (hi = apr_hash_first(scratch_pool, copies); + hi != NULL; + hi = apr_hash_next(hi)) + { + const char *copyfrom_path = apr_hash_this_key(hi); + apr_array_header_t *copies_with_same_source_path; + int i; + + svn_pool_clear(iterpool); + + copies_with_same_source_path = apr_hash_this_val(hi); + + if (strcmp(copyfrom_path, deleted_repos_relpath) == 0) + { + /* We found a copyfrom path which matches a deleted node. + * Check if the deleted node is an ancestor of the copied node. */ + for (i = 0; i < copies_with_same_source_path->nelts; i++) + { + struct copy_info *copy; + svn_boolean_t related; + struct repos_move_info *move; + + copy = APR_ARRAY_IDX(copies_with_same_source_path, i, + struct copy_info *); + SVN_ERR(check_move_ancestry(&related, + ra_session, repos_root_url, + deleted_repos_relpath, + deleted_rev, + copy->copyfrom_path, + copy->copyfrom_rev, + TRUE, iterpool)); + if (!related) + continue; + + /* Remember details of this move. */ + SVN_ERR(add_new_move(&move, deleted_repos_relpath, + copy->copyto_path, copy->copyfrom_rev, + copy->node_kind, deleted_rev, author, + moved_paths, ra_session, repos_root_url, + result_pool, iterpool)); + push_move(move, moves_table, result_pool); + } + } + else + { + /* Check if this deleted node is related to any copies in this + * revision. These could be moves of the deleted node which + * were merged here from other lines of history. */ + for (i = 0; i < copies_with_same_source_path->nelts; i++) + { + struct copy_info *copy; + struct repos_move_info *move = NULL; + + copy = APR_ARRAY_IDX(copies_with_same_source_path, i, + struct copy_info *); + SVN_ERR(find_related_move(&move, copy, deleted_repos_relpath, + deleted_rev, author, + moved_paths, + repos_root_url, repos_uuid, + ctx, ra_session, + result_pool, iterpool)); + if (move) + push_move(move, moves_table, result_pool); + } + } + } + svn_pool_destroy(iterpool); + + return SVN_NO_ERROR; +} + +/* Update MOVES_TABLE and MOVED_PATHS based on information from + * revision data in LOG_ENTRY, COPIES, and DELETED_PATHS. + * Use RA_SESSION to perform the necessary requests. */ +static svn_error_t * +find_moves_in_revision(svn_ra_session_t *ra_session, + apr_hash_t *moves_table, + apr_hash_t *moved_paths, + svn_log_entry_t *log_entry, + apr_hash_t *copies, + apr_array_header_t *deleted_paths, + const char *repos_root_url, + const char *repos_uuid, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + apr_pool_t *iterpool; + int i; + const svn_string_t *author; + + author = svn_hash_gets(log_entry->revprops, SVN_PROP_REVISION_AUTHOR); + iterpool = svn_pool_create(scratch_pool); + for (i = 0; i < deleted_paths->nelts; i++) + { + const char *deleted_repos_relpath; + + svn_pool_clear(iterpool); + + deleted_repos_relpath = APR_ARRAY_IDX(deleted_paths, i, const char *); + SVN_ERR(match_copies_to_deletion(deleted_repos_relpath, + log_entry->revision, + author ? author->data + : _("unknown author"), + copies, moves_table, moved_paths, + repos_root_url, repos_uuid, ra_session, + ctx, result_pool, iterpool)); + } + svn_pool_destroy(iterpool); + + return SVN_NO_ERROR; +} + +struct find_deleted_rev_baton +{ + /* Variables below are arguments provided by the caller of + * svn_ra_get_log2(). */ + const char *deleted_repos_relpath; + const char *related_repos_relpath; + svn_revnum_t related_peg_rev; + const char *repos_root_url; + const char *repos_uuid; + svn_client_ctx_t *ctx; + const char *victim_abspath; /* for notifications */ + + /* Variables below are results for the caller of svn_ra_get_log2(). */ + svn_revnum_t deleted_rev; + const char *deleted_rev_author; + svn_node_kind_t replacing_node_kind; + apr_pool_t *result_pool; + + apr_hash_t *moves_table; /* Obtained from find_moves_in_revision(). */ + struct repos_move_info *move; /* Last known move which affected the node. */ + + /* Extra RA session that can be used to make additional requests. */ + svn_ra_session_t *extra_ra_session; +}; + +/* If DELETED_RELPATH matches the moved-from path of a move in MOVES, + * or if DELETED_RELPATH is a child of a moved-to path in MOVES, return + * a struct move_info for the corresponding move. Else, return NULL. */ +static struct repos_move_info * +map_deleted_path_to_move(const char *deleted_relpath, + apr_array_header_t *moves, + apr_pool_t *scratch_pool) +{ + struct repos_move_info *closest_move = NULL; + apr_size_t min_components = 0; + int i; + + for (i = 0; i < moves->nelts; i++) + { + const char *relpath; + struct repos_move_info *move; + + move = APR_ARRAY_IDX(moves, i, struct repos_move_info *); + if (strcmp(move->moved_from_repos_relpath, deleted_relpath) == 0) + return move; + + relpath = svn_relpath_skip_ancestor(move->moved_to_repos_relpath, + deleted_relpath); + if (relpath) + { + /* This could be a nested move. Return the path-wise closest move. */ + const apr_size_t c = svn_path_component_count(relpath); + if (c == 0) + return move; + else if (min_components == 0 || c < min_components) + { + min_components = c; + closest_move = move; + } + } + } + + if (closest_move) + { + const char *relpath; + const char *moved_along_path; + struct repos_move_info *move; + + /* See if we can find an even closer move for this moved-along path. */ + relpath = svn_relpath_skip_ancestor(closest_move->moved_to_repos_relpath, + deleted_relpath); + moved_along_path = + svn_relpath_join(closest_move->moved_from_repos_relpath, relpath, + scratch_pool); + move = map_deleted_path_to_move(moved_along_path, moves, scratch_pool); + if (move) + return move; + } + + return closest_move; +} + +/* Search for nested moves in REVISION, given the already found MOVES, + * all DELETED_PATHS, and all COPIES, from the same revision. + * Append any nested moves to the MOVES array. */ +static svn_error_t * +find_nested_moves(apr_array_header_t *moves, + apr_hash_t *copies, + apr_array_header_t *deleted_paths, + apr_hash_t *moved_paths, + svn_revnum_t revision, + const char *author, + const char *repos_root_url, + const char *repos_uuid, + svn_ra_session_t *ra_session, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + apr_array_header_t *nested_moves; + int i; + apr_pool_t *iterpool; + + nested_moves = apr_array_make(result_pool, 0, + sizeof(struct repos_move_info *)); + iterpool = svn_pool_create(scratch_pool); + for (i = 0; i < deleted_paths->nelts; i++) + { + const char *deleted_path; + const char *child_relpath; + const char *moved_along_repos_relpath; + struct repos_move_info *move; + apr_array_header_t *copies_with_same_source_path; + int j; + svn_boolean_t related; + + svn_pool_clear(iterpool); + + deleted_path = APR_ARRAY_IDX(deleted_paths, i, const char *); + move = map_deleted_path_to_move(deleted_path, moves, iterpool); + if (move == NULL) + continue; + child_relpath = svn_relpath_skip_ancestor(move->moved_to_repos_relpath, + deleted_path); + if (child_relpath == NULL || child_relpath[0] == '\0') + continue; /* not a nested move */ + + /* Consider: svn mv A B; svn mv B/foo C/foo + * Copyfrom for C/foo is A/foo, even though C/foo was moved here from + * B/foo. A/foo was not deleted. It is B/foo which was deleted. + * We now know about the move A->B and moved-along child_relpath "foo". + * Try to detect an ancestral relationship between A/foo and the + * moved-along path. */ + moved_along_repos_relpath = + svn_relpath_join(move->moved_from_repos_relpath, child_relpath, + iterpool); + copies_with_same_source_path = svn_hash_gets(copies, + moved_along_repos_relpath); + if (copies_with_same_source_path == NULL) + continue; /* not a nested move */ + + for (j = 0; j < copies_with_same_source_path->nelts; j++) + { + struct copy_info *copy; + + copy = APR_ARRAY_IDX(copies_with_same_source_path, j, + struct copy_info *); + SVN_ERR(check_move_ancestry(&related, ra_session, repos_root_url, + moved_along_repos_relpath, + revision, + copy->copyfrom_path, + copy->copyfrom_rev, + TRUE, iterpool)); + if (related) + { + struct repos_move_info *nested_move; + + /* Remember details of this move. */ + SVN_ERR(add_new_move(&nested_move, moved_along_repos_relpath, + copy->copyto_path, copy->copyfrom_rev, + copy->node_kind, + revision, author, moved_paths, + ra_session, repos_root_url, + result_pool, iterpool)); + + /* Add this move to the list of nested moves in this revision. */ + APR_ARRAY_PUSH(nested_moves, struct repos_move_info *) = + nested_move; + } + } + } + svn_pool_destroy(iterpool); + + /* Add all nested moves found to the list of all moves in this revision. */ + apr_array_cat(moves, nested_moves); + + return SVN_NO_ERROR; +} + +/* Make a shallow copy of the copied LOG_ITEM in COPIES. */ +static void +cache_copied_item(apr_hash_t *copies, const char *changed_path, + svn_log_changed_path2_t *log_item) +{ + apr_pool_t *result_pool = apr_hash_pool_get(copies); + struct copy_info *copy = apr_palloc(result_pool, sizeof(*copy)); + apr_array_header_t *copies_with_same_source_path; + + copy->copyfrom_path = log_item->copyfrom_path; + if (log_item->copyfrom_path[0] == '/') + copy->copyfrom_path++; + copy->copyto_path = changed_path; + copy->copyfrom_rev = log_item->copyfrom_rev; + copy->node_kind = log_item->node_kind; + + copies_with_same_source_path = apr_hash_get(copies, copy->copyfrom_path, + APR_HASH_KEY_STRING); + if (copies_with_same_source_path == NULL) + { + copies_with_same_source_path = apr_array_make(result_pool, 1, + sizeof(struct copy_info *)); + apr_hash_set(copies, copy->copyfrom_path, APR_HASH_KEY_STRING, + copies_with_same_source_path); + } + APR_ARRAY_PUSH(copies_with_same_source_path, struct copy_info *) = copy; +} + +/* Implements svn_log_entry_receiver_t. + * + * Find the revision in which a node, optionally ancestrally related to the + * node specified via find_deleted_rev_baton, was deleted, When the revision + * was found, store it in BATON->DELETED_REV and abort the log operation + * by raising SVN_ERR_CEASE_INVOCATION. + * + * If no such revision can be found, leave BATON->DELETED_REV and + * BATON->REPLACING_NODE_KIND alone. + * + * If the node was replaced, set BATON->REPLACING_NODE_KIND to the node + * kind of the node which replaced the original node. If the node was not + * replaced, set BATON->REPLACING_NODE_KIND to svn_node_none. + * + * This function answers the same question as svn_ra_get_deleted_rev() but + * works in cases where we do not already know a revision in which the deleted + * node once used to exist. + * + * If the node was moved, rather than deleted, return move information + * in BATON->MOVE. + */ +static svn_error_t * +find_deleted_rev(void *baton, + svn_log_entry_t *log_entry, + apr_pool_t *scratch_pool) +{ + struct find_deleted_rev_baton *b = baton; + apr_hash_index_t *hi; + apr_pool_t *iterpool; + svn_boolean_t deleted_node_found = FALSE; + svn_node_kind_t replacing_node_kind = svn_node_none; + + if (b->ctx->notify_func2) + { + svn_wc_notify_t *notify; + + notify = svn_wc_create_notify( + b->victim_abspath, + svn_wc_notify_tree_conflict_details_progress, + scratch_pool), + notify->revision = log_entry->revision; + b->ctx->notify_func2(b->ctx->notify_baton2, notify, scratch_pool); + } + + /* No paths were changed in this revision. Nothing to do. */ + if (! log_entry->changed_paths2) + return SVN_NO_ERROR; + + iterpool = svn_pool_create(scratch_pool); + for (hi = apr_hash_first(scratch_pool, log_entry->changed_paths2); + hi != NULL; + hi = apr_hash_next(hi)) + { + const char *changed_path = apr_hash_this_key(hi); + svn_log_changed_path2_t *log_item = apr_hash_this_val(hi); + + svn_pool_clear(iterpool); + + /* ### Remove leading slash from paths in log entries. */ + if (changed_path[0] == '/') + changed_path++; + + /* Check if we already found the deleted node we're looking for. */ + if (!deleted_node_found && + svn_path_compare_paths(b->deleted_repos_relpath, changed_path) == 0 && + (log_item->action == 'D' || log_item->action == 'R')) + { + deleted_node_found = TRUE; + + if (b->related_repos_relpath != NULL && + b->related_peg_rev != SVN_INVALID_REVNUM) + { + svn_client__pathrev_t *yca_loc; + svn_error_t *err; + + /* We found a deleted node which occupies the correct path. + * To be certain that this is the deleted node we're looking for, + * we must establish whether it is ancestrally related to the + * "related node" specified in our baton. */ + err = find_yca(&yca_loc, + b->related_repos_relpath, + b->related_peg_rev, + b->deleted_repos_relpath, + rev_below(log_entry->revision), + b->repos_root_url, b->repos_uuid, + b->extra_ra_session, b->ctx, iterpool, iterpool); + if (err) + { + /* ### Happens for moves within other moves and copies. */ + if (err->apr_err == SVN_ERR_FS_NOT_FOUND) + { + svn_error_clear(err); + yca_loc = NULL; + } + else + return svn_error_trace(err); + } + + deleted_node_found = (yca_loc != NULL); + } + + if (deleted_node_found && log_item->action == 'R') + replacing_node_kind = log_item->node_kind; + } + } + svn_pool_destroy(iterpool); + + if (!deleted_node_found) + { + apr_array_header_t *moves; + + moves = apr_hash_get(b->moves_table, &log_entry->revision, + sizeof(svn_revnum_t)); + if (moves) + { + struct repos_move_info *move; + + move = map_deleted_path_to_move(b->deleted_repos_relpath, + moves, scratch_pool); + if (move) + { + const char *relpath; + + /* The node was moved. Update our search path accordingly. */ + b->move = move; + relpath = svn_relpath_skip_ancestor(move->moved_to_repos_relpath, + b->deleted_repos_relpath); + if (relpath) + b->deleted_repos_relpath = + svn_relpath_join(move->moved_from_repos_relpath, relpath, + b->result_pool); + } + } + } + else + { + svn_string_t *author; + + b->deleted_rev = log_entry->revision; + author = svn_hash_gets(log_entry->revprops, + SVN_PROP_REVISION_AUTHOR); + if (author) + b->deleted_rev_author = apr_pstrdup(b->result_pool, author->data); + else + b->deleted_rev_author = _("unknown author"); + + b->replacing_node_kind = replacing_node_kind; + + /* We're done. Abort the log operation. */ + return svn_error_create(SVN_ERR_CEASE_INVOCATION, NULL, NULL); + } + + return SVN_NO_ERROR; +} + +/* Return a localised string representation of the local part of a tree + conflict on a file. */ +static svn_error_t * +describe_local_file_node_change(const char **description, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_wc_conflict_reason_t local_change; + svn_wc_operation_t operation; + + local_change = svn_client_conflict_get_local_change(conflict); + operation = svn_client_conflict_get_operation(conflict); + + switch (local_change) + { + case svn_wc_conflict_reason_edited: + if (operation == svn_wc_operation_update || + operation == svn_wc_operation_switch) + *description = _("A file containing uncommitted changes was " + "found in the working copy."); + else if (operation == svn_wc_operation_merge) + *description = _("A file which differs from the corresponding " + "file on the merge source branch was found " + "in the working copy."); + break; + case svn_wc_conflict_reason_obstructed: + *description = _("A file which already occupies this path was found " + "in the working copy."); + break; + case svn_wc_conflict_reason_unversioned: + *description = _("An unversioned file was found in the working " + "copy."); + break; + case svn_wc_conflict_reason_deleted: + *description = _("A deleted file was found in the working copy."); + break; + case svn_wc_conflict_reason_missing: + if (operation == svn_wc_operation_update || + operation == svn_wc_operation_switch) + *description = _("No such file was found in the working copy."); + else if (operation == svn_wc_operation_merge) + { + /* ### display deleted revision */ + *description = _("No such file was found in the merge target " + "working copy.\nPerhaps the file has been " + "deleted or moved away in the repository's " + "history?"); + } + break; + case svn_wc_conflict_reason_added: + case svn_wc_conflict_reason_replaced: + { + /* ### show more details about copies or replacements? */ + *description = _("A file scheduled to be added to the " + "repository in the next commit was found in " + "the working copy."); + } + break; + case svn_wc_conflict_reason_moved_away: + { + const char *moved_to_abspath; + svn_error_t *err; + + err = svn_wc__node_was_moved_away(&moved_to_abspath, NULL, + ctx->wc_ctx, + conflict->local_abspath, + scratch_pool, + scratch_pool); + if (err) + { + if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND) + { + moved_to_abspath = NULL; + svn_error_clear(err); + } + else + return svn_error_trace(err); + } + if (operation == svn_wc_operation_update || + operation == svn_wc_operation_switch) + { + if (moved_to_abspath == NULL) + { + /* The move no longer exists. */ + *description = _("The file in the working copy had " + "been moved away at the time this " + "conflict was recorded."); + } + else + { + const char *wcroot_abspath; + + SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, + ctx->wc_ctx, + conflict->local_abspath, + scratch_pool, + scratch_pool)); + *description = apr_psprintf( + result_pool, + _("The file in the working copy was " + "moved away to\n'%s'."), + svn_dirent_local_style( + svn_dirent_skip_ancestor( + wcroot_abspath, + moved_to_abspath), + scratch_pool)); + } + } + else if (operation == svn_wc_operation_merge) + { + if (moved_to_abspath == NULL) + { + /* The move probably happened in branch history. + * This case cannot happen until we detect incoming + * moves, which we currently don't do. */ + /* ### find deleted/moved revision? */ + *description = _("The file in the working copy had " + "been moved away at the time this " + "conflict was recorded."); + } + else + { + /* This is a local move in the working copy. */ + const char *wcroot_abspath; + + SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, + ctx->wc_ctx, + conflict->local_abspath, + scratch_pool, + scratch_pool)); + *description = apr_psprintf( + result_pool, + _("The file in the working copy was " + "moved away to\n'%s'."), + svn_dirent_local_style( + svn_dirent_skip_ancestor( + wcroot_abspath, + moved_to_abspath), + scratch_pool)); + } + } + break; + } + case svn_wc_conflict_reason_moved_here: + { + const char *moved_from_abspath; + + SVN_ERR(svn_wc__node_was_moved_here(&moved_from_abspath, NULL, + ctx->wc_ctx, + conflict->local_abspath, + scratch_pool, + scratch_pool)); + if (operation == svn_wc_operation_update || + operation == svn_wc_operation_switch) + { + if (moved_from_abspath == NULL) + { + /* The move no longer exists. */ + *description = _("A file had been moved here in the " + "working copy at the time this " + "conflict was recorded."); + } + else + { + const char *wcroot_abspath; + + SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, + ctx->wc_ctx, + conflict->local_abspath, + scratch_pool, + scratch_pool)); + *description = apr_psprintf( + result_pool, + _("A file was moved here in the " + "working copy from\n'%s'."), + svn_dirent_local_style( + svn_dirent_skip_ancestor( + wcroot_abspath, + moved_from_abspath), + scratch_pool)); + } + } + else if (operation == svn_wc_operation_merge) + { + if (moved_from_abspath == NULL) + { + /* The move probably happened in branch history. + * This case cannot happen until we detect incoming + * moves, which we currently don't do. */ + /* ### find deleted/moved revision? */ + *description = _("A file had been moved here in the " + "working copy at the time this " + "conflict was recorded."); + } + else + { + const char *wcroot_abspath; + + SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, + ctx->wc_ctx, + conflict->local_abspath, + scratch_pool, + scratch_pool)); + /* This is a local move in the working copy. */ + *description = apr_psprintf( + result_pool, + _("A file was moved here in the " + "working copy from\n'%s'."), + svn_dirent_local_style( + svn_dirent_skip_ancestor( + wcroot_abspath, + moved_from_abspath), + scratch_pool)); + } + } + break; + } + } + + return SVN_NO_ERROR; +} + +/* Return a localised string representation of the local part of a tree + conflict on a directory. */ +static svn_error_t * +describe_local_dir_node_change(const char **description, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_wc_conflict_reason_t local_change; + svn_wc_operation_t operation; + + local_change = svn_client_conflict_get_local_change(conflict); + operation = svn_client_conflict_get_operation(conflict); + + switch (local_change) + { + case svn_wc_conflict_reason_edited: + if (operation == svn_wc_operation_update || + operation == svn_wc_operation_switch) + *description = _("A directory containing uncommitted changes " + "was found in the working copy."); + else if (operation == svn_wc_operation_merge) + *description = _("A directory which differs from the " + "corresponding directory on the merge source " + "branch was found in the working copy."); + break; + case svn_wc_conflict_reason_obstructed: + *description = _("A directory which already occupies this path was " + "found in the working copy."); + break; + case svn_wc_conflict_reason_unversioned: + *description = _("An unversioned directory was found in the " + "working copy."); + break; + case svn_wc_conflict_reason_deleted: + *description = _("A deleted directory was found in the " + "working copy."); + break; + case svn_wc_conflict_reason_missing: + if (operation == svn_wc_operation_update || + operation == svn_wc_operation_switch) + *description = _("No such directory was found in the working copy."); + else if (operation == svn_wc_operation_merge) + { + /* ### display deleted revision */ + *description = _("No such directory was found in the merge " + "target working copy.\nPerhaps the " + "directory has been deleted or moved away " + "in the repository's history?"); + } + break; + case svn_wc_conflict_reason_added: + case svn_wc_conflict_reason_replaced: + { + /* ### show more details about copies or replacements? */ + *description = _("A directory scheduled to be added to the " + "repository in the next commit was found in " + "the working copy."); + } + break; + case svn_wc_conflict_reason_moved_away: + { + const char *moved_to_abspath; + svn_error_t *err; + + err = svn_wc__node_was_moved_away(&moved_to_abspath, NULL, + ctx->wc_ctx, + conflict->local_abspath, + scratch_pool, + scratch_pool); + if (err) + { + if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND) + { + moved_to_abspath = NULL; + svn_error_clear(err); + } + else + return svn_error_trace(err); + } + + if (operation == svn_wc_operation_update || + operation == svn_wc_operation_switch) + { + if (moved_to_abspath == NULL) + { + /* The move no longer exists. */ + *description = _("The directory in the working copy " + "had been moved away at the time " + "this conflict was recorded."); + } + else + { + const char *wcroot_abspath; + + SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, + ctx->wc_ctx, + conflict->local_abspath, + scratch_pool, + scratch_pool)); + *description = apr_psprintf( + result_pool, + _("The directory in the working copy " + "was moved away to\n'%s'."), + svn_dirent_local_style( + svn_dirent_skip_ancestor( + wcroot_abspath, + moved_to_abspath), + scratch_pool)); + } + } + else if (operation == svn_wc_operation_merge) + { + if (moved_to_abspath == NULL) + { + /* The move probably happened in branch history. + * This case cannot happen until we detect incoming + * moves, which we currently don't do. */ + /* ### find deleted/moved revision? */ + *description = _("The directory had been moved away " + "at the time this conflict was " + "recorded."); + } + else + { + /* This is a local move in the working copy. */ + const char *wcroot_abspath; + + SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, + ctx->wc_ctx, + conflict->local_abspath, + scratch_pool, + scratch_pool)); + *description = apr_psprintf( + result_pool, + _("The directory was moved away to\n" + "'%s'."), + svn_dirent_local_style( + svn_dirent_skip_ancestor( + wcroot_abspath, + moved_to_abspath), + scratch_pool)); + } + } + } + break; + case svn_wc_conflict_reason_moved_here: + { + const char *moved_from_abspath; + + SVN_ERR(svn_wc__node_was_moved_here(&moved_from_abspath, NULL, + ctx->wc_ctx, + conflict->local_abspath, + scratch_pool, + scratch_pool)); + if (operation == svn_wc_operation_update || + operation == svn_wc_operation_switch) + { + if (moved_from_abspath == NULL) + { + /* The move no longer exists. */ + *description = _("A directory had been moved here at " + "the time this conflict was " + "recorded."); + } + else + { + const char *wcroot_abspath; + + SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, + ctx->wc_ctx, + conflict->local_abspath, + scratch_pool, + scratch_pool)); + *description = apr_psprintf( + result_pool, + _("A directory was moved here from\n" + "'%s'."), + svn_dirent_local_style( + svn_dirent_skip_ancestor( + wcroot_abspath, + moved_from_abspath), + scratch_pool)); + } + } + else if (operation == svn_wc_operation_merge) + { + if (moved_from_abspath == NULL) + { + /* The move probably happened in branch history. + * This case cannot happen until we detect incoming + * moves, which we currently don't do. */ + /* ### find deleted/moved revision? */ + *description = _("A directory had been moved here at " + "the time this conflict was " + "recorded."); + } + else + { + /* This is a local move in the working copy. */ + const char *wcroot_abspath; + + SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, + ctx->wc_ctx, + conflict->local_abspath, + scratch_pool, + scratch_pool)); + *description = apr_psprintf( + result_pool, + _("A directory was moved here in " + "the working copy from\n'%s'."), + svn_dirent_local_style( + svn_dirent_skip_ancestor( + wcroot_abspath, + moved_from_abspath), + scratch_pool)); + } + } + } + } + + return SVN_NO_ERROR; +} + +struct find_moves_baton +{ + /* Variables below are arguments provided by the caller of + * svn_ra_get_log2(). */ + const char *repos_root_url; + const char *repos_uuid; + svn_client_ctx_t *ctx; + const char *victim_abspath; /* for notifications */ + apr_pool_t *result_pool; + + /* A hash table mapping a revision number to an array of struct + * repos_move_info * elements, describing moves. + * + * Must be allocated in RESULT_POOL by the caller of svn_ra_get_log2(). + * + * If the node was moved, the DELETED_REV is present in this table, + * perhaps along with additional revisions. + * + * Given a sequence of moves which happened in the repository, such as: + * rA: mv x->z + * rA: mv a->b + * rB: mv b->c + * rC: mv c->d + * we map each revision number to all the moves which happened in the + * revision, which looks as follows: + * rA : [(x->z), (a->b)] + * rB : [(b->c)] + * rC : [(c->d)] + * This allows us to later find relevant moves based on a revision number. + * + * Additionally, we embed the number of the revision in which a move was + * found inside the repos_move_info structure: + * rA : [(rA, x->z), (rA, a->b)] + * rB : [(rB, b->c)] + * rC : [(rC, c->d)] + * And also, all moves pertaining to the same node are chained into a + * doubly-linked list via 'next' and 'prev' pointers (see definition of + * struct repos_move_info). This can be visualized as follows: + * rA : [(rA, x->z, prev=>NULL, next=>NULL), + * (rA, a->b, prev=>NULL, next=>(rB, b->c))] + * rB : [(rB, b->c), prev=>(rA, a->b), next=>(rC, c->d)] + * rC : [(rC, c->d), prev=>(rB, c->d), next=>NULL] + * This way, we can look up all moves relevant to a node, forwards and + * backwards in history, once we have located one move in the chain. + * + * In the above example, the data tells us that within the revision + * range rA:C, a was moved to d. However, within the revision range + * rA;B, a was moved to b. + */ + apr_hash_t *moves_table; + + /* Variables below hold state for find_moves() and are not + * intended to be used by the caller of svn_ra_get_log2(). + * Like all other variables, they must be initialized, however. */ + + /* Temporary map of moved paths to struct repos_move_info. + * Used to link multiple moves of the same node across revisions. */ + apr_hash_t *moved_paths; + + /* Extra RA session that can be used to make additional requests. */ + svn_ra_session_t *extra_ra_session; +}; + +/* Implements svn_log_entry_receiver_t. */ +static svn_error_t * +find_moves(void *baton, svn_log_entry_t *log_entry, apr_pool_t *scratch_pool) +{ + struct find_moves_baton *b = baton; + apr_hash_index_t *hi; + apr_pool_t *iterpool; + apr_array_header_t *deleted_paths; + apr_hash_t *copies; + apr_array_header_t *moves; + + if (b->ctx->notify_func2) + { + svn_wc_notify_t *notify; + + notify = svn_wc_create_notify( + b->victim_abspath, + svn_wc_notify_tree_conflict_details_progress, + scratch_pool), + notify->revision = log_entry->revision; + b->ctx->notify_func2(b->ctx->notify_baton2, notify, scratch_pool); + } + + /* No paths were changed in this revision. Nothing to do. */ + if (! log_entry->changed_paths2) + return SVN_NO_ERROR; + + copies = apr_hash_make(scratch_pool); + deleted_paths = apr_array_make(scratch_pool, 0, sizeof(const char *)); + iterpool = svn_pool_create(scratch_pool); + for (hi = apr_hash_first(scratch_pool, log_entry->changed_paths2); + hi != NULL; + hi = apr_hash_next(hi)) + { + const char *changed_path = apr_hash_this_key(hi); + svn_log_changed_path2_t *log_item = apr_hash_this_val(hi); + + svn_pool_clear(iterpool); + + /* ### Remove leading slash from paths in log entries. */ + if (changed_path[0] == '/') + changed_path++; + + /* For move detection, scan for copied nodes in this revision. */ + if (log_item->action == 'A' && log_item->copyfrom_path) + cache_copied_item(copies, changed_path, log_item); + + /* For move detection, store all deleted_paths. */ + if (log_item->action == 'D' || log_item->action == 'R') + APR_ARRAY_PUSH(deleted_paths, const char *) = + apr_pstrdup(scratch_pool, changed_path); + } + svn_pool_destroy(iterpool); + + /* Check for moves in this revision */ + SVN_ERR(find_moves_in_revision(b->extra_ra_session, + b->moves_table, b->moved_paths, + log_entry, copies, deleted_paths, + b->repos_root_url, b->repos_uuid, + b->ctx, b->result_pool, scratch_pool)); + + moves = apr_hash_get(b->moves_table, &log_entry->revision, + sizeof(svn_revnum_t)); + if (moves) + { + const svn_string_t *author; + + author = svn_hash_gets(log_entry->revprops, SVN_PROP_REVISION_AUTHOR); + SVN_ERR(find_nested_moves(moves, copies, deleted_paths, + b->moved_paths, log_entry->revision, + author ? author->data : _("unknown author"), + b->repos_root_url, + b->repos_uuid, + b->extra_ra_session, b->ctx, + b->result_pool, scratch_pool)); + } + + return SVN_NO_ERROR; +} + +/* Find all moves which occured in repository history starting at + * REPOS_RELPATH@START_REV until END_REV (where START_REV > END_REV). + * Return results in *MOVES_TABLE (see struct find_moves_baton for details). */ +static svn_error_t * +find_moves_in_revision_range(struct apr_hash_t **moves_table, + const char *repos_relpath, + const char *repos_root_url, + const char *repos_uuid, + const char *victim_abspath, + svn_revnum_t start_rev, + svn_revnum_t end_rev, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_ra_session_t *ra_session; + const char *url; + const char *corrected_url; + apr_array_header_t *paths; + apr_array_header_t *revprops; + struct find_moves_baton b = { 0 }; + + SVN_ERR_ASSERT(start_rev > end_rev); + + url = svn_path_url_add_component2(repos_root_url, repos_relpath, + scratch_pool); + SVN_ERR(svn_client__open_ra_session_internal(&ra_session, &corrected_url, + url, NULL, NULL, FALSE, FALSE, + ctx, scratch_pool, + scratch_pool)); + + paths = apr_array_make(scratch_pool, 1, sizeof(const char *)); + APR_ARRAY_PUSH(paths, const char *) = ""; + + revprops = apr_array_make(scratch_pool, 1, sizeof(const char *)); + APR_ARRAY_PUSH(revprops, const char *) = SVN_PROP_REVISION_AUTHOR; + + b.repos_root_url = repos_root_url; + b.repos_uuid = repos_uuid; + b.ctx = ctx; + b.victim_abspath = victim_abspath; + b.moves_table = apr_hash_make(result_pool); + b.moved_paths = apr_hash_make(scratch_pool); + b.result_pool = result_pool; + SVN_ERR(svn_ra__dup_session(&b.extra_ra_session, ra_session, NULL, + scratch_pool, scratch_pool)); + + SVN_ERR(svn_ra_get_log2(ra_session, paths, start_rev, end_rev, + 0, /* no limit */ + TRUE, /* need the changed paths list */ + FALSE, /* need to traverse copies */ + FALSE, /* no need for merged revisions */ + revprops, + find_moves, &b, + scratch_pool)); + + *moves_table = b.moves_table; + + return SVN_NO_ERROR; +} + +/* Return new move information for a moved-along child MOVED_ALONG_RELPATH. + * Set MOVE->NODE_KIND to MOVED_ALONG_NODE_KIND. + * Do not copy MOVE->NEXT and MOVE-PREV. + * If MOVED_ALONG_RELPATH is empty, this effectively copies MOVE to + * RESULT_POOL with NEXT and PREV pointers cleared. */ +static struct repos_move_info * +new_path_adjusted_move(struct repos_move_info *move, + const char *moved_along_relpath, + svn_node_kind_t moved_along_node_kind, + apr_pool_t *result_pool) +{ + struct repos_move_info *new_move; + + new_move = apr_pcalloc(result_pool, sizeof(*new_move)); + new_move->moved_from_repos_relpath = + svn_relpath_join(move->moved_from_repos_relpath, moved_along_relpath, + result_pool); + new_move->moved_to_repos_relpath = + svn_relpath_join(move->moved_to_repos_relpath, moved_along_relpath, + result_pool); + new_move->rev = move->rev; + new_move->rev_author = apr_pstrdup(result_pool, move->rev_author); + new_move->copyfrom_rev = move->copyfrom_rev; + new_move->node_kind = moved_along_node_kind; + /* Ignore prev and next pointers. Caller will set them if needed. */ + + return new_move; +} + +/* Given a list of MOVES_IN_REVISION, figure out which of these moves again + * move the node which was already moved by PREV_MOVE in the past . */ +static svn_error_t * +find_next_moves_in_revision(apr_array_header_t **next_moves, + apr_array_header_t *moves_in_revision, + struct repos_move_info *prev_move, + svn_ra_session_t *ra_session, + const char *repos_root_url, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + int i; + apr_pool_t *iterpool; + + iterpool = svn_pool_create(scratch_pool); + for (i = 0; i < moves_in_revision->nelts; i++) + { + struct repos_move_info *move; + const char *relpath; + const char *deleted_repos_relpath; + svn_boolean_t related; + svn_error_t *err; + + svn_pool_clear(iterpool); + + /* Check if this move affects the current known path of our node. */ + move = APR_ARRAY_IDX(moves_in_revision, i, struct repos_move_info *); + relpath = svn_relpath_skip_ancestor(move->moved_from_repos_relpath, + prev_move->moved_to_repos_relpath); + if (relpath == NULL) + continue; + + /* It does. So our node must have been deleted again. */ + deleted_repos_relpath = svn_relpath_join(move->moved_from_repos_relpath, + relpath, iterpool); + + /* Tracing back history of the delete-half of this move to the + * copyfrom-revision of the prior move we must end up at the + * delete-half of the prior move. */ + err = check_move_ancestry(&related, ra_session, repos_root_url, + deleted_repos_relpath, move->rev, + prev_move->moved_from_repos_relpath, + prev_move->copyfrom_rev, + FALSE, scratch_pool); + if (err && err->apr_err == SVN_ERR_FS_NOT_FOUND) + { + svn_error_clear(err); + continue; + } + else + SVN_ERR(err); + + if (related) + { + struct repos_move_info *new_move; + + /* We have a winner. */ + new_move = new_path_adjusted_move(move, relpath, prev_move->node_kind, + result_pool); + if (*next_moves == NULL) + *next_moves = apr_array_make(result_pool, 1, + sizeof(struct repos_move_info *)); + APR_ARRAY_PUSH(*next_moves, struct repos_move_info *) = new_move; + } + } + svn_pool_destroy(iterpool); + + return SVN_NO_ERROR; +} + +static int +compare_items_as_revs(const svn_sort__item_t *a, const svn_sort__item_t *b) +{ + return svn_sort_compare_revisions(a->key, b->key); +} + +/* Starting at MOVE->REV, loop over future revisions which contain moves, + * and look for matching next moves in each. Once found, return a list of + * (ambiguous, if more than one) moves in *NEXT_MOVES. */ +static svn_error_t * +find_next_moves(apr_array_header_t **next_moves, + apr_hash_t *moves_table, + struct repos_move_info *move, + svn_ra_session_t *ra_session, + const char *repos_root_url, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + apr_array_header_t *moves; + apr_array_header_t *revisions; + apr_pool_t *iterpool; + int i; + + *next_moves = NULL; + revisions = svn_sort__hash(moves_table, compare_items_as_revs, scratch_pool); + iterpool = svn_pool_create(scratch_pool); + for (i = 0; i < revisions->nelts; i++) + { + svn_sort__item_t item = APR_ARRAY_IDX(revisions, i, svn_sort__item_t); + svn_revnum_t rev = *(svn_revnum_t *)item.key; + + svn_pool_clear(iterpool); + + if (rev <= move->rev) + continue; + + moves = apr_hash_get(moves_table, &rev, sizeof(rev)); + SVN_ERR(find_next_moves_in_revision(next_moves, moves, move, + ra_session, repos_root_url, + result_pool, iterpool)); + if (*next_moves) + break; + } + svn_pool_destroy(iterpool); + + return SVN_NO_ERROR; +} + +/* Trace all future moves of the node moved by MOVE. + * Update MOVE->PREV and MOVE->NEXT accordingly. */ +static svn_error_t * +trace_moved_node(apr_hash_t *moves_table, + struct repos_move_info *move, + svn_ra_session_t *ra_session, + const char *repos_root_url, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + apr_array_header_t *next_moves; + + SVN_ERR(find_next_moves(&next_moves, moves_table, move, + ra_session, repos_root_url, + result_pool, scratch_pool)); + if (next_moves) + { + int i; + apr_pool_t *iterpool; + + move->next = next_moves; + iterpool = svn_pool_create(scratch_pool); + for (i = 0; i < next_moves->nelts; i++) + { + struct repos_move_info *next_move; + + svn_pool_clear(iterpool); + next_move = APR_ARRAY_IDX(next_moves, i, struct repos_move_info *); + next_move->prev = move; + SVN_ERR(trace_moved_node(moves_table, next_move, + ra_session, repos_root_url, + result_pool, iterpool)); + } + svn_pool_destroy(iterpool); + } + + return SVN_NO_ERROR; +} + +/* Given a list of MOVES_IN_REVISION, figure out which of these moves + * move the node which was later on moved by NEXT_MOVE. */ +static svn_error_t * +find_prev_move_in_revision(struct repos_move_info **prev_move, + apr_array_header_t *moves_in_revision, + struct repos_move_info *next_move, + svn_ra_session_t *ra_session, + const char *repos_root_url, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + int i; + apr_pool_t *iterpool; + + *prev_move = NULL; + + iterpool = svn_pool_create(scratch_pool); + for (i = 0; i < moves_in_revision->nelts; i++) + { + struct repos_move_info *move; + const char *relpath; + const char *deleted_repos_relpath; + svn_boolean_t related; + svn_error_t *err; + + svn_pool_clear(iterpool); + + /* Check if this move affects the current known path of our node. */ + move = APR_ARRAY_IDX(moves_in_revision, i, struct repos_move_info *); + relpath = svn_relpath_skip_ancestor(next_move->moved_from_repos_relpath, + move->moved_to_repos_relpath); + if (relpath == NULL) + continue; + + /* It does. So our node must have been deleted. */ + deleted_repos_relpath = svn_relpath_join( + next_move->moved_from_repos_relpath, + relpath, iterpool); + + /* Tracing back history of the delete-half of the next move to the + * copyfrom-revision of the prior move we must end up at the + * delete-half of the prior move. */ + err = check_move_ancestry(&related, ra_session, repos_root_url, + deleted_repos_relpath, next_move->rev, + move->moved_from_repos_relpath, + move->copyfrom_rev, + FALSE, scratch_pool); + if (err && err->apr_err == SVN_ERR_FS_NOT_FOUND) + { + svn_error_clear(err); + continue; + } + else + SVN_ERR(err); + + if (related) + { + /* We have a winner. */ + *prev_move = new_path_adjusted_move(move, relpath, + next_move->node_kind, + result_pool); + break; + } + } + svn_pool_destroy(iterpool); + + return SVN_NO_ERROR; +} + +static int +compare_items_as_revs_reverse(const svn_sort__item_t *a, + const svn_sort__item_t *b) +{ + int c = svn_sort_compare_revisions(a->key, b->key); + if (c < 0) + return 1; + if (c > 0) + return -1; + return c; +} + +/* Starting at MOVE->REV, loop over past revisions which contain moves, + * and look for a matching previous move in each. Once found, return + * it in *PREV_MOVE */ +static svn_error_t * +find_prev_move(struct repos_move_info **prev_move, + apr_hash_t *moves_table, + struct repos_move_info *move, + svn_ra_session_t *ra_session, + const char *repos_root_url, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + apr_array_header_t *moves; + apr_array_header_t *revisions; + apr_pool_t *iterpool; + int i; + + *prev_move = NULL; + revisions = svn_sort__hash(moves_table, compare_items_as_revs_reverse, + scratch_pool); + iterpool = svn_pool_create(scratch_pool); + for (i = 0; i < revisions->nelts; i++) + { + svn_sort__item_t item = APR_ARRAY_IDX(revisions, i, svn_sort__item_t); + svn_revnum_t rev = *(svn_revnum_t *)item.key; + + svn_pool_clear(iterpool); + + if (rev >= move->rev) + continue; + + moves = apr_hash_get(moves_table, &rev, sizeof(rev)); + SVN_ERR(find_prev_move_in_revision(prev_move, moves, move, + ra_session, repos_root_url, + result_pool, iterpool)); + if (*prev_move) + break; + } + svn_pool_destroy(iterpool); + + return SVN_NO_ERROR; +} + + +/* Trace all past moves of the node moved by MOVE. + * Update MOVE->PREV and MOVE->NEXT accordingly. */ +static svn_error_t * +trace_moved_node_backwards(apr_hash_t *moves_table, + struct repos_move_info *move, + svn_ra_session_t *ra_session, + const char *repos_root_url, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + struct repos_move_info *prev_move; + + SVN_ERR(find_prev_move(&prev_move, moves_table, move, + ra_session, repos_root_url, + result_pool, scratch_pool)); + if (prev_move) + { + move->prev = prev_move; + prev_move->next = apr_array_make(result_pool, 1, + sizeof(struct repos_move_info *)); + APR_ARRAY_PUSH(prev_move->next, struct repos_move_info *) = move; + + SVN_ERR(trace_moved_node_backwards(moves_table, prev_move, + ra_session, repos_root_url, + result_pool, scratch_pool)); + } + + return SVN_NO_ERROR; +} + +static svn_error_t * +reparent_session_and_fetch_node_kind(svn_node_kind_t *node_kind, + svn_ra_session_t *ra_session, + const char *url, + svn_revnum_t peg_rev, + apr_pool_t *scratch_pool) +{ + svn_error_t *err; + + err = svn_ra_reparent(ra_session, url, scratch_pool); + if (err) + { + if (err->apr_err == SVN_ERR_RA_ILLEGAL_URL) + { + svn_error_clear(err); + *node_kind = svn_node_unknown; + return SVN_NO_ERROR; + } + + return svn_error_trace(err); + } + + SVN_ERR(svn_ra_check_path(ra_session, "", peg_rev, node_kind, scratch_pool)); + + return SVN_NO_ERROR; +} + +/* Scan MOVES_TABLE for moves which affect a particular deleted node, and + * build a set of new move information for this node. + * Return heads of all possible move chains in *MOVES. + * + * MOVES_TABLE describes moves which happened at arbitrary paths in the + * repository. DELETED_REPOS_RELPATH may have been moved directly or it + * may have been moved along with a parent path. Move information returned + * from this function represents how DELETED_REPOS_RELPATH itself was moved + * from one path to another, effectively "zooming in" on the effective move + * operations which occurred for this particular node. */ +static svn_error_t * +find_operative_moves(apr_array_header_t **moves, + apr_hash_t *moves_table, + const char *deleted_repos_relpath, + svn_revnum_t deleted_rev, + svn_ra_session_t *ra_session, + const char *repos_root_url, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + apr_array_header_t *moves_in_deleted_rev; + int i; + apr_pool_t *iterpool; + const char *session_url, *url = NULL; + + moves_in_deleted_rev = apr_hash_get(moves_table, &deleted_rev, + sizeof(deleted_rev)); + if (moves_in_deleted_rev == NULL) + { + *moves = NULL; + return SVN_NO_ERROR; + } + + SVN_ERR(svn_ra_get_session_url(ra_session, &session_url, scratch_pool)); + + /* Look for operative moves in the revision where the node was deleted. */ + *moves = apr_array_make(scratch_pool, 0, sizeof(struct repos_move_info *)); + iterpool = svn_pool_create(scratch_pool); + for (i = 0; i < moves_in_deleted_rev->nelts; i++) + { + struct repos_move_info *move; + const char *relpath; + + svn_pool_clear(iterpool); + + move = APR_ARRAY_IDX(moves_in_deleted_rev, i, struct repos_move_info *); + relpath = svn_relpath_skip_ancestor(move->moved_from_repos_relpath, + deleted_repos_relpath); + if (relpath && relpath[0] != '\0') + { + svn_node_kind_t node_kind; + + url = svn_path_url_add_component2(repos_root_url, + deleted_repos_relpath, + iterpool); + SVN_ERR(reparent_session_and_fetch_node_kind(&node_kind, + ra_session, url, + rev_below(deleted_rev), + iterpool)); + move = new_path_adjusted_move(move, relpath, node_kind, result_pool); + } + APR_ARRAY_PUSH(*moves, struct repos_move_info *) = move; + } + + if (url != NULL) + SVN_ERR(svn_ra_reparent(ra_session, session_url, scratch_pool)); + + /* If we didn't find any applicable moves, return NULL. */ + if ((*moves)->nelts == 0) + { + *moves = NULL; + svn_pool_destroy(iterpool); + return SVN_NO_ERROR; + } + + /* Figure out what happened to these moves in future revisions. */ + for (i = 0; i < (*moves)->nelts; i++) + { + struct repos_move_info *move; + + svn_pool_clear(iterpool); + + move = APR_ARRAY_IDX(*moves, i, struct repos_move_info *); + SVN_ERR(trace_moved_node(moves_table, move, ra_session, repos_root_url, + result_pool, iterpool)); + } + + svn_pool_destroy(iterpool); + return SVN_NO_ERROR; +} + +/* Try to find a revision older than START_REV, and its author, which deleted + * DELETED_BASENAME in the directory PARENT_REPOS_RELPATH. Assume the deleted + * node is ancestrally related to RELATED_REPOS_RELPATH@RELATED_PEG_REV. + * If no such revision can be found, set *DELETED_REV to SVN_INVALID_REVNUM + * and *DELETED_REV_AUTHOR to NULL. + * If the node was replaced rather than deleted, set *REPLACING_NODE_KIND to + * the node kind of the replacing node. Else, set it to svn_node_unknown. + * Only request the log for revisions up to END_REV from the server. + * If the deleted node was moved, provide heads of move chains in *MOVES. + * If the node was not moved,set *MOVES to NULL. + */ +static svn_error_t * +find_revision_for_suspected_deletion(svn_revnum_t *deleted_rev, + const char **deleted_rev_author, + svn_node_kind_t *replacing_node_kind, + struct apr_array_header_t **moves, + svn_client_conflict_t *conflict, + const char *deleted_basename, + const char *parent_repos_relpath, + svn_revnum_t start_rev, + svn_revnum_t end_rev, + const char *related_repos_relpath, + svn_revnum_t related_peg_rev, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_ra_session_t *ra_session; + const char *url; + const char *corrected_url; + apr_array_header_t *paths; + apr_array_header_t *revprops; + const char *repos_root_url; + const char *repos_uuid; + struct find_deleted_rev_baton b = { 0 }; + const char *victim_abspath; + svn_error_t *err; + apr_hash_t *moves_table; + + SVN_ERR_ASSERT(start_rev > end_rev); + + SVN_ERR(svn_client_conflict_get_repos_info(&repos_root_url, &repos_uuid, + conflict, scratch_pool, + scratch_pool)); + victim_abspath = svn_client_conflict_get_local_abspath(conflict); + + SVN_ERR(find_moves_in_revision_range(&moves_table, parent_repos_relpath, + repos_root_url, repos_uuid, + victim_abspath, start_rev, end_rev, + ctx, result_pool, scratch_pool)); + + url = svn_path_url_add_component2(repos_root_url, parent_repos_relpath, + scratch_pool); + SVN_ERR(svn_client__open_ra_session_internal(&ra_session, &corrected_url, + url, NULL, NULL, FALSE, FALSE, + ctx, scratch_pool, + scratch_pool)); + + paths = apr_array_make(scratch_pool, 1, sizeof(const char *)); + APR_ARRAY_PUSH(paths, const char *) = ""; + + revprops = apr_array_make(scratch_pool, 1, sizeof(const char *)); + APR_ARRAY_PUSH(revprops, const char *) = SVN_PROP_REVISION_AUTHOR; + + b.victim_abspath = victim_abspath; + b.deleted_repos_relpath = svn_relpath_join(parent_repos_relpath, + deleted_basename, scratch_pool); + b.related_repos_relpath = related_repos_relpath; + b.related_peg_rev = related_peg_rev; + b.deleted_rev = SVN_INVALID_REVNUM; + b.replacing_node_kind = svn_node_unknown; + b.repos_root_url = repos_root_url; + b.repos_uuid = repos_uuid; + b.ctx = ctx; + b.moves_table = moves_table; + b.result_pool = result_pool; + SVN_ERR(svn_ra__dup_session(&b.extra_ra_session, ra_session, NULL, + scratch_pool, scratch_pool)); + + err = svn_ra_get_log2(ra_session, paths, start_rev, end_rev, + 0, /* no limit */ + TRUE, /* need the changed paths list */ + FALSE, /* need to traverse copies */ + FALSE, /* no need for merged revisions */ + revprops, + find_deleted_rev, &b, + scratch_pool); + if (err) + { + if (err->apr_err == SVN_ERR_CEASE_INVOCATION && + b.deleted_rev != SVN_INVALID_REVNUM) + + { + /* Log operation was aborted because we found deleted rev. */ + svn_error_clear(err); + } + else + return svn_error_trace(err); + } + + if (b.deleted_rev == SVN_INVALID_REVNUM) + { + struct repos_move_info *move = b.move; + + if (move) + { + *deleted_rev = move->rev; + *deleted_rev_author = move->rev_author; + *replacing_node_kind = b.replacing_node_kind; + SVN_ERR(find_operative_moves(moves, moves_table, + b.deleted_repos_relpath, + move->rev, + ra_session, repos_root_url, + result_pool, scratch_pool)); + } + else + { + /* We could not determine the revision in which the node was + * deleted. */ + *deleted_rev = SVN_INVALID_REVNUM; + *deleted_rev_author = NULL; + *replacing_node_kind = svn_node_unknown; + *moves = NULL; + } + return SVN_NO_ERROR; + } + else + { + *deleted_rev = b.deleted_rev; + *deleted_rev_author = b.deleted_rev_author; + *replacing_node_kind = b.replacing_node_kind; + SVN_ERR(find_operative_moves(moves, moves_table, + b.deleted_repos_relpath, b.deleted_rev, + ra_session, repos_root_url, + result_pool, scratch_pool)); + } + + return SVN_NO_ERROR; +} + +/* Details for tree conflicts involving a locally missing node. */ +struct conflict_tree_local_missing_details +{ + /* If not SVN_INVALID_REVNUM, the node was deleted in DELETED_REV. */ + svn_revnum_t deleted_rev; + + /* Author who committed DELETED_REV. */ + const char *deleted_rev_author; + + /* The path which was deleted relative to the repository root. */ + const char *deleted_repos_relpath; + + /* Move information about the conflict victim. If not NULL, this is an + * array of repos_move_info elements. Each element is the head of a + * move chain which starts in DELETED_REV. */ + apr_array_header_t *moves; + + /* Move information about siblings. Siblings are nodes which share + * a youngest common ancestor with the conflict victim. E.g. in case + * of a merge operation they are part of the merge source branch. + * If not NULL, this is an array of repos_move_info elements. + * Each element is the head of a move chain, which starts at some + * point in history after siblings and conflict victim forked off + * their common ancestor. */ + apr_array_header_t *sibling_moves; + + /* If not NULL, this is the move target abspath. */ + const char *moved_to_abspath; +}; + +static svn_error_t * +find_related_node(const char **related_repos_relpath, + svn_revnum_t *related_peg_rev, + const char *younger_related_repos_relpath, + svn_revnum_t younger_related_peg_rev, + const char *older_repos_relpath, + svn_revnum_t older_peg_rev, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + const char *repos_root_url; + const char *related_url; + const char *corrected_url; + svn_node_kind_t related_node_kind; + svn_ra_session_t *ra_session; + + *related_repos_relpath = NULL; + *related_peg_rev = SVN_INVALID_REVNUM; + + SVN_ERR(svn_client_conflict_get_repos_info(&repos_root_url, NULL, + conflict, + scratch_pool, scratch_pool)); + related_url = svn_path_url_add_component2(repos_root_url, + younger_related_repos_relpath, + scratch_pool); + SVN_ERR(svn_client__open_ra_session_internal(&ra_session, + &corrected_url, + related_url, NULL, + NULL, + FALSE, + FALSE, + ctx, + scratch_pool, + scratch_pool)); + SVN_ERR(svn_ra_check_path(ra_session, "", younger_related_peg_rev, + &related_node_kind, scratch_pool)); + if (related_node_kind == svn_node_none) + { + svn_revnum_t related_deleted_rev; + const char *related_deleted_rev_author; + svn_node_kind_t related_replacing_node_kind; + const char *related_basename; + const char *related_parent_repos_relpath; + apr_array_header_t *related_moves; + + /* Looks like the younger node, which we'd like to use as our + * 'related node', was deleted. Try to find its deleted revision + * so we can calculate a peg revision at which it exists. + * The younger node is related to the older node, so we can use + * the older node to guide us in our search. */ + related_basename = svn_relpath_basename(younger_related_repos_relpath, + scratch_pool); + related_parent_repos_relpath = + svn_relpath_dirname(younger_related_repos_relpath, scratch_pool); + SVN_ERR(find_revision_for_suspected_deletion( + &related_deleted_rev, &related_deleted_rev_author, + &related_replacing_node_kind, &related_moves, + conflict, related_basename, + related_parent_repos_relpath, + younger_related_peg_rev, 0, + older_repos_relpath, older_peg_rev, + ctx, conflict->pool, scratch_pool)); + + /* If we can't find a related node, bail. */ + if (related_deleted_rev == SVN_INVALID_REVNUM) + return SVN_NO_ERROR; + + /* The node should exist in the revision before it was deleted. */ + *related_repos_relpath = younger_related_repos_relpath; + *related_peg_rev = rev_below(related_deleted_rev); + } + else + { + *related_repos_relpath = younger_related_repos_relpath; + *related_peg_rev = younger_related_peg_rev; + } + + return SVN_NO_ERROR; +} + +/* Determine if REPOS_RELPATH@PEG_REV was moved at some point in its history. + * History's range of interest ends at END_REV which must be older than PEG_REV. + * + * VICTIM_ABSPATH is the abspath of a conflict victim in the working copy and + * will be used in notifications. + * + * Return any applicable move chain heads in *MOVES. + * If no moves can be found, set *MOVES to NULL. */ +static svn_error_t * +find_moves_in_natural_history(apr_array_header_t **moves, + const char *repos_relpath, + svn_revnum_t peg_rev, + svn_node_kind_t node_kind, + svn_revnum_t end_rev, + const char *victim_abspath, + const char *repos_root_url, + const char *repos_uuid, + svn_ra_session_t *ra_session, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + apr_hash_t *moves_table; + apr_array_header_t *revs; + apr_array_header_t *most_recent_moves = NULL; + int i; + apr_pool_t *iterpool; + + *moves = NULL; + + SVN_ERR(find_moves_in_revision_range(&moves_table, repos_relpath, + repos_root_url, repos_uuid, + victim_abspath, peg_rev, end_rev, + ctx, scratch_pool, scratch_pool)); + + iterpool = svn_pool_create(scratch_pool); + + /* Scan the moves table for applicable moves. */ + revs = svn_sort__hash(moves_table, compare_items_as_revs, scratch_pool); + for (i = revs->nelts - 1; i >= 0; i--) + { + svn_sort__item_t item = APR_ARRAY_IDX(revs, i, svn_sort__item_t); + apr_array_header_t *moves_in_rev = apr_hash_get(moves_table, item.key, + sizeof(svn_revnum_t)); + int j; + + svn_pool_clear(iterpool); + + /* Was repos relpath moved to its location in this revision? */ + for (j = 0; j < moves_in_rev->nelts; j++) + { + struct repos_move_info *move; + const char *relpath; + + move = APR_ARRAY_IDX(moves_in_rev, j, struct repos_move_info *); + relpath = svn_relpath_skip_ancestor(move->moved_to_repos_relpath, + repos_relpath); + if (relpath) + { + /* If the move did not happen in our peg revision, make + * sure this move happened on the same line of history. */ + if (move->rev != peg_rev) + { + svn_client__pathrev_t *yca_loc; + svn_error_t *err; + + err = find_yca(&yca_loc, repos_relpath, peg_rev, + repos_relpath, move->rev, + repos_root_url, repos_uuid, + NULL, ctx, iterpool, iterpool); + if (err) + { + if (err->apr_err == SVN_ERR_FS_NOT_FOUND) + { + svn_error_clear(err); + yca_loc = NULL; + } + else + return svn_error_trace(err); + } + + if (yca_loc == NULL || yca_loc->rev != move->rev) + continue; + } + + if (most_recent_moves == NULL) + most_recent_moves = + apr_array_make(result_pool, 1, + sizeof(struct repos_move_info *)); + + /* Copy the move to result pool (even if relpath is ""). */ + move = new_path_adjusted_move(move, relpath, node_kind, + result_pool); + APR_ARRAY_PUSH(most_recent_moves, + struct repos_move_info *) = move; + } + } + + /* If we found one move, or several ambiguous moves, we're done. */ + if (most_recent_moves) + break; + } + + if (most_recent_moves && most_recent_moves->nelts > 0) + { + *moves = apr_array_make(result_pool, 1, + sizeof(struct repos_move_info *)); + + /* Figure out what happened to the most recent moves in prior + * revisions and build move chains. */ + for (i = 0; i < most_recent_moves->nelts; i++) + { + struct repos_move_info *move; + + svn_pool_clear(iterpool); + + move = APR_ARRAY_IDX(most_recent_moves, i, struct repos_move_info *); + SVN_ERR(trace_moved_node_backwards(moves_table, move, + ra_session, repos_root_url, + result_pool, iterpool)); + /* Follow the move chain backwards. */ + while (move->prev) + move = move->prev; + + /* Return move heads. */ + APR_ARRAY_PUSH(*moves, struct repos_move_info *) = move; + } + } + + svn_pool_destroy(iterpool); + + return SVN_NO_ERROR; +} + +/* Implements tree_conflict_get_details_func_t. */ +static svn_error_t * +conflict_tree_get_details_local_missing(svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + const char *old_repos_relpath; + const char *new_repos_relpath; + const char *parent_repos_relpath; + svn_revnum_t parent_peg_rev; + svn_revnum_t old_rev; + svn_revnum_t new_rev; + svn_revnum_t deleted_rev; + const char *deleted_rev_author; + svn_node_kind_t replacing_node_kind; + const char *deleted_basename; + struct conflict_tree_local_missing_details *details; + apr_array_header_t *moves = NULL; + apr_array_header_t *sibling_moves = NULL; + const char *related_repos_relpath; + svn_revnum_t related_peg_rev; + const char *repos_root_url; + const char *repos_uuid; + + SVN_ERR(svn_client_conflict_get_incoming_old_repos_location( + &old_repos_relpath, &old_rev, NULL, conflict, + scratch_pool, scratch_pool)); + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + &new_repos_relpath, &new_rev, NULL, conflict, + scratch_pool, scratch_pool)); + + /* Scan the conflict victim's parent's log to find a revision which + * deleted the node. */ + deleted_basename = svn_dirent_basename(conflict->local_abspath, + scratch_pool); + SVN_ERR(svn_wc__node_get_repos_info(&parent_peg_rev, &parent_repos_relpath, + &repos_root_url, &repos_uuid, + ctx->wc_ctx, + svn_dirent_dirname( + conflict->local_abspath, + scratch_pool), + scratch_pool, + scratch_pool)); + + /* Pick the younger incoming node as our 'related node' which helps + * pin-pointing the deleted conflict victim in history. */ + related_repos_relpath = + (old_rev < new_rev ? new_repos_relpath : old_repos_relpath); + related_peg_rev = (old_rev < new_rev ? new_rev : old_rev); + + /* Make sure we're going to search the related node in a revision where + * it exists. The younger incoming node might have been deleted in HEAD. */ + if (related_repos_relpath != NULL && related_peg_rev != SVN_INVALID_REVNUM) + SVN_ERR(find_related_node( + &related_repos_relpath, &related_peg_rev, + related_repos_relpath, related_peg_rev, + (old_rev < new_rev ? old_repos_relpath : new_repos_relpath), + (old_rev < new_rev ? old_rev : new_rev), + conflict, ctx, scratch_pool, scratch_pool)); + + SVN_ERR(find_revision_for_suspected_deletion( + &deleted_rev, &deleted_rev_author, &replacing_node_kind, &moves, + conflict, deleted_basename, parent_repos_relpath, + parent_peg_rev, 0, related_repos_relpath, related_peg_rev, + ctx, conflict->pool, scratch_pool)); + + /* If the victim was not deleted then check if the related path was moved. */ + if (deleted_rev == SVN_INVALID_REVNUM) + { + const char *victim_abspath; + svn_ra_session_t *ra_session; + const char *url, *corrected_url; + svn_client__pathrev_t *yca_loc; + svn_revnum_t end_rev; + svn_node_kind_t related_node_kind; + + /* ### The following describes all moves in terms of forward-merges, + * should do we something else for reverse-merges? */ + + victim_abspath = svn_client_conflict_get_local_abspath(conflict); + url = svn_path_url_add_component2(repos_root_url, related_repos_relpath, + scratch_pool); + SVN_ERR(svn_client__open_ra_session_internal(&ra_session, + &corrected_url, + url, NULL, NULL, + FALSE, + FALSE, + ctx, + scratch_pool, + scratch_pool)); + + /* Set END_REV to our best guess of the nearest YCA revision. */ + SVN_ERR(find_nearest_yca(&yca_loc, related_repos_relpath, related_peg_rev, + parent_repos_relpath, parent_peg_rev, + repos_root_url, repos_uuid, ra_session, ctx, + scratch_pool, scratch_pool)); + if (yca_loc == NULL) + return SVN_NO_ERROR; + end_rev = yca_loc->rev; + + /* END_REV must be smaller than RELATED_PEG_REV, else the call + to find_moves_in_natural_history() below will error out. */ + if (end_rev >= related_peg_rev) + end_rev = related_peg_rev > 0 ? related_peg_rev - 1 : 0; + + SVN_ERR(svn_ra_check_path(ra_session, "", related_peg_rev, + &related_node_kind, scratch_pool)); + SVN_ERR(find_moves_in_natural_history(&sibling_moves, + related_repos_relpath, + related_peg_rev, + related_node_kind, + end_rev, + victim_abspath, + repos_root_url, repos_uuid, + ra_session, ctx, + conflict->pool, scratch_pool)); + + if (sibling_moves == NULL) + return SVN_NO_ERROR; + + /* ## TODO: Find the missing node in the WC. */ + } + + details = apr_pcalloc(conflict->pool, sizeof(*details)); + details->deleted_rev = deleted_rev; + details->deleted_rev_author = deleted_rev_author; + if (deleted_rev != SVN_INVALID_REVNUM) + details->deleted_repos_relpath = svn_relpath_join(parent_repos_relpath, + deleted_basename, + conflict->pool); + details->moves = moves; + details->sibling_moves = sibling_moves; + + conflict->tree_conflict_local_details = details; + + return SVN_NO_ERROR; +} + +/* Return a localised string representation of the local part of a tree + conflict on a non-existent node. */ +static svn_error_t * +describe_local_none_node_change(const char **description, + svn_client_conflict_t *conflict, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_wc_conflict_reason_t local_change; + svn_wc_operation_t operation; + + local_change = svn_client_conflict_get_local_change(conflict); + operation = svn_client_conflict_get_operation(conflict); + + switch (local_change) + { + case svn_wc_conflict_reason_edited: + *description = _("An item containing uncommitted changes was " + "found in the working copy."); + break; + case svn_wc_conflict_reason_obstructed: + *description = _("An item which already occupies this path was found in " + "the working copy."); + break; + case svn_wc_conflict_reason_deleted: + *description = _("A deleted item was found in the working copy."); + break; + case svn_wc_conflict_reason_missing: + if (operation == svn_wc_operation_update || + operation == svn_wc_operation_switch) + *description = _("No such file or directory was found in the " + "working copy."); + else if (operation == svn_wc_operation_merge) + { + /* ### display deleted revision */ + *description = _("No such file or directory was found in the " + "merge target working copy.\nThe item may " + "have been deleted or moved away in the " + "repository's history."); + } + break; + case svn_wc_conflict_reason_unversioned: + *description = _("An unversioned item was found in the working " + "copy."); + break; + case svn_wc_conflict_reason_added: + case svn_wc_conflict_reason_replaced: + *description = _("An item scheduled to be added to the repository " + "in the next commit was found in the working " + "copy."); + break; + case svn_wc_conflict_reason_moved_away: + *description = _("The item in the working copy had been moved " + "away at the time this conflict was recorded."); + break; + case svn_wc_conflict_reason_moved_here: + *description = _("An item had been moved here in the working copy " + "at the time this conflict was recorded."); + break; + } + + return SVN_NO_ERROR; +} + +/* Append a description of a move chain beginning at NEXT to DESCRIPTION. */ +static const char * +append_moved_to_chain_description(const char *description, + apr_array_header_t *next, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + if (next == NULL) + return description; + + while (next) + { + struct repos_move_info *move; + + /* Describe the first possible move chain only. Adding multiple chains + * to the description would just be confusing. The user may select a + * different move destination while resolving the conflict. */ + move = APR_ARRAY_IDX(next, 0, struct repos_move_info *); + + description = apr_psprintf(scratch_pool, + _("%s\nAnd then moved away to '^/%s' by " + "%s in r%ld."), + description, move->moved_to_repos_relpath, + move->rev_author, move->rev); + next = move->next; + } + + return apr_pstrdup(result_pool, description); +} + +/* Implements tree_conflict_get_description_func_t. */ +static svn_error_t * +conflict_tree_get_local_description_generic(const char **description, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_node_kind_t victim_node_kind; + + victim_node_kind = svn_client_conflict_tree_get_victim_node_kind(conflict); + + *description = NULL; + + switch (victim_node_kind) + { + case svn_node_file: + case svn_node_symlink: + SVN_ERR(describe_local_file_node_change(description, conflict, ctx, + result_pool, scratch_pool)); + break; + case svn_node_dir: + SVN_ERR(describe_local_dir_node_change(description, conflict, ctx, + result_pool, scratch_pool)); + break; + case svn_node_none: + case svn_node_unknown: + SVN_ERR(describe_local_none_node_change(description, conflict, + result_pool, scratch_pool)); + break; + } + + return SVN_NO_ERROR; +} + +/* Implements tree_conflict_get_description_func_t. */ +static svn_error_t * +conflict_tree_get_description_local_missing(const char **description, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + struct conflict_tree_local_missing_details *details; + + details = conflict->tree_conflict_local_details; + if (details == NULL) + return svn_error_trace(conflict_tree_get_local_description_generic( + description, conflict, ctx, + result_pool, scratch_pool)); + + if (details->moves || details->sibling_moves) + { + struct repos_move_info *move; + + *description = _("No such file or directory was found in the " + "merge target working copy.\n"); + + if (details->moves) + { + move = APR_ARRAY_IDX(details->moves, 0, struct repos_move_info *); + if (move->node_kind == svn_node_file) + *description = apr_psprintf( + result_pool, + _("%sThe file was moved to '^/%s' in r%ld by %s."), + *description, move->moved_to_repos_relpath, + move->rev, move->rev_author); + else if (move->node_kind == svn_node_dir) + *description = apr_psprintf( + result_pool, + _("%sThe directory was moved to '^/%s' in " + "r%ld by %s."), + *description, move->moved_to_repos_relpath, + move->rev, move->rev_author); + else + *description = apr_psprintf( + result_pool, + _("%sThe item was moved to '^/%s' in r%ld by %s."), + *description, move->moved_to_repos_relpath, + move->rev, move->rev_author); + *description = append_moved_to_chain_description(*description, + move->next, + result_pool, + scratch_pool); + } + + if (details->sibling_moves) + { + move = APR_ARRAY_IDX(details->sibling_moves, 0, + struct repos_move_info *); + if (move->node_kind == svn_node_file) + *description = apr_psprintf( + result_pool, + _("%sThe file '^/%s' was moved to '^/%s' " + "in r%ld by %s."), + *description, move->moved_from_repos_relpath, + move->moved_to_repos_relpath, + move->rev, move->rev_author); + else if (move->node_kind == svn_node_dir) + *description = apr_psprintf( + result_pool, + _("%sThe directory '^/%s' was moved to '^/%s' " + "in r%ld by %s."), + *description, move->moved_from_repos_relpath, + move->moved_to_repos_relpath, + move->rev, move->rev_author); + else + *description = apr_psprintf( + result_pool, + _("%sThe item '^/%s' was moved to '^/%s' " + "in r%ld by %s."), + *description, move->moved_from_repos_relpath, + move->moved_to_repos_relpath, + move->rev, move->rev_author); + *description = append_moved_to_chain_description(*description, + move->next, + result_pool, + scratch_pool); + } + } + else + *description = apr_psprintf( + result_pool, + _("No such file or directory was found in the " + "merge target working copy.\n'^/%s' was deleted " + "in r%ld by %s."), + details->deleted_repos_relpath, + details->deleted_rev, details->deleted_rev_author); + + return SVN_NO_ERROR; +} + +/* Return a localised string representation of the incoming part of a + conflict; NULL for non-localised odd cases. */ +static const char * +describe_incoming_change(svn_node_kind_t kind, svn_wc_conflict_action_t action, + svn_wc_operation_t operation) +{ + switch (kind) + { + case svn_node_file: + case svn_node_symlink: + if (operation == svn_wc_operation_update) + { + switch (action) + { + case svn_wc_conflict_action_edit: + return _("An update operation tried to edit a file."); + case svn_wc_conflict_action_add: + return _("An update operation tried to add a file."); + case svn_wc_conflict_action_delete: + return _("An update operation tried to delete or move " + "a file."); + case svn_wc_conflict_action_replace: + return _("An update operation tried to replace a file."); + } + } + else if (operation == svn_wc_operation_switch) + { + switch (action) + { + case svn_wc_conflict_action_edit: + return _("A switch operation tried to edit a file."); + case svn_wc_conflict_action_add: + return _("A switch operation tried to add a file."); + case svn_wc_conflict_action_delete: + return _("A switch operation tried to delete or move " + "a file."); + case svn_wc_conflict_action_replace: + return _("A switch operation tried to replace a file."); + } + } + else if (operation == svn_wc_operation_merge) + { + switch (action) + { + case svn_wc_conflict_action_edit: + return _("A merge operation tried to edit a file."); + case svn_wc_conflict_action_add: + return _("A merge operation tried to add a file."); + case svn_wc_conflict_action_delete: + return _("A merge operation tried to delete or move " + "a file."); + case svn_wc_conflict_action_replace: + return _("A merge operation tried to replace a file."); + } + } + break; + case svn_node_dir: + if (operation == svn_wc_operation_update) + { + switch (action) + { + case svn_wc_conflict_action_edit: + return _("An update operation tried to change a directory."); + case svn_wc_conflict_action_add: + return _("An update operation tried to add a directory."); + case svn_wc_conflict_action_delete: + return _("An update operation tried to delete or move " + "a directory."); + case svn_wc_conflict_action_replace: + return _("An update operation tried to replace a directory."); + } + } + else if (operation == svn_wc_operation_switch) + { + switch (action) + { + case svn_wc_conflict_action_edit: + return _("A switch operation tried to edit a directory."); + case svn_wc_conflict_action_add: + return _("A switch operation tried to add a directory."); + case svn_wc_conflict_action_delete: + return _("A switch operation tried to delete or move " + "a directory."); + case svn_wc_conflict_action_replace: + return _("A switch operation tried to replace a directory."); + } + } + else if (operation == svn_wc_operation_merge) + { + switch (action) + { + case svn_wc_conflict_action_edit: + return _("A merge operation tried to edit a directory."); + case svn_wc_conflict_action_add: + return _("A merge operation tried to add a directory."); + case svn_wc_conflict_action_delete: + return _("A merge operation tried to delete or move " + "a directory."); + case svn_wc_conflict_action_replace: + return _("A merge operation tried to replace a directory."); + } + } + break; + case svn_node_none: + case svn_node_unknown: + if (operation == svn_wc_operation_update) + { + switch (action) + { + case svn_wc_conflict_action_edit: + return _("An update operation tried to edit an item."); + case svn_wc_conflict_action_add: + return _("An update operation tried to add an item."); + case svn_wc_conflict_action_delete: + return _("An update operation tried to delete or move " + "an item."); + case svn_wc_conflict_action_replace: + return _("An update operation tried to replace an item."); + } + } + else if (operation == svn_wc_operation_switch) + { + switch (action) + { + case svn_wc_conflict_action_edit: + return _("A switch operation tried to edit an item."); + case svn_wc_conflict_action_add: + return _("A switch operation tried to add an item."); + case svn_wc_conflict_action_delete: + return _("A switch operation tried to delete or move " + "an item."); + case svn_wc_conflict_action_replace: + return _("A switch operation tried to replace an item."); + } + } + else if (operation == svn_wc_operation_merge) + { + switch (action) + { + case svn_wc_conflict_action_edit: + return _("A merge operation tried to edit an item."); + case svn_wc_conflict_action_add: + return _("A merge operation tried to add an item."); + case svn_wc_conflict_action_delete: + return _("A merge operation tried to delete or move " + "an item."); + case svn_wc_conflict_action_replace: + return _("A merge operation tried to replace an item."); + } + } + break; + } + + return NULL; +} + +/* Return a localised string representation of the operation part of a + conflict. */ +static const char * +operation_str(svn_wc_operation_t operation) +{ + switch (operation) + { + case svn_wc_operation_update: return _("upon update"); + case svn_wc_operation_switch: return _("upon switch"); + case svn_wc_operation_merge: return _("upon merge"); + case svn_wc_operation_none: return _("upon none"); + } + SVN_ERR_MALFUNCTION_NO_RETURN(); + return NULL; +} + +svn_error_t * +svn_client_conflict_prop_get_description(const char **description, + svn_client_conflict_t *conflict, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + const char *reason_str, *action_str; + + /* We provide separately translatable strings for the values that we + * know about, and a fall-back in case any other values occur. */ + switch (svn_client_conflict_get_local_change(conflict)) + { + case svn_wc_conflict_reason_edited: + reason_str = _("local edit"); + break; + case svn_wc_conflict_reason_added: + reason_str = _("local add"); + break; + case svn_wc_conflict_reason_deleted: + reason_str = _("local delete"); + break; + case svn_wc_conflict_reason_obstructed: + reason_str = _("local obstruction"); + break; + default: + reason_str = apr_psprintf( + scratch_pool, _("local %s"), + svn_token__to_word( + map_conflict_reason, + svn_client_conflict_get_local_change(conflict))); + break; + } + switch (svn_client_conflict_get_incoming_change(conflict)) + { + case svn_wc_conflict_action_edit: + action_str = _("incoming edit"); + break; + case svn_wc_conflict_action_add: + action_str = _("incoming add"); + break; + case svn_wc_conflict_action_delete: + action_str = _("incoming delete"); + break; + default: + action_str = apr_psprintf( + scratch_pool, _("incoming %s"), + svn_token__to_word( + map_conflict_action, + svn_client_conflict_get_incoming_change(conflict))); + break; + } + SVN_ERR_ASSERT(reason_str && action_str); + + *description = apr_psprintf(result_pool, _("%s, %s %s"), + reason_str, action_str, + operation_str( + svn_client_conflict_get_operation(conflict))); + + return SVN_NO_ERROR; +} + +/* Implements tree_conflict_get_description_func_t. */ +static svn_error_t * +conflict_tree_get_incoming_description_generic( + const char **incoming_change_description, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + const char *action; + svn_node_kind_t incoming_kind; + svn_wc_conflict_action_t conflict_action; + svn_wc_operation_t conflict_operation; + + conflict_action = svn_client_conflict_get_incoming_change(conflict); + conflict_operation = svn_client_conflict_get_operation(conflict); + + /* Determine the node kind of the incoming change. */ + incoming_kind = svn_node_unknown; + if (conflict_action == svn_wc_conflict_action_edit || + conflict_action == svn_wc_conflict_action_delete) + { + /* Change is acting on 'src_left' version of the node. */ + SVN_ERR(svn_client_conflict_get_incoming_old_repos_location( + NULL, NULL, &incoming_kind, conflict, scratch_pool, + scratch_pool)); + } + else if (conflict_action == svn_wc_conflict_action_add || + conflict_action == svn_wc_conflict_action_replace) + { + /* Change is acting on 'src_right' version of the node. + * + * ### For 'replace', the node kind is ambiguous. However, src_left + * ### is NULL for replace, so we must use src_right. */ + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + NULL, NULL, &incoming_kind, conflict, scratch_pool, + scratch_pool)); + } + + action = describe_incoming_change(incoming_kind, conflict_action, + conflict_operation); + if (action) + { + *incoming_change_description = apr_pstrdup(result_pool, action); + } + else + { + /* A catch-all message for very rare or nominally impossible cases. + It will not be pretty, but is closer to an internal error than + an ordinary user-facing string. */ + *incoming_change_description = apr_psprintf(result_pool, + _("incoming %s %s"), + svn_node_kind_to_word(incoming_kind), + svn_token__to_word(map_conflict_action, + conflict_action)); + } + return SVN_NO_ERROR; +} + +/* Details for tree conflicts involving incoming deletions and replacements. */ +struct conflict_tree_incoming_delete_details +{ + /* If not SVN_INVALID_REVNUM, the node was deleted in DELETED_REV. */ + svn_revnum_t deleted_rev; + + /* If not SVN_INVALID_REVNUM, the node was added in ADDED_REV. The incoming + * delete is the result of a reverse application of this addition. */ + svn_revnum_t added_rev; + + /* The path which was deleted/added relative to the repository root. */ + const char *repos_relpath; + + /* Author who committed DELETED_REV/ADDED_REV. */ + const char *rev_author; + + /* New node kind for a replaced node. This is svn_node_none for deletions. */ + svn_node_kind_t replacing_node_kind; + + /* Move information. If not NULL, this is an array of repos_move_info * + * elements. Each element is the head of a move chain which starts in + * DELETED_REV or in ADDED_REV (in which case moves should be interpreted + * in reverse). */ + apr_array_header_t *moves; + + /* A map of repos_relpaths and working copy nodes for an incoming move. + * + * Each key is a "const char *" repository relpath corresponding to a + * possible repository-side move destination node in the revision which + * is the target revision in case of update and switch, or the merge-right + * revision in case of a merge. + * + * Each value is an apr_array_header_t *. + * Each array consists of "const char *" absolute paths to working copy + * nodes which correspond to the repository node selected by the map key. + * Each such working copy node is a potential local move target which can + * be chosen to "follow" the incoming move when resolving a tree conflict. + * + * This may be an empty hash map in case if there is no move target path + * in the working copy. */ + apr_hash_t *wc_move_targets; + + /* The preferred move target repository relpath. This is our key into + * the WC_MOVE_TARGETS map above (can be overridden by the user). */ + const char *move_target_repos_relpath; + + /* The current index into the list of working copy nodes corresponding to + * MOVE_TARGET_REPOS_REPLATH (can be overridden by the user). */ + int wc_move_target_idx; +}; + +/* Get the currently selected repository-side move target path. + * If none was selected yet, determine and return a default one. */ +static const char * +get_moved_to_repos_relpath( + struct conflict_tree_incoming_delete_details *details, + apr_pool_t *scratch_pool) +{ + struct repos_move_info *move; + + if (details->move_target_repos_relpath) + return details->move_target_repos_relpath; + + if (details->wc_move_targets && apr_hash_count(details->wc_move_targets) > 0) + { + svn_sort__item_t item; + apr_array_header_t *repos_relpaths; + + repos_relpaths = svn_sort__hash(details->wc_move_targets, + svn_sort_compare_items_as_paths, + scratch_pool); + item = APR_ARRAY_IDX(repos_relpaths, 0, svn_sort__item_t); + return (const char *)item.key; + } + + move = APR_ARRAY_IDX(details->moves, 0, struct repos_move_info *); + return move->moved_to_repos_relpath; +} + +static const char * +describe_incoming_deletion_upon_update( + struct conflict_tree_incoming_delete_details *details, + svn_node_kind_t victim_node_kind, + svn_revnum_t old_rev, + svn_revnum_t new_rev, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + if (details->replacing_node_kind == svn_node_file || + details->replacing_node_kind == svn_node_symlink) + { + if (victim_node_kind == svn_node_dir) + { + const char *description = + apr_psprintf(result_pool, + _("Directory updated from r%ld to r%ld was " + "replaced with a file by %s in r%ld."), + old_rev, new_rev, + details->rev_author, details->deleted_rev); + if (details->moves) + { + struct repos_move_info *move; + + move = APR_ARRAY_IDX(details->moves, 0, struct repos_move_info *); + description = + apr_psprintf(result_pool, + _("%s\nThe replaced directory was moved to " + "'^/%s'."), description, + get_moved_to_repos_relpath(details, scratch_pool)); + return append_moved_to_chain_description(description, + move->next, + result_pool, + scratch_pool); + } + return description; + } + else if (victim_node_kind == svn_node_file || + victim_node_kind == svn_node_symlink) + { + const char *description = + apr_psprintf(result_pool, + _("File updated from r%ld to r%ld was replaced " + "with a file from another line of history by " + "%s in r%ld."), + old_rev, new_rev, + details->rev_author, details->deleted_rev); + if (details->moves) + { + struct repos_move_info *move; + + move = APR_ARRAY_IDX(details->moves, 0, struct repos_move_info *); + description = + apr_psprintf(result_pool, + _("%s\nThe replaced file was moved to '^/%s'."), + description, + get_moved_to_repos_relpath(details, scratch_pool)); + return append_moved_to_chain_description(description, + move->next, + result_pool, + scratch_pool); + } + return description; + } + else + { + const char *description = + apr_psprintf(result_pool, + _("Item updated from r%ld to r%ld was replaced " + "with a file by %s in r%ld."), old_rev, new_rev, + details->rev_author, details->deleted_rev); + if (details->moves) + { + struct repos_move_info *move; + + move = APR_ARRAY_IDX(details->moves, 0, struct repos_move_info *); + description = + apr_psprintf(result_pool, + _("%s\nThe replaced item was moved to '^/%s'."), + description, + get_moved_to_repos_relpath(details, scratch_pool)); + return append_moved_to_chain_description(description, + move->next, + result_pool, + scratch_pool); + } + return description; + } + } + else if (details->replacing_node_kind == svn_node_dir) + { + if (victim_node_kind == svn_node_dir) + { + const char *description = + apr_psprintf(result_pool, + _("Directory updated from r%ld to r%ld was " + "replaced with a directory from another line " + "of history by %s in r%ld."), + old_rev, new_rev, + details->rev_author, details->deleted_rev); + if (details->moves) + { + struct repos_move_info *move; + + move = APR_ARRAY_IDX(details->moves, 0, struct repos_move_info *); + description = + apr_psprintf(result_pool, + _("%s\nThe replaced directory was moved to " + "'^/%s'."), description, + get_moved_to_repos_relpath(details, scratch_pool)); + return append_moved_to_chain_description(description, + move->next, + result_pool, + scratch_pool); + } + return description; + } + else if (victim_node_kind == svn_node_file || + victim_node_kind == svn_node_symlink) + { + const char *description = + apr_psprintf(result_pool, + _("File updated from r%ld to r%ld was " + "replaced with a directory by %s in r%ld."), + old_rev, new_rev, + details->rev_author, details->deleted_rev); + if (details->moves) + { + struct repos_move_info *move; + + move = APR_ARRAY_IDX(details->moves, 0, struct repos_move_info *); + description = + apr_psprintf(result_pool, + _("%s\nThe replaced file was moved to '^/%s'."), + description, + get_moved_to_repos_relpath(details, scratch_pool)); + return append_moved_to_chain_description(description, + move->next, + result_pool, + scratch_pool); + } + return description; + } + else + { + const char *description = + apr_psprintf(result_pool, + _("Item updated from r%ld to r%ld was replaced " + "by %s in r%ld."), old_rev, new_rev, + details->rev_author, details->deleted_rev); + if (details->moves) + { + struct repos_move_info *move; + + move = APR_ARRAY_IDX(details->moves, 0, struct repos_move_info *); + description = + apr_psprintf(result_pool, + _("%s\nThe replaced item was moved to '^/%s'."), + description, + get_moved_to_repos_relpath(details, scratch_pool)); + return append_moved_to_chain_description(description, + move->next, + result_pool, + scratch_pool); + } + return description; + } + } + else + { + if (victim_node_kind == svn_node_dir) + { + if (details->moves) + { + const char *description; + struct repos_move_info *move; + + move = APR_ARRAY_IDX(details->moves, 0, struct repos_move_info *); + description = + apr_psprintf(result_pool, + _("Directory updated from r%ld to r%ld was " + "moved to '^/%s' by %s in r%ld."), + old_rev, new_rev, + get_moved_to_repos_relpath(details, scratch_pool), + details->rev_author, details->deleted_rev); + return append_moved_to_chain_description(description, + move->next, + result_pool, + scratch_pool); + } + else + return apr_psprintf(result_pool, + _("Directory updated from r%ld to r%ld was " + "deleted by %s in r%ld."), + old_rev, new_rev, + details->rev_author, details->deleted_rev); + } + else if (victim_node_kind == svn_node_file || + victim_node_kind == svn_node_symlink) + { + if (details->moves) + { + struct repos_move_info *move; + const char *description; + + move = APR_ARRAY_IDX(details->moves, 0, struct repos_move_info *); + description = + apr_psprintf(result_pool, + _("File updated from r%ld to r%ld was moved " + "to '^/%s' by %s in r%ld."), old_rev, new_rev, + get_moved_to_repos_relpath(details, scratch_pool), + details->rev_author, details->deleted_rev); + return append_moved_to_chain_description(description, + move->next, + result_pool, + scratch_pool); + } + else + return apr_psprintf(result_pool, + _("File updated from r%ld to r%ld was " + "deleted by %s in r%ld."), old_rev, new_rev, + details->rev_author, details->deleted_rev); + } + else + { + if (details->moves) + { + const char *description; + struct repos_move_info *move; + + move = APR_ARRAY_IDX(details->moves, 0, struct repos_move_info *); + description = + apr_psprintf(result_pool, + _("Item updated from r%ld to r%ld was moved " + "to '^/%s' by %s in r%ld."), old_rev, new_rev, + get_moved_to_repos_relpath(details, scratch_pool), + details->rev_author, details->deleted_rev); + return append_moved_to_chain_description(description, + move->next, + result_pool, + scratch_pool); + } + else + return apr_psprintf(result_pool, + _("Item updated from r%ld to r%ld was " + "deleted by %s in r%ld."), old_rev, new_rev, + details->rev_author, details->deleted_rev); + } + } +} + +static const char * +describe_incoming_reverse_addition_upon_update( + struct conflict_tree_incoming_delete_details *details, + svn_node_kind_t victim_node_kind, + svn_revnum_t old_rev, + svn_revnum_t new_rev, + apr_pool_t *result_pool) +{ + if (details->replacing_node_kind == svn_node_file || + details->replacing_node_kind == svn_node_symlink) + { + if (victim_node_kind == svn_node_dir) + return apr_psprintf(result_pool, + _("Directory updated backwards from r%ld to r%ld " + "was a file before the replacement made by %s " + "in r%ld."), old_rev, new_rev, + details->rev_author, details->added_rev); + else if (victim_node_kind == svn_node_file || + victim_node_kind == svn_node_symlink) + return apr_psprintf(result_pool, + _("File updated backwards from r%ld to r%ld was a " + "file from another line of history before the " + "replacement made by %s in r%ld."), + old_rev, new_rev, + details->rev_author, details->added_rev); + else + return apr_psprintf(result_pool, + _("Item updated backwards from r%ld to r%ld was " + "replaced with a file by %s in r%ld."), + old_rev, new_rev, + details->rev_author, details->added_rev); + } + else if (details->replacing_node_kind == svn_node_dir) + { + if (victim_node_kind == svn_node_dir) + return apr_psprintf(result_pool, + _("Directory updated backwards from r%ld to r%ld " + "was a directory from another line of history " + "before the replacement made by %s in " + "r%ld."), old_rev, new_rev, + details->rev_author, details->added_rev); + else if (victim_node_kind == svn_node_file || + victim_node_kind == svn_node_symlink) + return apr_psprintf(result_pool, + _("File updated backwards from r%ld to r%ld was a " + "directory before the replacement made by %s " + "in r%ld."), old_rev, new_rev, + details->rev_author, details->added_rev); + else + return apr_psprintf(result_pool, + _("Item updated backwards from r%ld to r%ld was " + "replaced with a directory by %s in r%ld."), + old_rev, new_rev, + details->rev_author, details->added_rev); + } + else + { + if (victim_node_kind == svn_node_dir) + return apr_psprintf(result_pool, + _("Directory updated backwards from r%ld to r%ld " + "did not exist before it was added by %s in " + "r%ld."), old_rev, new_rev, + details->rev_author, details->added_rev); + else if (victim_node_kind == svn_node_file || + victim_node_kind == svn_node_symlink) + return apr_psprintf(result_pool, + _("File updated backwards from r%ld to r%ld did " + "not exist before it was added by %s in r%ld."), + old_rev, new_rev, + details->rev_author, details->added_rev); + else + return apr_psprintf(result_pool, + _("Item updated backwards from r%ld to r%ld did " + "not exist before it was added by %s in r%ld."), + old_rev, new_rev, + details->rev_author, details->added_rev); + } +} + +static const char * +describe_incoming_deletion_upon_switch( + struct conflict_tree_incoming_delete_details *details, + svn_node_kind_t victim_node_kind, + const char *old_repos_relpath, + svn_revnum_t old_rev, + const char *new_repos_relpath, + svn_revnum_t new_rev, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + if (details->replacing_node_kind == svn_node_file || + details->replacing_node_kind == svn_node_symlink) + { + if (victim_node_kind == svn_node_dir) + { + const char *description = + apr_psprintf(result_pool, + _("Directory switched from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\n" + "was replaced with a file by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->deleted_rev); + if (details->moves) + { + struct repos_move_info *move; + + move = APR_ARRAY_IDX(details->moves, 0, struct repos_move_info *); + description = + apr_psprintf(result_pool, + _("%s\nThe replaced directory was moved " + "to '^/%s'."), description, + get_moved_to_repos_relpath(details, scratch_pool)); + return append_moved_to_chain_description(description, + move->next, + result_pool, + scratch_pool); + } + return description; + } + else if (victim_node_kind == svn_node_file || + victim_node_kind == svn_node_symlink) + { + const char *description = + apr_psprintf(result_pool, + _("File switched from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\nwas " + "replaced with a file from another line of " + "history by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->deleted_rev); + if (details->moves) + { + struct repos_move_info *move; + + move = APR_ARRAY_IDX(details->moves, 0, struct repos_move_info *); + description = + apr_psprintf(result_pool, + _("%s\nThe replaced file was moved to '^/%s'."), + description, + get_moved_to_repos_relpath(details, scratch_pool)); + return append_moved_to_chain_description(description, + move->next, + result_pool, + scratch_pool); + } + return description; + } + else + { + const char *description = + apr_psprintf(result_pool, + _("Item switched from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\nwas " + "replaced with a file by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->deleted_rev); + if (details->moves) + { + struct repos_move_info *move; + + move = APR_ARRAY_IDX(details->moves, 0, struct repos_move_info *); + description = + apr_psprintf(result_pool, + _("%s\nThe replaced item was moved to '^/%s'."), + description, + get_moved_to_repos_relpath(details, scratch_pool)); + return append_moved_to_chain_description(description, + move->next, + result_pool, + scratch_pool); + } + return description; + } + } + else if (details->replacing_node_kind == svn_node_dir) + { + if (victim_node_kind == svn_node_dir) + { + const char *description = + apr_psprintf(result_pool, + _("Directory switched from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\n" + "was replaced with a directory from another " + "line of history by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->deleted_rev); + if (details->moves) + { + struct repos_move_info *move; + + move = APR_ARRAY_IDX(details->moves, 0, struct repos_move_info *); + description = + apr_psprintf(result_pool, + _("%s\nThe replaced directory was moved to " + "'^/%s'."), description, + get_moved_to_repos_relpath(details, scratch_pool)); + return append_moved_to_chain_description(description, + move->next, + result_pool, + scratch_pool); + } + return description; + } + else if (victim_node_kind == svn_node_file || + victim_node_kind == svn_node_symlink) + { + const char *description = + apr_psprintf(result_pool, + _("File switched from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\n" + "was replaced with a directory by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->deleted_rev); + if (details->moves) + { + struct repos_move_info *move; + + move = APR_ARRAY_IDX(details->moves, 0, struct repos_move_info *); + description = + apr_psprintf(result_pool, + _("%s\nThe replaced file was moved to '^/%s'."), + description, + get_moved_to_repos_relpath(details, scratch_pool)); + return append_moved_to_chain_description(description, + move->next, + result_pool, + scratch_pool); + } + return description; + } + else + { + const char *description = + apr_psprintf(result_pool, + _("Item switched from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\nwas " + "replaced with a directory by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->deleted_rev); + if (details->moves) + { + struct repos_move_info *move; + + move = APR_ARRAY_IDX(details->moves, 0, struct repos_move_info *); + description = + apr_psprintf(result_pool, + _("%s\nThe replaced item was moved to '^/%s'."), + description, + get_moved_to_repos_relpath(details, scratch_pool)); + return append_moved_to_chain_description(description, + move->next, + result_pool, + scratch_pool); + } + return description; + } + } + else + { + if (victim_node_kind == svn_node_dir) + { + if (details->moves) + { + struct repos_move_info *move; + const char *description; + + move = APR_ARRAY_IDX(details->moves, 0, struct repos_move_info *); + description = + apr_psprintf(result_pool, + _("Directory switched from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\n" + "was moved to '^/%s' by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + get_moved_to_repos_relpath(details, scratch_pool), + details->rev_author, details->deleted_rev); + return append_moved_to_chain_description(description, + move->next, + result_pool, + scratch_pool); + } + else + return apr_psprintf(result_pool, + _("Directory switched from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\n" + "was deleted by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->deleted_rev); + } + else if (victim_node_kind == svn_node_file || + victim_node_kind == svn_node_symlink) + { + if (details->moves) + { + struct repos_move_info *move; + const char *description; + + move = APR_ARRAY_IDX(details->moves, 0, struct repos_move_info *); + description = + apr_psprintf(result_pool, + _("File switched from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\nwas " + "moved to '^/%s' by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + get_moved_to_repos_relpath(details, scratch_pool), + details->rev_author, details->deleted_rev); + return append_moved_to_chain_description(description, + move->next, + result_pool, + scratch_pool); + } + else + return apr_psprintf(result_pool, + _("File switched from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\nwas " + "deleted by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->deleted_rev); + } + else + { + if (details->moves) + { + struct repos_move_info *move; + const char *description; + + move = APR_ARRAY_IDX(details->moves, 0, struct repos_move_info *); + description = + apr_psprintf(result_pool, + _("Item switched from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\nwas " + "moved to '^/%s' by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + get_moved_to_repos_relpath(details, scratch_pool), + details->rev_author, details->deleted_rev); + return append_moved_to_chain_description(description, + move->next, + result_pool, + scratch_pool); + } + else + return apr_psprintf(result_pool, + _("Item switched from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\nwas " + "deleted by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->deleted_rev); + } + } +} + +static const char * +describe_incoming_reverse_addition_upon_switch( + struct conflict_tree_incoming_delete_details *details, + svn_node_kind_t victim_node_kind, + const char *old_repos_relpath, + svn_revnum_t old_rev, + const char *new_repos_relpath, + svn_revnum_t new_rev, + apr_pool_t *result_pool) +{ + if (details->replacing_node_kind == svn_node_file || + details->replacing_node_kind == svn_node_symlink) + { + if (victim_node_kind == svn_node_dir) + return apr_psprintf(result_pool, + _("Directory switched from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\n" + "was a file before the replacement made by %s " + "in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->added_rev); + else if (victim_node_kind == svn_node_file || + victim_node_kind == svn_node_symlink) + return apr_psprintf(result_pool, + _("File switched from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\nwas a " + "file from another line of history before the " + "replacement made by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->added_rev); + else + return apr_psprintf(result_pool, + _("Item switched from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\nwas " + "replaced with a file by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->added_rev); + } + else if (details->replacing_node_kind == svn_node_dir) + { + if (victim_node_kind == svn_node_dir) + return apr_psprintf(result_pool, + _("Directory switched from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\n" + "was a directory from another line of history " + "before the replacement made by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->added_rev); + else if (victim_node_kind == svn_node_file || + victim_node_kind == svn_node_symlink) + return apr_psprintf(result_pool, + _("Directory switched from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\n" + "was a file before the replacement made by %s " + "in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->added_rev); + else + return apr_psprintf(result_pool, + _("Item switched from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\nwas " + "replaced with a directory by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->added_rev); + } + else + { + if (victim_node_kind == svn_node_dir) + return apr_psprintf(result_pool, + _("Directory switched from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\n" + "did not exist before it was added by %s in " + "r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->added_rev); + else if (victim_node_kind == svn_node_file || + victim_node_kind == svn_node_symlink) + return apr_psprintf(result_pool, + _("File switched from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\ndid " + "not exist before it was added by %s in " + "r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->added_rev); + else + return apr_psprintf(result_pool, + _("Item switched from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\ndid " + "not exist before it was added by %s in " + "r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->added_rev); + } +} + +static const char * +describe_incoming_deletion_upon_merge( + struct conflict_tree_incoming_delete_details *details, + svn_node_kind_t victim_node_kind, + const char *old_repos_relpath, + svn_revnum_t old_rev, + const char *new_repos_relpath, + svn_revnum_t new_rev, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + if (details->replacing_node_kind == svn_node_file || + details->replacing_node_kind == svn_node_symlink) + { + if (victim_node_kind == svn_node_dir) + { + const char *description = + apr_psprintf(result_pool, + _("Directory merged from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\n" + "was replaced with a file by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->deleted_rev); + if (details->moves) + { + struct repos_move_info *move; + + move = APR_ARRAY_IDX(details->moves, 0, struct repos_move_info *); + description = + apr_psprintf(result_pool, + _("%s\nThe replaced directory was moved to " + "'^/%s'."), description, + get_moved_to_repos_relpath(details, scratch_pool)); + return append_moved_to_chain_description(description, + move->next, + result_pool, + scratch_pool); + } + return description; + } + else if (victim_node_kind == svn_node_file || + victim_node_kind == svn_node_symlink) + { + const char *description = + apr_psprintf(result_pool, + _("File merged from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\nwas " + "replaced with a file from another line of " + "history by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->deleted_rev); + if (details->moves) + { + struct repos_move_info *move; + + move = APR_ARRAY_IDX(details->moves, 0, struct repos_move_info *); + description = + apr_psprintf(result_pool, + _("%s\nThe replaced file was moved to '^/%s'."), + description, + get_moved_to_repos_relpath(details, scratch_pool)); + return append_moved_to_chain_description(description, + move->next, + result_pool, + scratch_pool); + } + return description; + } + else + return apr_psprintf(result_pool, + _("Item merged from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\nwas " + "replaced with a file by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->deleted_rev); + } + else if (details->replacing_node_kind == svn_node_dir) + { + if (victim_node_kind == svn_node_dir) + { + const char *description = + apr_psprintf(result_pool, + _("Directory merged from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\n" + "was replaced with a directory from another " + "line of history by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->deleted_rev); + if (details->moves) + { + struct repos_move_info *move; + + move = APR_ARRAY_IDX(details->moves, 0, struct repos_move_info *); + description = + apr_psprintf(result_pool, + _("%s\nThe replaced directory was moved to " + "'^/%s'."), description, + get_moved_to_repos_relpath(details, scratch_pool)); + return append_moved_to_chain_description(description, + move->next, + result_pool, + scratch_pool); + } + return description; + } + else if (victim_node_kind == svn_node_file || + victim_node_kind == svn_node_symlink) + { + const char *description = + apr_psprintf(result_pool, + _("File merged from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\n" + "was replaced with a directory by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->deleted_rev); + if (details->moves) + { + struct repos_move_info *move; + + move = APR_ARRAY_IDX(details->moves, 0, struct repos_move_info *); + description = + apr_psprintf(result_pool, + _("%s\nThe replaced file was moved to '^/%s'."), + description, + get_moved_to_repos_relpath(details, scratch_pool)); + return append_moved_to_chain_description(description, + move->next, + result_pool, + scratch_pool); + } + return description; + } + else + { + const char *description = + apr_psprintf(result_pool, + _("Item merged from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\nwas " + "replaced with a directory by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->deleted_rev); + if (details->moves) + { + struct repos_move_info *move; + + move = APR_ARRAY_IDX(details->moves, 0, struct repos_move_info *); + description = + apr_psprintf(result_pool, + _("%s\nThe replaced item was moved to '^/%s'."), + description, + get_moved_to_repos_relpath(details, scratch_pool)); + return append_moved_to_chain_description(description, + move->next, + result_pool, + scratch_pool); + } + return description; + } + } + else + { + if (victim_node_kind == svn_node_dir) + { + if (details->moves) + { + struct repos_move_info *move; + const char *description; + + move = APR_ARRAY_IDX(details->moves, 0, struct repos_move_info *); + description = + apr_psprintf(result_pool, + _("Directory merged from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\nwas " + "moved to '^/%s' by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + get_moved_to_repos_relpath(details, scratch_pool), + details->rev_author, details->deleted_rev); + return append_moved_to_chain_description(description, + move->next, + result_pool, + scratch_pool); + } + else + return apr_psprintf(result_pool, + _("Directory merged from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\nwas " + "deleted by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->deleted_rev); + } + else if (victim_node_kind == svn_node_file || + victim_node_kind == svn_node_symlink) + { + if (details->moves) + { + struct repos_move_info *move; + const char *description; + + move = APR_ARRAY_IDX(details->moves, 0, struct repos_move_info *); + description = + apr_psprintf(result_pool, + _("File merged from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\nwas " + "moved to '^/%s' by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + get_moved_to_repos_relpath(details, scratch_pool), + details->rev_author, details->deleted_rev); + return append_moved_to_chain_description(description, + move->next, + result_pool, + scratch_pool); + } + else + return apr_psprintf(result_pool, + _("File merged from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\nwas " + "deleted by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->deleted_rev); + } + else + { + if (details->moves) + { + struct repos_move_info *move; + const char *description; + + move = APR_ARRAY_IDX(details->moves, 0, struct repos_move_info *); + description = + apr_psprintf(result_pool, + _("Item merged from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\nwas " + "moved to '^/%s' by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + get_moved_to_repos_relpath(details, scratch_pool), + details->rev_author, details->deleted_rev); + return append_moved_to_chain_description(description, + move->next, + result_pool, + scratch_pool); + } + else + return apr_psprintf(result_pool, + _("Item merged from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\nwas " + "deleted by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->deleted_rev); + } + } +} + +static const char * +describe_incoming_reverse_addition_upon_merge( + struct conflict_tree_incoming_delete_details *details, + svn_node_kind_t victim_node_kind, + const char *old_repos_relpath, + svn_revnum_t old_rev, + const char *new_repos_relpath, + svn_revnum_t new_rev, + apr_pool_t *result_pool) +{ + if (details->replacing_node_kind == svn_node_file || + details->replacing_node_kind == svn_node_symlink) + { + if (victim_node_kind == svn_node_dir) + return apr_psprintf(result_pool, + _("Directory reverse-merged from\n'^/%s@%ld'\nto " + "^/%s@%ld was a file before the replacement " + "made by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->added_rev); + else if (victim_node_kind == svn_node_file || + victim_node_kind == svn_node_symlink) + return apr_psprintf(result_pool, + _("File reverse-merged from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\n" + "was a file from another line of history before " + "the replacement made by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->added_rev); + else + return apr_psprintf(result_pool, + _("Item reverse-merged from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\n" + "was replaced with a file by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->added_rev); + } + else if (details->replacing_node_kind == svn_node_dir) + { + if (victim_node_kind == svn_node_dir) + return apr_psprintf(result_pool, + _("Directory reverse-merged from\n'^/%s@%ld'\nto " + "^/%s@%ld was a directory from another line " + "of history before the replacement made by %s " + "in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->added_rev); + else if (victim_node_kind == svn_node_file || + victim_node_kind == svn_node_symlink) + return apr_psprintf(result_pool, + _("Directory reverse-merged from\n'^/%s@%ld'\nto " + "^/%s@%ld was a file before the replacement " + "made by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->added_rev); + else + return apr_psprintf(result_pool, + _("Item reverse-merged from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\n" + "was replaced with a directory by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->added_rev); + } + else + { + if (victim_node_kind == svn_node_dir) + return apr_psprintf(result_pool, + _("Directory reverse-merged from\n'^/%s@%ld'\nto " + "^/%s@%ld did not exist before it was added " + "by %s in r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->added_rev); + else if (victim_node_kind == svn_node_file || + victim_node_kind == svn_node_symlink) + return apr_psprintf(result_pool, + _("File reverse-merged from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\n" + "did not exist before it was added by %s in " + "r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->added_rev); + else + return apr_psprintf(result_pool, + _("Item reverse-merged from\n" + "'^/%s@%ld'\nto\n'^/%s@%ld'\n" + "did not exist before it was added by %s in " + "r%ld."), + old_repos_relpath, old_rev, + new_repos_relpath, new_rev, + details->rev_author, details->added_rev); + } +} + +/* Implements tree_conflict_get_description_func_t. */ +static svn_error_t * +conflict_tree_get_description_incoming_delete( + const char **incoming_change_description, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + const char *action; + svn_node_kind_t victim_node_kind; + svn_wc_operation_t conflict_operation; + const char *old_repos_relpath; + svn_revnum_t old_rev; + const char *new_repos_relpath; + svn_revnum_t new_rev; + struct conflict_tree_incoming_delete_details *details; + + if (conflict->tree_conflict_incoming_details == NULL) + return svn_error_trace(conflict_tree_get_incoming_description_generic( + incoming_change_description, + conflict, ctx, result_pool, scratch_pool)); + + conflict_operation = svn_client_conflict_get_operation(conflict); + victim_node_kind = svn_client_conflict_tree_get_victim_node_kind(conflict); + SVN_ERR(svn_client_conflict_get_incoming_old_repos_location( + &old_repos_relpath, &old_rev, NULL, conflict, scratch_pool, + scratch_pool)); + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + &new_repos_relpath, &new_rev, NULL, conflict, scratch_pool, + scratch_pool)); + + details = conflict->tree_conflict_incoming_details; + + if (conflict_operation == svn_wc_operation_update) + { + if (details->deleted_rev != SVN_INVALID_REVNUM) + { + action = describe_incoming_deletion_upon_update(details, + victim_node_kind, + old_rev, + new_rev, + result_pool, + scratch_pool); + } + else /* details->added_rev != SVN_INVALID_REVNUM */ + { + /* This deletion is really the reverse change of an addition. */ + action = describe_incoming_reverse_addition_upon_update( + details, victim_node_kind, old_rev, new_rev, result_pool); + } + } + else if (conflict_operation == svn_wc_operation_switch) + { + if (details->deleted_rev != SVN_INVALID_REVNUM) + { + action = describe_incoming_deletion_upon_switch(details, + victim_node_kind, + old_repos_relpath, + old_rev, + new_repos_relpath, + new_rev, + result_pool, + scratch_pool); + } + else /* details->added_rev != SVN_INVALID_REVNUM */ + { + /* This deletion is really the reverse change of an addition. */ + action = describe_incoming_reverse_addition_upon_switch( + details, victim_node_kind, old_repos_relpath, old_rev, + new_repos_relpath, new_rev, result_pool); + + } + } + else if (conflict_operation == svn_wc_operation_merge) + { + if (details->deleted_rev != SVN_INVALID_REVNUM) + { + action = describe_incoming_deletion_upon_merge(details, + victim_node_kind, + old_repos_relpath, + old_rev, + new_repos_relpath, + new_rev, + result_pool, + scratch_pool); + } + else /* details->added_rev != SVN_INVALID_REVNUM */ + { + /* This deletion is really the reverse change of an addition. */ + action = describe_incoming_reverse_addition_upon_merge( + details, victim_node_kind, old_repos_relpath, old_rev, + new_repos_relpath, new_rev, result_pool); + } + } + + *incoming_change_description = apr_pstrdup(result_pool, action); + + return SVN_NO_ERROR; +} + +/* Baton for find_added_rev(). */ +struct find_added_rev_baton +{ + const char *victim_abspath; + svn_client_ctx_t *ctx; + svn_revnum_t added_rev; + const char *repos_relpath; + const char *parent_repos_relpath; + apr_pool_t *pool; +}; + +/* Implements svn_location_segment_receiver_t. + * Finds the revision in which a node was added by tracing 'start' + * revisions in location segments reported for the node. + * If the PARENT_REPOS_RELPATH in the baton is not NULL, only consider + * segments in which the node existed somwhere beneath this path. */ +static svn_error_t * +find_added_rev(svn_location_segment_t *segment, + void *baton, + apr_pool_t *scratch_pool) +{ + struct find_added_rev_baton *b = baton; + + if (b->ctx->notify_func2) + { + svn_wc_notify_t *notify; + + notify = svn_wc_create_notify( + b->victim_abspath, + svn_wc_notify_tree_conflict_details_progress, + scratch_pool), + notify->revision = segment->range_start; + b->ctx->notify_func2(b->ctx->notify_baton2, notify, scratch_pool); + } + + if (segment->path) /* not interested in gaps */ + { + if (b->parent_repos_relpath == NULL || + svn_relpath_skip_ancestor(b->parent_repos_relpath, + segment->path) != NULL) + { + b->added_rev = segment->range_start; + b->repos_relpath = apr_pstrdup(b->pool, segment->path); + } + } + + return SVN_NO_ERROR; +} + +/* Find conflict details in the case where a revision which added a node was + * applied in reverse, resulting in an incoming deletion. */ +static svn_error_t * +get_incoming_delete_details_for_reverse_addition( + struct conflict_tree_incoming_delete_details **details, + const char *repos_root_url, + const char *old_repos_relpath, + svn_revnum_t old_rev, + svn_revnum_t new_rev, + svn_client_ctx_t *ctx, + const char *victim_abspath, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_ra_session_t *ra_session; + const char *url; + const char *corrected_url; + svn_string_t *author_revprop; + struct find_added_rev_baton b = { 0 }; + + url = svn_path_url_add_component2(repos_root_url, old_repos_relpath, + scratch_pool); + SVN_ERR(svn_client__open_ra_session_internal(&ra_session, + &corrected_url, + url, NULL, NULL, + FALSE, + FALSE, + ctx, + scratch_pool, + scratch_pool)); + + *details = apr_pcalloc(result_pool, sizeof(**details)); + b.ctx = ctx; + b.victim_abspath = victim_abspath; + b.added_rev = SVN_INVALID_REVNUM; + b.repos_relpath = NULL; + b.parent_repos_relpath = NULL; + b.pool = scratch_pool; + + /* Figure out when this node was added. */ + SVN_ERR(svn_ra_get_location_segments(ra_session, "", old_rev, + old_rev, new_rev, + find_added_rev, &b, + scratch_pool)); + + SVN_ERR(svn_ra_rev_prop(ra_session, b.added_rev, + SVN_PROP_REVISION_AUTHOR, + &author_revprop, scratch_pool)); + (*details)->deleted_rev = SVN_INVALID_REVNUM; + (*details)->added_rev = b.added_rev; + (*details)->repos_relpath = apr_pstrdup(result_pool, b.repos_relpath); + if (author_revprop) + (*details)->rev_author = apr_pstrdup(result_pool, author_revprop->data); + else + (*details)->rev_author = _("unknown author"); + + /* Check for replacement. */ + (*details)->replacing_node_kind = svn_node_none; + if ((*details)->added_rev > 0) + { + svn_node_kind_t replaced_node_kind; + + SVN_ERR(svn_ra_check_path(ra_session, "", + rev_below((*details)->added_rev), + &replaced_node_kind, scratch_pool)); + if (replaced_node_kind != svn_node_none) + SVN_ERR(svn_ra_check_path(ra_session, "", (*details)->added_rev, + &(*details)->replacing_node_kind, + scratch_pool)); + } + + return SVN_NO_ERROR; +} + +/* Follow each move chain starting a MOVE all the way to the end to find + * the possible working copy locations for VICTIM_ABSPATH which corresponds + * to VICTIM_REPOS_REPLATH@VICTIM_REVISION. + * Add each such location to the WC_MOVE_TARGETS hash table, keyed on the + * repos_relpath which is the corresponding move destination in the repository. + * This function is recursive. */ +static svn_error_t * +follow_move_chains(apr_hash_t *wc_move_targets, + struct repos_move_info *move, + svn_client_ctx_t *ctx, + const char *victim_abspath, + svn_node_kind_t victim_node_kind, + const char *victim_repos_relpath, + svn_revnum_t victim_revision, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + /* If this is the end of a move chain, look for matching paths in + * the working copy and add them to our collection if found. */ + if (move->next == NULL) + { + apr_array_header_t *candidate_abspaths; + + /* Gather candidate nodes which represent this moved_to_repos_relpath. */ + SVN_ERR(svn_wc__guess_incoming_move_target_nodes( + &candidate_abspaths, ctx->wc_ctx, + victim_abspath, victim_node_kind, + move->moved_to_repos_relpath, + scratch_pool, scratch_pool)); + if (candidate_abspaths->nelts > 0) + { + apr_array_header_t *moved_to_abspaths; + int i; + apr_pool_t *iterpool = svn_pool_create(scratch_pool); + + moved_to_abspaths = apr_array_make(result_pool, 1, + sizeof (const char *)); + + for (i = 0; i < candidate_abspaths->nelts; i++) + { + const char *candidate_abspath; + const char *repos_root_url; + const char *repos_uuid; + const char *candidate_repos_relpath; + svn_revnum_t candidate_revision; + + svn_pool_clear(iterpool); + + candidate_abspath = APR_ARRAY_IDX(candidate_abspaths, i, + const char *); + SVN_ERR(svn_wc__node_get_origin(NULL, &candidate_revision, + &candidate_repos_relpath, + &repos_root_url, + &repos_uuid, + NULL, NULL, + ctx->wc_ctx, + candidate_abspath, + FALSE, + iterpool, iterpool)); + + if (candidate_revision == SVN_INVALID_REVNUM) + continue; + + /* If the conflict victim and the move target candidate + * are not from the same revision we must ensure that + * they are related. */ + if (candidate_revision != victim_revision) + { + svn_client__pathrev_t *yca_loc; + svn_error_t *err; + + err = find_yca(&yca_loc, victim_repos_relpath, + victim_revision, + candidate_repos_relpath, + candidate_revision, + repos_root_url, repos_uuid, + NULL, ctx, iterpool, iterpool); + if (err) + { + if (err->apr_err == SVN_ERR_FS_NOT_FOUND) + { + svn_error_clear(err); + yca_loc = NULL; + } + else + return svn_error_trace(err); + } + + if (yca_loc == NULL) + continue; + } + + APR_ARRAY_PUSH(moved_to_abspaths, const char *) = + apr_pstrdup(result_pool, candidate_abspath); + } + svn_pool_destroy(iterpool); + + svn_hash_sets(wc_move_targets, move->moved_to_repos_relpath, + moved_to_abspaths); + } + } + else + { + int i; + apr_pool_t *iterpool; + + /* Recurse into each of the possible move chains. */ + iterpool = svn_pool_create(scratch_pool); + for (i = 0; i < move->next->nelts; i++) + { + struct repos_move_info *next_move; + + svn_pool_clear(iterpool); + + next_move = APR_ARRAY_IDX(move->next, i, struct repos_move_info *); + SVN_ERR(follow_move_chains(wc_move_targets, next_move, + ctx, victim_abspath, victim_node_kind, + victim_repos_relpath, victim_revision, + result_pool, iterpool)); + + } + svn_pool_destroy(iterpool); + } + + return SVN_NO_ERROR; +} + +static svn_error_t * +init_wc_move_targets(struct conflict_tree_incoming_delete_details *details, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + int i; + const char *victim_abspath; + svn_node_kind_t victim_node_kind; + const char *incoming_new_repos_relpath; + svn_revnum_t incoming_new_pegrev; + svn_wc_operation_t operation; + + victim_abspath = svn_client_conflict_get_local_abspath(conflict); + victim_node_kind = svn_client_conflict_tree_get_victim_node_kind(conflict); + operation = svn_client_conflict_get_operation(conflict); + /* ### Should we get the old location in case of reverse-merges? */ + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + &incoming_new_repos_relpath, &incoming_new_pegrev, + NULL, conflict, + scratch_pool, scratch_pool)); + details->wc_move_targets = apr_hash_make(conflict->pool); + for (i = 0; i < details->moves->nelts; i++) + { + struct repos_move_info *move; + + move = APR_ARRAY_IDX(details->moves, i, struct repos_move_info *); + SVN_ERR(follow_move_chains(details->wc_move_targets, move, + ctx, victim_abspath, + victim_node_kind, + incoming_new_repos_relpath, + incoming_new_pegrev, + conflict->pool, scratch_pool)); + } + + /* Initialize to the first possible move target. Hopefully, + * in most cases there will only be one candidate anyway. */ + details->move_target_repos_relpath = + get_moved_to_repos_relpath(details, scratch_pool); + details->wc_move_target_idx = 0; + + /* If only one move target exists after an update or switch, + * recommend a resolution option which follows the incoming move. */ + if (apr_hash_count(details->wc_move_targets) == 1 && + (operation == svn_wc_operation_update || + operation == svn_wc_operation_switch)) + { + apr_array_header_t *wc_abspaths; + + wc_abspaths = svn_hash_gets(details->wc_move_targets, + details->move_target_repos_relpath); + if (wc_abspaths->nelts == 1) + { + svn_client_conflict_option_id_t recommended[] = + { + /* Only one of these will be present for any given conflict. */ + svn_client_conflict_option_incoming_move_file_text_merge, + svn_client_conflict_option_incoming_move_dir_merge, + svn_client_conflict_option_local_move_file_text_merge + }; + apr_array_header_t *options; + + SVN_ERR(svn_client_conflict_tree_get_resolution_options( + &options, conflict, ctx, scratch_pool, scratch_pool)); + for (i = 0; i < (sizeof(recommended) / sizeof(recommended[0])); i++) + { + svn_client_conflict_option_id_t option_id = recommended[i]; + + if (svn_client_conflict_option_find_by_id(options, option_id)) + { + conflict->recommended_option_id = option_id; + break; + } + } + } + } + + return SVN_NO_ERROR; +} + +/* Implements tree_conflict_get_details_func_t. + * Find the revision in which the victim was deleted in the repository. */ +static svn_error_t * +conflict_tree_get_details_incoming_delete(svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + const char *old_repos_relpath; + const char *new_repos_relpath; + const char *repos_root_url; + svn_revnum_t old_rev; + svn_revnum_t new_rev; + svn_node_kind_t old_kind; + svn_node_kind_t new_kind; + struct conflict_tree_incoming_delete_details *details; + svn_wc_operation_t operation; + + SVN_ERR(svn_client_conflict_get_incoming_old_repos_location( + &old_repos_relpath, &old_rev, &old_kind, conflict, scratch_pool, + scratch_pool)); + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + &new_repos_relpath, &new_rev, &new_kind, conflict, scratch_pool, + scratch_pool)); + SVN_ERR(svn_client_conflict_get_repos_info(&repos_root_url, NULL, + conflict, + scratch_pool, scratch_pool)); + operation = svn_client_conflict_get_operation(conflict); + + if (operation == svn_wc_operation_update) + { + if (old_rev < new_rev) + { + const char *parent_repos_relpath; + svn_revnum_t parent_peg_rev; + svn_revnum_t deleted_rev; + const char *deleted_rev_author; + svn_node_kind_t replacing_node_kind; + apr_array_header_t *moves; + const char *related_repos_relpath; + svn_revnum_t related_peg_rev; + + /* The update operation went forward in history. */ + SVN_ERR(svn_wc__node_get_repos_info(&parent_peg_rev, + &parent_repos_relpath, + NULL, NULL, + ctx->wc_ctx, + svn_dirent_dirname( + conflict->local_abspath, + scratch_pool), + scratch_pool, + scratch_pool)); + if (new_kind == svn_node_none) + { + SVN_ERR(find_related_node(&related_repos_relpath, + &related_peg_rev, + new_repos_relpath, new_rev, + old_repos_relpath, old_rev, + conflict, ctx, + scratch_pool, scratch_pool)); + } + else + { + /* related to self */ + related_repos_relpath = NULL; + related_peg_rev = SVN_INVALID_REVNUM; + } + + SVN_ERR(find_revision_for_suspected_deletion( + &deleted_rev, &deleted_rev_author, &replacing_node_kind, + &moves, conflict, + svn_dirent_basename(conflict->local_abspath, scratch_pool), + parent_repos_relpath, parent_peg_rev, + new_kind == svn_node_none ? 0 : old_rev, + related_repos_relpath, related_peg_rev, + ctx, conflict->pool, scratch_pool)); + if (deleted_rev == SVN_INVALID_REVNUM) + { + /* We could not determine the revision in which the node was + * deleted. We cannot provide the required details so the best + * we can do is fall back to the default description. */ + return SVN_NO_ERROR; + } + + details = apr_pcalloc(conflict->pool, sizeof(*details)); + details->deleted_rev = deleted_rev; + details->added_rev = SVN_INVALID_REVNUM; + details->repos_relpath = apr_pstrdup(conflict->pool, + new_repos_relpath); + details->rev_author = deleted_rev_author; + details->replacing_node_kind = replacing_node_kind; + details->moves = moves; + } + else /* new_rev < old_rev */ + { + /* The update operation went backwards in history. + * Figure out when this node was added. */ + SVN_ERR(get_incoming_delete_details_for_reverse_addition( + &details, repos_root_url, old_repos_relpath, + old_rev, new_rev, ctx, + svn_client_conflict_get_local_abspath(conflict), + conflict->pool, scratch_pool)); + } + } + else if (operation == svn_wc_operation_switch || + operation == svn_wc_operation_merge) + { + if (old_rev < new_rev) + { + svn_revnum_t deleted_rev; + const char *deleted_rev_author; + svn_node_kind_t replacing_node_kind; + apr_array_header_t *moves; + + /* The switch/merge operation went forward in history. + * + * The deletion of the node happened on the branch we switched to + * or merged from. Scan new_repos_relpath's parent's log to find + * the revision which deleted the node. */ + SVN_ERR(find_revision_for_suspected_deletion( + &deleted_rev, &deleted_rev_author, &replacing_node_kind, + &moves, conflict, + svn_relpath_basename(new_repos_relpath, scratch_pool), + svn_relpath_dirname(new_repos_relpath, scratch_pool), + new_rev, old_rev, old_repos_relpath, old_rev, ctx, + conflict->pool, scratch_pool)); + if (deleted_rev == SVN_INVALID_REVNUM) + { + /* We could not determine the revision in which the node was + * deleted. We cannot provide the required details so the best + * we can do is fall back to the default description. */ + return SVN_NO_ERROR; + } + + details = apr_pcalloc(conflict->pool, sizeof(*details)); + details->deleted_rev = deleted_rev; + details->added_rev = SVN_INVALID_REVNUM; + details->repos_relpath = apr_pstrdup(conflict->pool, + new_repos_relpath); + details->rev_author = apr_pstrdup(conflict->pool, + deleted_rev_author); + details->replacing_node_kind = replacing_node_kind; + details->moves = moves; + } + else /* new_rev < old_rev */ + { + /* The switch/merge operation went backwards in history. + * Figure out when the node we switched away from, or merged + * from another branch, was added. */ + SVN_ERR(get_incoming_delete_details_for_reverse_addition( + &details, repos_root_url, old_repos_relpath, + old_rev, new_rev, ctx, + svn_client_conflict_get_local_abspath(conflict), + conflict->pool, scratch_pool)); + } + } + else + { + details = NULL; + } + + conflict->tree_conflict_incoming_details = details; + + if (details && details->moves) + SVN_ERR(init_wc_move_targets(details, conflict, ctx, scratch_pool)); + + return SVN_NO_ERROR; +} + +/* Details for tree conflicts involving incoming additions. */ +struct conflict_tree_incoming_add_details +{ + /* If not SVN_INVALID_REVNUM, the node was added in ADDED_REV. */ + svn_revnum_t added_rev; + + /* If not SVN_INVALID_REVNUM, the node was deleted in DELETED_REV. + * Note that both ADDED_REV and DELETED_REV may be valid for update/switch. + * See comment in conflict_tree_get_details_incoming_add() for details. */ + svn_revnum_t deleted_rev; + + /* The path which was added/deleted relative to the repository root. */ + const char *repos_relpath; + + /* Authors who committed ADDED_REV/DELETED_REV. */ + const char *added_rev_author; + const char *deleted_rev_author; + + /* Move information. If not NULL, this is an array of repos_move_info * + * elements. Each element is the head of a move chain which starts in + * ADDED_REV or in DELETED_REV (in which case moves should be interpreted + * in reverse). */ + apr_array_header_t *moves; +}; + +/* Implements tree_conflict_get_details_func_t. + * Find the revision in which the victim was added in the repository. */ +static svn_error_t * +conflict_tree_get_details_incoming_add(svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + const char *old_repos_relpath; + const char *new_repos_relpath; + const char *repos_root_url; + svn_revnum_t old_rev; + svn_revnum_t new_rev; + struct conflict_tree_incoming_add_details *details; + svn_wc_operation_t operation; + + SVN_ERR(svn_client_conflict_get_incoming_old_repos_location( + &old_repos_relpath, &old_rev, NULL, conflict, scratch_pool, + scratch_pool)); + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + &new_repos_relpath, &new_rev, NULL, conflict, scratch_pool, + scratch_pool)); + SVN_ERR(svn_client_conflict_get_repos_info(&repos_root_url, NULL, + conflict, + scratch_pool, scratch_pool)); + operation = svn_client_conflict_get_operation(conflict); + + if (operation == svn_wc_operation_update || + operation == svn_wc_operation_switch) + { + /* Only the new repository location is recorded for the node which + * caused an incoming addition. There is no pre-update/pre-switch + * revision to be recorded for the node since it does not exist in + * the repository at that revision. + * The implication is that we cannot know whether the operation went + * forward or backwards in history. So always try to find an added + * and a deleted revision for the node. Users must figure out by whether + * the addition or deletion caused the conflict. */ + const char *url; + const char *corrected_url; + svn_string_t *author_revprop; + struct find_added_rev_baton b = { 0 }; + svn_ra_session_t *ra_session; + svn_revnum_t deleted_rev; + svn_revnum_t head_rev; + + url = svn_path_url_add_component2(repos_root_url, new_repos_relpath, + scratch_pool); + SVN_ERR(svn_client__open_ra_session_internal(&ra_session, + &corrected_url, + url, NULL, NULL, + FALSE, + FALSE, + ctx, + scratch_pool, + scratch_pool)); + + details = apr_pcalloc(conflict->pool, sizeof(*details)); + b.ctx = ctx, + b.victim_abspath = svn_client_conflict_get_local_abspath(conflict), + b.added_rev = SVN_INVALID_REVNUM; + b.repos_relpath = NULL; + b.parent_repos_relpath = NULL; + b.pool = scratch_pool; + + /* Figure out when this node was added. */ + SVN_ERR(svn_ra_get_location_segments(ra_session, "", new_rev, + new_rev, SVN_INVALID_REVNUM, + find_added_rev, &b, + scratch_pool)); + + SVN_ERR(svn_ra_rev_prop(ra_session, b.added_rev, + SVN_PROP_REVISION_AUTHOR, + &author_revprop, scratch_pool)); + details->repos_relpath = apr_pstrdup(conflict->pool, b.repos_relpath); + details->added_rev = b.added_rev; + if (author_revprop) + details->added_rev_author = apr_pstrdup(conflict->pool, + author_revprop->data); + else + details->added_rev_author = _("unknown author"); + details->deleted_rev = SVN_INVALID_REVNUM; + details->deleted_rev_author = NULL; + + /* Figure out whether this node was deleted later. + * ### Could probably optimize by infering both addition and deletion + * ### from svn_ra_get_location_segments() call above. */ + SVN_ERR(svn_ra_get_latest_revnum(ra_session, &head_rev, scratch_pool)); + if (new_rev < head_rev) + { + SVN_ERR(svn_ra_get_deleted_rev(ra_session, "", new_rev, head_rev, + &deleted_rev, scratch_pool)); + if (SVN_IS_VALID_REVNUM(deleted_rev)) + { + SVN_ERR(svn_ra_rev_prop(ra_session, deleted_rev, + SVN_PROP_REVISION_AUTHOR, + &author_revprop, scratch_pool)); + details->deleted_rev = deleted_rev; + if (author_revprop) + details->deleted_rev_author = apr_pstrdup(conflict->pool, + author_revprop->data); + else + details->deleted_rev_author = _("unknown author"); + } + } + } + else if (operation == svn_wc_operation_merge) + { + if (old_rev < new_rev) + { + /* The merge operation went forwards in history. + * The addition of the node happened on the branch we merged form. + * Scan the nodes's history to find the revision which added it. */ + const char *url; + const char *corrected_url; + svn_string_t *author_revprop; + struct find_added_rev_baton b = { 0 }; + svn_ra_session_t *ra_session; + + url = svn_path_url_add_component2(repos_root_url, new_repos_relpath, + scratch_pool); + SVN_ERR(svn_client__open_ra_session_internal(&ra_session, + &corrected_url, + url, NULL, NULL, + FALSE, + FALSE, + ctx, + scratch_pool, + scratch_pool)); + + details = apr_pcalloc(conflict->pool, sizeof(*details)); + b.victim_abspath = svn_client_conflict_get_local_abspath(conflict); + b.ctx = ctx; + b.added_rev = SVN_INVALID_REVNUM; + b.repos_relpath = NULL; + b.parent_repos_relpath = NULL; + b.pool = scratch_pool; + + /* Figure out when this node was added. */ + SVN_ERR(svn_ra_get_location_segments(ra_session, "", new_rev, + new_rev, old_rev, + find_added_rev, &b, + scratch_pool)); + + SVN_ERR(svn_ra_rev_prop(ra_session, b.added_rev, + SVN_PROP_REVISION_AUTHOR, + &author_revprop, scratch_pool)); + details->repos_relpath = apr_pstrdup(conflict->pool, b.repos_relpath); + details->added_rev = b.added_rev; + if (author_revprop) + details->added_rev_author = apr_pstrdup(conflict->pool, + author_revprop->data); + else + details->added_rev_author = _("unknown author"); + details->deleted_rev = SVN_INVALID_REVNUM; + details->deleted_rev_author = NULL; + } + else + { + /* The merge operation was a reverse-merge. + * This addition is in fact a deletion, applied in reverse, + * which happened on the branch we merged from. + * Find the revision which deleted the node. */ + svn_revnum_t deleted_rev; + const char *deleted_rev_author; + svn_node_kind_t replacing_node_kind; + apr_array_header_t *moves; + + SVN_ERR(find_revision_for_suspected_deletion( + &deleted_rev, &deleted_rev_author, &replacing_node_kind, + &moves, conflict, + svn_relpath_basename(old_repos_relpath, scratch_pool), + svn_relpath_dirname(old_repos_relpath, scratch_pool), + old_rev, new_rev, + NULL, SVN_INVALID_REVNUM, /* related to self */ + ctx, + conflict->pool, scratch_pool)); + if (deleted_rev == SVN_INVALID_REVNUM) + { + /* We could not determine the revision in which the node was + * deleted. We cannot provide the required details so the best + * we can do is fall back to the default description. */ + return SVN_NO_ERROR; + } + + details = apr_pcalloc(conflict->pool, sizeof(*details)); + details->repos_relpath = apr_pstrdup(conflict->pool, + new_repos_relpath); + details->deleted_rev = deleted_rev; + details->deleted_rev_author = apr_pstrdup(conflict->pool, + deleted_rev_author); + + details->added_rev = SVN_INVALID_REVNUM; + details->added_rev_author = NULL; + details->moves = moves; + } + } + else + { + details = NULL; + } + + conflict->tree_conflict_incoming_details = details; + + return SVN_NO_ERROR; +} + +static const char * +describe_incoming_add_upon_update( + struct conflict_tree_incoming_add_details *details, + svn_node_kind_t new_node_kind, + svn_revnum_t new_rev, + apr_pool_t *result_pool) +{ + if (new_node_kind == svn_node_dir) + { + if (SVN_IS_VALID_REVNUM(details->added_rev) && + SVN_IS_VALID_REVNUM(details->deleted_rev)) + return apr_psprintf(result_pool, + _("A new directory appeared during update to r%ld; " + "it was added by %s in r%ld and later deleted " + "by %s in r%ld."), new_rev, + details->added_rev_author, details->added_rev, + details->deleted_rev_author, details->deleted_rev); + else if (SVN_IS_VALID_REVNUM(details->added_rev)) + return apr_psprintf(result_pool, + _("A new directory appeared during update to r%ld; " + "it was added by %s in r%ld."), new_rev, + details->added_rev_author, details->added_rev); + else + return apr_psprintf(result_pool, + _("A new directory appeared during update to r%ld; " + "it was deleted by %s in r%ld."), new_rev, + details->deleted_rev_author, details->deleted_rev); + } + else if (new_node_kind == svn_node_file || + new_node_kind == svn_node_symlink) + { + if (SVN_IS_VALID_REVNUM(details->added_rev) && + SVN_IS_VALID_REVNUM(details->deleted_rev)) + return apr_psprintf(result_pool, + _("A new file appeared during update to r%ld; " + "it was added by %s in r%ld and later deleted " + "by %s in r%ld."), new_rev, + details->added_rev_author, details->added_rev, + details->deleted_rev_author, details->deleted_rev); + else if (SVN_IS_VALID_REVNUM(details->added_rev)) + return apr_psprintf(result_pool, + _("A new file appeared during update to r%ld; " + "it was added by %s in r%ld."), new_rev, + details->added_rev_author, details->added_rev); + else + return apr_psprintf(result_pool, + _("A new file appeared during update to r%ld; " + "it was deleted by %s in r%ld."), new_rev, + details->deleted_rev_author, details->deleted_rev); + } + else + { + if (SVN_IS_VALID_REVNUM(details->added_rev) && + SVN_IS_VALID_REVNUM(details->deleted_rev)) + return apr_psprintf(result_pool, + _("A new item appeared during update to r%ld; " + "it was added by %s in r%ld and later deleted " + "by %s in r%ld."), new_rev, + details->added_rev_author, details->added_rev, + details->deleted_rev_author, details->deleted_rev); + else if (SVN_IS_VALID_REVNUM(details->added_rev)) + return apr_psprintf(result_pool, + _("A new item appeared during update to r%ld; " + "it was added by %s in r%ld."), new_rev, + details->added_rev_author, details->added_rev); + else + return apr_psprintf(result_pool, + _("A new item appeared during update to r%ld; " + "it was deleted by %s in r%ld."), new_rev, + details->deleted_rev_author, details->deleted_rev); + } +} + +static const char * +describe_incoming_add_upon_switch( + struct conflict_tree_incoming_add_details *details, + svn_node_kind_t victim_node_kind, + const char *new_repos_relpath, + svn_revnum_t new_rev, + apr_pool_t *result_pool) +{ + if (victim_node_kind == svn_node_dir) + { + if (SVN_IS_VALID_REVNUM(details->added_rev) && + SVN_IS_VALID_REVNUM(details->deleted_rev)) + return apr_psprintf(result_pool, + _("A new directory appeared during switch to\n" + "'^/%s@%ld'.\n" + "It was added by %s in r%ld and later deleted " + "by %s in r%ld."), new_repos_relpath, new_rev, + details->added_rev_author, details->added_rev, + details->deleted_rev_author, details->deleted_rev); + else if (SVN_IS_VALID_REVNUM(details->added_rev)) + return apr_psprintf(result_pool, + _("A new directory appeared during switch to\n" + "'^/%s@%ld'.\nIt was added by %s in r%ld."), + new_repos_relpath, new_rev, + details->added_rev_author, details->added_rev); + else + return apr_psprintf(result_pool, + _("A new directory appeared during switch to\n" + "'^/%s@%ld'.\nIt was deleted by %s in r%ld."), + new_repos_relpath, new_rev, + details->deleted_rev_author, details->deleted_rev); + } + else if (victim_node_kind == svn_node_file || + victim_node_kind == svn_node_symlink) + { + if (SVN_IS_VALID_REVNUM(details->added_rev) && + SVN_IS_VALID_REVNUM(details->deleted_rev)) + return apr_psprintf(result_pool, + _("A new file appeared during switch to\n" + "'^/%s@%ld'.\n" + "It was added by %s in r%ld and later deleted " + "by %s in r%ld."), new_repos_relpath, new_rev, + details->added_rev_author, details->added_rev, + details->deleted_rev_author, details->deleted_rev); + else if (SVN_IS_VALID_REVNUM(details->added_rev)) + return apr_psprintf(result_pool, + _("A new file appeared during switch to\n" + "'^/%s@%ld'.\n" + "It was added by %s in r%ld."), + new_repos_relpath, new_rev, + details->added_rev_author, details->added_rev); + else + return apr_psprintf(result_pool, + _("A new file appeared during switch to\n" + "'^/%s@%ld'.\n" + "It was deleted by %s in r%ld."), + new_repos_relpath, new_rev, + details->deleted_rev_author, details->deleted_rev); + } + else + { + if (SVN_IS_VALID_REVNUM(details->added_rev) && + SVN_IS_VALID_REVNUM(details->deleted_rev)) + return apr_psprintf(result_pool, + _("A new item appeared during switch to\n" + "'^/%s@%ld'.\n" + "It was added by %s in r%ld and later deleted " + "by %s in r%ld."), new_repos_relpath, new_rev, + details->added_rev_author, details->added_rev, + details->deleted_rev_author, details->deleted_rev); + else if (SVN_IS_VALID_REVNUM(details->added_rev)) + return apr_psprintf(result_pool, + _("A new item appeared during switch to\n" + "'^/%s@%ld'.\n" + "It was added by %s in r%ld."), + new_repos_relpath, new_rev, + details->added_rev_author, details->added_rev); + else + return apr_psprintf(result_pool, + _("A new item appeared during switch to\n" + "'^/%s@%ld'.\n" + "It was deleted by %s in r%ld."), + new_repos_relpath, new_rev, + details->deleted_rev_author, details->deleted_rev); + } +} + +static const char * +describe_incoming_add_upon_merge( + struct conflict_tree_incoming_add_details *details, + svn_node_kind_t new_node_kind, + svn_revnum_t old_rev, + const char *new_repos_relpath, + svn_revnum_t new_rev, + apr_pool_t *result_pool) +{ + if (new_node_kind == svn_node_dir) + { + if (old_rev + 1 == new_rev) + return apr_psprintf(result_pool, + _("A new directory appeared during merge of\n" + "'^/%s:%ld'.\nIt was added by %s in r%ld."), + new_repos_relpath, new_rev, + details->added_rev_author, details->added_rev); + else + return apr_psprintf(result_pool, + _("A new directory appeared during merge of\n" + "'^/%s:%ld-%ld'.\nIt was added by %s in r%ld."), + new_repos_relpath, old_rev + 1, new_rev, + details->added_rev_author, details->added_rev); + } + else if (new_node_kind == svn_node_file || + new_node_kind == svn_node_symlink) + { + if (old_rev + 1 == new_rev) + return apr_psprintf(result_pool, + _("A new file appeared during merge of\n" + "'^/%s:%ld'.\nIt was added by %s in r%ld."), + new_repos_relpath, new_rev, + details->added_rev_author, details->added_rev); + else + return apr_psprintf(result_pool, + _("A new file appeared during merge of\n" + "'^/%s:%ld-%ld'.\nIt was added by %s in r%ld."), + new_repos_relpath, old_rev + 1, new_rev, + details->added_rev_author, details->added_rev); + } + else + { + if (old_rev + 1 == new_rev) + return apr_psprintf(result_pool, + _("A new item appeared during merge of\n" + "'^/%s:%ld'.\nIt was added by %s in r%ld."), + new_repos_relpath, new_rev, + details->added_rev_author, details->added_rev); + else + return apr_psprintf(result_pool, + _("A new item appeared during merge of\n" + "'^/%s:%ld-%ld'.\nIt was added by %s in r%ld."), + new_repos_relpath, old_rev + 1, new_rev, + details->added_rev_author, details->added_rev); + } +} + +static const char * +describe_incoming_reverse_deletion_upon_merge( + struct conflict_tree_incoming_add_details *details, + svn_node_kind_t new_node_kind, + const char *old_repos_relpath, + svn_revnum_t old_rev, + svn_revnum_t new_rev, + apr_pool_t *result_pool) +{ + if (new_node_kind == svn_node_dir) + { + if (new_rev + 1 == old_rev) + return apr_psprintf(result_pool, + _("A new directory appeared during reverse-merge of" + "\n'^/%s:%ld'.\nIt was deleted by %s in r%ld."), + old_repos_relpath, old_rev, + details->deleted_rev_author, + details->deleted_rev); + else + return apr_psprintf(result_pool, + _("A new directory appeared during reverse-merge " + "of\n'^/%s:%ld-%ld'.\n" + "It was deleted by %s in r%ld."), + old_repos_relpath, new_rev, rev_below(old_rev), + details->deleted_rev_author, + details->deleted_rev); + } + else if (new_node_kind == svn_node_file || + new_node_kind == svn_node_symlink) + { + if (new_rev + 1 == old_rev) + return apr_psprintf(result_pool, + _("A new file appeared during reverse-merge of\n" + "'^/%s:%ld'.\nIt was deleted by %s in r%ld."), + old_repos_relpath, old_rev, + details->deleted_rev_author, + details->deleted_rev); + else + return apr_psprintf(result_pool, + _("A new file appeared during reverse-merge of\n" + "'^/%s:%ld-%ld'.\nIt was deleted by %s in r%ld."), + old_repos_relpath, new_rev + 1, old_rev, + details->deleted_rev_author, + details->deleted_rev); + } + else + { + if (new_rev + 1 == old_rev) + return apr_psprintf(result_pool, + _("A new item appeared during reverse-merge of\n" + "'^/%s:%ld'.\nIt was deleted by %s in r%ld."), + old_repos_relpath, old_rev, + details->deleted_rev_author, + details->deleted_rev); + else + return apr_psprintf(result_pool, + _("A new item appeared during reverse-merge of\n" + "'^/%s:%ld-%ld'.\nIt was deleted by %s in r%ld."), + old_repos_relpath, new_rev + 1, old_rev, + details->deleted_rev_author, + details->deleted_rev); + } +} + +/* Implements tree_conflict_get_description_func_t. */ +static svn_error_t * +conflict_tree_get_description_incoming_add( + const char **incoming_change_description, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + const char *action; + svn_node_kind_t victim_node_kind; + svn_wc_operation_t conflict_operation; + const char *old_repos_relpath; + svn_revnum_t old_rev; + svn_node_kind_t old_node_kind; + const char *new_repos_relpath; + svn_revnum_t new_rev; + svn_node_kind_t new_node_kind; + struct conflict_tree_incoming_add_details *details; + + if (conflict->tree_conflict_incoming_details == NULL) + return svn_error_trace(conflict_tree_get_incoming_description_generic( + incoming_change_description, conflict, ctx, + result_pool, scratch_pool)); + + conflict_operation = svn_client_conflict_get_operation(conflict); + victim_node_kind = svn_client_conflict_tree_get_victim_node_kind(conflict); + + SVN_ERR(svn_client_conflict_get_incoming_old_repos_location( + &old_repos_relpath, &old_rev, &old_node_kind, conflict, + scratch_pool, scratch_pool)); + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + &new_repos_relpath, &new_rev, &new_node_kind, conflict, + scratch_pool, scratch_pool)); + + details = conflict->tree_conflict_incoming_details; + + if (conflict_operation == svn_wc_operation_update) + { + action = describe_incoming_add_upon_update(details, + new_node_kind, + new_rev, + result_pool); + } + else if (conflict_operation == svn_wc_operation_switch) + { + action = describe_incoming_add_upon_switch(details, + victim_node_kind, + new_repos_relpath, + new_rev, + result_pool); + } + else if (conflict_operation == svn_wc_operation_merge) + { + if (old_rev < new_rev) + action = describe_incoming_add_upon_merge(details, + new_node_kind, + old_rev, + new_repos_relpath, + new_rev, + result_pool); + else + action = describe_incoming_reverse_deletion_upon_merge( + details, new_node_kind, old_repos_relpath, + old_rev, new_rev, result_pool); + } + + *incoming_change_description = apr_pstrdup(result_pool, action); + + return SVN_NO_ERROR; +} + +/* Details for tree conflicts involving incoming edits. + * Note that we store an array of these. Each element corresponds to a + * revision within the old/new range in which a modification occured. */ +struct conflict_tree_incoming_edit_details +{ + /* The revision in which the edit ocurred. */ + svn_revnum_t rev; + + /* The author of the revision. */ + const char *author; + + /** Is the text modified? May be svn_tristate_unknown. */ + svn_tristate_t text_modified; + + /** Are properties modified? May be svn_tristate_unknown. */ + svn_tristate_t props_modified; + + /** For directories, are children modified? + * May be svn_tristate_unknown. */ + svn_tristate_t children_modified; + + /* The path which was edited, relative to the repository root. */ + const char *repos_relpath; +}; + +/* Baton for find_modified_rev(). */ +struct find_modified_rev_baton { + const char *victim_abspath; + svn_client_ctx_t *ctx; + apr_array_header_t *edits; + const char *repos_relpath; + svn_node_kind_t node_kind; + apr_pool_t *result_pool; + apr_pool_t *scratch_pool; +}; + +/* Implements svn_log_entry_receiver_t. */ +static svn_error_t * +find_modified_rev(void *baton, + svn_log_entry_t *log_entry, + apr_pool_t *scratch_pool) +{ + struct find_modified_rev_baton *b = baton; + struct conflict_tree_incoming_edit_details *details = NULL; + svn_string_t *author; + apr_hash_index_t *hi; + apr_pool_t *iterpool; + + if (b->ctx->notify_func2) + { + svn_wc_notify_t *notify; + + notify = svn_wc_create_notify( + b->victim_abspath, + svn_wc_notify_tree_conflict_details_progress, + scratch_pool), + notify->revision = log_entry->revision; + b->ctx->notify_func2(b->ctx->notify_baton2, notify, scratch_pool); + } + + /* No paths were changed in this revision. Nothing to do. */ + if (! log_entry->changed_paths2) + return SVN_NO_ERROR; + + details = apr_pcalloc(b->result_pool, sizeof(*details)); + details->rev = log_entry->revision; + author = svn_hash_gets(log_entry->revprops, SVN_PROP_REVISION_AUTHOR); + if (author) + details->author = apr_pstrdup(b->result_pool, author->data); + else + details->author = _("unknown author"); + + details->text_modified = svn_tristate_unknown; + details->props_modified = svn_tristate_unknown; + details->children_modified = svn_tristate_unknown; + + iterpool = svn_pool_create(scratch_pool); + for (hi = apr_hash_first(scratch_pool, log_entry->changed_paths2); + hi != NULL; + hi = apr_hash_next(hi)) + { + void *val; + const char *path; + svn_log_changed_path2_t *log_item; + + svn_pool_clear(iterpool); + + apr_hash_this(hi, (void *) &path, NULL, &val); + log_item = val; + + /* ### Remove leading slash from paths in log entries. */ + if (path[0] == '/') + path = svn_relpath_canonicalize(path, iterpool); + + if (svn_path_compare_paths(b->repos_relpath, path) == 0 && + (log_item->action == 'M' || log_item->action == 'A')) + { + details->text_modified = log_item->text_modified; + details->props_modified = log_item->props_modified; + details->repos_relpath = apr_pstrdup(b->result_pool, path); + + if (log_item->copyfrom_path) + b->repos_relpath = apr_pstrdup(b->scratch_pool, + log_item->copyfrom_path); + } + else if (b->node_kind == svn_node_dir && + svn_relpath_skip_ancestor(b->repos_relpath, path) != NULL) + details->children_modified = svn_tristate_true; + } + + if (b->node_kind == svn_node_dir && + details->children_modified == svn_tristate_unknown) + details->children_modified = svn_tristate_false; + + APR_ARRAY_PUSH(b->edits, struct conflict_tree_incoming_edit_details *) = + details; + + svn_pool_destroy(iterpool); + + return SVN_NO_ERROR; +} + +/* Implements tree_conflict_get_details_func_t. + * Find one or more revisions in which the victim was modified in the + * repository. */ +static svn_error_t * +conflict_tree_get_details_incoming_edit(svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + const char *old_repos_relpath; + const char *new_repos_relpath; + const char *repos_root_url; + svn_revnum_t old_rev; + svn_revnum_t new_rev; + svn_node_kind_t old_node_kind; + svn_node_kind_t new_node_kind; + svn_wc_operation_t operation; + const char *url; + const char *corrected_url; + svn_ra_session_t *ra_session; + apr_array_header_t *paths; + apr_array_header_t *revprops; + struct find_modified_rev_baton b = { 0 }; + + SVN_ERR(svn_client_conflict_get_incoming_old_repos_location( + &old_repos_relpath, &old_rev, &old_node_kind, conflict, + scratch_pool, scratch_pool)); + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + &new_repos_relpath, &new_rev, &new_node_kind, conflict, + scratch_pool, scratch_pool)); + SVN_ERR(svn_client_conflict_get_repos_info(&repos_root_url, NULL, + conflict, + scratch_pool, scratch_pool)); + operation = svn_client_conflict_get_operation(conflict); + if (operation == svn_wc_operation_update) + { + b.node_kind = old_rev < new_rev ? new_node_kind : old_node_kind; + + /* If there is no node then we cannot find any edits. */ + if (b.node_kind == svn_node_none) + return SVN_NO_ERROR; + + url = svn_path_url_add_component2(repos_root_url, + old_rev < new_rev ? new_repos_relpath + : old_repos_relpath, + scratch_pool); + + b.repos_relpath = old_rev < new_rev ? new_repos_relpath + : old_repos_relpath; + } + else if (operation == svn_wc_operation_switch || + operation == svn_wc_operation_merge) + { + url = svn_path_url_add_component2(repos_root_url, new_repos_relpath, + scratch_pool); + + b.repos_relpath = new_repos_relpath; + b.node_kind = new_node_kind; + } + + SVN_ERR(svn_client__open_ra_session_internal(&ra_session, + &corrected_url, + url, NULL, NULL, + FALSE, + FALSE, + ctx, + scratch_pool, + scratch_pool)); + + paths = apr_array_make(scratch_pool, 1, sizeof(const char *)); + APR_ARRAY_PUSH(paths, const char *) = ""; + + revprops = apr_array_make(scratch_pool, 1, sizeof(const char *)); + APR_ARRAY_PUSH(revprops, const char *) = SVN_PROP_REVISION_AUTHOR; + + b.ctx = ctx; + b.victim_abspath = svn_client_conflict_get_local_abspath(conflict); + b.result_pool = conflict->pool; + b.scratch_pool = scratch_pool; + b.edits = apr_array_make( + conflict->pool, 0, + sizeof(struct conflict_tree_incoming_edit_details *)); + + SVN_ERR(svn_ra_get_log2(ra_session, paths, + old_rev < new_rev ? old_rev : new_rev, + old_rev < new_rev ? new_rev : old_rev, + 0, /* no limit */ + TRUE, /* need the changed paths list */ + FALSE, /* need to traverse copies */ + FALSE, /* no need for merged revisions */ + revprops, + find_modified_rev, &b, + scratch_pool)); + + conflict->tree_conflict_incoming_details = b.edits; + + return SVN_NO_ERROR; +} + +static const char * +describe_incoming_edit_upon_update(svn_revnum_t old_rev, + svn_revnum_t new_rev, + svn_node_kind_t old_node_kind, + svn_node_kind_t new_node_kind, + apr_pool_t *result_pool) +{ + if (old_rev < new_rev) + { + if (new_node_kind == svn_node_dir) + return apr_psprintf(result_pool, + _("Changes destined for a directory arrived " + "via the following revisions during update " + "from r%ld to r%ld."), old_rev, new_rev); + else if (new_node_kind == svn_node_file || + new_node_kind == svn_node_symlink) + return apr_psprintf(result_pool, + _("Changes destined for a file arrived " + "via the following revisions during update " + "from r%ld to r%ld"), old_rev, new_rev); + else + return apr_psprintf(result_pool, + _("Changes from the following revisions arrived " + "during update from r%ld to r%ld"), + old_rev, new_rev); + } + else + { + if (new_node_kind == svn_node_dir) + return apr_psprintf(result_pool, + _("Changes destined for a directory arrived " + "via the following revisions during backwards " + "update from r%ld to r%ld"), + old_rev, new_rev); + else if (new_node_kind == svn_node_file || + new_node_kind == svn_node_symlink) + return apr_psprintf(result_pool, + _("Changes destined for a file arrived " + "via the following revisions during backwards " + "update from r%ld to r%ld"), + old_rev, new_rev); + else + return apr_psprintf(result_pool, + _("Changes from the following revisions arrived " + "during backwards update from r%ld to r%ld"), + old_rev, new_rev); + } +} + +static const char * +describe_incoming_edit_upon_switch(const char *new_repos_relpath, + svn_revnum_t new_rev, + svn_node_kind_t new_node_kind, + apr_pool_t *result_pool) +{ + if (new_node_kind == svn_node_dir) + return apr_psprintf(result_pool, + _("Changes destined for a directory arrived via " + "the following revisions during switch to\n" + "'^/%s@r%ld'"), + new_repos_relpath, new_rev); + else if (new_node_kind == svn_node_file || + new_node_kind == svn_node_symlink) + return apr_psprintf(result_pool, + _("Changes destined for a directory arrived via " + "the following revisions during switch to\n" + "'^/%s@r%ld'"), + new_repos_relpath, new_rev); + else + return apr_psprintf(result_pool, + _("Changes from the following revisions arrived " + "during switch to\n'^/%s@r%ld'"), + new_repos_relpath, new_rev); +} + +/* Return a string showing the list of revisions in EDITS, ensuring + * the string won't grow too large for display. */ +static const char * +describe_incoming_edit_list_modified_revs(apr_array_header_t *edits, + apr_pool_t *result_pool) +{ + int num_revs_to_skip; + static const int min_revs_for_skipping = 5; + static const int max_revs_to_display = 8; + const char *s = ""; + int i; + + if (edits->nelts <= max_revs_to_display) + num_revs_to_skip = 0; + else + { + /* Check if we should insert a placeholder for some revisions because + * the string would grow too long for display otherwise. */ + num_revs_to_skip = edits->nelts - max_revs_to_display; + if (num_revs_to_skip < min_revs_for_skipping) + { + /* Don't bother with the placeholder. Just list all revisions. */ + num_revs_to_skip = 0; + } + } + + for (i = 0; i < edits->nelts; i++) + { + struct conflict_tree_incoming_edit_details *details; + + details = APR_ARRAY_IDX(edits, i, + struct conflict_tree_incoming_edit_details *); + if (num_revs_to_skip > 0) + { + /* Insert a placeholder for revisions falling into the middle of + * the range so we'll get something that looks like: + * 1, 2, 3, 4, 5 [ placeholder ] 95, 96, 97, 98, 99 */ + if (i < max_revs_to_display / 2) + s = apr_psprintf(result_pool, _("%s r%ld by %s%s"), s, + details->rev, details->author, + i < edits->nelts - 1 ? "," : ""); + else if (i >= max_revs_to_display / 2 && + i < edits->nelts - (max_revs_to_display / 2)) + continue; + else + { + if (i == edits->nelts - (max_revs_to_display / 2)) + s = apr_psprintf(result_pool, + _("%s\n [%d revisions omitted for " + "brevity],\n"), + s, num_revs_to_skip); + + s = apr_psprintf(result_pool, _("%s r%ld by %s%s"), s, + details->rev, details->author, + i < edits->nelts - 1 ? "," : ""); + } + } + else + s = apr_psprintf(result_pool, _("%s r%ld by %s%s"), s, + details->rev, details->author, + i < edits->nelts - 1 ? "," : ""); + } + + return s; +} + +/* Implements tree_conflict_get_description_func_t. */ +static svn_error_t * +conflict_tree_get_description_incoming_edit( + const char **incoming_change_description, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + const char *action; + svn_wc_operation_t conflict_operation; + const char *old_repos_relpath; + svn_revnum_t old_rev; + svn_node_kind_t old_node_kind; + const char *new_repos_relpath; + svn_revnum_t new_rev; + svn_node_kind_t new_node_kind; + apr_array_header_t *edits; + + if (conflict->tree_conflict_incoming_details == NULL) + return svn_error_trace(conflict_tree_get_incoming_description_generic( + incoming_change_description, conflict, ctx, + result_pool, scratch_pool)); + + SVN_ERR(svn_client_conflict_get_incoming_old_repos_location( + &old_repos_relpath, &old_rev, &old_node_kind, conflict, + scratch_pool, scratch_pool)); + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + &new_repos_relpath, &new_rev, &new_node_kind, conflict, + scratch_pool, scratch_pool)); + + conflict_operation = svn_client_conflict_get_operation(conflict); + + edits = conflict->tree_conflict_incoming_details; + + if (conflict_operation == svn_wc_operation_update) + action = describe_incoming_edit_upon_update(old_rev, new_rev, + old_node_kind, new_node_kind, + scratch_pool); + else if (conflict_operation == svn_wc_operation_switch) + action = describe_incoming_edit_upon_switch(new_repos_relpath, new_rev, + new_node_kind, scratch_pool); + else if (conflict_operation == svn_wc_operation_merge) + { + /* Handle merge inline because it returns early sometimes. */ + if (old_rev < new_rev) + { + if (old_rev + 1 == new_rev) + { + if (new_node_kind == svn_node_dir) + action = apr_psprintf(scratch_pool, + _("Changes destined for a directory " + "arrived during merge of\n" + "'^/%s:%ld'."), + new_repos_relpath, new_rev); + else if (new_node_kind == svn_node_file || + new_node_kind == svn_node_symlink) + action = apr_psprintf(scratch_pool, + _("Changes destined for a file " + "arrived during merge of\n" + "'^/%s:%ld'."), + new_repos_relpath, new_rev); + else + action = apr_psprintf(scratch_pool, + _("Changes arrived during merge of\n" + "'^/%s:%ld'."), + new_repos_relpath, new_rev); + + *incoming_change_description = apr_pstrdup(result_pool, action); + + return SVN_NO_ERROR; + } + else + { + if (new_node_kind == svn_node_dir) + action = apr_psprintf(scratch_pool, + _("Changes destined for a directory " + "arrived via the following revisions " + "during merge of\n'^/%s:%ld-%ld'"), + new_repos_relpath, old_rev + 1, new_rev); + else if (new_node_kind == svn_node_file || + new_node_kind == svn_node_symlink) + action = apr_psprintf(scratch_pool, + _("Changes destined for a file " + "arrived via the following revisions " + "during merge of\n'^/%s:%ld-%ld'"), + new_repos_relpath, old_rev + 1, new_rev); + else + action = apr_psprintf(scratch_pool, + _("Changes from the following revisions " + "arrived during merge of\n" + "'^/%s:%ld-%ld'"), + new_repos_relpath, old_rev + 1, new_rev); + } + } + else + { + if (new_rev + 1 == old_rev) + { + if (new_node_kind == svn_node_dir) + action = apr_psprintf(scratch_pool, + _("Changes destined for a directory " + "arrived during reverse-merge of\n" + "'^/%s:%ld'."), + new_repos_relpath, old_rev); + else if (new_node_kind == svn_node_file || + new_node_kind == svn_node_symlink) + action = apr_psprintf(scratch_pool, + _("Changes destined for a file " + "arrived during reverse-merge of\n" + "'^/%s:%ld'."), + new_repos_relpath, old_rev); + else + action = apr_psprintf(scratch_pool, + _("Changes arrived during reverse-merge " + "of\n'^/%s:%ld'."), + new_repos_relpath, old_rev); + + *incoming_change_description = apr_pstrdup(result_pool, action); + + return SVN_NO_ERROR; + } + else + { + if (new_node_kind == svn_node_dir) + action = apr_psprintf(scratch_pool, + _("Changes destined for a directory " + "arrived via the following revisions " + "during reverse-merge of\n" + "'^/%s:%ld-%ld'"), + new_repos_relpath, new_rev + 1, old_rev); + else if (new_node_kind == svn_node_file || + new_node_kind == svn_node_symlink) + action = apr_psprintf(scratch_pool, + _("Changes destined for a file " + "arrived via the following revisions " + "during reverse-merge of\n" + "'^/%s:%ld-%ld'"), + new_repos_relpath, new_rev + 1, old_rev); + + else + action = apr_psprintf(scratch_pool, + _("Changes from the following revisions " + "arrived during reverse-merge of\n" + "'^/%s:%ld-%ld'"), + new_repos_relpath, new_rev + 1, old_rev); + } + } + } + + action = apr_psprintf(scratch_pool, "%s:\n%s", action, + describe_incoming_edit_list_modified_revs( + edits, scratch_pool)); + *incoming_change_description = apr_pstrdup(result_pool, action); + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_conflict_tree_get_description( + const char **incoming_change_description, + const char **local_change_description, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + SVN_ERR(conflict->tree_conflict_get_incoming_description_func( + incoming_change_description, + conflict, ctx, result_pool, scratch_pool)); + + SVN_ERR(conflict->tree_conflict_get_local_description_func( + local_change_description, + conflict, ctx, result_pool, scratch_pool)); + + return SVN_NO_ERROR; +} + +void +svn_client_conflict_option_set_merged_propval( + svn_client_conflict_option_t *option, + const svn_string_t *merged_propval) +{ + option->type_data.prop.merged_propval = svn_string_dup(merged_propval, + option->pool); +} + +/* Implements conflict_option_resolve_func_t. */ +static svn_error_t * +resolve_postpone(svn_client_conflict_option_t *option, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + return SVN_NO_ERROR; /* Nothing to do. */ +} + +/* Implements conflict_option_resolve_func_t. */ +static svn_error_t * +resolve_text_conflict(svn_client_conflict_option_t *option, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + svn_client_conflict_option_id_t option_id; + const char *local_abspath; + const char *lock_abspath; + svn_wc_conflict_choice_t conflict_choice; + svn_error_t *err; + + option_id = svn_client_conflict_option_get_id(option); + conflict_choice = conflict_option_id_to_wc_conflict_choice(option_id); + local_abspath = svn_client_conflict_get_local_abspath(conflict); + + SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, ctx->wc_ctx, + local_abspath, + scratch_pool, scratch_pool)); + err = svn_wc__conflict_text_mark_resolved(ctx->wc_ctx, + local_abspath, + conflict_choice, + ctx->cancel_func, + ctx->cancel_baton, + ctx->notify_func2, + ctx->notify_baton2, + scratch_pool); + err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx, + lock_abspath, + scratch_pool)); + svn_io_sleep_for_timestamps(local_abspath, scratch_pool); + SVN_ERR(err); + + conflict->resolution_text = option_id; + + return SVN_NO_ERROR; +} + +/* Implements conflict_option_resolve_func_t. */ +static svn_error_t * +resolve_prop_conflict(svn_client_conflict_option_t *option, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + svn_client_conflict_option_id_t option_id; + svn_wc_conflict_choice_t conflict_choice; + const char *local_abspath; + const char *lock_abspath; + const char *propname = option->type_data.prop.propname; + svn_error_t *err; + const svn_string_t *merged_value; + + option_id = svn_client_conflict_option_get_id(option); + conflict_choice = conflict_option_id_to_wc_conflict_choice(option_id); + local_abspath = svn_client_conflict_get_local_abspath(conflict); + + if (option_id == svn_client_conflict_option_merged_text) + merged_value = option->type_data.prop.merged_propval; + else + merged_value = NULL; + + SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, ctx->wc_ctx, + local_abspath, + scratch_pool, scratch_pool)); + err = svn_wc__conflict_prop_mark_resolved(ctx->wc_ctx, local_abspath, + propname, conflict_choice, + merged_value, + ctx->notify_func2, + ctx->notify_baton2, + scratch_pool); + err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx, + lock_abspath, + scratch_pool)); + svn_io_sleep_for_timestamps(local_abspath, scratch_pool); + SVN_ERR(err); + + if (propname[0] == '\0') + { + apr_hash_index_t *hi; + + /* All properties have been resolved to the same option. */ + for (hi = apr_hash_first(scratch_pool, conflict->prop_conflicts); + hi; + hi = apr_hash_next(hi)) + { + const char *this_propname = apr_hash_this_key(hi); + + svn_hash_sets(conflict->resolved_props, + apr_pstrdup(apr_hash_pool_get(conflict->resolved_props), + this_propname), + option); + svn_hash_sets(conflict->prop_conflicts, this_propname, NULL); + } + + conflict->legacy_prop_conflict_propname = NULL; + } + else + { + svn_hash_sets(conflict->resolved_props, + apr_pstrdup(apr_hash_pool_get(conflict->resolved_props), + propname), + option); + svn_hash_sets(conflict->prop_conflicts, propname, NULL); + + if (apr_hash_count(conflict->prop_conflicts) > 0) + conflict->legacy_prop_conflict_propname = + apr_hash_this_key(apr_hash_first(scratch_pool, + conflict->prop_conflicts)); + else + conflict->legacy_prop_conflict_propname = NULL; + } + + return SVN_NO_ERROR; +} + +/* Implements conflict_option_resolve_func_t. */ +static svn_error_t * +resolve_accept_current_wc_state(svn_client_conflict_option_t *option, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + svn_client_conflict_option_id_t option_id; + const char *local_abspath; + const char *lock_abspath; + svn_error_t *err; + + option_id = svn_client_conflict_option_get_id(option); + local_abspath = svn_client_conflict_get_local_abspath(conflict); + + if (option_id != svn_client_conflict_option_accept_current_wc_state) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Tree conflict on '%s' can only be resolved " + "to the current working copy state"), + svn_dirent_local_style(local_abspath, + scratch_pool)); + + SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, ctx->wc_ctx, + local_abspath, + scratch_pool, scratch_pool)); + + /* Resolve to current working copy state. */ + err = svn_wc__del_tree_conflict(ctx->wc_ctx, local_abspath, scratch_pool); + + /* svn_wc__del_tree_conflict doesn't handle notification for us */ + if (ctx->notify_func2) + ctx->notify_func2(ctx->notify_baton2, + svn_wc_create_notify(local_abspath, + svn_wc_notify_resolved_tree, + scratch_pool), + scratch_pool); + + err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx, + lock_abspath, + scratch_pool)); + SVN_ERR(err); + + conflict->resolution_tree = option_id; + + return SVN_NO_ERROR; +} + +/* Implements conflict_option_resolve_func_t. */ +static svn_error_t * +resolve_update_break_moved_away(svn_client_conflict_option_t *option, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + const char *local_abspath; + const char *lock_abspath; + svn_error_t *err; + + local_abspath = svn_client_conflict_get_local_abspath(conflict); + + SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, ctx->wc_ctx, + local_abspath, + scratch_pool, scratch_pool)); + err = svn_wc__conflict_tree_update_break_moved_away(ctx->wc_ctx, + local_abspath, + ctx->cancel_func, + ctx->cancel_baton, + ctx->notify_func2, + ctx->notify_baton2, + scratch_pool); + err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx, + lock_abspath, + scratch_pool)); + SVN_ERR(err); + + conflict->resolution_tree = svn_client_conflict_option_get_id(option); + + return SVN_NO_ERROR; +} + +/* Implements conflict_option_resolve_func_t. */ +static svn_error_t * +resolve_update_raise_moved_away(svn_client_conflict_option_t *option, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + const char *local_abspath; + const char *lock_abspath; + svn_error_t *err; + + local_abspath = svn_client_conflict_get_local_abspath(conflict); + + SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, ctx->wc_ctx, + local_abspath, + scratch_pool, scratch_pool)); + err = svn_wc__conflict_tree_update_raise_moved_away(ctx->wc_ctx, + local_abspath, + ctx->cancel_func, + ctx->cancel_baton, + ctx->notify_func2, + ctx->notify_baton2, + scratch_pool); + err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx, + lock_abspath, + scratch_pool)); + SVN_ERR(err); + + conflict->resolution_tree = svn_client_conflict_option_get_id(option); + + return SVN_NO_ERROR; +} + +/* Implements conflict_option_resolve_func_t. */ +static svn_error_t * +resolve_update_moved_away_node(svn_client_conflict_option_t *option, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + const char *local_abspath; + const char *lock_abspath; + svn_error_t *err; + + local_abspath = svn_client_conflict_get_local_abspath(conflict); + + SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, ctx->wc_ctx, + local_abspath, + scratch_pool, scratch_pool)); + err = svn_wc__conflict_tree_update_moved_away_node(ctx->wc_ctx, + local_abspath, + ctx->cancel_func, + ctx->cancel_baton, + ctx->notify_func2, + ctx->notify_baton2, + scratch_pool); + err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx, + lock_abspath, + scratch_pool)); + svn_io_sleep_for_timestamps(local_abspath, scratch_pool); + SVN_ERR(err); + + conflict->resolution_tree = svn_client_conflict_option_get_id(option); + + return SVN_NO_ERROR; +} + +/* Verify the local working copy state matches what we expect when an + * incoming add vs add tree conflict exists after an update operation. + * We assume the update operation leaves the working copy in a state which + * prefers the local change and cancels the incoming addition. + * Run a quick sanity check and error out if it looks as if the + * working copy was modified since, even though it's not easy to make + * such modifications without also clearing the conflict marker. */ +static svn_error_t * +verify_local_state_for_incoming_add_upon_update( + svn_client_conflict_t *conflict, + svn_client_conflict_option_t *option, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + const char *local_abspath; + svn_client_conflict_option_id_t option_id; + const char *wcroot_abspath; + svn_wc_operation_t operation; + const char *incoming_new_repos_relpath; + svn_revnum_t incoming_new_pegrev; + svn_node_kind_t incoming_new_kind; + const char *base_repos_relpath; + svn_revnum_t base_rev; + svn_node_kind_t base_kind; + const char *local_style_relpath; + svn_boolean_t is_added; + svn_error_t *err; + + local_abspath = svn_client_conflict_get_local_abspath(conflict); + option_id = svn_client_conflict_option_get_id(option); + SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, ctx->wc_ctx, + local_abspath, scratch_pool, + scratch_pool)); + operation = svn_client_conflict_get_operation(conflict); + SVN_ERR_ASSERT(operation == svn_wc_operation_update); + + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + &incoming_new_repos_relpath, &incoming_new_pegrev, + &incoming_new_kind, conflict, scratch_pool, + scratch_pool)); + + local_style_relpath = svn_dirent_local_style( + svn_dirent_skip_ancestor(wcroot_abspath, + local_abspath), + scratch_pool); + + /* Check if a local addition addition replaces the incoming new node. */ + err = svn_wc__node_get_base(&base_kind, &base_rev, &base_repos_relpath, + NULL, NULL, NULL, ctx->wc_ctx, local_abspath, + FALSE, scratch_pool, scratch_pool); + if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND) + { + if (option_id == svn_client_conflict_option_incoming_add_ignore) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, err, + _("Cannot resolve tree conflict on '%s' " + "(expected a base node but found none)"), + local_style_relpath); + else if (option_id == + svn_client_conflict_option_incoming_added_dir_replace) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, err, + _("Cannot resolve tree conflict on '%s' " + "(expected a base node but found none)"), + local_style_relpath); + else + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, err, + _("Unexpected option id '%d'"), option_id); + } + else if (err) + return svn_error_trace(err); + + if (base_kind != incoming_new_kind) + { + if (option_id == svn_client_conflict_option_incoming_add_ignore) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Cannot resolve tree conflict on '%s' " + "(expected base node kind '%s', " + "but found '%s')"), + local_style_relpath, + svn_node_kind_to_word(incoming_new_kind), + svn_node_kind_to_word(base_kind)); + else if (option_id == + svn_client_conflict_option_incoming_added_dir_replace) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Cannot resolve tree conflict on '%s' " + "(expected base node kind '%s', " + "but found '%s')"), + local_style_relpath, + svn_node_kind_to_word(incoming_new_kind), + svn_node_kind_to_word(base_kind)); + else + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Unexpected option id '%d'"), option_id); + } + + if (strcmp(base_repos_relpath, incoming_new_repos_relpath) != 0 || + base_rev != incoming_new_pegrev) + { + if (option_id == svn_client_conflict_option_incoming_add_ignore) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Cannot resolve tree conflict on '%s' " + "(expected base node from '^/%s@%ld', " + "but found '^/%s@%ld')"), + local_style_relpath, + incoming_new_repos_relpath, + incoming_new_pegrev, + base_repos_relpath, base_rev); + else if (option_id == + svn_client_conflict_option_incoming_added_dir_replace) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Cannot resolve tree conflict on '%s' " + "(expected base node from '^/%s@%ld', " + "but found '^/%s@%ld')"), + local_style_relpath, + incoming_new_repos_relpath, + incoming_new_pegrev, + base_repos_relpath, base_rev); + else + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Unexpected option id '%d'"), option_id); + } + + SVN_ERR(svn_wc__node_is_added(&is_added, ctx->wc_ctx, local_abspath, + scratch_pool)); + if (!is_added) + { + if (option_id == svn_client_conflict_option_incoming_add_ignore) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Cannot resolve tree conflict on '%s' " + "(expected an added item, but the item " + "is not added)"), + local_style_relpath); + + else if (option_id == + svn_client_conflict_option_incoming_added_dir_replace) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Cannot resolve tree conflict on '%s' " + "(expected an added item, but the item " + "is not added)"), + local_style_relpath); + else + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Unexpected option id '%d'"), option_id); + } + + return SVN_NO_ERROR; +} + + +/* Implements conflict_option_resolve_func_t. */ +static svn_error_t * +resolve_incoming_add_ignore(svn_client_conflict_option_t *option, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + const char *local_abspath; + const char *lock_abspath; + svn_wc_operation_t operation; + svn_error_t *err; + + local_abspath = svn_client_conflict_get_local_abspath(conflict); + operation = svn_client_conflict_get_operation(conflict); + + SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, ctx->wc_ctx, + local_abspath, + scratch_pool, scratch_pool)); + + if (operation == svn_wc_operation_update) + { + err = verify_local_state_for_incoming_add_upon_update(conflict, option, + ctx, scratch_pool); + if (err) + goto unlock_wc; + } + + /* All other options for this conflict actively fetch the incoming + * new node. We can ignore the incoming new node by doing nothing. */ + + /* Resolve to current working copy state. */ + err = svn_wc__del_tree_conflict(ctx->wc_ctx, local_abspath, scratch_pool); + + /* svn_wc__del_tree_conflict doesn't handle notification for us */ + if (ctx->notify_func2) + ctx->notify_func2(ctx->notify_baton2, + svn_wc_create_notify(local_abspath, + svn_wc_notify_resolved_tree, + scratch_pool), + scratch_pool); + +unlock_wc: + err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx, + lock_abspath, + scratch_pool)); + SVN_ERR(err); + + conflict->resolution_tree = svn_client_conflict_option_get_id(option); + + return SVN_NO_ERROR; +} + +/* Delete entry and wc props from a set of properties. */ +static void +filter_props(apr_hash_t *props, apr_pool_t *scratch_pool) +{ + apr_hash_index_t *hi; + + for (hi = apr_hash_first(scratch_pool, props); + hi != NULL; + hi = apr_hash_next(hi)) + { + const char *propname = apr_hash_this_key(hi); + + if (!svn_wc_is_normal_prop(propname)) + svn_hash_sets(props, propname, NULL); + } +} + +/* Implements conflict_option_resolve_func_t. */ +static svn_error_t * +resolve_merge_incoming_added_file_text_update( + svn_client_conflict_option_t *option, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + const char *wc_tmpdir; + const char *local_abspath; + const char *lock_abspath; + svn_wc_merge_outcome_t merge_content_outcome; + svn_wc_notify_state_t merge_props_outcome; + const char *empty_file_abspath; + const char *working_file_tmp_abspath; + svn_stream_t *working_file_stream; + svn_stream_t *working_file_tmp_stream; + apr_hash_t *working_props; + apr_array_header_t *propdiffs; + svn_error_t *err; + + local_abspath = svn_client_conflict_get_local_abspath(conflict); + + /* Set up tempory storage for the working version of file. */ + SVN_ERR(svn_wc__get_tmpdir(&wc_tmpdir, ctx->wc_ctx, local_abspath, + scratch_pool, scratch_pool)); + SVN_ERR(svn_stream_open_unique(&working_file_tmp_stream, + &working_file_tmp_abspath, wc_tmpdir, + /* Don't delete automatically! */ + svn_io_file_del_none, + scratch_pool, scratch_pool)); + + /* Copy the detranslated working file to temporary storage. */ + SVN_ERR(svn_wc__translated_stream(&working_file_stream, ctx->wc_ctx, + local_abspath, local_abspath, + SVN_WC_TRANSLATE_TO_NF, + scratch_pool, scratch_pool)); + SVN_ERR(svn_stream_copy3(working_file_stream, working_file_tmp_stream, + ctx->cancel_func, ctx->cancel_baton, + scratch_pool)); + + /* Get a copy of the working file's properties. */ + SVN_ERR(svn_wc_prop_list2(&working_props, ctx->wc_ctx, local_abspath, + scratch_pool, scratch_pool)); + filter_props(working_props, scratch_pool); + + /* Create an empty file as fake "merge-base" for the two added files. + * The files are not ancestrally related so this is the best we can do. */ + SVN_ERR(svn_io_open_unique_file3(NULL, &empty_file_abspath, NULL, + svn_io_file_del_on_pool_cleanup, + scratch_pool, scratch_pool)); + + /* Create a property diff which shows all props as added. */ + SVN_ERR(svn_prop_diffs(&propdiffs, working_props, + apr_hash_make(scratch_pool), scratch_pool)); + + /* ### The following WC modifications should be atomic. */ + SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, ctx->wc_ctx, + local_abspath, + scratch_pool, scratch_pool)); + + /* Revert the path in order to restore the repository's line of + * history, which is part of the BASE tree. This revert operation + * is why are being careful about not losing the temporary copy. */ + err = svn_wc_revert5(ctx->wc_ctx, local_abspath, svn_depth_empty, + FALSE, NULL, TRUE, FALSE, + NULL, NULL, /* no cancellation */ + ctx->notify_func2, ctx->notify_baton2, + scratch_pool); + if (err) + goto unlock_wc; + + /* Perform the file merge. ### Merge into tempfile and then rename on top? */ + err = svn_wc_merge5(&merge_content_outcome, &merge_props_outcome, + ctx->wc_ctx, empty_file_abspath, + working_file_tmp_abspath, local_abspath, + NULL, NULL, NULL, /* labels */ + NULL, NULL, /* conflict versions */ + FALSE, /* dry run */ + NULL, NULL, /* diff3_cmd, merge_options */ + NULL, propdiffs, + NULL, NULL, /* conflict func/baton */ + NULL, NULL, /* don't allow user to cancel here */ + scratch_pool); + +unlock_wc: + if (err) + err = svn_error_quick_wrapf( + err, _("If needed, a backup copy of '%s' can be found at '%s'"), + svn_dirent_local_style(local_abspath, scratch_pool), + svn_dirent_local_style(working_file_tmp_abspath, scratch_pool)); + err = svn_error_compose_create(err, + svn_wc__release_write_lock(ctx->wc_ctx, + lock_abspath, + scratch_pool)); + svn_io_sleep_for_timestamps(local_abspath, scratch_pool); + SVN_ERR(err); + + if (ctx->notify_func2) + { + svn_wc_notify_t *notify; + + /* Tell the world about the file merge that just happened. */ + notify = svn_wc_create_notify(local_abspath, + svn_wc_notify_update_update, + scratch_pool); + if (merge_content_outcome == svn_wc_merge_conflict) + notify->content_state = svn_wc_notify_state_conflicted; + else + notify->content_state = svn_wc_notify_state_merged; + notify->prop_state = merge_props_outcome; + notify->kind = svn_node_file; + ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool); + + /* And also about the successfully resolved tree conflict. */ + notify = svn_wc_create_notify(local_abspath, svn_wc_notify_resolved_tree, + scratch_pool); + ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool); + } + + conflict->resolution_tree = svn_client_conflict_option_get_id(option); + + /* All is good -- remove temporary copy of the working file. */ + SVN_ERR(svn_io_remove_file2(working_file_tmp_abspath, TRUE, scratch_pool)); + + return SVN_NO_ERROR; +} + +/* Implements conflict_option_resolve_func_t. */ +static svn_error_t * +resolve_merge_incoming_added_file_text_merge( + svn_client_conflict_option_t *option, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + svn_ra_session_t *ra_session; + const char *url; + const char *corrected_url; + const char *repos_root_url; + const char *wc_tmpdir; + const char *incoming_new_repos_relpath; + svn_revnum_t incoming_new_pegrev; + const char *local_abspath; + const char *lock_abspath; + svn_wc_merge_outcome_t merge_content_outcome; + svn_wc_notify_state_t merge_props_outcome; + apr_file_t *incoming_new_file; + const char *incoming_new_tmp_abspath; + const char *empty_file_abspath; + svn_stream_t *incoming_new_stream; + apr_hash_t *incoming_new_props; + apr_array_header_t *propdiffs; + svn_error_t *err; + + local_abspath = svn_client_conflict_get_local_abspath(conflict); + + /* Set up temporary storage for the repository version of file. */ + SVN_ERR(svn_wc__get_tmpdir(&wc_tmpdir, ctx->wc_ctx, local_abspath, + scratch_pool, scratch_pool)); + SVN_ERR(svn_io_open_unique_file3(&incoming_new_file, + &incoming_new_tmp_abspath, wc_tmpdir, + svn_io_file_del_on_pool_cleanup, + scratch_pool, scratch_pool)); + incoming_new_stream = svn_stream_from_aprfile2(incoming_new_file, TRUE, + scratch_pool); + + /* Fetch the incoming added file from the repository. */ + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + &incoming_new_repos_relpath, &incoming_new_pegrev, + NULL, conflict, scratch_pool, + scratch_pool)); + SVN_ERR(svn_client_conflict_get_repos_info(&repos_root_url, NULL, + conflict, scratch_pool, + scratch_pool)); + url = svn_path_url_add_component2(repos_root_url, incoming_new_repos_relpath, + scratch_pool); + SVN_ERR(svn_client__open_ra_session_internal(&ra_session, &corrected_url, + url, NULL, NULL, FALSE, FALSE, + ctx, scratch_pool, + scratch_pool)); + SVN_ERR(svn_ra_get_file(ra_session, "", incoming_new_pegrev, + incoming_new_stream, NULL, /* fetched_rev */ + &incoming_new_props, scratch_pool)); + + /* Flush file to disk. */ + SVN_ERR(svn_stream_close(incoming_new_stream)); + SVN_ERR(svn_io_file_flush(incoming_new_file, scratch_pool)); + + filter_props(incoming_new_props, scratch_pool); + + /* Create an empty file as fake "merge-base" for the two added files. + * The files are not ancestrally related so this is the best we can do. */ + SVN_ERR(svn_io_open_unique_file3(NULL, &empty_file_abspath, NULL, + svn_io_file_del_on_pool_cleanup, + scratch_pool, scratch_pool)); + + /* Create a property diff which shows all props as added. */ + SVN_ERR(svn_prop_diffs(&propdiffs, incoming_new_props, + apr_hash_make(scratch_pool), scratch_pool)); + + /* ### The following WC modifications should be atomic. */ + SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, ctx->wc_ctx, + local_abspath, + scratch_pool, scratch_pool)); + /* Resolve to current working copy state. svn_wc_merge5() requires this. */ + err = svn_wc__del_tree_conflict(ctx->wc_ctx, local_abspath, scratch_pool); + if (err) + return svn_error_compose_create(err, + svn_wc__release_write_lock(ctx->wc_ctx, + lock_abspath, + scratch_pool)); + /* Perform the file merge. ### Merge into tempfile and then rename on top? */ + err = svn_wc_merge5(&merge_content_outcome, &merge_props_outcome, + ctx->wc_ctx, empty_file_abspath, + incoming_new_tmp_abspath, local_abspath, + NULL, NULL, NULL, /* labels */ + NULL, NULL, /* conflict versions */ + FALSE, /* dry run */ + NULL, NULL, /* diff3_cmd, merge_options */ + NULL, propdiffs, + NULL, NULL, /* conflict func/baton */ + NULL, NULL, /* don't allow user to cancel here */ + scratch_pool); + err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx, + lock_abspath, + scratch_pool)); + svn_io_sleep_for_timestamps(local_abspath, scratch_pool); + SVN_ERR(err); + + if (ctx->notify_func2) + { + svn_wc_notify_t *notify; + + /* Tell the world about the file merge that just happened. */ + notify = svn_wc_create_notify(local_abspath, + svn_wc_notify_update_update, + scratch_pool); + if (merge_content_outcome == svn_wc_merge_conflict) + notify->content_state = svn_wc_notify_state_conflicted; + else + notify->content_state = svn_wc_notify_state_merged; + notify->prop_state = merge_props_outcome; + notify->kind = svn_node_file; + ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool); + + /* And also about the successfully resolved tree conflict. */ + notify = svn_wc_create_notify(local_abspath, svn_wc_notify_resolved_tree, + scratch_pool); + ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool); + } + + conflict->resolution_tree = svn_client_conflict_option_get_id(option); + + return SVN_NO_ERROR; +} + +/* Implements conflict_option_resolve_func_t. */ +static svn_error_t * +resolve_merge_incoming_added_file_replace_and_merge( + svn_client_conflict_option_t *option, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + svn_ra_session_t *ra_session; + const char *url; + const char *corrected_url; + const char *repos_root_url; + const char *incoming_new_repos_relpath; + svn_revnum_t incoming_new_pegrev; + apr_file_t *incoming_new_file; + svn_stream_t *incoming_new_stream; + apr_hash_t *incoming_new_props; + const char *local_abspath; + const char *lock_abspath; + const char *wc_tmpdir; + svn_stream_t *working_file_tmp_stream; + const char *working_file_tmp_abspath; + svn_stream_t *working_file_stream; + apr_hash_t *working_props; + svn_error_t *err; + svn_wc_merge_outcome_t merge_content_outcome; + svn_wc_notify_state_t merge_props_outcome; + apr_file_t *empty_file; + const char *empty_file_abspath; + apr_array_header_t *propdiffs; + + local_abspath = svn_client_conflict_get_local_abspath(conflict); + + /* Set up tempory storage for the working version of file. */ + SVN_ERR(svn_wc__get_tmpdir(&wc_tmpdir, ctx->wc_ctx, local_abspath, + scratch_pool, scratch_pool)); + SVN_ERR(svn_stream_open_unique(&working_file_tmp_stream, + &working_file_tmp_abspath, wc_tmpdir, + svn_io_file_del_on_pool_cleanup, + scratch_pool, scratch_pool)); + + /* Copy the detranslated working file to temporary storage. */ + SVN_ERR(svn_wc__translated_stream(&working_file_stream, ctx->wc_ctx, + local_abspath, local_abspath, + SVN_WC_TRANSLATE_TO_NF, + scratch_pool, scratch_pool)); + SVN_ERR(svn_stream_copy3(working_file_stream, working_file_tmp_stream, + ctx->cancel_func, ctx->cancel_baton, + scratch_pool)); + + /* Get a copy of the working file's properties. */ + SVN_ERR(svn_wc_prop_list2(&working_props, ctx->wc_ctx, local_abspath, + scratch_pool, scratch_pool)); + + /* Fetch the incoming added file from the repository. */ + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + &incoming_new_repos_relpath, &incoming_new_pegrev, + NULL, conflict, scratch_pool, + scratch_pool)); + SVN_ERR(svn_client_conflict_get_repos_info(&repos_root_url, NULL, + conflict, scratch_pool, + scratch_pool)); + url = svn_path_url_add_component2(repos_root_url, incoming_new_repos_relpath, + scratch_pool); + SVN_ERR(svn_client__open_ra_session_internal(&ra_session, &corrected_url, + url, NULL, NULL, FALSE, FALSE, + ctx, scratch_pool, + scratch_pool)); + if (corrected_url) + url = corrected_url; + SVN_ERR(svn_io_open_unique_file3(&incoming_new_file, NULL, wc_tmpdir, + svn_io_file_del_on_pool_cleanup, + scratch_pool, scratch_pool)); + incoming_new_stream = svn_stream_from_aprfile2(incoming_new_file, TRUE, + scratch_pool); + SVN_ERR(svn_ra_get_file(ra_session, "", incoming_new_pegrev, + incoming_new_stream, NULL, /* fetched_rev */ + &incoming_new_props, scratch_pool)); + /* Flush file to disk. */ + SVN_ERR(svn_io_file_flush(incoming_new_file, scratch_pool)); + + /* Reset the stream in preparation for adding its content to WC. */ + SVN_ERR(svn_stream_reset(incoming_new_stream)); + + SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, ctx->wc_ctx, + local_abspath, + scratch_pool, scratch_pool)); + + /* ### The following WC modifications should be atomic. */ + + /* Replace the working file with the file from the repository. */ + err = svn_wc_delete4(ctx->wc_ctx, local_abspath, FALSE, FALSE, + NULL, NULL, /* don't allow user to cancel here */ + ctx->notify_func2, ctx->notify_baton2, + scratch_pool); + if (err) + goto unlock_wc; + err = svn_wc_add_repos_file4(ctx->wc_ctx, local_abspath, + incoming_new_stream, + NULL, /* ### could we merge first, then set + ### the merged content here? */ + incoming_new_props, + NULL, /* ### merge props first, set here? */ + url, incoming_new_pegrev, + NULL, NULL, /* don't allow user to cancel here */ + scratch_pool); + if (err) + goto unlock_wc; + + if (ctx->notify_func2) + { + svn_wc_notify_t *notify = svn_wc_create_notify(local_abspath, + svn_wc_notify_add, + scratch_pool); + notify->kind = svn_node_file; + ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool); + } + + /* Resolve to current working copy state. svn_wc_merge5() requires this. */ + err = svn_wc__del_tree_conflict(ctx->wc_ctx, local_abspath, scratch_pool); + if (err) + goto unlock_wc; + + /* Create an empty file as fake "merge-base" for the two added files. + * The files are not ancestrally related so this is the best we can do. */ + err = svn_io_open_unique_file3(&empty_file, &empty_file_abspath, NULL, + svn_io_file_del_on_pool_cleanup, + scratch_pool, scratch_pool); + if (err) + goto unlock_wc; + + filter_props(incoming_new_props, scratch_pool); + + /* Create a property diff for the files. */ + err = svn_prop_diffs(&propdiffs, incoming_new_props, + working_props, scratch_pool); + if (err) + goto unlock_wc; + + /* Perform the file merge. */ + err = svn_wc_merge5(&merge_content_outcome, &merge_props_outcome, + ctx->wc_ctx, empty_file_abspath, + working_file_tmp_abspath, local_abspath, + NULL, NULL, NULL, /* labels */ + NULL, NULL, /* conflict versions */ + FALSE, /* dry run */ + NULL, NULL, /* diff3_cmd, merge_options */ + NULL, propdiffs, + NULL, NULL, /* conflict func/baton */ + NULL, NULL, /* don't allow user to cancel here */ + scratch_pool); + if (err) + goto unlock_wc; + + if (ctx->notify_func2) + { + svn_wc_notify_t *notify = svn_wc_create_notify( + local_abspath, + svn_wc_notify_update_update, + scratch_pool); + + if (merge_content_outcome == svn_wc_merge_conflict) + notify->content_state = svn_wc_notify_state_conflicted; + else + notify->content_state = svn_wc_notify_state_merged; + notify->prop_state = merge_props_outcome; + notify->kind = svn_node_file; + ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool); + } + +unlock_wc: + err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx, + lock_abspath, + scratch_pool)); + svn_io_sleep_for_timestamps(local_abspath, scratch_pool); + SVN_ERR(err); + + SVN_ERR(svn_stream_close(incoming_new_stream)); + + if (ctx->notify_func2) + { + svn_wc_notify_t *notify = svn_wc_create_notify( + local_abspath, + svn_wc_notify_resolved_tree, + scratch_pool); + + ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool); + } + + conflict->resolution_tree = svn_client_conflict_option_get_id(option); + + return SVN_NO_ERROR; +} + +static svn_error_t * +raise_tree_conflict(const char *local_abspath, + svn_wc_conflict_action_t incoming_change, + svn_wc_conflict_reason_t local_change, + svn_node_kind_t local_node_kind, + svn_node_kind_t merge_left_kind, + svn_node_kind_t merge_right_kind, + const char *repos_root_url, + const char *repos_uuid, + const char *repos_relpath, + svn_revnum_t merge_left_rev, + svn_revnum_t merge_right_rev, + svn_wc_context_t *wc_ctx, + svn_wc_notify_func2_t notify_func2, + void *notify_baton2, + apr_pool_t *scratch_pool) +{ + svn_wc_conflict_description2_t *conflict; + const svn_wc_conflict_version_t *left_version; + const svn_wc_conflict_version_t *right_version; + + left_version = svn_wc_conflict_version_create2(repos_root_url, + repos_uuid, + repos_relpath, + merge_left_rev, + merge_left_kind, + scratch_pool); + right_version = svn_wc_conflict_version_create2(repos_root_url, + repos_uuid, + repos_relpath, + merge_right_rev, + merge_right_kind, + scratch_pool); + conflict = svn_wc_conflict_description_create_tree2(local_abspath, + local_node_kind, + svn_wc_operation_merge, + left_version, + right_version, + scratch_pool); + conflict->action = incoming_change; + conflict->reason = local_change; + + SVN_ERR(svn_wc__add_tree_conflict(wc_ctx, conflict, scratch_pool)); + + if (notify_func2) + { + svn_wc_notify_t *notify; + + notify = svn_wc_create_notify(local_abspath, svn_wc_notify_tree_conflict, + scratch_pool); + notify->kind = local_node_kind; + notify_func2(notify_baton2, notify, scratch_pool); + } + + return SVN_NO_ERROR; +} + +struct merge_newly_added_dir_baton { + const char *target_abspath; + svn_client_ctx_t *ctx; + const char *repos_root_url; + const char *repos_uuid; + const char *added_repos_relpath; + svn_revnum_t merge_left_rev; + svn_revnum_t merge_right_rev; +}; + +static svn_error_t * +merge_added_dir_props(const char *target_abspath, + const char *added_repos_relpath, + apr_hash_t *added_props, + const char *repos_root_url, + const char *repos_uuid, + svn_revnum_t merge_left_rev, + svn_revnum_t merge_right_rev, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + svn_wc_notify_state_t property_state; + apr_array_header_t *propchanges; + const svn_wc_conflict_version_t *left_version; + const svn_wc_conflict_version_t *right_version; + apr_hash_index_t *hi; + + left_version = svn_wc_conflict_version_create2( + repos_root_url, repos_uuid, added_repos_relpath, + merge_left_rev, svn_node_none, scratch_pool); + + right_version = svn_wc_conflict_version_create2( + repos_root_url, repos_uuid, added_repos_relpath, + merge_right_rev, svn_node_dir, scratch_pool); + + propchanges = apr_array_make(scratch_pool, apr_hash_count(added_props), + sizeof(svn_prop_t)); + for (hi = apr_hash_first(scratch_pool, added_props); + hi; + hi = apr_hash_next(hi)) + { + svn_prop_t prop; + + prop.name = apr_hash_this_key(hi); + prop.value = apr_hash_this_val(hi); + + if (svn_wc_is_normal_prop(prop.name)) + APR_ARRAY_PUSH(propchanges, svn_prop_t) = prop; + } + + SVN_ERR(svn_wc_merge_props3(&property_state, ctx->wc_ctx, + target_abspath, + left_version, right_version, + apr_hash_make(scratch_pool), + propchanges, + FALSE, /* not a dry-run */ + NULL, NULL, NULL, NULL, + scratch_pool)); + + if (ctx->notify_func2) + { + svn_wc_notify_t *notify; + + notify = svn_wc_create_notify(target_abspath, + svn_wc_notify_update_update, + scratch_pool); + notify->kind = svn_node_dir; + notify->content_state = svn_wc_notify_state_unchanged;; + notify->prop_state = property_state; + ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool); + } + + return SVN_NO_ERROR; +} + +/* An svn_diff_tree_processor_t callback. */ +static svn_error_t * +diff_dir_added(const char *relpath, + const svn_diff_source_t *copyfrom_source, + const svn_diff_source_t *right_source, + apr_hash_t *copyfrom_props, + apr_hash_t *right_props, + void *dir_baton, + const struct svn_diff_tree_processor_t *processor, + apr_pool_t *scratch_pool) +{ + struct merge_newly_added_dir_baton *b = processor->baton; + const char *local_abspath; + const char *copyfrom_url; + svn_node_kind_t db_kind; + svn_node_kind_t on_disk_kind; + apr_hash_index_t *hi; + + /* Handle the root of the added directory tree. */ + if (relpath[0] == '\0') + { + /* ### svn_wc_merge_props3() requires this... */ + SVN_ERR(svn_wc__del_tree_conflict(b->ctx->wc_ctx, b->target_abspath, + scratch_pool)); + SVN_ERR(merge_added_dir_props(b->target_abspath, + b->added_repos_relpath, right_props, + b->repos_root_url, b->repos_uuid, + b->merge_left_rev, b->merge_right_rev, + b->ctx, scratch_pool)); + return SVN_NO_ERROR; + + } + + local_abspath = svn_dirent_join(b->target_abspath, relpath, scratch_pool); + + SVN_ERR(svn_wc_read_kind2(&db_kind, b->ctx->wc_ctx, local_abspath, + FALSE, FALSE, scratch_pool)); + SVN_ERR(svn_io_check_path(local_abspath, &on_disk_kind, scratch_pool)); + + if (db_kind == svn_node_dir && on_disk_kind == svn_node_dir) + { + SVN_ERR(merge_added_dir_props(svn_dirent_join(b->target_abspath, relpath, + scratch_pool), + b->added_repos_relpath, right_props, + b->repos_root_url, b->repos_uuid, + b->merge_left_rev, b->merge_right_rev, + b->ctx, scratch_pool)); + return SVN_NO_ERROR; + } + + if (db_kind != svn_node_none && db_kind != svn_node_unknown) + { + SVN_ERR(raise_tree_conflict( + local_abspath, svn_wc_conflict_action_add, + svn_wc_conflict_reason_obstructed, + db_kind, svn_node_none, svn_node_dir, + b->repos_root_url, b->repos_uuid, + svn_relpath_join(b->added_repos_relpath, relpath, scratch_pool), + b->merge_left_rev, b->merge_right_rev, + b->ctx->wc_ctx, b->ctx->notify_func2, b->ctx->notify_baton2, + scratch_pool)); + return SVN_NO_ERROR; + } + + if (on_disk_kind != svn_node_none) + { + SVN_ERR(raise_tree_conflict( + local_abspath, svn_wc_conflict_action_add, + svn_wc_conflict_reason_obstructed, db_kind, + svn_node_none, svn_node_dir, b->repos_root_url, b->repos_uuid, + svn_relpath_join(b->added_repos_relpath, relpath, scratch_pool), + b->merge_left_rev, b->merge_right_rev, + b->ctx->wc_ctx, b->ctx->notify_func2, b->ctx->notify_baton2, + scratch_pool)); + return SVN_NO_ERROR; + } + + SVN_ERR(svn_io_dir_make(local_abspath, APR_OS_DEFAULT, scratch_pool)); + copyfrom_url = apr_pstrcat(scratch_pool, b->repos_root_url, "/", + right_source->repos_relpath, SVN_VA_NULL); + SVN_ERR(svn_wc_add4(b->ctx->wc_ctx, local_abspath, svn_depth_infinity, + copyfrom_url, right_source->revision, + NULL, NULL, /* cancel func/baton */ + b->ctx->notify_func2, b->ctx->notify_baton2, + scratch_pool)); + + for (hi = apr_hash_first(scratch_pool, right_props); + hi; + hi = apr_hash_next(hi)) + { + const char *propname = apr_hash_this_key(hi); + const svn_string_t *propval = apr_hash_this_val(hi); + + SVN_ERR(svn_wc_prop_set4(b->ctx->wc_ctx, local_abspath, + propname, propval, svn_depth_empty, + FALSE, NULL /* do not skip checks */, + NULL, NULL, /* cancel func/baton */ + b->ctx->notify_func2, b->ctx->notify_baton2, + scratch_pool)); + } + + return SVN_NO_ERROR; +} + +static svn_error_t * +merge_added_files(const char *local_abspath, + const char *incoming_added_file_abspath, + apr_hash_t *incoming_added_file_props, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + svn_wc_merge_outcome_t merge_content_outcome; + svn_wc_notify_state_t merge_props_outcome; + apr_file_t *empty_file; + const char *empty_file_abspath; + apr_array_header_t *propdiffs; + apr_hash_t *working_props; + + /* Create an empty file as fake "merge-base" for the two added files. + * The files are not ancestrally related so this is the best we can do. */ + SVN_ERR(svn_io_open_unique_file3(&empty_file, &empty_file_abspath, NULL, + svn_io_file_del_on_pool_cleanup, + scratch_pool, scratch_pool)); + + /* Get a copy of the working file's properties. */ + SVN_ERR(svn_wc_prop_list2(&working_props, ctx->wc_ctx, local_abspath, + scratch_pool, scratch_pool)); + + /* Create a property diff for the files. */ + SVN_ERR(svn_prop_diffs(&propdiffs, incoming_added_file_props, + working_props, scratch_pool)); + + /* Perform the file merge. */ + SVN_ERR(svn_wc_merge5(&merge_content_outcome, &merge_props_outcome, + ctx->wc_ctx, empty_file_abspath, + incoming_added_file_abspath, local_abspath, + NULL, NULL, NULL, /* labels */ + NULL, NULL, /* conflict versions */ + FALSE, /* dry run */ + NULL, NULL, /* diff3_cmd, merge_options */ + NULL, propdiffs, + NULL, NULL, /* conflict func/baton */ + NULL, NULL, /* don't allow user to cancel here */ + scratch_pool)); + + if (ctx->notify_func2) + { + svn_wc_notify_t *notify = svn_wc_create_notify( + local_abspath, + svn_wc_notify_update_update, + scratch_pool); + + if (merge_content_outcome == svn_wc_merge_conflict) + notify->content_state = svn_wc_notify_state_conflicted; + else + notify->content_state = svn_wc_notify_state_merged; + notify->prop_state = merge_props_outcome; + notify->kind = svn_node_file; + ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool); + } + + return SVN_NO_ERROR; +} + +/* An svn_diff_tree_processor_t callback. */ +static svn_error_t * +diff_file_added(const char *relpath, + const svn_diff_source_t *copyfrom_source, + const svn_diff_source_t *right_source, + const char *copyfrom_file, + const char *right_file, + apr_hash_t *copyfrom_props, + apr_hash_t *right_props, + void *file_baton, + const struct svn_diff_tree_processor_t *processor, + apr_pool_t *scratch_pool) +{ + struct merge_newly_added_dir_baton *b = processor->baton; + const char *local_abspath; + svn_node_kind_t db_kind; + svn_node_kind_t on_disk_kind; + apr_array_header_t *propsarray; + apr_array_header_t *regular_props; + + local_abspath = svn_dirent_join(b->target_abspath, relpath, scratch_pool); + + SVN_ERR(svn_wc_read_kind2(&db_kind, b->ctx->wc_ctx, local_abspath, + FALSE, FALSE, scratch_pool)); + SVN_ERR(svn_io_check_path(local_abspath, &on_disk_kind, scratch_pool)); + + if (db_kind == svn_node_file && on_disk_kind == svn_node_file) + { + propsarray = svn_prop_hash_to_array(right_props, scratch_pool); + SVN_ERR(svn_categorize_props(propsarray, NULL, NULL, ®ular_props, + scratch_pool)); + SVN_ERR(merge_added_files(local_abspath, right_file, + svn_prop_array_to_hash(regular_props, + scratch_pool), + b->ctx, scratch_pool)); + return SVN_NO_ERROR; + } + + if (db_kind != svn_node_none && db_kind != svn_node_unknown) + { + SVN_ERR(raise_tree_conflict( + local_abspath, svn_wc_conflict_action_add, + svn_wc_conflict_reason_obstructed, + db_kind, svn_node_none, svn_node_file, + b->repos_root_url, b->repos_uuid, + svn_relpath_join(b->added_repos_relpath, relpath, scratch_pool), + b->merge_left_rev, b->merge_right_rev, + b->ctx->wc_ctx, b->ctx->notify_func2, b->ctx->notify_baton2, + scratch_pool)); + return SVN_NO_ERROR; + } + + if (on_disk_kind != svn_node_none) + { + SVN_ERR(raise_tree_conflict( + local_abspath, svn_wc_conflict_action_add, + svn_wc_conflict_reason_obstructed, db_kind, + svn_node_none, svn_node_file, b->repos_root_url, b->repos_uuid, + svn_relpath_join(b->added_repos_relpath, relpath, scratch_pool), + b->merge_left_rev, b->merge_right_rev, + b->ctx->wc_ctx, b->ctx->notify_func2, b->ctx->notify_baton2, + scratch_pool)); + return SVN_NO_ERROR; + } + + propsarray = svn_prop_hash_to_array(right_props, scratch_pool); + SVN_ERR(svn_categorize_props(propsarray, NULL, NULL, ®ular_props, + scratch_pool)); + SVN_ERR(svn_io_copy_file(right_file, local_abspath, FALSE, scratch_pool)); + SVN_ERR(svn_wc_add_from_disk3(b->ctx->wc_ctx, local_abspath, + svn_prop_array_to_hash(regular_props, + scratch_pool), + FALSE, b->ctx->notify_func2, + b->ctx->notify_baton2, scratch_pool)); + + return SVN_NO_ERROR; +} + +/* Merge a newly added directory into TARGET_ABSPATH in the working copy. + * + * This uses a diff-tree processor because our standard merge operation + * is not set up for merges where the merge-source anchor is itself an + * added directory (i.e. does not exist on one side of the diff). + * The standard merge will only merge additions of children of a path + * that exists across the entire revision range being merged. + * But in our case, SOURCE1 does not yet exist in REV1, but SOURCE2 + * does exist in REV2. Thus we use a diff processor. + */ +static svn_error_t * +merge_newly_added_dir(const char *added_repos_relpath, + const char *source1, + svn_revnum_t rev1, + const char *source2, + svn_revnum_t rev2, + const char *target_abspath, + svn_boolean_t reverse_merge, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_diff_tree_processor_t *processor; + struct merge_newly_added_dir_baton baton = { 0 }; + const svn_diff_tree_processor_t *diff_processor; + svn_ra_session_t *ra_session; + const char *corrected_url; + svn_ra_session_t *extra_ra_session; + const svn_ra_reporter3_t *reporter; + void *reporter_baton; + const svn_delta_editor_t *diff_editor; + void *diff_edit_baton; + const char *anchor1; + const char *anchor2; + const char *target1; + const char *target2; + + svn_uri_split(&anchor1, &target1, source1, scratch_pool); + svn_uri_split(&anchor2, &target2, source2, scratch_pool); + + baton.target_abspath = target_abspath; + baton.ctx = ctx; + baton.added_repos_relpath = added_repos_relpath; + SVN_ERR(svn_wc__node_get_repos_info(NULL, NULL, + &baton.repos_root_url, &baton.repos_uuid, + ctx->wc_ctx, target_abspath, + scratch_pool, scratch_pool)); + baton.merge_left_rev = rev1; + baton.merge_right_rev = rev2; + + processor = svn_diff__tree_processor_create(&baton, scratch_pool); + processor->dir_added = diff_dir_added; + processor->file_added = diff_file_added; + + diff_processor = processor; + if (reverse_merge) + diff_processor = svn_diff__tree_processor_reverse_create(diff_processor, + NULL, + scratch_pool); + + /* Filter the first path component using a filter processor, until we fixed + the diff processing to handle this directly */ + diff_processor = svn_diff__tree_processor_filter_create( + diff_processor, target1, scratch_pool); + + SVN_ERR(svn_client__open_ra_session_internal(&ra_session, &corrected_url, + anchor2, NULL, NULL, FALSE, + FALSE, ctx, + scratch_pool, scratch_pool)); + if (corrected_url) + anchor2 = corrected_url; + + /* Extra RA session is used during the editor calls to fetch file contents. */ + SVN_ERR(svn_ra__dup_session(&extra_ra_session, ra_session, anchor2, + scratch_pool, scratch_pool)); + + /* Create a repos-repos diff editor. */ + SVN_ERR(svn_client__get_diff_editor2( + &diff_editor, &diff_edit_baton, + extra_ra_session, svn_depth_infinity, rev1, TRUE, + diff_processor, ctx->cancel_func, ctx->cancel_baton, + scratch_pool)); + + /* We want to switch our txn into URL2 */ + SVN_ERR(svn_ra_do_diff3(ra_session, &reporter, &reporter_baton, + rev2, target1, svn_depth_infinity, TRUE, TRUE, + source2, diff_editor, diff_edit_baton, scratch_pool)); + + /* Drive the reporter; do the diff. */ + SVN_ERR(reporter->set_path(reporter_baton, "", rev1, + svn_depth_infinity, + FALSE, NULL, + scratch_pool)); + + SVN_ERR(reporter->finish_report(reporter_baton, scratch_pool)); + + return SVN_NO_ERROR; +} + +/* Implements conflict_option_resolve_func_t. */ +static svn_error_t * +resolve_merge_incoming_added_dir_merge(svn_client_conflict_option_t *option, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + const char *repos_root_url; + const char *incoming_old_repos_relpath; + svn_revnum_t incoming_old_pegrev; + const char *incoming_new_repos_relpath; + svn_revnum_t incoming_new_pegrev; + const char *local_abspath; + const char *lock_abspath; + struct conflict_tree_incoming_add_details *details; + const char *added_repos_relpath; + const char *source1; + svn_revnum_t rev1; + const char *source2; + svn_revnum_t rev2; + svn_error_t *err; + + local_abspath = svn_client_conflict_get_local_abspath(conflict); + + details = conflict->tree_conflict_incoming_details; + if (details == NULL) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Conflict resolution option '%d' requires " + "details for tree conflict at '%s' to be " + "fetched from the repository"), + option->id, + svn_dirent_local_style(local_abspath, + scratch_pool)); + + /* Set up merge sources to merge the entire incoming added directory tree. */ + SVN_ERR(svn_client_conflict_get_repos_info(&repos_root_url, NULL, + conflict, scratch_pool, + scratch_pool)); + source1 = svn_path_url_add_component2(repos_root_url, + details->repos_relpath, + scratch_pool); + SVN_ERR(svn_client_conflict_get_incoming_old_repos_location( + &incoming_old_repos_relpath, &incoming_old_pegrev, + NULL, conflict, scratch_pool, scratch_pool)); + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + &incoming_new_repos_relpath, &incoming_new_pegrev, + NULL, conflict, scratch_pool, scratch_pool)); + if (incoming_old_pegrev < incoming_new_pegrev) /* forward merge */ + { + if (details->added_rev == SVN_INVALID_REVNUM) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Could not determine when '%s' was " + "added the repository"), + svn_dirent_local_style(local_abspath, + scratch_pool)); + rev1 = rev_below(details->added_rev); + source2 = svn_path_url_add_component2(repos_root_url, + incoming_new_repos_relpath, + scratch_pool); + rev2 = incoming_new_pegrev; + added_repos_relpath = incoming_new_repos_relpath; + } + else /* reverse-merge */ + { + if (details->deleted_rev == SVN_INVALID_REVNUM) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Could not determine when '%s' was " + "deleted from the repository"), + svn_dirent_local_style(local_abspath, + scratch_pool)); + rev1 = details->deleted_rev; + source2 = svn_path_url_add_component2(repos_root_url, + incoming_old_repos_relpath, + scratch_pool); + rev2 = incoming_old_pegrev; + added_repos_relpath = incoming_new_repos_relpath; + } + + /* ### The following WC modifications should be atomic. */ + SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, ctx->wc_ctx, + local_abspath, + scratch_pool, scratch_pool)); + + /* ### wrap in a transaction */ + err = merge_newly_added_dir(added_repos_relpath, + source1, rev1, source2, rev2, + local_abspath, + (incoming_old_pegrev > incoming_new_pegrev), + ctx, scratch_pool, scratch_pool); + if (!err) + err = svn_wc__del_tree_conflict(ctx->wc_ctx, local_abspath, scratch_pool); + + err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx, + lock_abspath, + scratch_pool)); + svn_io_sleep_for_timestamps(local_abspath, scratch_pool); + SVN_ERR(err); + + if (ctx->notify_func2) + ctx->notify_func2(ctx->notify_baton2, + svn_wc_create_notify(local_abspath, + svn_wc_notify_resolved_tree, + scratch_pool), + scratch_pool); + + conflict->resolution_tree = svn_client_conflict_option_get_id(option); + + return SVN_NO_ERROR; +} + +/* Implements conflict_option_resolve_func_t. */ +static svn_error_t * +resolve_update_incoming_added_dir_merge(svn_client_conflict_option_t *option, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + const char *local_abspath; + const char *lock_abspath; + svn_error_t *err; + + local_abspath = svn_client_conflict_get_local_abspath(conflict); + + SVN_ERR(svn_wc__acquire_write_lock_for_resolve( + &lock_abspath, ctx->wc_ctx, local_abspath, + scratch_pool, scratch_pool)); + + err = svn_wc__conflict_tree_update_local_add(ctx->wc_ctx, + local_abspath, + ctx->cancel_func, + ctx->cancel_baton, + ctx->notify_func2, + ctx->notify_baton2, + scratch_pool); + + err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx, + lock_abspath, + scratch_pool)); + SVN_ERR(err); + + return SVN_NO_ERROR; +} + +/* A baton for notification_adjust_func(). */ +struct notification_adjust_baton +{ + svn_wc_notify_func2_t inner_func; + void *inner_baton; + const char *checkout_abspath; + const char *final_abspath; +}; + +/* A svn_wc_notify_func2_t function that wraps BATON->inner_func (whose + * baton is BATON->inner_baton) and adjusts the notification paths that + * start with BATON->checkout_abspath to start instead with + * BATON->final_abspath. */ +static void +notification_adjust_func(void *baton, + const svn_wc_notify_t *notify, + apr_pool_t *pool) +{ + struct notification_adjust_baton *nb = baton; + svn_wc_notify_t *inner_notify = svn_wc_dup_notify(notify, pool); + const char *relpath; + + relpath = svn_dirent_skip_ancestor(nb->checkout_abspath, notify->path); + inner_notify->path = svn_dirent_join(nb->final_abspath, relpath, pool); + + if (nb->inner_func) + nb->inner_func(nb->inner_baton, inner_notify, pool); +} + +/* Resolve a dir/dir "incoming add vs local obstruction" tree conflict by + * replacing the local directory with the incoming directory. + * If MERGE_DIRS is set, also merge the directories after replacing. */ +static svn_error_t * +merge_incoming_added_dir_replace(svn_client_conflict_option_t *option, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + svn_boolean_t merge_dirs, + apr_pool_t *scratch_pool) +{ + svn_ra_session_t *ra_session; + const char *url; + const char *corrected_url; + const char *repos_root_url; + const char *incoming_new_repos_relpath; + svn_revnum_t incoming_new_pegrev; + const char *local_abspath; + const char *lock_abspath; + const char *tmpdir_abspath, *tmp_abspath; + svn_error_t *err; + svn_revnum_t copy_src_revnum; + svn_opt_revision_t copy_src_peg_revision; + svn_boolean_t timestamp_sleep; + svn_wc_notify_func2_t old_notify_func2 = ctx->notify_func2; + void *old_notify_baton2 = ctx->notify_baton2; + struct notification_adjust_baton nb; + + local_abspath = svn_client_conflict_get_local_abspath(conflict); + + /* Find the URL of the incoming added directory in the repository. */ + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + &incoming_new_repos_relpath, &incoming_new_pegrev, + NULL, conflict, scratch_pool, + scratch_pool)); + SVN_ERR(svn_client_conflict_get_repos_info(&repos_root_url, NULL, + conflict, scratch_pool, + scratch_pool)); + url = svn_path_url_add_component2(repos_root_url, incoming_new_repos_relpath, + scratch_pool); + SVN_ERR(svn_client__open_ra_session_internal(&ra_session, &corrected_url, + url, NULL, NULL, FALSE, FALSE, + ctx, scratch_pool, + scratch_pool)); + if (corrected_url) + url = corrected_url; + + + /* Find a temporary location in which to check out the copy source. */ + SVN_ERR(svn_wc__get_tmpdir(&tmpdir_abspath, ctx->wc_ctx, local_abspath, + scratch_pool, scratch_pool)); + + SVN_ERR(svn_io_open_unique_file3(NULL, &tmp_abspath, tmpdir_abspath, + svn_io_file_del_on_close, + scratch_pool, scratch_pool)); + + /* Make a new checkout of the requested source. While doing so, + * resolve copy_src_revnum to an actual revision number in case it + * was until now 'invalid' meaning 'head'. Ask this function not to + * sleep for timestamps, by passing a sleep_needed output param. + * Send notifications for all nodes except the root node, and adjust + * them to refer to the destination rather than this temporary path. */ + + nb.inner_func = ctx->notify_func2; + nb.inner_baton = ctx->notify_baton2; + nb.checkout_abspath = tmp_abspath; + nb.final_abspath = local_abspath; + ctx->notify_func2 = notification_adjust_func; + ctx->notify_baton2 = &nb; + + copy_src_peg_revision.kind = svn_opt_revision_number; + copy_src_peg_revision.value.number = incoming_new_pegrev; + + err = svn_client__checkout_internal(©_src_revnum, ×tamp_sleep, + url, tmp_abspath, + ©_src_peg_revision, + ©_src_peg_revision, + svn_depth_infinity, + TRUE, /* we want to ignore externals */ + FALSE, /* we don't allow obstructions */ + ra_session, ctx, scratch_pool); + + ctx->notify_func2 = old_notify_func2; + ctx->notify_baton2 = old_notify_baton2; + + SVN_ERR(err); + + /* ### The following WC modifications should be atomic. */ + + SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, ctx->wc_ctx, + svn_dirent_dirname( + local_abspath, + scratch_pool), + scratch_pool, scratch_pool)); + + /* Remove the working directory. */ + err = svn_wc_delete4(ctx->wc_ctx, local_abspath, FALSE, FALSE, + NULL, NULL, /* don't allow user to cancel here */ + ctx->notify_func2, ctx->notify_baton2, + scratch_pool); + if (err) + goto unlock_wc; + + /* Schedule dst_path for addition in parent, with copy history. + Don't send any notification here. + Then remove the temporary checkout's .svn dir in preparation for + moving the rest of it into the final destination. */ + err = svn_wc_copy3(ctx->wc_ctx, tmp_abspath, local_abspath, + TRUE /* metadata_only */, + NULL, NULL, /* don't allow user to cancel here */ + NULL, NULL, scratch_pool); + if (err) + goto unlock_wc; + + err = svn_wc__acquire_write_lock(NULL, ctx->wc_ctx, tmp_abspath, + FALSE, scratch_pool, scratch_pool); + if (err) + goto unlock_wc; + err = svn_wc_remove_from_revision_control2(ctx->wc_ctx, + tmp_abspath, + FALSE, FALSE, + NULL, NULL, /* don't cancel */ + scratch_pool); + if (err) + goto unlock_wc; + + /* Move the temporary disk tree into place. */ + err = svn_io_file_rename2(tmp_abspath, local_abspath, FALSE, scratch_pool); + if (err) + goto unlock_wc; + + if (ctx->notify_func2) + { + svn_wc_notify_t *notify = svn_wc_create_notify(local_abspath, + svn_wc_notify_add, + scratch_pool); + notify->kind = svn_node_dir; + ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool); + } + + /* Resolve to current working copy state. + * svn_client__merge_locked() requires this. */ + err = svn_wc__del_tree_conflict(ctx->wc_ctx, local_abspath, scratch_pool); + if (err) + goto unlock_wc; + + if (merge_dirs) + { + svn_revnum_t base_revision; + const char *base_repos_relpath; + struct find_added_rev_baton b = { 0 }; + + /* Find the URL and revision of the directory we have just replaced. */ + err = svn_wc__node_get_base(NULL, &base_revision, &base_repos_relpath, + NULL, NULL, NULL, ctx->wc_ctx, local_abspath, + FALSE, scratch_pool, scratch_pool); + if (err) + goto unlock_wc; + + url = svn_path_url_add_component2(repos_root_url, base_repos_relpath, + scratch_pool); + + /* Trace the replaced directory's history to its origin. */ + err = svn_ra_reparent(ra_session, url, scratch_pool); + if (err) + goto unlock_wc; + b.victim_abspath = local_abspath; + b.ctx = ctx; + b.added_rev = SVN_INVALID_REVNUM; + b.repos_relpath = NULL; + b.parent_repos_relpath = svn_relpath_dirname(base_repos_relpath, + scratch_pool); + b.pool = scratch_pool; + + err = svn_ra_get_location_segments(ra_session, "", base_revision, + base_revision, SVN_INVALID_REVNUM, + find_added_rev, &b, + scratch_pool); + if (err) + goto unlock_wc; + + if (b.added_rev == SVN_INVALID_REVNUM) + { + err = svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Could not determine the revision in " + "which '^/%s' was added to the " + "repository.\n"), + base_repos_relpath); + goto unlock_wc; + } + + /* Merge the replaced directory into the directory which replaced it. + * We do not need to consider a reverse-merge here since the source of + * this merge was part of the merge target working copy, not a branch + * in the repository. */ + err = merge_newly_added_dir(base_repos_relpath, + url, rev_below(b.added_rev), url, + base_revision, local_abspath, FALSE, + ctx, scratch_pool, scratch_pool); + if (err) + goto unlock_wc; + } + +unlock_wc: + err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx, + lock_abspath, + scratch_pool)); + svn_io_sleep_for_timestamps(local_abspath, scratch_pool); + SVN_ERR(err); + + if (ctx->notify_func2) + { + svn_wc_notify_t *notify = svn_wc_create_notify( + local_abspath, + svn_wc_notify_resolved_tree, + scratch_pool); + + ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool); + } + + conflict->resolution_tree = svn_client_conflict_option_get_id(option); + + return SVN_NO_ERROR; +} + +/* Implements conflict_option_resolve_func_t. */ +static svn_error_t * +resolve_merge_incoming_added_dir_replace(svn_client_conflict_option_t *option, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + return svn_error_trace(merge_incoming_added_dir_replace(option, + conflict, + ctx, + FALSE, + scratch_pool)); +} + +/* Implements conflict_option_resolve_func_t. */ +static svn_error_t * +resolve_merge_incoming_added_dir_replace_and_merge( + svn_client_conflict_option_t *option, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + return svn_error_trace(merge_incoming_added_dir_replace(option, + conflict, + ctx, + TRUE, + scratch_pool)); +} + +/* Verify the local working copy state matches what we expect when an + * incoming deletion tree conflict exists. + * We assume update/merge/switch operations leave the working copy in a + * state which prefers the local change and cancels the deletion. + * Run a quick sanity check and error out if it looks as if the + * working copy was modified since, even though it's not easy to make + * such modifications without also clearing the conflict marker. */ +static svn_error_t * +verify_local_state_for_incoming_delete(svn_client_conflict_t *conflict, + svn_client_conflict_option_t *option, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + const char *local_abspath; + const char *wcroot_abspath; + svn_wc_operation_t operation; + + local_abspath = svn_client_conflict_get_local_abspath(conflict); + SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, ctx->wc_ctx, + local_abspath, scratch_pool, + scratch_pool)); + operation = svn_client_conflict_get_operation(conflict); + + if (operation == svn_wc_operation_update || + operation == svn_wc_operation_switch) + { + struct conflict_tree_incoming_delete_details *details; + svn_boolean_t is_copy; + svn_revnum_t copyfrom_rev; + const char *copyfrom_repos_relpath; + + details = conflict->tree_conflict_incoming_details; + if (details == NULL) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Conflict resolution option '%d' requires " + "details for tree conflict at '%s' to be " + "fetched from the repository."), + option->id, + svn_dirent_local_style(local_abspath, + scratch_pool)); + + /* Ensure that the item is a copy of itself from before it was deleted. + * Update and switch are supposed to set this up when flagging the + * conflict. */ + SVN_ERR(svn_wc__node_get_origin(&is_copy, ©from_rev, + ©from_repos_relpath, + NULL, NULL, NULL, NULL, + ctx->wc_ctx, local_abspath, FALSE, + scratch_pool, scratch_pool)); + if (!is_copy) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Cannot resolve tree conflict on '%s' " + "(expected a copied item, but the item " + "is not a copy)"), + svn_dirent_local_style( + svn_dirent_skip_ancestor( + wcroot_abspath, + conflict->local_abspath), + scratch_pool)); + else if (details->deleted_rev == SVN_INVALID_REVNUM && + details->added_rev == SVN_INVALID_REVNUM) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Could not find the revision in which '%s' " + "was deleted from the repository"), + svn_dirent_local_style( + svn_dirent_skip_ancestor( + wcroot_abspath, + conflict->local_abspath), + scratch_pool)); + else if (details->deleted_rev != SVN_INVALID_REVNUM && + copyfrom_rev >= details->deleted_rev) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Cannot resolve tree conflict on '%s' " + "(expected an item copied from a revision " + "smaller than r%ld, but the item was " + "copied from r%ld)"), + svn_dirent_local_style( + svn_dirent_skip_ancestor( + wcroot_abspath, conflict->local_abspath), + scratch_pool), + details->deleted_rev, copyfrom_rev); + + else if (details->added_rev != SVN_INVALID_REVNUM && + copyfrom_rev < details->added_rev) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Cannot resolve tree conflict on '%s' " + "(expected an item copied from a revision " + "larger than r%ld, but the item was " + "copied from r%ld)"), + svn_dirent_local_style( + svn_dirent_skip_ancestor( + wcroot_abspath, conflict->local_abspath), + scratch_pool), + details->added_rev, copyfrom_rev); + else if (operation == svn_wc_operation_update) + { + const char *old_repos_relpath; + + SVN_ERR(svn_client_conflict_get_incoming_old_repos_location( + &old_repos_relpath, NULL, NULL, conflict, + scratch_pool, scratch_pool)); + if (strcmp(copyfrom_repos_relpath, details->repos_relpath) != 0 && + strcmp(copyfrom_repos_relpath, old_repos_relpath) != 0) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Cannot resolve tree conflict on '%s' " + "(expected an item copied from '^/%s' " + "or from '^/%s' but the item was " + "copied from '^/%s@%ld')"), + svn_dirent_local_style( + svn_dirent_skip_ancestor( + wcroot_abspath, conflict->local_abspath), + scratch_pool), + details->repos_relpath, + old_repos_relpath, + copyfrom_repos_relpath, copyfrom_rev); + } + else if (operation == svn_wc_operation_switch) + { + const char *old_repos_relpath; + + SVN_ERR(svn_client_conflict_get_incoming_old_repos_location( + &old_repos_relpath, NULL, NULL, conflict, + scratch_pool, scratch_pool)); + + if (strcmp(copyfrom_repos_relpath, old_repos_relpath) != 0) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Cannot resolve tree conflict on '%s' " + "(expected an item copied from '^/%s', " + "but the item was copied from " + "'^/%s@%ld')"), + svn_dirent_local_style( + svn_dirent_skip_ancestor( + wcroot_abspath, + conflict->local_abspath), + scratch_pool), + old_repos_relpath, + copyfrom_repos_relpath, copyfrom_rev); + } + } + else if (operation == svn_wc_operation_merge) + { + svn_node_kind_t victim_node_kind; + svn_node_kind_t on_disk_kind; + + /* For merge, all we can do is ensure that the item still exists. */ + victim_node_kind = + svn_client_conflict_tree_get_victim_node_kind(conflict); + SVN_ERR(svn_io_check_path(local_abspath, &on_disk_kind, scratch_pool)); + + if (victim_node_kind != on_disk_kind) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Cannot resolve tree conflict on '%s' " + "(expected node kind '%s' but found '%s')"), + svn_dirent_local_style( + svn_dirent_skip_ancestor( + wcroot_abspath, conflict->local_abspath), + scratch_pool), + svn_node_kind_to_word(victim_node_kind), + svn_node_kind_to_word(on_disk_kind)); + } + + return SVN_NO_ERROR; +} + +/* Implements conflict_option_resolve_func_t. */ +static svn_error_t * +resolve_incoming_delete_ignore(svn_client_conflict_option_t *option, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + svn_client_conflict_option_id_t option_id; + const char *local_abspath; + const char *lock_abspath; + svn_error_t *err; + + option_id = svn_client_conflict_option_get_id(option); + local_abspath = svn_client_conflict_get_local_abspath(conflict); + + SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, ctx->wc_ctx, + local_abspath, + scratch_pool, scratch_pool)); + + err = verify_local_state_for_incoming_delete(conflict, option, ctx, + scratch_pool); + if (err) + goto unlock_wc; + + /* Resolve to the current working copy state. */ + err = svn_wc__del_tree_conflict(ctx->wc_ctx, local_abspath, scratch_pool); + + /* svn_wc__del_tree_conflict doesn't handle notification for us */ + if (ctx->notify_func2) + ctx->notify_func2(ctx->notify_baton2, + svn_wc_create_notify(local_abspath, + svn_wc_notify_resolved_tree, + scratch_pool), + scratch_pool); + +unlock_wc: + err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx, + lock_abspath, + scratch_pool)); + SVN_ERR(err); + + conflict->resolution_tree = option_id; + + return SVN_NO_ERROR; +} + +/* Implements conflict_option_resolve_func_t. */ +static svn_error_t * +resolve_incoming_delete_accept(svn_client_conflict_option_t *option, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + svn_client_conflict_option_id_t option_id; + const char *local_abspath; + const char *parent_abspath; + const char *lock_abspath; + svn_error_t *err; + + option_id = svn_client_conflict_option_get_id(option); + local_abspath = svn_client_conflict_get_local_abspath(conflict); + + /* Deleting a node requires a lock on the node's parent. */ + parent_abspath = svn_dirent_dirname(local_abspath, scratch_pool); + SVN_ERR(svn_wc__acquire_write_lock_for_resolve(&lock_abspath, ctx->wc_ctx, + parent_abspath, + scratch_pool, scratch_pool)); + + err = verify_local_state_for_incoming_delete(conflict, option, ctx, + scratch_pool); + if (err) + goto unlock_wc; + + /* Delete the tree conflict victim. Marks the conflict resolved. */ + err = svn_wc_delete4(ctx->wc_ctx, local_abspath, FALSE, FALSE, + NULL, NULL, /* don't allow user to cancel here */ + ctx->notify_func2, ctx->notify_baton2, + scratch_pool); + if (err) + { + if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND) + { + /* Not a versioned path. This can happen if the victim has already + * been deleted in our branche's history, for example. Either way, + * the item is gone, which is what we want, so don't treat this as + * a fatal error. */ + svn_error_clear(err); + + /* Resolve to current working copy state. */ + err = svn_wc__del_tree_conflict(ctx->wc_ctx, local_abspath, + scratch_pool); + } + + if (err) + goto unlock_wc; + } + + if (ctx->notify_func2) + ctx->notify_func2(ctx->notify_baton2, + svn_wc_create_notify(local_abspath, + svn_wc_notify_resolved_tree, + scratch_pool), + scratch_pool); + +unlock_wc: + err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx, + lock_abspath, + scratch_pool)); + SVN_ERR(err); + + conflict->resolution_tree = option_id; + + return SVN_NO_ERROR; +} + +/* Implements conflict_option_resolve_func_t. */ +static svn_error_t * +resolve_incoming_move_file_text_merge(svn_client_conflict_option_t *option, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + svn_client_conflict_option_id_t option_id; + const char *local_abspath; + svn_wc_operation_t operation; + const char *lock_abspath; + svn_error_t *err; + const char *repos_root_url; + const char *incoming_old_repos_relpath; + svn_revnum_t incoming_old_pegrev; + const char *incoming_new_repos_relpath; + svn_revnum_t incoming_new_pegrev; + const char *wc_tmpdir; + const char *ancestor_abspath; + svn_stream_t *ancestor_stream; + apr_hash_t *ancestor_props; + apr_hash_t *victim_props; + apr_hash_t *move_target_props; + const char *ancestor_url; + const char *corrected_url; + svn_ra_session_t *ra_session; + svn_wc_merge_outcome_t merge_content_outcome; + svn_wc_notify_state_t merge_props_outcome; + apr_array_header_t *propdiffs; + struct conflict_tree_incoming_delete_details *details; + apr_array_header_t *possible_moved_to_abspaths; + const char *moved_to_abspath; + const char *incoming_abspath = NULL; + + local_abspath = svn_client_conflict_get_local_abspath(conflict); + operation = svn_client_conflict_get_operation(conflict); + details = conflict->tree_conflict_incoming_details; + if (details == NULL || details->moves == NULL) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("The specified conflict resolution option " + "requires details for tree conflict at '%s' " + "to be fetched from the repository first."), + svn_dirent_local_style(local_abspath, + scratch_pool)); + if (operation == svn_wc_operation_none) + return svn_error_createf(SVN_ERR_WC_CORRUPT, NULL, + _("Invalid operation code '%d' recorded for " + "conflict at '%s'"), operation, + svn_dirent_local_style(local_abspath, + scratch_pool)); + + option_id = svn_client_conflict_option_get_id(option); + SVN_ERR_ASSERT(option_id == + svn_client_conflict_option_incoming_move_file_text_merge || + option_id == + svn_client_conflict_option_incoming_move_dir_merge); + + SVN_ERR(svn_client_conflict_get_repos_info(&repos_root_url, NULL, + conflict, scratch_pool, + scratch_pool)); + SVN_ERR(svn_client_conflict_get_incoming_old_repos_location( + &incoming_old_repos_relpath, &incoming_old_pegrev, + NULL, conflict, scratch_pool, + scratch_pool)); + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + &incoming_new_repos_relpath, &incoming_new_pegrev, + NULL, conflict, scratch_pool, + scratch_pool)); + + /* Set up temporary storage for the common ancestor version of the file. */ + SVN_ERR(svn_wc__get_tmpdir(&wc_tmpdir, ctx->wc_ctx, local_abspath, + scratch_pool, scratch_pool)); + SVN_ERR(svn_stream_open_unique(&ancestor_stream, + &ancestor_abspath, wc_tmpdir, + svn_io_file_del_on_pool_cleanup, + scratch_pool, scratch_pool)); + + /* Fetch the ancestor file's content. */ + ancestor_url = svn_path_url_add_component2(repos_root_url, + incoming_old_repos_relpath, + scratch_pool); + SVN_ERR(svn_client__open_ra_session_internal(&ra_session, &corrected_url, + ancestor_url, NULL, NULL, + FALSE, FALSE, ctx, + scratch_pool, scratch_pool)); + SVN_ERR(svn_ra_get_file(ra_session, "", incoming_old_pegrev, + ancestor_stream, NULL, /* fetched_rev */ + &ancestor_props, scratch_pool)); + filter_props(ancestor_props, scratch_pool); + + /* Close stream to flush ancestor file to disk. */ + SVN_ERR(svn_stream_close(ancestor_stream)); + + possible_moved_to_abspaths = + svn_hash_gets(details->wc_move_targets, + get_moved_to_repos_relpath(details, scratch_pool)); + moved_to_abspath = APR_ARRAY_IDX(possible_moved_to_abspaths, + details->wc_move_target_idx, + const char *); + + /* ### The following WC modifications should be atomic. */ + SVN_ERR(svn_wc__acquire_write_lock_for_resolve( + &lock_abspath, ctx->wc_ctx, + svn_dirent_get_longest_ancestor(local_abspath, + moved_to_abspath, + scratch_pool), + scratch_pool, scratch_pool)); + + err = verify_local_state_for_incoming_delete(conflict, option, ctx, + scratch_pool); + if (err) + goto unlock_wc; + + /* Get a copy of the conflict victim's properties. */ + err = svn_wc_prop_list2(&victim_props, ctx->wc_ctx, local_abspath, + scratch_pool, scratch_pool); + if (err) + goto unlock_wc; + + /* Get a copy of the move target's properties. */ + err = svn_wc_prop_list2(&move_target_props, ctx->wc_ctx, + moved_to_abspath, + scratch_pool, scratch_pool); + if (err) + goto unlock_wc; + + /* Create a property diff for the files. */ + err = svn_prop_diffs(&propdiffs, move_target_props, victim_props, + scratch_pool); + if (err) + goto unlock_wc; + + if (operation == svn_wc_operation_update || + operation == svn_wc_operation_switch) + { + svn_stream_t *working_stream; + svn_stream_t *incoming_stream; + + /* Create a temporary copy of the working file in repository-normal form. + * Set up this temporary file to be automatically removed. */ + err = svn_stream_open_unique(&incoming_stream, + &incoming_abspath, wc_tmpdir, + svn_io_file_del_on_pool_cleanup, + scratch_pool, scratch_pool); + if (err) + goto unlock_wc; + + err = svn_wc__translated_stream(&working_stream, ctx->wc_ctx, + local_abspath, local_abspath, + SVN_WC_TRANSLATE_TO_NF, + scratch_pool, scratch_pool); + if (err) + goto unlock_wc; + + err = svn_stream_copy3(working_stream, incoming_stream, + NULL, NULL, /* no cancellation */ + scratch_pool); + if (err) + goto unlock_wc; + } + else if (operation == svn_wc_operation_merge) + { + svn_stream_t *incoming_stream; + svn_stream_t *move_target_stream; + + /* Set aside the current move target file. This is required to apply + * the move, and only then perform a three-way text merge between + * the ancestor's file, our working file (which we would move to + * the destination), and the file that we have set aside, which + * contains the incoming fulltext. + * Set up this temporary file to NOT be automatically removed. */ + err = svn_stream_open_unique(&incoming_stream, + &incoming_abspath, wc_tmpdir, + svn_io_file_del_none, + scratch_pool, scratch_pool); + if (err) + goto unlock_wc; + + err = svn_wc__translated_stream(&move_target_stream, ctx->wc_ctx, + moved_to_abspath, moved_to_abspath, + SVN_WC_TRANSLATE_TO_NF, + scratch_pool, scratch_pool); + if (err) + goto unlock_wc; + + err = svn_stream_copy3(move_target_stream, incoming_stream, + NULL, NULL, /* no cancellation */ + scratch_pool); + if (err) + goto unlock_wc; + + /* Apply the incoming move. */ + err = svn_io_remove_file2(moved_to_abspath, FALSE, scratch_pool); + if (err) + goto unlock_wc; + err = svn_wc__move2(ctx->wc_ctx, local_abspath, moved_to_abspath, + FALSE, /* ordinary (not meta-data only) move */ + FALSE, /* mixed-revisions don't apply to files */ + NULL, NULL, /* don't allow user to cancel here */ + NULL, NULL, /* no extra notification */ + scratch_pool); + if (err) + goto unlock_wc; + } + else + SVN_ERR_MALFUNCTION(); + + /* Perform the file merge. */ + err = svn_wc_merge5(&merge_content_outcome, &merge_props_outcome, + ctx->wc_ctx, ancestor_abspath, + incoming_abspath, moved_to_abspath, + NULL, NULL, NULL, /* labels */ + NULL, NULL, /* conflict versions */ + FALSE, /* dry run */ + NULL, NULL, /* diff3_cmd, merge_options */ + apr_hash_count(ancestor_props) ? ancestor_props : NULL, + propdiffs, + NULL, NULL, /* conflict func/baton */ + NULL, NULL, /* don't allow user to cancel here */ + scratch_pool); + svn_io_sleep_for_timestamps(moved_to_abspath, scratch_pool); + if (err) + goto unlock_wc; + + if (operation == svn_wc_operation_merge && incoming_abspath) + { + err = svn_io_remove_file2(incoming_abspath, TRUE, scratch_pool); + if (err) + goto unlock_wc; + incoming_abspath = NULL; + } + + if (ctx->notify_func2) + { + svn_wc_notify_t *notify; + + /* Tell the world about the file merge that just happened. */ + notify = svn_wc_create_notify(moved_to_abspath, + svn_wc_notify_update_update, + scratch_pool); + if (merge_content_outcome == svn_wc_merge_conflict) + notify->content_state = svn_wc_notify_state_conflicted; + else + notify->content_state = svn_wc_notify_state_merged; + notify->prop_state = merge_props_outcome; + notify->kind = svn_node_file; + ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool); + } + + if (operation == svn_wc_operation_update || + operation == svn_wc_operation_switch) + { + /* Delete the tree conflict victim (clears the tree conflict marker). */ + err = svn_wc_delete4(ctx->wc_ctx, local_abspath, FALSE, FALSE, + NULL, NULL, /* don't allow user to cancel here */ + NULL, NULL, /* no extra notification */ + scratch_pool); + if (err) + goto unlock_wc; + } + + if (ctx->notify_func2) + { + svn_wc_notify_t *notify; + + notify = svn_wc_create_notify(local_abspath, svn_wc_notify_resolved_tree, + scratch_pool); + ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool); + } + + conflict->resolution_tree = option_id; + +unlock_wc: + if (err && operation == svn_wc_operation_merge && incoming_abspath) + err = svn_error_quick_wrapf( + err, _("If needed, a backup copy of '%s' can be found at '%s'"), + svn_dirent_local_style(moved_to_abspath, scratch_pool), + svn_dirent_local_style(incoming_abspath, scratch_pool)); + err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx, + lock_abspath, + scratch_pool)); + SVN_ERR(err); + + return SVN_NO_ERROR; +} + +/* Implements conflict_option_resolve_func_t. */ +static svn_error_t * +resolve_incoming_move_dir_merge(svn_client_conflict_option_t *option, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + svn_client_conflict_option_id_t option_id; + const char *local_abspath; + svn_wc_operation_t operation; + const char *lock_abspath; + svn_error_t *err; + const char *repos_root_url; + const char *repos_uuid; + const char *incoming_old_repos_relpath; + svn_revnum_t incoming_old_pegrev; + const char *incoming_new_repos_relpath; + svn_revnum_t incoming_new_pegrev; + const char *victim_repos_relpath; + svn_revnum_t victim_peg_rev; + const char *moved_to_repos_relpath; + svn_revnum_t moved_to_peg_rev; + struct conflict_tree_incoming_delete_details *details; + apr_array_header_t *possible_moved_to_abspaths; + const char *moved_to_abspath; + svn_client__pathrev_t *yca_loc; + svn_opt_revision_t yca_opt_rev; + svn_client__conflict_report_t *conflict_report; + svn_boolean_t is_copy; + svn_boolean_t is_modified; + + local_abspath = svn_client_conflict_get_local_abspath(conflict); + operation = svn_client_conflict_get_operation(conflict); + details = conflict->tree_conflict_incoming_details; + if (details == NULL || details->moves == NULL) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("The specified conflict resolution option " + "requires details for tree conflict at '%s' " + "to be fetched from the repository first."), + svn_dirent_local_style(local_abspath, + scratch_pool)); + + option_id = svn_client_conflict_option_get_id(option); + SVN_ERR_ASSERT(option_id == + svn_client_conflict_option_incoming_move_dir_merge); + + SVN_ERR(svn_client_conflict_get_repos_info(&repos_root_url, &repos_uuid, + conflict, scratch_pool, + scratch_pool)); + SVN_ERR(svn_client_conflict_get_incoming_old_repos_location( + &incoming_old_repos_relpath, &incoming_old_pegrev, + NULL, conflict, scratch_pool, + scratch_pool)); + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + &incoming_new_repos_relpath, &incoming_new_pegrev, + NULL, conflict, scratch_pool, + scratch_pool)); + + /* Get repository location of the moved-away node (the conflict victim). */ + if (operation == svn_wc_operation_update || + operation == svn_wc_operation_switch) + { + victim_repos_relpath = incoming_old_repos_relpath; + victim_peg_rev = incoming_old_pegrev; + } + else if (operation == svn_wc_operation_merge) + SVN_ERR(svn_wc__node_get_repos_info(&victim_peg_rev, &victim_repos_relpath, + NULL, NULL, ctx->wc_ctx, local_abspath, + scratch_pool, scratch_pool)); + + /* Get repository location of the moved-here node (incoming move). */ + possible_moved_to_abspaths = + svn_hash_gets(details->wc_move_targets, + get_moved_to_repos_relpath(details, scratch_pool)); + moved_to_abspath = APR_ARRAY_IDX(possible_moved_to_abspaths, + details->wc_move_target_idx, + const char *); + + /* ### The following WC modifications should be atomic. */ + + SVN_ERR(svn_wc__acquire_write_lock_for_resolve( + &lock_abspath, ctx->wc_ctx, + svn_dirent_get_longest_ancestor(local_abspath, + moved_to_abspath, + scratch_pool), + scratch_pool, scratch_pool)); + + err = svn_wc__node_get_origin(&is_copy, &moved_to_peg_rev, + &moved_to_repos_relpath, + NULL, NULL, NULL, NULL, + ctx->wc_ctx, moved_to_abspath, FALSE, + scratch_pool, scratch_pool); + if (err) + goto unlock_wc; + if (!is_copy && operation == svn_wc_operation_merge) + { + err = svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Cannot resolve tree conflict on '%s' " + "(expected a copied item at '%s', but the " + "item is not a copy)"), + svn_dirent_local_style(local_abspath, + scratch_pool), + svn_dirent_local_style(moved_to_abspath, + scratch_pool)); + goto unlock_wc; + } + + if (moved_to_repos_relpath == NULL || moved_to_peg_rev == SVN_INVALID_REVNUM) + { + err = svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Cannot resolve tree conflict on '%s' " + "(could not determine origin of '%s')"), + svn_dirent_local_style(local_abspath, + scratch_pool), + svn_dirent_local_style(moved_to_abspath, + scratch_pool)); + goto unlock_wc; + } + + /* Now find the youngest common ancestor of these nodes. */ + err = find_yca(&yca_loc, victim_repos_relpath, victim_peg_rev, + moved_to_repos_relpath, moved_to_peg_rev, + repos_root_url, repos_uuid, + NULL, ctx, scratch_pool, scratch_pool); + if (err) + goto unlock_wc; + + if (yca_loc == NULL) + { + err = svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Cannot resolve tree conflict on '%s' " + "(could not find common ancestor of '^/%s@%ld' " + " and '^/%s@%ld')"), + svn_dirent_local_style(local_abspath, + scratch_pool), + victim_repos_relpath, victim_peg_rev, + moved_to_repos_relpath, moved_to_peg_rev); + goto unlock_wc; + } + + yca_opt_rev.kind = svn_opt_revision_number; + yca_opt_rev.value.number = yca_loc->rev; + + err = verify_local_state_for_incoming_delete(conflict, option, ctx, + scratch_pool); + if (err) + goto unlock_wc; + + if (operation == svn_wc_operation_merge) + { + const char *move_target_url; + svn_opt_revision_t incoming_new_opt_rev; + + /* Revert the incoming move target directory. */ + SVN_ERR(svn_wc_revert5(ctx->wc_ctx, moved_to_abspath, svn_depth_infinity, + FALSE, NULL, TRUE, FALSE, + NULL, NULL, /* no cancellation */ + ctx->notify_func2, ctx->notify_baton2, + scratch_pool)); + + /* The move operation is not part of natural history. We must replicate + * this move in our history. Record a move in the working copy. */ + err = svn_wc__move2(ctx->wc_ctx, local_abspath, moved_to_abspath, + FALSE, /* this is not a meta-data only move */ + TRUE, /* allow mixed-revisions just in case */ + NULL, NULL, /* don't allow user to cancel here */ + ctx->notify_func2, ctx->notify_baton2, + scratch_pool); + if (err) + goto unlock_wc; + + /* Merge YCA_URL@YCA_REV->MOVE_TARGET_URL@MERGE_RIGHT into move target. */ + move_target_url = apr_pstrcat(scratch_pool, repos_root_url, "/", + get_moved_to_repos_relpath(details, + scratch_pool), + SVN_VA_NULL); + incoming_new_opt_rev.kind = svn_opt_revision_number; + incoming_new_opt_rev.value.number = incoming_new_pegrev; + err = svn_client__merge_locked(&conflict_report, + yca_loc->url, &yca_opt_rev, + move_target_url, &incoming_new_opt_rev, + moved_to_abspath, svn_depth_infinity, + TRUE, TRUE, /* do a no-ancestry merge */ + FALSE, FALSE, FALSE, + TRUE, /* Allow mixed-rev just in case, + * since conflict victims can't be + * updated to straighten out + * mixed-rev trees. */ + NULL, ctx, scratch_pool, scratch_pool); + if (err) + goto unlock_wc; + } + else + { + SVN_ERR_ASSERT(operation == svn_wc_operation_update || + operation == svn_wc_operation_switch); + + /* Merge local modifications into the incoming move target dir. */ + err = svn_wc__has_local_mods(&is_modified, ctx->wc_ctx, local_abspath, + TRUE, ctx->cancel_func, ctx->cancel_baton, + scratch_pool); + if (err) + goto unlock_wc; + + if (is_modified) + { + err = svn_wc__conflict_tree_update_incoming_move(ctx->wc_ctx, + local_abspath, + moved_to_abspath, + ctx->cancel_func, + ctx->cancel_baton, + ctx->notify_func2, + ctx->notify_baton2, + scratch_pool); + if (err) + goto unlock_wc; + } + + /* The move operation is part of our natural history. + * Delete the tree conflict victim (clears the tree conflict marker). */ + err = svn_wc_delete4(ctx->wc_ctx, local_abspath, FALSE, FALSE, + NULL, NULL, /* don't allow user to cancel here */ + NULL, NULL, /* no extra notification */ + scratch_pool); + if (err) + goto unlock_wc; + } + + if (ctx->notify_func2) + { + svn_wc_notify_t *notify; + + notify = svn_wc_create_notify(local_abspath, svn_wc_notify_resolved_tree, + scratch_pool); + ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool); + } + + conflict->resolution_tree = option_id; + +unlock_wc: + err = svn_error_compose_create(err, svn_wc__release_write_lock(ctx->wc_ctx, + lock_abspath, + scratch_pool)); + SVN_ERR(err); + + return SVN_NO_ERROR; +} + +/* Implements conflict_option_resolve_func_t. */ +static svn_error_t * +resolve_local_move_file_merge(svn_client_conflict_option_t *option, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + const char *lock_abspath; + svn_error_t *err; + const char *repos_root_url; + const char *incoming_old_repos_relpath; + svn_revnum_t incoming_old_pegrev; + const char *incoming_new_repos_relpath; + svn_revnum_t incoming_new_pegrev; + const char *wc_tmpdir; + const char *ancestor_tmp_abspath; + const char *incoming_tmp_abspath; + apr_hash_t *ancestor_props; + apr_hash_t *incoming_props; + svn_stream_t *stream; + const char *url; + const char *corrected_url; + const char *old_session_url; + svn_ra_session_t *ra_session; + svn_wc_merge_outcome_t merge_content_outcome; + svn_wc_notify_state_t merge_props_outcome; + apr_array_header_t *propdiffs; + struct conflict_tree_local_missing_details *details; + + details = conflict->tree_conflict_local_details; + + SVN_ERR(svn_client_conflict_get_repos_info(&repos_root_url, NULL, + conflict, scratch_pool, + scratch_pool)); + SVN_ERR(svn_client_conflict_get_incoming_old_repos_location( + &incoming_old_repos_relpath, &incoming_old_pegrev, + NULL, conflict, scratch_pool, + scratch_pool)); + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + &incoming_new_repos_relpath, &incoming_new_pegrev, + NULL, conflict, scratch_pool, + scratch_pool)); + + SVN_ERR(svn_wc__get_tmpdir(&wc_tmpdir, ctx->wc_ctx, + details->moved_to_abspath, + scratch_pool, scratch_pool)); + + /* Fetch the common ancestor file's content. */ + SVN_ERR(svn_stream_open_unique(&stream, &ancestor_tmp_abspath, wc_tmpdir, + svn_io_file_del_on_pool_cleanup, + scratch_pool, scratch_pool)); + url = svn_path_url_add_component2(repos_root_url, + incoming_old_repos_relpath, + scratch_pool); + SVN_ERR(svn_client__open_ra_session_internal(&ra_session, &corrected_url, + url, NULL, NULL, + FALSE, FALSE, ctx, + scratch_pool, scratch_pool)); + SVN_ERR(svn_ra_get_file(ra_session, "", incoming_old_pegrev, stream, NULL, + &ancestor_props, scratch_pool)); + filter_props(ancestor_props, scratch_pool); + + /* Close stream to flush the file to disk. */ + SVN_ERR(svn_stream_close(stream)); + + /* Do the same for the incoming file's content. */ + SVN_ERR(svn_stream_open_unique(&stream, &incoming_tmp_abspath, wc_tmpdir, + svn_io_file_del_on_pool_cleanup, + scratch_pool, scratch_pool)); + url = svn_path_url_add_component2(repos_root_url, + incoming_new_repos_relpath, + scratch_pool); + SVN_ERR(svn_client__ensure_ra_session_url(&old_session_url, ra_session, + url, scratch_pool)); + SVN_ERR(svn_ra_get_file(ra_session, "", incoming_new_pegrev, stream, NULL, + &incoming_props, scratch_pool)); + /* Close stream to flush the file to disk. */ + SVN_ERR(svn_stream_close(stream)); + + filter_props(incoming_props, scratch_pool); + + /* Create a property diff for the files. */ + SVN_ERR(svn_prop_diffs(&propdiffs, incoming_props, ancestor_props, + scratch_pool)); + + /* ### The following WC modifications should be atomic. */ + SVN_ERR(svn_wc__acquire_write_lock_for_resolve( + &lock_abspath, ctx->wc_ctx, + svn_dirent_get_longest_ancestor(conflict->local_abspath, + details->moved_to_abspath, + scratch_pool), + scratch_pool, scratch_pool)); + + /* Perform the file merge. */ + err = svn_wc_merge5(&merge_content_outcome, &merge_props_outcome, + ctx->wc_ctx, + ancestor_tmp_abspath, incoming_tmp_abspath, + details->moved_to_abspath, + NULL, NULL, NULL, /* labels */ + NULL, NULL, /* conflict versions */ + FALSE, /* dry run */ + NULL, NULL, /* diff3_cmd, merge_options */ + apr_hash_count(ancestor_props) ? ancestor_props : NULL, + propdiffs, + NULL, NULL, /* conflict func/baton */ + NULL, NULL, /* don't allow user to cancel here */ + scratch_pool); + svn_io_sleep_for_timestamps(details->moved_to_abspath, scratch_pool); + if (err) + return svn_error_compose_create(err, + svn_wc__release_write_lock(ctx->wc_ctx, + lock_abspath, + scratch_pool)); + + err = svn_wc__del_tree_conflict(ctx->wc_ctx, conflict->local_abspath, + scratch_pool); + err = svn_error_compose_create(err, + svn_wc__release_write_lock(ctx->wc_ctx, + lock_abspath, + scratch_pool)); + if (err) + return svn_error_trace(err); + + if (ctx->notify_func2) + { + svn_wc_notify_t *notify; + + /* Tell the world about the file merge that just happened. */ + notify = svn_wc_create_notify(details->moved_to_abspath, + svn_wc_notify_update_update, + scratch_pool); + if (merge_content_outcome == svn_wc_merge_conflict) + notify->content_state = svn_wc_notify_state_conflicted; + else + notify->content_state = svn_wc_notify_state_merged; + notify->prop_state = merge_props_outcome; + notify->kind = svn_node_file; + ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool); + + /* And also about the successfully resolved tree conflict. */ + notify = svn_wc_create_notify(conflict->local_abspath, + svn_wc_notify_resolved_tree, + scratch_pool); + ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool); + } + + conflict->resolution_tree = svn_client_conflict_option_get_id(option); + + return SVN_NO_ERROR; +} + +static svn_error_t * +assert_text_conflict(svn_client_conflict_t *conflict, apr_pool_t *scratch_pool) +{ + svn_boolean_t text_conflicted; + + SVN_ERR(svn_client_conflict_get_conflicted(&text_conflicted, NULL, NULL, + conflict, scratch_pool, + scratch_pool)); + + SVN_ERR_ASSERT(text_conflicted); /* ### return proper error? */ + + return SVN_NO_ERROR; +} + +static svn_error_t * +assert_prop_conflict(svn_client_conflict_t *conflict, apr_pool_t *scratch_pool) +{ + apr_array_header_t *props_conflicted; + + SVN_ERR(svn_client_conflict_get_conflicted(NULL, &props_conflicted, NULL, + conflict, scratch_pool, + scratch_pool)); + + /* ### return proper error? */ + SVN_ERR_ASSERT(props_conflicted && props_conflicted->nelts > 0); + + return SVN_NO_ERROR; +} + +static svn_error_t * +assert_tree_conflict(svn_client_conflict_t *conflict, apr_pool_t *scratch_pool) +{ + svn_boolean_t tree_conflicted; + + SVN_ERR(svn_client_conflict_get_conflicted(NULL, NULL, &tree_conflicted, + conflict, scratch_pool, + scratch_pool)); + + SVN_ERR_ASSERT(tree_conflicted); /* ### return proper error? */ + + return SVN_NO_ERROR; +} + +/* Helper to add to conflict resolution option to array of OPTIONS. + * Resolution option object will be allocated from OPTIONS->POOL + * and DESCRIPTION will be copied to this pool. + * Returns pointer to the created conflict resolution option. */ +static svn_client_conflict_option_t * +add_resolution_option(apr_array_header_t *options, + svn_client_conflict_t *conflict, + svn_client_conflict_option_id_t id, + const char *label, + const char *description, + conflict_option_resolve_func_t resolve_func) +{ + svn_client_conflict_option_t *option; + + option = apr_pcalloc(options->pool, sizeof(*option)); + option->pool = options->pool; + option->id = id; + option->label = apr_pstrdup(option->pool, label); + option->description = apr_pstrdup(option->pool, description); + option->conflict = conflict; + option->do_resolve_func = resolve_func; + + APR_ARRAY_PUSH(options, const svn_client_conflict_option_t *) = option; + + return option; +} + +svn_error_t * +svn_client_conflict_text_get_resolution_options(apr_array_header_t **options, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + const char *mime_type; + + SVN_ERR(assert_text_conflict(conflict, scratch_pool)); + + *options = apr_array_make(result_pool, 7, + sizeof(svn_client_conflict_option_t *)); + + add_resolution_option(*options, conflict, + svn_client_conflict_option_postpone, + _("Postpone"), + _("skip this conflict and leave it unresolved"), + resolve_postpone); + + mime_type = svn_client_conflict_text_get_mime_type(conflict); + if (mime_type && svn_mime_type_is_binary(mime_type)) + { + /* Resolver options for a binary file conflict. */ + add_resolution_option(*options, conflict, + svn_client_conflict_option_base_text, + _("Accept base"), + _("discard local and incoming changes for this binary file"), + resolve_text_conflict); + + add_resolution_option(*options, conflict, + svn_client_conflict_option_incoming_text, + _("Accept incoming"), + _("accept incoming version of binary file"), + resolve_text_conflict); + + add_resolution_option(*options, conflict, + svn_client_conflict_option_working_text, + _("Mark as resolved"), + _("accept binary file as it appears in the working copy"), + resolve_text_conflict); + } + else + { + /* Resolver options for a text file conflict. */ + add_resolution_option(*options, conflict, + svn_client_conflict_option_base_text, + _("Accept base"), + _("discard local and incoming changes for this file"), + resolve_text_conflict); + + add_resolution_option(*options, conflict, + svn_client_conflict_option_incoming_text, + _("Accept incoming"), + _("accept incoming version of entire file"), + resolve_text_conflict); + + add_resolution_option(*options, conflict, + svn_client_conflict_option_working_text, + _("Reject incoming"), + _("reject all incoming changes for this file"), + resolve_text_conflict); + + add_resolution_option(*options, conflict, + svn_client_conflict_option_incoming_text_where_conflicted, + _("Accept incoming for conflicts"), + _("accept changes only where they conflict"), + resolve_text_conflict); + + add_resolution_option(*options, conflict, + svn_client_conflict_option_working_text_where_conflicted, + _("Reject conflicts"), + _("reject changes which conflict and accept the rest"), + resolve_text_conflict); + + add_resolution_option(*options, conflict, + svn_client_conflict_option_merged_text, + _("Mark as resolved"), + _("accept the file as it appears in the working copy"), + resolve_text_conflict); + } + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_conflict_prop_get_resolution_options(apr_array_header_t **options, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + SVN_ERR(assert_prop_conflict(conflict, scratch_pool)); + + *options = apr_array_make(result_pool, 7, + sizeof(svn_client_conflict_option_t *)); + + add_resolution_option(*options, conflict, + svn_client_conflict_option_postpone, + _("Postpone"), + _("skip this conflict and leave it unresolved"), + resolve_postpone); + + add_resolution_option(*options, conflict, + svn_client_conflict_option_base_text, + _("Accept base"), + _("discard local and incoming changes for this property"), + resolve_prop_conflict); + + add_resolution_option(*options, conflict, + svn_client_conflict_option_incoming_text, + _("Accept incoming"), + _("accept incoming version of entire property value"), + resolve_prop_conflict); + + add_resolution_option(*options, conflict, + svn_client_conflict_option_working_text, + _("Mark as resolved"), + _("accept working copy version of entire property value"), + resolve_prop_conflict); + + add_resolution_option(*options, conflict, + svn_client_conflict_option_incoming_text_where_conflicted, + _("Accept incoming for conflicts"), + _("accept incoming changes only where they conflict"), + resolve_prop_conflict); + + add_resolution_option(*options, conflict, + svn_client_conflict_option_working_text_where_conflicted, + _("Reject conflicts"), + _("reject changes which conflict and accept the rest"), + resolve_prop_conflict); + + add_resolution_option(*options, conflict, + svn_client_conflict_option_merged_text, + _("Accept merged"), + _("accept merged version of property value"), + resolve_prop_conflict); + + return SVN_NO_ERROR; +} + +/* Configure 'accept current wc state' resolution option for a tree conflict. */ +static svn_error_t * +configure_option_accept_current_wc_state(svn_client_conflict_t *conflict, + apr_array_header_t *options) +{ + svn_wc_operation_t operation; + svn_wc_conflict_action_t incoming_change; + svn_wc_conflict_reason_t local_change; + conflict_option_resolve_func_t do_resolve_func; + + operation = svn_client_conflict_get_operation(conflict); + incoming_change = svn_client_conflict_get_incoming_change(conflict); + local_change = svn_client_conflict_get_local_change(conflict); + + if ((operation == svn_wc_operation_update || + operation == svn_wc_operation_switch) && + (local_change == svn_wc_conflict_reason_moved_away || + local_change == svn_wc_conflict_reason_deleted || + local_change == svn_wc_conflict_reason_replaced) && + incoming_change == svn_wc_conflict_action_edit) + { + /* We must break moves if the user accepts the current working copy + * state instead of updating a moved-away node or updating children + * moved outside of deleted or replaced directory nodes. + * Else such moves would be left in an invalid state. */ + do_resolve_func = resolve_update_break_moved_away; + } + else + do_resolve_func = resolve_accept_current_wc_state; + + add_resolution_option(options, conflict, + svn_client_conflict_option_accept_current_wc_state, + _("Mark as resolved"), + _("accept current working copy state"), + do_resolve_func); + + return SVN_NO_ERROR; +} + +/* Configure 'update move destination' resolution option for a tree conflict. */ +static svn_error_t * +configure_option_update_move_destination(svn_client_conflict_t *conflict, + apr_array_header_t *options) +{ + svn_wc_operation_t operation; + svn_wc_conflict_action_t incoming_change; + svn_wc_conflict_reason_t local_change; + + operation = svn_client_conflict_get_operation(conflict); + incoming_change = svn_client_conflict_get_incoming_change(conflict); + local_change = svn_client_conflict_get_local_change(conflict); + + if ((operation == svn_wc_operation_update || + operation == svn_wc_operation_switch) && + incoming_change == svn_wc_conflict_action_edit && + local_change == svn_wc_conflict_reason_moved_away) + { + add_resolution_option( + options, conflict, + svn_client_conflict_option_update_move_destination, + _("Update move destination"), + _("apply incoming changes to move destination"), + resolve_update_moved_away_node); + } + + return SVN_NO_ERROR; +} + +/* Configure 'update raise moved away children' resolution option for a tree + * conflict. */ +static svn_error_t * +configure_option_update_raise_moved_away_children( + svn_client_conflict_t *conflict, + apr_array_header_t *options) +{ + svn_wc_operation_t operation; + svn_wc_conflict_action_t incoming_change; + svn_wc_conflict_reason_t local_change; + svn_node_kind_t victim_node_kind; + + operation = svn_client_conflict_get_operation(conflict); + incoming_change = svn_client_conflict_get_incoming_change(conflict); + local_change = svn_client_conflict_get_local_change(conflict); + victim_node_kind = svn_client_conflict_tree_get_victim_node_kind(conflict); + + if ((operation == svn_wc_operation_update || + operation == svn_wc_operation_switch) && + incoming_change == svn_wc_conflict_action_edit && + (local_change == svn_wc_conflict_reason_deleted || + local_change == svn_wc_conflict_reason_replaced) && + victim_node_kind == svn_node_dir) + { + add_resolution_option( + options, conflict, + svn_client_conflict_option_update_any_moved_away_children, + _("Update any moved-away children"), + _("prepare for updating moved-away children, if any"), + resolve_update_raise_moved_away); + } + + return SVN_NO_ERROR; +} + +/* Configure 'incoming add ignore' resolution option for a tree conflict. */ +static svn_error_t * +configure_option_incoming_add_ignore(svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_array_header_t *options, + apr_pool_t *scratch_pool) +{ + svn_wc_operation_t operation; + svn_wc_conflict_action_t incoming_change; + svn_wc_conflict_reason_t local_change; + const char *incoming_new_repos_relpath; + svn_revnum_t incoming_new_pegrev; + svn_node_kind_t victim_node_kind; + + operation = svn_client_conflict_get_operation(conflict); + incoming_change = svn_client_conflict_get_incoming_change(conflict); + local_change = svn_client_conflict_get_local_change(conflict); + victim_node_kind = svn_client_conflict_tree_get_victim_node_kind(conflict); + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + &incoming_new_repos_relpath, &incoming_new_pegrev, + NULL, conflict, scratch_pool, + scratch_pool)); + + /* This option is only available for directories. */ + if (victim_node_kind == svn_node_dir && + incoming_change == svn_wc_conflict_action_add && + (local_change == svn_wc_conflict_reason_obstructed || + local_change == svn_wc_conflict_reason_added)) + { + const char *description; + const char *wcroot_abspath; + + SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, ctx->wc_ctx, + conflict->local_abspath, scratch_pool, + scratch_pool)); + if (operation == svn_wc_operation_merge) + description = + apr_psprintf(scratch_pool, + _("ignore and do not add '^/%s@%ld' here"), + incoming_new_repos_relpath, incoming_new_pegrev); + else if (operation == svn_wc_operation_update || + operation == svn_wc_operation_switch) + { + if (victim_node_kind == svn_node_file) + description = + apr_psprintf(scratch_pool, + _("replace '^/%s@%ld' with the locally added file"), + incoming_new_repos_relpath, incoming_new_pegrev); + else if (victim_node_kind == svn_node_dir) + description = + apr_psprintf(scratch_pool, + _("replace '^/%s@%ld' with the locally added " + "directory"), + incoming_new_repos_relpath, incoming_new_pegrev); + else + description = + apr_psprintf(scratch_pool, + _("replace '^/%s@%ld' with the locally added item"), + incoming_new_repos_relpath, incoming_new_pegrev); + } + else + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("unexpected operation code '%d'"), + operation); + add_resolution_option( + options, conflict, svn_client_conflict_option_incoming_add_ignore, + _("Ignore incoming addition"), description, resolve_incoming_add_ignore); + } + + return SVN_NO_ERROR; +} + +/* Configure 'incoming added file text merge' resolution option for a tree + * conflict. */ +static svn_error_t * +configure_option_incoming_added_file_text_merge(svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_array_header_t *options, + apr_pool_t *scratch_pool) +{ + svn_wc_operation_t operation; + svn_wc_conflict_action_t incoming_change; + svn_wc_conflict_reason_t local_change; + svn_node_kind_t victim_node_kind; + const char *incoming_new_repos_relpath; + svn_revnum_t incoming_new_pegrev; + svn_node_kind_t incoming_new_kind; + + operation = svn_client_conflict_get_operation(conflict); + incoming_change = svn_client_conflict_get_incoming_change(conflict); + local_change = svn_client_conflict_get_local_change(conflict); + victim_node_kind = svn_client_conflict_tree_get_victim_node_kind(conflict); + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + &incoming_new_repos_relpath, &incoming_new_pegrev, + &incoming_new_kind, conflict, scratch_pool, + scratch_pool)); + + if (victim_node_kind == svn_node_file && + incoming_new_kind == svn_node_file && + incoming_change == svn_wc_conflict_action_add && + (local_change == svn_wc_conflict_reason_obstructed || + local_change == svn_wc_conflict_reason_added)) + { + const char *description; + const char *wcroot_abspath; + + SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, ctx->wc_ctx, + conflict->local_abspath, scratch_pool, + scratch_pool)); + + if (operation == svn_wc_operation_merge) + description = + apr_psprintf(scratch_pool, _("merge '^/%s@%ld' into '%s'"), + incoming_new_repos_relpath, incoming_new_pegrev, + svn_dirent_local_style( + svn_dirent_skip_ancestor(wcroot_abspath, + conflict->local_abspath), + scratch_pool)); + else + description = + apr_psprintf(scratch_pool, _("merge local '%s' and '^/%s@%ld'"), + svn_dirent_local_style( + svn_dirent_skip_ancestor(wcroot_abspath, + conflict->local_abspath), + scratch_pool), + incoming_new_repos_relpath, incoming_new_pegrev); + + add_resolution_option( + options, conflict, + svn_client_conflict_option_incoming_added_file_text_merge, + _("Merge the files"), description, + operation == svn_wc_operation_merge + ? resolve_merge_incoming_added_file_text_merge + : resolve_merge_incoming_added_file_text_update); + } + + return SVN_NO_ERROR; +} + +/* Configure 'incoming added file replace and merge' resolution option for a + * tree conflict. */ +static svn_error_t * +configure_option_incoming_added_file_replace_and_merge( + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_array_header_t *options, + apr_pool_t *scratch_pool) +{ + svn_wc_operation_t operation; + svn_wc_conflict_action_t incoming_change; + svn_wc_conflict_reason_t local_change; + svn_node_kind_t victim_node_kind; + const char *incoming_new_repos_relpath; + svn_revnum_t incoming_new_pegrev; + svn_node_kind_t incoming_new_kind; + + operation = svn_client_conflict_get_operation(conflict); + incoming_change = svn_client_conflict_get_incoming_change(conflict); + local_change = svn_client_conflict_get_local_change(conflict); + victim_node_kind = svn_client_conflict_tree_get_victim_node_kind(conflict); + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + &incoming_new_repos_relpath, &incoming_new_pegrev, + &incoming_new_kind, conflict, scratch_pool, + scratch_pool)); + + if (operation == svn_wc_operation_merge && + victim_node_kind == svn_node_file && + incoming_new_kind == svn_node_file && + incoming_change == svn_wc_conflict_action_add && + local_change == svn_wc_conflict_reason_obstructed) + { + const char *wcroot_abspath; + const char *description; + + SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, ctx->wc_ctx, + conflict->local_abspath, scratch_pool, + scratch_pool)); + description = + apr_psprintf(scratch_pool, + _("delete '%s', copy '^/%s@%ld' here, and merge the files"), + svn_dirent_local_style( + svn_dirent_skip_ancestor(wcroot_abspath, + conflict->local_abspath), + scratch_pool), + incoming_new_repos_relpath, incoming_new_pegrev); + + add_resolution_option( + options, conflict, + svn_client_conflict_option_incoming_added_file_replace_and_merge, + _("Replace and merge"), + description, resolve_merge_incoming_added_file_replace_and_merge); + } + + return SVN_NO_ERROR; +} + +/* Configure 'incoming added dir merge' resolution option for a tree + * conflict. */ +static svn_error_t * +configure_option_incoming_added_dir_merge(svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_array_header_t *options, + apr_pool_t *scratch_pool) +{ + svn_wc_operation_t operation; + svn_wc_conflict_action_t incoming_change; + svn_wc_conflict_reason_t local_change; + svn_node_kind_t victim_node_kind; + const char *incoming_new_repos_relpath; + svn_revnum_t incoming_new_pegrev; + svn_node_kind_t incoming_new_kind; + + operation = svn_client_conflict_get_operation(conflict); + incoming_change = svn_client_conflict_get_incoming_change(conflict); + local_change = svn_client_conflict_get_local_change(conflict); + victim_node_kind = svn_client_conflict_tree_get_victim_node_kind(conflict); + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + &incoming_new_repos_relpath, &incoming_new_pegrev, + &incoming_new_kind, conflict, scratch_pool, + scratch_pool)); + + if (victim_node_kind == svn_node_dir && + incoming_new_kind == svn_node_dir && + incoming_change == svn_wc_conflict_action_add && + (local_change == svn_wc_conflict_reason_added || + (operation == svn_wc_operation_merge && + local_change == svn_wc_conflict_reason_obstructed))) + + { + const char *description; + const char *wcroot_abspath; + + SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, ctx->wc_ctx, + conflict->local_abspath, scratch_pool, + scratch_pool)); + if (operation == svn_wc_operation_merge) + description = + apr_psprintf(scratch_pool, _("merge '^/%s@%ld' into '%s'"), + incoming_new_repos_relpath, incoming_new_pegrev, + svn_dirent_local_style( + svn_dirent_skip_ancestor(wcroot_abspath, + conflict->local_abspath), + scratch_pool)); + else + description = + apr_psprintf(scratch_pool, _("merge local '%s' and '^/%s@%ld'"), + svn_dirent_local_style( + svn_dirent_skip_ancestor(wcroot_abspath, + conflict->local_abspath), + scratch_pool), + incoming_new_repos_relpath, incoming_new_pegrev); + + add_resolution_option(options, conflict, + svn_client_conflict_option_incoming_added_dir_merge, + _("Merge the directories"), description, + operation == svn_wc_operation_merge + ? resolve_merge_incoming_added_dir_merge + : resolve_update_incoming_added_dir_merge); + } + + return SVN_NO_ERROR; +} + +/* Configure 'incoming added dir replace' resolution option for a tree + * conflict. */ +static svn_error_t * +configure_option_incoming_added_dir_replace(svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_array_header_t *options, + apr_pool_t *scratch_pool) +{ + svn_wc_operation_t operation; + svn_wc_conflict_action_t incoming_change; + svn_wc_conflict_reason_t local_change; + svn_node_kind_t victim_node_kind; + const char *incoming_new_repos_relpath; + svn_revnum_t incoming_new_pegrev; + svn_node_kind_t incoming_new_kind; + + operation = svn_client_conflict_get_operation(conflict); + incoming_change = svn_client_conflict_get_incoming_change(conflict); + local_change = svn_client_conflict_get_local_change(conflict); + victim_node_kind = svn_client_conflict_tree_get_victim_node_kind(conflict); + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + &incoming_new_repos_relpath, &incoming_new_pegrev, + &incoming_new_kind, conflict, scratch_pool, + scratch_pool)); + + if (operation == svn_wc_operation_merge && + victim_node_kind == svn_node_dir && + incoming_new_kind == svn_node_dir && + incoming_change == svn_wc_conflict_action_add && + local_change == svn_wc_conflict_reason_obstructed) + { + const char *description; + const char *wcroot_abspath; + + SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, ctx->wc_ctx, + conflict->local_abspath, scratch_pool, + scratch_pool)); + description = + apr_psprintf(scratch_pool, _("delete '%s' and copy '^/%s@%ld' here"), + svn_dirent_local_style( + svn_dirent_skip_ancestor(wcroot_abspath, + conflict->local_abspath), + scratch_pool), + incoming_new_repos_relpath, incoming_new_pegrev); + add_resolution_option( + options, conflict, + svn_client_conflict_option_incoming_added_dir_replace, + _("Delete my directory and replace it with incoming directory"), + description, resolve_merge_incoming_added_dir_replace); + } + + return SVN_NO_ERROR; +} + +/* Configure 'incoming added dir replace and merge' resolution option + * for a tree conflict. */ +static svn_error_t * +configure_option_incoming_added_dir_replace_and_merge( + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_array_header_t *options, + apr_pool_t *scratch_pool) +{ + svn_wc_operation_t operation; + svn_wc_conflict_action_t incoming_change; + svn_wc_conflict_reason_t local_change; + svn_node_kind_t victim_node_kind; + const char *incoming_new_repos_relpath; + svn_revnum_t incoming_new_pegrev; + svn_node_kind_t incoming_new_kind; + + operation = svn_client_conflict_get_operation(conflict); + incoming_change = svn_client_conflict_get_incoming_change(conflict); + local_change = svn_client_conflict_get_local_change(conflict); + victim_node_kind = svn_client_conflict_tree_get_victim_node_kind(conflict); + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + &incoming_new_repos_relpath, &incoming_new_pegrev, + &incoming_new_kind, conflict, scratch_pool, + scratch_pool)); + + if (operation == svn_wc_operation_merge && + victim_node_kind == svn_node_dir && + incoming_new_kind == svn_node_dir && + incoming_change == svn_wc_conflict_action_add && + local_change == svn_wc_conflict_reason_obstructed) + { + const char *description; + const char *wcroot_abspath; + + SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, ctx->wc_ctx, + conflict->local_abspath, scratch_pool, + scratch_pool)); + description = + apr_psprintf(scratch_pool, + _("delete '%s', copy '^/%s@%ld' here, and merge the directories"), + svn_dirent_local_style( + svn_dirent_skip_ancestor(wcroot_abspath, + conflict->local_abspath), + scratch_pool), + incoming_new_repos_relpath, incoming_new_pegrev); + + add_resolution_option( + options, conflict, + svn_client_conflict_option_incoming_added_dir_replace_and_merge, + _("Replace and merge"), + description, resolve_merge_incoming_added_dir_replace_and_merge); + } + + return SVN_NO_ERROR; +} + +/* Configure 'incoming delete ignore' resolution option for a tree conflict. */ +static svn_error_t * +configure_option_incoming_delete_ignore(svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_array_header_t *options, + apr_pool_t *scratch_pool) +{ + svn_wc_operation_t operation; + svn_wc_conflict_action_t incoming_change; + svn_wc_conflict_reason_t local_change; + const char *incoming_new_repos_relpath; + svn_revnum_t incoming_new_pegrev; + + operation = svn_client_conflict_get_operation(conflict); + incoming_change = svn_client_conflict_get_incoming_change(conflict); + local_change = svn_client_conflict_get_local_change(conflict); + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + &incoming_new_repos_relpath, &incoming_new_pegrev, + NULL, conflict, scratch_pool, + scratch_pool)); + + if (incoming_change == svn_wc_conflict_action_delete) + { + const char *description; + struct conflict_tree_incoming_delete_details *incoming_details; + svn_boolean_t is_incoming_move; + + incoming_details = conflict->tree_conflict_incoming_details; + is_incoming_move = (incoming_details != NULL && + incoming_details->moves != NULL); + if (local_change == svn_wc_conflict_reason_moved_away || + local_change == svn_wc_conflict_reason_edited) + { + /* An option which ignores the incoming deletion makes no sense + * if we know there was a local move and/or an incoming move. */ + if (is_incoming_move) + return SVN_NO_ERROR; + } + else if (local_change == svn_wc_conflict_reason_deleted) + { + /* If the local item was deleted and conflict details were fetched + * and indicate that there was no move, then this is an actual + * 'delete vs delete' situation. An option which ignores the incoming + * deletion makes no sense in that case because there is no local + * node to preserve. */ + if (!is_incoming_move) + return SVN_NO_ERROR; + } + else if (local_change == svn_wc_conflict_reason_missing && + operation == svn_wc_operation_merge) + { + struct conflict_tree_local_missing_details *local_details; + svn_boolean_t is_local_move; /* "local" to branch history */ + + local_details = conflict->tree_conflict_local_details; + is_local_move = (local_details != NULL && + local_details->moves != NULL); + + if (!is_incoming_move && !is_local_move) + return SVN_NO_ERROR; + } + + description = + apr_psprintf(scratch_pool, _("ignore the deletion of '^/%s@%ld'"), + incoming_new_repos_relpath, incoming_new_pegrev); + + add_resolution_option(options, conflict, + svn_client_conflict_option_incoming_delete_ignore, + _("Ignore incoming deletion"), description, + resolve_incoming_delete_ignore); + } + + return SVN_NO_ERROR; +} + +/* Configure 'incoming delete accept' resolution option for a tree conflict. */ +static svn_error_t * +configure_option_incoming_delete_accept(svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_array_header_t *options, + apr_pool_t *scratch_pool) +{ + svn_wc_conflict_action_t incoming_change; + svn_wc_conflict_reason_t local_change; + const char *incoming_new_repos_relpath; + svn_revnum_t incoming_new_pegrev; + + incoming_change = svn_client_conflict_get_incoming_change(conflict); + local_change = svn_client_conflict_get_local_change(conflict); + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + &incoming_new_repos_relpath, &incoming_new_pegrev, + NULL, conflict, scratch_pool, + scratch_pool)); + + if (incoming_change == svn_wc_conflict_action_delete) + { + struct conflict_tree_incoming_delete_details *incoming_details; + svn_boolean_t is_incoming_move; + + incoming_details = conflict->tree_conflict_incoming_details; + is_incoming_move = (incoming_details != NULL && + incoming_details->moves != NULL); + if (is_incoming_move && + (local_change == svn_wc_conflict_reason_edited || + local_change == svn_wc_conflict_reason_moved_away)) + { + /* An option which accepts the incoming deletion makes no sense + * if we know there was a local move and/or an incoming move. */ + return SVN_NO_ERROR; + } + else + { + const char *description; + const char *wcroot_abspath; + const char *local_abspath; + + SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, ctx->wc_ctx, + conflict->local_abspath, scratch_pool, + scratch_pool)); + local_abspath = svn_client_conflict_get_local_abspath(conflict); + description = + apr_psprintf(scratch_pool, _("accept the deletion of '%s'"), + svn_dirent_local_style(svn_dirent_skip_ancestor(wcroot_abspath, + local_abspath), + scratch_pool)); + add_resolution_option( + options, conflict, + svn_client_conflict_option_incoming_delete_accept, + _("Accept incoming deletion"), description, + resolve_incoming_delete_accept); + } + } + + return SVN_NO_ERROR; +} + +static svn_error_t * +describe_incoming_move_merge_conflict_option( + const char **description, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + struct conflict_tree_incoming_delete_details *details, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + apr_array_header_t *move_target_wc_abspaths; + svn_wc_operation_t operation; + const char *victim_abspath; + const char *moved_to_abspath; + const char *wcroot_abspath; + + move_target_wc_abspaths = + svn_hash_gets(details->wc_move_targets, + get_moved_to_repos_relpath(details, scratch_pool)); + moved_to_abspath = APR_ARRAY_IDX(move_target_wc_abspaths, + details->wc_move_target_idx, + const char *); + + victim_abspath = svn_client_conflict_get_local_abspath(conflict); + SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, ctx->wc_ctx, + victim_abspath, scratch_pool, + scratch_pool)); + + operation = svn_client_conflict_get_operation(conflict); + if (operation == svn_wc_operation_merge) + *description = + apr_psprintf( + result_pool, _("move '%s' to '%s' and merge"), + svn_dirent_local_style(svn_dirent_skip_ancestor(wcroot_abspath, + victim_abspath), + scratch_pool), + svn_dirent_local_style(svn_dirent_skip_ancestor(wcroot_abspath, + moved_to_abspath), + scratch_pool)); + else + *description = + apr_psprintf( + result_pool, _("move and merge local changes from '%s' into '%s'"), + svn_dirent_local_style(svn_dirent_skip_ancestor(wcroot_abspath, + victim_abspath), + scratch_pool), + svn_dirent_local_style(svn_dirent_skip_ancestor(wcroot_abspath, + moved_to_abspath), + scratch_pool)); + + return SVN_NO_ERROR; +} + +/* Configure 'incoming move file merge' resolution option for + * a tree conflict. */ +static svn_error_t * +configure_option_incoming_move_file_merge(svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_array_header_t *options, + apr_pool_t *scratch_pool) +{ + svn_node_kind_t victim_node_kind; + svn_wc_conflict_action_t incoming_change; + const char *incoming_old_repos_relpath; + svn_revnum_t incoming_old_pegrev; + svn_node_kind_t incoming_old_kind; + const char *incoming_new_repos_relpath; + svn_revnum_t incoming_new_pegrev; + svn_node_kind_t incoming_new_kind; + incoming_change = svn_client_conflict_get_incoming_change(conflict); + victim_node_kind = svn_client_conflict_tree_get_victim_node_kind(conflict); + SVN_ERR(svn_client_conflict_get_incoming_old_repos_location( + &incoming_old_repos_relpath, &incoming_old_pegrev, + &incoming_old_kind, conflict, scratch_pool, + scratch_pool)); + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + &incoming_new_repos_relpath, &incoming_new_pegrev, + &incoming_new_kind, conflict, scratch_pool, + scratch_pool)); + + if (victim_node_kind == svn_node_file && + incoming_old_kind == svn_node_file && + incoming_new_kind == svn_node_none && + incoming_change == svn_wc_conflict_action_delete) + { + struct conflict_tree_incoming_delete_details *details; + const char *description; + + details = conflict->tree_conflict_incoming_details; + if (details == NULL || details->moves == NULL) + return SVN_NO_ERROR; + + if (apr_hash_count(details->wc_move_targets) == 0) + return SVN_NO_ERROR; + + SVN_ERR(describe_incoming_move_merge_conflict_option(&description, + conflict, ctx, + details, + scratch_pool, + scratch_pool)); + add_resolution_option( + options, conflict, + svn_client_conflict_option_incoming_move_file_text_merge, + _("Move and merge"), description, + resolve_incoming_move_file_text_merge); + } + + return SVN_NO_ERROR; +} + +/* Configure 'incoming move dir merge' resolution option for + * a tree conflict. */ +static svn_error_t * +configure_option_incoming_dir_merge(svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_array_header_t *options, + apr_pool_t *scratch_pool) +{ + svn_node_kind_t victim_node_kind; + svn_wc_conflict_action_t incoming_change; + svn_wc_conflict_reason_t local_change; + const char *incoming_old_repos_relpath; + svn_revnum_t incoming_old_pegrev; + svn_node_kind_t incoming_old_kind; + const char *incoming_new_repos_relpath; + svn_revnum_t incoming_new_pegrev; + svn_node_kind_t incoming_new_kind; + + incoming_change = svn_client_conflict_get_incoming_change(conflict); + local_change = svn_client_conflict_get_local_change(conflict); + victim_node_kind = svn_client_conflict_tree_get_victim_node_kind(conflict); + SVN_ERR(svn_client_conflict_get_incoming_old_repos_location( + &incoming_old_repos_relpath, &incoming_old_pegrev, + &incoming_old_kind, conflict, scratch_pool, + scratch_pool)); + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + &incoming_new_repos_relpath, &incoming_new_pegrev, + &incoming_new_kind, conflict, scratch_pool, + scratch_pool)); + + if (victim_node_kind == svn_node_dir && + incoming_old_kind == svn_node_dir && + incoming_new_kind == svn_node_none && + incoming_change == svn_wc_conflict_action_delete && + local_change == svn_wc_conflict_reason_edited) + { + struct conflict_tree_incoming_delete_details *details; + const char *description; + + details = conflict->tree_conflict_incoming_details; + if (details == NULL || details->moves == NULL) + return SVN_NO_ERROR; + + if (apr_hash_count(details->wc_move_targets) == 0) + return SVN_NO_ERROR; + + SVN_ERR(describe_incoming_move_merge_conflict_option(&description, + conflict, ctx, + details, + scratch_pool, + scratch_pool)); + add_resolution_option(options, conflict, + svn_client_conflict_option_incoming_move_dir_merge, + _("Move and merge"), description, + resolve_incoming_move_dir_merge); + } + + return SVN_NO_ERROR; +} + +/* Configure 'local move file merge' resolution option for + * a tree conflict. */ +static svn_error_t * +configure_option_local_move_file_merge(svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_array_header_t *options, + apr_pool_t *scratch_pool) +{ + svn_wc_operation_t operation; + svn_wc_conflict_action_t incoming_change; + svn_wc_conflict_reason_t local_change; + const char *incoming_new_repos_relpath; + svn_revnum_t incoming_new_pegrev; + + operation = svn_client_conflict_get_operation(conflict); + incoming_change = svn_client_conflict_get_incoming_change(conflict); + local_change = svn_client_conflict_get_local_change(conflict); + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + &incoming_new_repos_relpath, &incoming_new_pegrev, + NULL, conflict, scratch_pool, + scratch_pool)); + + if (operation == svn_wc_operation_merge && + incoming_change == svn_wc_conflict_action_edit && + local_change == svn_wc_conflict_reason_missing) + { + struct conflict_tree_local_missing_details *details; + + details = conflict->tree_conflict_local_details; + if (details != NULL && details->moves != NULL) + { + apr_hash_t *wc_move_targets = apr_hash_make(scratch_pool); + apr_pool_t *iterpool; + int i; + + iterpool = svn_pool_create(scratch_pool); + for (i = 0; i < details->moves->nelts; i++) + { + struct repos_move_info *move; + + svn_pool_clear(iterpool); + move = APR_ARRAY_IDX(details->moves, i, struct repos_move_info *); + SVN_ERR(follow_move_chains(wc_move_targets, move, ctx, + conflict->local_abspath, + svn_node_file, + incoming_new_repos_relpath, + incoming_new_pegrev, + scratch_pool, iterpool)); + } + svn_pool_destroy(iterpool); + + if (apr_hash_count(wc_move_targets) > 0) + { + apr_array_header_t *move_target_repos_relpaths; + const svn_sort__item_t *item; + apr_array_header_t *moved_to_abspaths; + const char *description; + const char *wcroot_abspath; + + /* Initialize to the first possible move target. Hopefully, + * in most cases there will only be one candidate anyway. */ + move_target_repos_relpaths = svn_sort__hash( + wc_move_targets, + svn_sort_compare_items_as_paths, + scratch_pool); + item = &APR_ARRAY_IDX(move_target_repos_relpaths, + 0, svn_sort__item_t); + moved_to_abspaths = item->value; + details->moved_to_abspath = + apr_pstrdup(conflict->pool, + APR_ARRAY_IDX(moved_to_abspaths, 0, const char *)); + + SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, ctx->wc_ctx, + conflict->local_abspath, + scratch_pool, scratch_pool)); + description = + apr_psprintf( + scratch_pool, _("apply changes to move destination '%s'"), + svn_dirent_local_style( + svn_dirent_skip_ancestor(wcroot_abspath, + details->moved_to_abspath), + scratch_pool)); + + add_resolution_option( + options, conflict, + svn_client_conflict_option_local_move_file_text_merge, + _("Apply to move destination"), + description, resolve_local_move_file_merge); + } + else + details->moved_to_abspath = NULL; + } + } + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_conflict_option_get_moved_to_repos_relpath_candidates( + apr_array_header_t **possible_moved_to_repos_relpaths, + svn_client_conflict_option_t *option, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_client_conflict_t *conflict = option->conflict; + struct conflict_tree_incoming_delete_details *details; + const char *victim_abspath; + apr_array_header_t *sorted_repos_relpaths; + int i; + + SVN_ERR_ASSERT(svn_client_conflict_option_get_id(option) == + svn_client_conflict_option_incoming_move_file_text_merge || + svn_client_conflict_option_get_id(option) == + svn_client_conflict_option_incoming_move_dir_merge); + + victim_abspath = svn_client_conflict_get_local_abspath(conflict); + details = conflict->tree_conflict_incoming_details; + if (details == NULL || details->wc_move_targets == NULL) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Getting a list of possible move targets " + "requires details for tree conflict at '%s' " + "to be fetched from the repository first"), + svn_dirent_local_style(victim_abspath, + scratch_pool)); + + /* Return a copy of the repos replath candidate list. */ + sorted_repos_relpaths = svn_sort__hash(details->wc_move_targets, + svn_sort_compare_items_as_paths, + scratch_pool); + + *possible_moved_to_repos_relpaths = apr_array_make( + result_pool, + sorted_repos_relpaths->nelts, + sizeof (const char *)); + for (i = 0; i < sorted_repos_relpaths->nelts; i++) + { + svn_sort__item_t item; + const char *repos_relpath; + + item = APR_ARRAY_IDX(sorted_repos_relpaths, i, svn_sort__item_t); + repos_relpath = item.key; + APR_ARRAY_PUSH(*possible_moved_to_repos_relpaths, const char *) = + apr_pstrdup(result_pool, repos_relpath); + } + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_conflict_option_set_moved_to_repos_relpath( + svn_client_conflict_option_t *option, + int preferred_move_target_idx, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + svn_client_conflict_t *conflict = option->conflict; + struct conflict_tree_incoming_delete_details *details; + const char *victim_abspath; + apr_array_header_t *move_target_repos_relpaths; + svn_sort__item_t item; + const char *move_target_repos_relpath; + apr_hash_index_t *hi; + + SVN_ERR_ASSERT(svn_client_conflict_option_get_id(option) == + svn_client_conflict_option_incoming_move_file_text_merge || + svn_client_conflict_option_get_id(option) == + svn_client_conflict_option_incoming_move_dir_merge); + + victim_abspath = svn_client_conflict_get_local_abspath(conflict); + details = conflict->tree_conflict_incoming_details; + if (details == NULL || details->wc_move_targets == NULL) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Setting a move target requires details " + "for tree conflict at '%s' to be fetched " + "from the repository first"), + svn_dirent_local_style(victim_abspath, + scratch_pool)); + + if (preferred_move_target_idx < 0 || + preferred_move_target_idx >= apr_hash_count(details->wc_move_targets)) + return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL, + _("Index '%d' is out of bounds of the possible " + "move target list for '%s'"), + preferred_move_target_idx, + svn_dirent_local_style(victim_abspath, + scratch_pool)); + + /* Translate the index back into a hash table key. */ + move_target_repos_relpaths = + svn_sort__hash(details->wc_move_targets, + svn_sort_compare_items_as_paths, + scratch_pool); + item = APR_ARRAY_IDX(move_target_repos_relpaths, preferred_move_target_idx, + svn_sort__item_t); + move_target_repos_relpath = item.key; + /* Find our copy of the hash key and remember the user's preference. */ + for (hi = apr_hash_first(scratch_pool, details->wc_move_targets); + hi != NULL; + hi = apr_hash_next(hi)) + { + const char *repos_relpath = apr_hash_this_key(hi); + + if (strcmp(move_target_repos_relpath, repos_relpath) == 0) + { + details->move_target_repos_relpath = repos_relpath; + /* Update option description. */ + SVN_ERR(describe_incoming_move_merge_conflict_option( + &option->description, + conflict, ctx, + details, + conflict->pool, + scratch_pool)); + + return SVN_NO_ERROR; + } + } + + return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL, + _("Repository path '%s' not found in list of " + "possible move targets for '%s'"), + move_target_repos_relpath, + svn_dirent_local_style(victim_abspath, + scratch_pool)); +} + +svn_error_t * +svn_client_conflict_option_get_moved_to_abspath_candidates( + apr_array_header_t **possible_moved_to_abspaths, + svn_client_conflict_option_t *option, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_client_conflict_t *conflict = option->conflict; + struct conflict_tree_incoming_delete_details *details; + const char *victim_abspath; + apr_array_header_t *move_target_wc_abspaths; + int i; + + SVN_ERR_ASSERT(svn_client_conflict_option_get_id(option) == + svn_client_conflict_option_incoming_move_file_text_merge || + svn_client_conflict_option_get_id(option) == + svn_client_conflict_option_incoming_move_dir_merge); + + victim_abspath = svn_client_conflict_get_local_abspath(conflict); + details = conflict->tree_conflict_incoming_details; + if (details == NULL || details->wc_move_targets == NULL) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Getting a list of possible move targets " + "requires details for tree conflict at '%s' " + "to be fetched from the repository first"), + svn_dirent_local_style(victim_abspath, + scratch_pool)); + + move_target_wc_abspaths = + svn_hash_gets(details->wc_move_targets, + get_moved_to_repos_relpath(details, scratch_pool)); + + /* Return a copy of the option's move target candidate list. */ + *possible_moved_to_abspaths = + apr_array_make(result_pool, move_target_wc_abspaths->nelts, + sizeof (const char *)); + for (i = 0; i < move_target_wc_abspaths->nelts; i++) + { + const char *moved_to_abspath; + + moved_to_abspath = APR_ARRAY_IDX(move_target_wc_abspaths, i, + const char *); + APR_ARRAY_PUSH(*possible_moved_to_abspaths, const char *) = + apr_pstrdup(result_pool, moved_to_abspath); + } + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_conflict_option_set_moved_to_abspath( + svn_client_conflict_option_t *option, + int preferred_move_target_idx, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + svn_client_conflict_t *conflict = option->conflict; + struct conflict_tree_incoming_delete_details *details; + const char *victim_abspath; + apr_array_header_t *move_target_wc_abspaths; + + SVN_ERR_ASSERT(svn_client_conflict_option_get_id(option) == + svn_client_conflict_option_incoming_move_file_text_merge || + svn_client_conflict_option_get_id(option) == + svn_client_conflict_option_incoming_move_dir_merge); + + victim_abspath = svn_client_conflict_get_local_abspath(conflict); + details = conflict->tree_conflict_incoming_details; + if (details == NULL || details->wc_move_targets == NULL) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Setting a move target requires details " + "for tree conflict at '%s' to be fetched " + "from the repository first"), + svn_dirent_local_style(victim_abspath, + scratch_pool)); + + move_target_wc_abspaths = + svn_hash_gets(details->wc_move_targets, + get_moved_to_repos_relpath(details, scratch_pool)); + + if (preferred_move_target_idx < 0 || + preferred_move_target_idx > move_target_wc_abspaths->nelts) + return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL, + _("Index '%d' is out of bounds of the possible " + "move target list for '%s'"), + preferred_move_target_idx, + svn_dirent_local_style(victim_abspath, + scratch_pool)); + + /* Record the user's preference. */ + details->wc_move_target_idx = preferred_move_target_idx; + + /* Update option description. */ + SVN_ERR(describe_incoming_move_merge_conflict_option(&option->description, + conflict, ctx, + details, + conflict->pool, + scratch_pool)); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_conflict_tree_get_resolution_options(apr_array_header_t **options, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + SVN_ERR(assert_tree_conflict(conflict, scratch_pool)); + + *options = apr_array_make(result_pool, 2, + sizeof(svn_client_conflict_option_t *)); + + /* Add postpone option. */ + add_resolution_option(*options, conflict, + svn_client_conflict_option_postpone, + _("Postpone"), + _("skip this conflict and leave it unresolved"), + resolve_postpone); + + /* Add an option which marks the conflict resolved. */ + SVN_ERR(configure_option_accept_current_wc_state(conflict, *options)); + + /* Configure options which offer automatic resolution. */ + SVN_ERR(configure_option_update_move_destination(conflict, *options)); + SVN_ERR(configure_option_update_raise_moved_away_children(conflict, + *options)); + SVN_ERR(configure_option_incoming_add_ignore(conflict, ctx, *options, + scratch_pool)); + SVN_ERR(configure_option_incoming_added_file_text_merge(conflict, ctx, + *options, + scratch_pool)); + SVN_ERR(configure_option_incoming_added_file_replace_and_merge(conflict, + ctx, + *options, + scratch_pool)); + SVN_ERR(configure_option_incoming_added_dir_merge(conflict, ctx, + *options, + scratch_pool)); + SVN_ERR(configure_option_incoming_added_dir_replace(conflict, ctx, + *options, + scratch_pool)); + SVN_ERR(configure_option_incoming_added_dir_replace_and_merge(conflict, + ctx, + *options, + scratch_pool)); + SVN_ERR(configure_option_incoming_delete_ignore(conflict, ctx, *options, + scratch_pool)); + SVN_ERR(configure_option_incoming_delete_accept(conflict, ctx, *options, + scratch_pool)); + SVN_ERR(configure_option_incoming_move_file_merge(conflict, ctx, *options, + scratch_pool)); + SVN_ERR(configure_option_incoming_dir_merge(conflict, ctx, *options, + scratch_pool)); + SVN_ERR(configure_option_local_move_file_merge(conflict, ctx, *options, + scratch_pool)); + + return SVN_NO_ERROR; +} + +/* Swallow authz failures and return SVN_NO_ERROR in that case. + * Otherwise, return ERR unchanged. */ +static svn_error_t * +ignore_authz_failures(svn_error_t *err) +{ + if (err && ( svn_error_find_cause(err, SVN_ERR_AUTHZ_UNREADABLE) + || svn_error_find_cause(err, SVN_ERR_RA_NOT_AUTHORIZED) + || svn_error_find_cause(err, SVN_ERR_RA_DAV_FORBIDDEN))) + { + svn_error_clear(err); + err = SVN_NO_ERROR; + } + + return err; +} + +svn_error_t * +svn_client_conflict_tree_get_details(svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + SVN_ERR(assert_tree_conflict(conflict, scratch_pool)); + + if (ctx->notify_func2) + { + svn_wc_notify_t *notify; + + notify = svn_wc_create_notify( + svn_client_conflict_get_local_abspath(conflict), + svn_wc_notify_begin_search_tree_conflict_details, + scratch_pool), + ctx->notify_func2(ctx->notify_baton2, notify, + scratch_pool); + } + + /* Collecting conflict details may fail due to insufficient access rights. + * This is not a failure but simply restricts our future options. */ + if (conflict->tree_conflict_get_incoming_details_func) + SVN_ERR(ignore_authz_failures( + conflict->tree_conflict_get_incoming_details_func(conflict, ctx, + scratch_pool))); + + + if (conflict->tree_conflict_get_local_details_func) + SVN_ERR(ignore_authz_failures( + conflict->tree_conflict_get_local_details_func(conflict, ctx, + scratch_pool))); + + if (ctx->notify_func2) + { + svn_wc_notify_t *notify; + + notify = svn_wc_create_notify( + svn_client_conflict_get_local_abspath(conflict), + svn_wc_notify_end_search_tree_conflict_details, + scratch_pool), + ctx->notify_func2(ctx->notify_baton2, notify, + scratch_pool); + } + + return SVN_NO_ERROR; +} + +svn_client_conflict_option_id_t +svn_client_conflict_option_get_id(svn_client_conflict_option_t *option) +{ + return option->id; +} + +const char * +svn_client_conflict_option_get_label(svn_client_conflict_option_t *option, + apr_pool_t *result_pool) +{ + return apr_pstrdup(result_pool, option->label); +} + +const char * +svn_client_conflict_option_get_description(svn_client_conflict_option_t *option, + apr_pool_t *result_pool) +{ + return apr_pstrdup(result_pool, option->description); +} + +svn_client_conflict_option_id_t +svn_client_conflict_get_recommended_option_id(svn_client_conflict_t *conflict) +{ + return conflict->recommended_option_id; +} + +svn_error_t * +svn_client_conflict_text_resolve(svn_client_conflict_t *conflict, + svn_client_conflict_option_t *option, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + SVN_ERR(assert_text_conflict(conflict, scratch_pool)); + SVN_ERR(option->do_resolve_func(option, conflict, ctx, scratch_pool)); + + return SVN_NO_ERROR; +} + +svn_client_conflict_option_t * +svn_client_conflict_option_find_by_id(apr_array_header_t *options, + svn_client_conflict_option_id_t option_id) +{ + int i; + + for (i = 0; i < options->nelts; i++) + { + svn_client_conflict_option_t *this_option; + svn_client_conflict_option_id_t this_option_id; + + this_option = APR_ARRAY_IDX(options, i, svn_client_conflict_option_t *); + this_option_id = svn_client_conflict_option_get_id(this_option); + + if (this_option_id == option_id) + return this_option; + } + + return NULL; +} + +svn_error_t * +svn_client_conflict_text_resolve_by_id( + svn_client_conflict_t *conflict, + svn_client_conflict_option_id_t option_id, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + apr_array_header_t *resolution_options; + svn_client_conflict_option_t *option; + + SVN_ERR(svn_client_conflict_text_get_resolution_options( + &resolution_options, conflict, ctx, + scratch_pool, scratch_pool)); + option = svn_client_conflict_option_find_by_id(resolution_options, + option_id); + if (option == NULL) + return svn_error_createf(SVN_ERR_CLIENT_CONFLICT_OPTION_NOT_APPLICABLE, + NULL, + _("Inapplicable conflict resolution option " + "given for conflicted path '%s'"), + svn_dirent_local_style(conflict->local_abspath, + scratch_pool)); + + SVN_ERR(svn_client_conflict_text_resolve(conflict, option, ctx, scratch_pool)); + + return SVN_NO_ERROR; +} + +svn_client_conflict_option_id_t +svn_client_conflict_text_get_resolution(svn_client_conflict_t *conflict) +{ + return conflict->resolution_text; +} + +svn_error_t * +svn_client_conflict_prop_resolve(svn_client_conflict_t *conflict, + const char *propname, + svn_client_conflict_option_t *option, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + SVN_ERR(assert_prop_conflict(conflict, scratch_pool)); + option->type_data.prop.propname = propname; + SVN_ERR(option->do_resolve_func(option, conflict, ctx, scratch_pool)); + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_conflict_prop_resolve_by_id( + svn_client_conflict_t *conflict, + const char *propname, + svn_client_conflict_option_id_t option_id, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + apr_array_header_t *resolution_options; + svn_client_conflict_option_t *option; + + SVN_ERR(svn_client_conflict_prop_get_resolution_options( + &resolution_options, conflict, ctx, + scratch_pool, scratch_pool)); + option = svn_client_conflict_option_find_by_id(resolution_options, + option_id); + if (option == NULL) + return svn_error_createf(SVN_ERR_CLIENT_CONFLICT_OPTION_NOT_APPLICABLE, + NULL, + _("Inapplicable conflict resolution option " + "given for conflicted path '%s'"), + svn_dirent_local_style(conflict->local_abspath, + scratch_pool)); + SVN_ERR(svn_client_conflict_prop_resolve(conflict, propname, option, ctx, + scratch_pool)); + + return SVN_NO_ERROR; +} + +svn_client_conflict_option_id_t +svn_client_conflict_prop_get_resolution(svn_client_conflict_t *conflict, + const char *propname) +{ + svn_client_conflict_option_t *option; + + option = svn_hash_gets(conflict->resolved_props, propname); + if (option == NULL) + return svn_client_conflict_option_unspecified; + + return svn_client_conflict_option_get_id(option); +} + +svn_error_t * +svn_client_conflict_tree_resolve(svn_client_conflict_t *conflict, + svn_client_conflict_option_t *option, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + SVN_ERR(assert_tree_conflict(conflict, scratch_pool)); + SVN_ERR(option->do_resolve_func(option, conflict, ctx, scratch_pool)); + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_conflict_tree_resolve_by_id( + svn_client_conflict_t *conflict, + svn_client_conflict_option_id_t option_id, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + apr_array_header_t *resolution_options; + svn_client_conflict_option_t *option; + + SVN_ERR(svn_client_conflict_tree_get_resolution_options( + &resolution_options, conflict, ctx, + scratch_pool, scratch_pool)); + option = svn_client_conflict_option_find_by_id(resolution_options, + option_id); + if (option == NULL) + return svn_error_createf(SVN_ERR_CLIENT_CONFLICT_OPTION_NOT_APPLICABLE, + NULL, + _("Inapplicable conflict resolution option " + "given for conflicted path '%s'"), + svn_dirent_local_style(conflict->local_abspath, + scratch_pool)); + SVN_ERR(svn_client_conflict_tree_resolve(conflict, option, ctx, scratch_pool)); + + return SVN_NO_ERROR; +} + +svn_client_conflict_option_id_t +svn_client_conflict_tree_get_resolution(svn_client_conflict_t *conflict) +{ + return conflict->resolution_tree; +} + +/* Return the legacy conflict descriptor which is wrapped by CONFLICT. */ +static const svn_wc_conflict_description2_t * +get_conflict_desc2_t(svn_client_conflict_t *conflict) +{ + if (conflict->legacy_text_conflict) + return conflict->legacy_text_conflict; + + if (conflict->legacy_tree_conflict) + return conflict->legacy_tree_conflict; + + if (conflict->prop_conflicts && conflict->legacy_prop_conflict_propname) + return svn_hash_gets(conflict->prop_conflicts, + conflict->legacy_prop_conflict_propname); + + return NULL; +} + +svn_error_t * +svn_client_conflict_get_conflicted(svn_boolean_t *text_conflicted, + apr_array_header_t **props_conflicted, + svn_boolean_t *tree_conflicted, + svn_client_conflict_t *conflict, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + if (text_conflicted) + *text_conflicted = (conflict->legacy_text_conflict != NULL); + + if (props_conflicted) + { + if (conflict->prop_conflicts) + SVN_ERR(svn_hash_keys(props_conflicted, conflict->prop_conflicts, + result_pool)); + else + *props_conflicted = apr_array_make(result_pool, 0, + sizeof(const char*)); + } + + if (tree_conflicted) + *tree_conflicted = (conflict->legacy_tree_conflict != NULL); + + return SVN_NO_ERROR; +} + +const char * +svn_client_conflict_get_local_abspath(svn_client_conflict_t *conflict) +{ + return conflict->local_abspath; +} + +svn_wc_operation_t +svn_client_conflict_get_operation(svn_client_conflict_t *conflict) +{ + return get_conflict_desc2_t(conflict)->operation; +} + +svn_wc_conflict_action_t +svn_client_conflict_get_incoming_change(svn_client_conflict_t *conflict) +{ + return get_conflict_desc2_t(conflict)->action; +} + +svn_wc_conflict_reason_t +svn_client_conflict_get_local_change(svn_client_conflict_t *conflict) +{ + return get_conflict_desc2_t(conflict)->reason; +} + +svn_error_t * +svn_client_conflict_get_repos_info(const char **repos_root_url, + const char **repos_uuid, + svn_client_conflict_t *conflict, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + if (repos_root_url) + { + if (get_conflict_desc2_t(conflict)->src_left_version) + *repos_root_url = + get_conflict_desc2_t(conflict)->src_left_version->repos_url; + else if (get_conflict_desc2_t(conflict)->src_right_version) + *repos_root_url = + get_conflict_desc2_t(conflict)->src_right_version->repos_url; + else + *repos_root_url = NULL; + } + + if (repos_uuid) + { + if (get_conflict_desc2_t(conflict)->src_left_version) + *repos_uuid = + get_conflict_desc2_t(conflict)->src_left_version->repos_uuid; + else if (get_conflict_desc2_t(conflict)->src_right_version) + *repos_uuid = + get_conflict_desc2_t(conflict)->src_right_version->repos_uuid; + else + *repos_uuid = NULL; + } + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_conflict_get_incoming_old_repos_location( + const char **incoming_old_repos_relpath, + svn_revnum_t *incoming_old_pegrev, + svn_node_kind_t *incoming_old_node_kind, + svn_client_conflict_t *conflict, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + if (incoming_old_repos_relpath) + { + if (get_conflict_desc2_t(conflict)->src_left_version) + *incoming_old_repos_relpath = + get_conflict_desc2_t(conflict)->src_left_version->path_in_repos; + else + *incoming_old_repos_relpath = NULL; + } + + if (incoming_old_pegrev) + { + if (get_conflict_desc2_t(conflict)->src_left_version) + *incoming_old_pegrev = + get_conflict_desc2_t(conflict)->src_left_version->peg_rev; + else + *incoming_old_pegrev = SVN_INVALID_REVNUM; + } + + if (incoming_old_node_kind) + { + if (get_conflict_desc2_t(conflict)->src_left_version) + *incoming_old_node_kind = + get_conflict_desc2_t(conflict)->src_left_version->node_kind; + else + *incoming_old_node_kind = svn_node_none; + } + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_conflict_get_incoming_new_repos_location( + const char **incoming_new_repos_relpath, + svn_revnum_t *incoming_new_pegrev, + svn_node_kind_t *incoming_new_node_kind, + svn_client_conflict_t *conflict, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + if (incoming_new_repos_relpath) + { + if (get_conflict_desc2_t(conflict)->src_right_version) + *incoming_new_repos_relpath = + get_conflict_desc2_t(conflict)->src_right_version->path_in_repos; + else + *incoming_new_repos_relpath = NULL; + } + + if (incoming_new_pegrev) + { + if (get_conflict_desc2_t(conflict)->src_right_version) + *incoming_new_pegrev = + get_conflict_desc2_t(conflict)->src_right_version->peg_rev; + else + *incoming_new_pegrev = SVN_INVALID_REVNUM; + } + + if (incoming_new_node_kind) + { + if (get_conflict_desc2_t(conflict)->src_right_version) + *incoming_new_node_kind = + get_conflict_desc2_t(conflict)->src_right_version->node_kind; + else + *incoming_new_node_kind = svn_node_none; + } + + return SVN_NO_ERROR; +} + +svn_node_kind_t +svn_client_conflict_tree_get_victim_node_kind(svn_client_conflict_t *conflict) +{ + SVN_ERR_ASSERT_NO_RETURN(assert_tree_conflict(conflict, conflict->pool) + == SVN_NO_ERROR); + + return get_conflict_desc2_t(conflict)->node_kind; +} + +svn_error_t * +svn_client_conflict_prop_get_propvals(const svn_string_t **base_propval, + const svn_string_t **working_propval, + const svn_string_t **incoming_old_propval, + const svn_string_t **incoming_new_propval, + svn_client_conflict_t *conflict, + const char *propname, + apr_pool_t *result_pool) +{ + const svn_wc_conflict_description2_t *desc; + + SVN_ERR(assert_prop_conflict(conflict, conflict->pool)); + + desc = svn_hash_gets(conflict->prop_conflicts, propname); + if (desc == NULL) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Property '%s' is not in conflict."), propname); + + if (base_propval) + *base_propval = + svn_string_dup(desc->prop_value_base, result_pool); + + if (working_propval) + *working_propval = + svn_string_dup(desc->prop_value_working, result_pool); + + if (incoming_old_propval) + *incoming_old_propval = + svn_string_dup(desc->prop_value_incoming_old, result_pool); + + if (incoming_new_propval) + *incoming_new_propval = + svn_string_dup(desc->prop_value_incoming_new, result_pool); + + return SVN_NO_ERROR; +} + +const char * +svn_client_conflict_prop_get_reject_abspath(svn_client_conflict_t *conflict) +{ + SVN_ERR_ASSERT_NO_RETURN(assert_prop_conflict(conflict, conflict->pool) + == SVN_NO_ERROR); + + /* svn_wc_conflict_description2_t stores this path in 'their_abspath' */ + return get_conflict_desc2_t(conflict)->their_abspath; +} + +const char * +svn_client_conflict_text_get_mime_type(svn_client_conflict_t *conflict) +{ + SVN_ERR_ASSERT_NO_RETURN(assert_text_conflict(conflict, conflict->pool) + == SVN_NO_ERROR); + + return get_conflict_desc2_t(conflict)->mime_type; +} + +svn_error_t * +svn_client_conflict_text_get_contents(const char **base_abspath, + const char **working_abspath, + const char **incoming_old_abspath, + const char **incoming_new_abspath, + svn_client_conflict_t *conflict, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + SVN_ERR(assert_text_conflict(conflict, scratch_pool)); + + if (base_abspath) + { + if (svn_client_conflict_get_operation(conflict) == + svn_wc_operation_merge) + *base_abspath = NULL; /* ### WC base contents not available yet */ + else /* update/switch */ + *base_abspath = get_conflict_desc2_t(conflict)->base_abspath; + } + + if (working_abspath) + *working_abspath = get_conflict_desc2_t(conflict)->my_abspath; + + if (incoming_old_abspath) + *incoming_old_abspath = get_conflict_desc2_t(conflict)->base_abspath; + + if (incoming_new_abspath) + *incoming_new_abspath = get_conflict_desc2_t(conflict)->their_abspath; + + return SVN_NO_ERROR; +} + +/* Set up type-specific data for a new conflict object. */ +static svn_error_t * +conflict_type_specific_setup(svn_client_conflict_t *conflict, + apr_pool_t *scratch_pool) +{ + svn_boolean_t tree_conflicted; + svn_wc_conflict_action_t incoming_change; + svn_wc_conflict_reason_t local_change; + + /* For now, we only deal with tree conflicts here. */ + SVN_ERR(svn_client_conflict_get_conflicted(NULL, NULL, &tree_conflicted, + conflict, scratch_pool, + scratch_pool)); + if (!tree_conflicted) + return SVN_NO_ERROR; + + /* Set a default description function. */ + conflict->tree_conflict_get_incoming_description_func = + conflict_tree_get_incoming_description_generic; + conflict->tree_conflict_get_local_description_func = + conflict_tree_get_local_description_generic; + + incoming_change = svn_client_conflict_get_incoming_change(conflict); + local_change = svn_client_conflict_get_local_change(conflict); + + /* Set type-specific description and details functions. */ + if (incoming_change == svn_wc_conflict_action_delete || + incoming_change == svn_wc_conflict_action_replace) + { + conflict->tree_conflict_get_incoming_description_func = + conflict_tree_get_description_incoming_delete; + conflict->tree_conflict_get_incoming_details_func = + conflict_tree_get_details_incoming_delete; + } + else if (incoming_change == svn_wc_conflict_action_add) + { + conflict->tree_conflict_get_incoming_description_func = + conflict_tree_get_description_incoming_add; + conflict->tree_conflict_get_incoming_details_func = + conflict_tree_get_details_incoming_add; + } + else if (incoming_change == svn_wc_conflict_action_edit) + { + conflict->tree_conflict_get_incoming_description_func = + conflict_tree_get_description_incoming_edit; + conflict->tree_conflict_get_incoming_details_func = + conflict_tree_get_details_incoming_edit; + } + + if (local_change == svn_wc_conflict_reason_missing) + { + conflict->tree_conflict_get_local_description_func = + conflict_tree_get_description_local_missing; + conflict->tree_conflict_get_local_details_func = + conflict_tree_get_details_local_missing; + } + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_conflict_get(svn_client_conflict_t **conflict, + const char *local_abspath, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + const apr_array_header_t *descs; + int i; + + *conflict = apr_pcalloc(result_pool, sizeof(**conflict)); + + (*conflict)->local_abspath = apr_pstrdup(result_pool, local_abspath); + (*conflict)->resolution_text = svn_client_conflict_option_unspecified; + (*conflict)->resolution_tree = svn_client_conflict_option_unspecified; + (*conflict)->resolved_props = apr_hash_make(result_pool); + (*conflict)->recommended_option_id = svn_client_conflict_option_unspecified; + (*conflict)->pool = result_pool; + + /* Add all legacy conflict descriptors we can find. Eventually, this code + * path should stop relying on svn_wc_conflict_description2_t entirely. */ + SVN_ERR(svn_wc__read_conflict_descriptions2_t(&descs, ctx->wc_ctx, + local_abspath, + result_pool, scratch_pool)); + for (i = 0; i < descs->nelts; i++) + { + const svn_wc_conflict_description2_t *desc; + + desc = APR_ARRAY_IDX(descs, i, const svn_wc_conflict_description2_t *); + add_legacy_desc_to_conflict(desc, *conflict, result_pool); + } + + SVN_ERR(conflict_type_specific_setup(*conflict, scratch_pool)); + + return SVN_NO_ERROR; +} + +/* Baton for conflict_status_walker */ +struct conflict_status_walker_baton +{ + svn_client_conflict_walk_func_t conflict_walk_func; + void *conflict_walk_func_baton; + svn_client_ctx_t *ctx; + svn_wc_notify_func2_t notify_func; + void *notify_baton; + svn_boolean_t resolved_a_tree_conflict; + apr_hash_t *unresolved_tree_conflicts; +}; + +/* Implements svn_wc_notify_func2_t to collect new conflicts caused by + resolving a tree conflict. */ +static void +tree_conflict_collector(void *baton, + const svn_wc_notify_t *notify, + apr_pool_t *pool) +{ + struct conflict_status_walker_baton *cswb = baton; + + if (cswb->notify_func) + cswb->notify_func(cswb->notify_baton, notify, pool); + + if (cswb->unresolved_tree_conflicts + && (notify->action == svn_wc_notify_tree_conflict + || notify->prop_state == svn_wc_notify_state_conflicted + || notify->content_state == svn_wc_notify_state_conflicted)) + { + if (!svn_hash_gets(cswb->unresolved_tree_conflicts, notify->path)) + { + const char *tc_abspath; + apr_pool_t *hash_pool; + + hash_pool = apr_hash_pool_get(cswb->unresolved_tree_conflicts); + tc_abspath = apr_pstrdup(hash_pool, notify->path); + svn_hash_sets(cswb->unresolved_tree_conflicts, tc_abspath, ""); + } + } +} + +/* + * Record a tree conflict resolution failure due to error condition ERR + * in the RESOLVE_LATER hash table. If the hash table is not available + * (meaning the caller does not wish to retry resolution later), or if + * the error condition does not indicate circumstances where another + * existing tree conflict is blocking the resolution attempt, then + * return the error ERR itself. + */ +static svn_error_t * +handle_tree_conflict_resolution_failure(const char *local_abspath, + svn_error_t *err, + apr_hash_t *unresolved_tree_conflicts) +{ + const char *tc_abspath; + + if (!unresolved_tree_conflicts + || (err->apr_err != SVN_ERR_WC_OBSTRUCTED_UPDATE + && err->apr_err != SVN_ERR_WC_FOUND_CONFLICT)) + return svn_error_trace(err); /* Give up. Do not retry resolution later. */ + + svn_error_clear(err); + tc_abspath = apr_pstrdup(apr_hash_pool_get(unresolved_tree_conflicts), + local_abspath); + + svn_hash_sets(unresolved_tree_conflicts, tc_abspath, ""); + + return SVN_NO_ERROR; /* Caller may retry after resolving other conflicts. */ +} + +/* Implements svn_wc_status4_t to walk all conflicts to resolve. + */ +static svn_error_t * +conflict_status_walker(void *baton, + const char *local_abspath, + const svn_wc_status3_t *status, + apr_pool_t *scratch_pool) +{ + struct conflict_status_walker_baton *cswb = baton; + svn_client_conflict_t *conflict; + svn_error_t *err; + svn_boolean_t tree_conflicted; + + if (!status->conflicted) + return SVN_NO_ERROR; + + SVN_ERR(svn_client_conflict_get(&conflict, local_abspath, cswb->ctx, + scratch_pool, scratch_pool)); + SVN_ERR(svn_client_conflict_get_conflicted(NULL, NULL, &tree_conflicted, + conflict, scratch_pool, + scratch_pool)); + err = cswb->conflict_walk_func(cswb->conflict_walk_func_baton, + conflict, scratch_pool); + if (err) + { + if (tree_conflicted) + SVN_ERR(handle_tree_conflict_resolution_failure( + local_abspath, err, cswb->unresolved_tree_conflicts)); + + else + return svn_error_trace(err); + } + + if (tree_conflicted) + { + svn_client_conflict_option_id_t resolution; + + resolution = svn_client_conflict_tree_get_resolution(conflict); + if (resolution != svn_client_conflict_option_unspecified && + resolution != svn_client_conflict_option_postpone) + cswb->resolved_a_tree_conflict = TRUE; + } + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_conflict_walk(const char *local_abspath, + svn_depth_t depth, + svn_client_conflict_walk_func_t conflict_walk_func, + void *conflict_walk_func_baton, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + struct conflict_status_walker_baton cswb; + apr_pool_t *iterpool = NULL; + svn_error_t *err = SVN_NO_ERROR; + + if (depth == svn_depth_unknown) + depth = svn_depth_infinity; + + cswb.conflict_walk_func = conflict_walk_func; + cswb.conflict_walk_func_baton = conflict_walk_func_baton; + cswb.ctx = ctx; + cswb.resolved_a_tree_conflict = FALSE; + cswb.unresolved_tree_conflicts = apr_hash_make(scratch_pool); + + if (ctx->notify_func2) + ctx->notify_func2(ctx->notify_baton2, + svn_wc_create_notify( + local_abspath, + svn_wc_notify_conflict_resolver_starting, + scratch_pool), + scratch_pool); + + /* Swap in our notify_func wrapper. We must revert this before returning! */ + cswb.notify_func = ctx->notify_func2; + cswb.notify_baton = ctx->notify_baton2; + ctx->notify_func2 = tree_conflict_collector; + ctx->notify_baton2 = &cswb; + + err = svn_wc_walk_status(ctx->wc_ctx, + local_abspath, + depth, + FALSE /* get_all */, + FALSE /* no_ignore */, + TRUE /* ignore_text_mods */, + NULL /* ignore_patterns */, + conflict_status_walker, &cswb, + ctx->cancel_func, ctx->cancel_baton, + scratch_pool); + + /* If we got new tree conflicts (or delayed conflicts) during the initial + walk, we now walk them one by one as closure. */ + while (!err && cswb.unresolved_tree_conflicts && + apr_hash_count(cswb.unresolved_tree_conflicts)) + { + apr_hash_index_t *hi; + svn_wc_status3_t *status = NULL; + const char *tc_abspath = NULL; + + if (iterpool) + svn_pool_clear(iterpool); + else + iterpool = svn_pool_create(scratch_pool); + + hi = apr_hash_first(scratch_pool, cswb.unresolved_tree_conflicts); + cswb.unresolved_tree_conflicts = apr_hash_make(scratch_pool); + cswb.resolved_a_tree_conflict = FALSE; + + for (; hi && !err; hi = apr_hash_next(hi)) + { + svn_pool_clear(iterpool); + + tc_abspath = apr_hash_this_key(hi); + + if (ctx->cancel_func) + { + err = ctx->cancel_func(ctx->cancel_baton); + if (err) + break; + } + + err = svn_error_trace(svn_wc_status3(&status, ctx->wc_ctx, + tc_abspath, + iterpool, iterpool)); + if (err) + break; + + err = svn_error_trace(conflict_status_walker(&cswb, tc_abspath, + status, scratch_pool)); + if (err) + break; + } + + if (!err && !cswb.resolved_a_tree_conflict && tc_abspath && + apr_hash_count(cswb.unresolved_tree_conflicts)) + { + /* None of the remaining conflicts got resolved, without any error. + * Disable the 'unresolved_tree_conflicts' cache and try again. */ + cswb.unresolved_tree_conflicts = NULL; + + /* Run the most recent resolve operation again. + * We still have status and tc_abspath for that one. + * This should uncover the error which prevents resolution. */ + err = svn_error_trace(conflict_status_walker(&cswb, tc_abspath, + status, scratch_pool)); + SVN_ERR_ASSERT(err != NULL); + + err = svn_error_createf( + SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, err, + _("Unable to resolve pending conflict on '%s'"), + svn_dirent_local_style(tc_abspath, scratch_pool)); + break; + } + } + + if (iterpool) + svn_pool_destroy(iterpool); + + ctx->notify_func2 = cswb.notify_func; + ctx->notify_baton2 = cswb.notify_baton; + + if (!err && ctx->notify_func2) + ctx->notify_func2(ctx->notify_baton2, + svn_wc_create_notify(local_abspath, + svn_wc_notify_conflict_resolver_done, + scratch_pool), + scratch_pool); + + return svn_error_trace(err); +} diff --git a/subversion/libsvn_client/copy.c b/subversion/libsvn_client/copy.c index af6a75b83698..b2e3a44d797b 100644 --- a/subversion/libsvn_client/copy.c +++ b/subversion/libsvn_client/copy.c @@ -1711,13 +1711,9 @@ repos_to_repos_copy(const apr_array_header_t *copy_pairs, SVN_ERR(svn_ra_check_path(ra_session, dst_rel, SVN_INVALID_REVNUM, &dst_kind, pool)); if (dst_kind != svn_node_none) - { - const char *path = svn_uri_skip_ancestor(repos_root, - pair->dst_abspath_or_url, - pool); - return svn_error_createf(SVN_ERR_FS_ALREADY_EXISTS, NULL, - _("Path '/%s' already exists"), path); - } + return svn_error_createf(SVN_ERR_FS_ALREADY_EXISTS, NULL, + _("Path '%s' already exists"), + pair->dst_abspath_or_url); /* More info for our INFO structure. */ info->src_path = src_rel; /* May be NULL, if outside RA session scope */ @@ -2433,10 +2429,10 @@ repos_to_wc_copy_single(svn_boolean_t *timestamp_sleep, *timestamp_sleep = TRUE; - /* Schedule dst_path for addition in parent, with copy history. - Don't send any notification here. - Then remove the temporary checkout's .svn dir in preparation for - moving the rest of it into the final destination. */ + /* Schedule dst_path for addition in parent, with copy history. + Don't send any notification here. + Then remove the temporary checkout's .svn dir in preparation for + moving the rest of it into the final destination. */ SVN_ERR(svn_wc_copy3(ctx->wc_ctx, tmp_abspath, dst_abspath, TRUE /* metadata_only */, ctx->cancel_func, ctx->cancel_baton, @@ -2451,7 +2447,7 @@ repos_to_wc_copy_single(svn_boolean_t *timestamp_sleep, pool)); /* Move the temporary disk tree into place. */ - SVN_ERR(svn_io_file_rename(tmp_abspath, dst_abspath, pool)); + SVN_ERR(svn_io_file_rename2(tmp_abspath, dst_abspath, FALSE, pool)); } else { @@ -2580,7 +2576,7 @@ repos_to_wc_copy_single(svn_boolean_t *timestamp_sleep, static svn_error_t * repos_to_wc_copy_locked(svn_boolean_t *timestamp_sleep, const apr_array_header_t *copy_pairs, - const char *top_dst_path, + const char *top_dst_abspath, svn_boolean_t ignore_externals, svn_boolean_t pin_externals, const apr_hash_t *externals_to_pin, @@ -2600,39 +2596,25 @@ repos_to_wc_copy_locked(svn_boolean_t *timestamp_sleep, /* Decide whether the two repositories are the same or not. */ { - svn_error_t *src_err, *dst_err; - const char *parent; const char *parent_abspath; const char *src_uuid, *dst_uuid; /* Get the repository uuid of SRC_URL */ - src_err = svn_ra_get_uuid2(ra_session, &src_uuid, iterpool); - if (src_err && src_err->apr_err != SVN_ERR_RA_NO_REPOS_UUID) - return svn_error_trace(src_err); + SVN_ERR(svn_ra_get_uuid2(ra_session, &src_uuid, iterpool)); /* Get repository uuid of dst's parent directory, since dst may not exist. ### TODO: we should probably walk up the wc here, in case the parent dir has an imaginary URL. */ if (copy_pairs->nelts == 1) - parent = svn_dirent_dirname(top_dst_path, scratch_pool); + parent_abspath = svn_dirent_dirname(top_dst_abspath, scratch_pool); else - parent = top_dst_path; + parent_abspath = top_dst_abspath; - SVN_ERR(svn_dirent_get_absolute(&parent_abspath, parent, scratch_pool)); - dst_err = svn_client_get_repos_root(NULL /* root_url */, &dst_uuid, - parent_abspath, ctx, - iterpool, iterpool); - if (dst_err && dst_err->apr_err != SVN_ERR_RA_NO_REPOS_UUID) - return dst_err; - - /* If either of the UUIDs are nonexistent, then at least one of - the repositories must be very old. Rather than punish the - user, just assume the repositories are different, so no - copy-history is attempted. */ - if (src_err || dst_err || (! src_uuid) || (! dst_uuid)) - same_repositories = FALSE; - else - same_repositories = (strcmp(src_uuid, dst_uuid) == 0); + SVN_ERR(svn_client_get_repos_root(NULL /* root_url */, &dst_uuid, + parent_abspath, ctx, + iterpool, iterpool)); + /* ### Also check repos_root_url? */ + same_repositories = (strcmp(src_uuid, dst_uuid) == 0); } /* Perform the move for each of the copy_pairs. */ @@ -2668,7 +2650,7 @@ repos_to_wc_copy(svn_boolean_t *timestamp_sleep, apr_pool_t *pool) { svn_ra_session_t *ra_session; - const char *top_src_url, *top_dst_path; + const char *top_src_url, *top_dst_abspath; apr_pool_t *iterpool = svn_pool_create(pool); const char *lock_abspath; int i; @@ -2693,13 +2675,13 @@ repos_to_wc_copy(svn_boolean_t *timestamp_sleep, pair->src_abspath_or_url = apr_pstrdup(pool, src); } - SVN_ERR(get_copy_pair_ancestors(copy_pairs, &top_src_url, &top_dst_path, + SVN_ERR(get_copy_pair_ancestors(copy_pairs, &top_src_url, &top_dst_abspath, NULL, pool)); - lock_abspath = top_dst_path; + lock_abspath = top_dst_abspath; if (copy_pairs->nelts == 1) { top_src_url = svn_uri_dirname(top_src_url, pool); - lock_abspath = svn_dirent_dirname(top_dst_path, pool); + lock_abspath = svn_dirent_dirname(top_dst_abspath, pool); } /* Open a repository session to the longest common src ancestor. We do not @@ -2771,7 +2753,7 @@ repos_to_wc_copy(svn_boolean_t *timestamp_sleep, SVN_WC__CALL_WITH_WRITE_LOCK( repos_to_wc_copy_locked(timestamp_sleep, - copy_pairs, top_dst_path, ignore_externals, + copy_pairs, top_dst_abspath, ignore_externals, pin_externals, externals_to_pin, ra_session, ctx, pool), ctx->wc_ctx, lock_abspath, FALSE, pool); diff --git a/subversion/libsvn_client/deprecated.c b/subversion/libsvn_client/deprecated.c index b1760a4e3738..dc20b2772286 100644 --- a/subversion/libsvn_client/deprecated.c +++ b/subversion/libsvn_client/deprecated.c @@ -1330,6 +1330,26 @@ svn_client_export(svn_revnum_t *result_rev, /*** From list.c ***/ +svn_error_t * +svn_client_list3(const char *path_or_url, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *revision, + svn_depth_t depth, + apr_uint32_t dirent_fields, + svn_boolean_t fetch_locks, + svn_boolean_t include_externals, + svn_client_list_func2_t list_func, + void *baton, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_error_trace(svn_client_list4(path_or_url, peg_revision, + revision, NULL, depth, + dirent_fields, fetch_locks, + include_externals, + list_func, baton, ctx, pool)); +} + /* Baton for use with wrap_list_func */ struct list_func_wrapper_baton { void *list_func1_baton; diff --git a/subversion/libsvn_client/diff.c b/subversion/libsvn_client/diff.c index 4817ffdf1016..ba6e91eb2e7b 100644 --- a/subversion/libsvn_client/diff.c +++ b/subversion/libsvn_client/diff.c @@ -230,113 +230,158 @@ adjust_paths_for_diff_labels(const char **index_path, /* Generate a label for the diff output for file PATH at revision REVNUM. If REVNUM is invalid then it is assumed to be the current working copy. Assumes the paths are already in the desired style (local - vs internal). Allocate the label in POOL. */ + vs internal). Allocate the label in RESULT-POOL. */ static const char * diff_label(const char *path, svn_revnum_t revnum, - apr_pool_t *pool) + apr_pool_t *result_pool) { const char *label; if (revnum >= 0) - label = apr_psprintf(pool, _("%s\t(revision %ld)"), path, revnum); + label = apr_psprintf(result_pool, _("%s\t(revision %ld)"), path, revnum); else if (revnum == DIFF_REVNUM_NONEXISTENT) - label = apr_psprintf(pool, _("%s\t(nonexistent)"), path); + label = apr_psprintf(result_pool, _("%s\t(nonexistent)"), path); else /* SVN_INVALID_REVNUM */ - label = apr_psprintf(pool, _("%s\t(working copy)"), path); + label = apr_psprintf(result_pool, _("%s\t(working copy)"), path); return label; } +/* Standard modes produced in git style diffs */ +static const int exec_mode = 0755; +static const int noexec_mode = 0644; +static const int kind_file_mode = 0100000; +/*static const kind_dir_mode = 0040000;*/ +static const int kind_symlink_mode = 0120000; + /* Print a git diff header for an addition within a diff between PATH1 and - * PATH2 to the stream OS using HEADER_ENCODING. - * All allocations are done in RESULT_POOL. */ + * PATH2 to the stream OS using HEADER_ENCODING. */ static svn_error_t * print_git_diff_header_added(svn_stream_t *os, const char *header_encoding, const char *path1, const char *path2, - apr_pool_t *result_pool) + svn_boolean_t exec_bit, + svn_boolean_t symlink_bit, + apr_pool_t *scratch_pool) { - SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool, + int new_mode = (exec_bit ? exec_mode : noexec_mode) + | (symlink_bit ? kind_symlink_mode : kind_file_mode); + + SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool, "diff --git a/%s b/%s%s", path1, path2, APR_EOL_STR)); - SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool, - "new file mode 10644" APR_EOL_STR)); + SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool, + "new file mode %06o" APR_EOL_STR, + new_mode)); return SVN_NO_ERROR; } /* Print a git diff header for a deletion within a diff between PATH1 and - * PATH2 to the stream OS using HEADER_ENCODING. - * All allocations are done in RESULT_POOL. */ + * PATH2 to the stream OS using HEADER_ENCODING. */ static svn_error_t * print_git_diff_header_deleted(svn_stream_t *os, const char *header_encoding, const char *path1, const char *path2, - apr_pool_t *result_pool) + svn_boolean_t exec_bit, + svn_boolean_t symlink_bit, + apr_pool_t *scratch_pool) { - SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool, + int old_mode = (exec_bit ? exec_mode : noexec_mode) + | (symlink_bit ? kind_symlink_mode : kind_file_mode); + SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool, "diff --git a/%s b/%s%s", path1, path2, APR_EOL_STR)); - SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool, - "deleted file mode 10644" - APR_EOL_STR)); + SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool, + "deleted file mode %06o" APR_EOL_STR, + old_mode)); return SVN_NO_ERROR; } /* Print a git diff header for a copy from COPYFROM_PATH to PATH to the stream - * OS using HEADER_ENCODING. All allocations are done in RESULT_POOL. */ + * OS using HEADER_ENCODING. */ static svn_error_t * print_git_diff_header_copied(svn_stream_t *os, const char *header_encoding, const char *copyfrom_path, svn_revnum_t copyfrom_rev, const char *path, - apr_pool_t *result_pool) + apr_pool_t *scratch_pool) { - SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool, + SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool, "diff --git a/%s b/%s%s", copyfrom_path, path, APR_EOL_STR)); if (copyfrom_rev != SVN_INVALID_REVNUM) - SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool, + SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool, "copy from %s@%ld%s", copyfrom_path, copyfrom_rev, APR_EOL_STR)); else - SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool, + SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool, "copy from %s%s", copyfrom_path, APR_EOL_STR)); - SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool, + SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool, "copy to %s%s", path, APR_EOL_STR)); return SVN_NO_ERROR; } /* Print a git diff header for a rename from COPYFROM_PATH to PATH to the - * stream OS using HEADER_ENCODING. All allocations are done in RESULT_POOL. */ + * stream OS using HEADER_ENCODING. */ static svn_error_t * print_git_diff_header_renamed(svn_stream_t *os, const char *header_encoding, const char *copyfrom_path, const char *path, - apr_pool_t *result_pool) + apr_pool_t *scratch_pool) { - SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool, + SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool, "diff --git a/%s b/%s%s", copyfrom_path, path, APR_EOL_STR)); - SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool, + SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool, "rename from %s%s", copyfrom_path, APR_EOL_STR)); - SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool, + SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool, "rename to %s%s", path, APR_EOL_STR)); return SVN_NO_ERROR; } /* Print a git diff header for a modification within a diff between PATH1 and - * PATH2 to the stream OS using HEADER_ENCODING. - * All allocations are done in RESULT_POOL. */ + * PATH2 to the stream OS using HEADER_ENCODING. */ static svn_error_t * print_git_diff_header_modified(svn_stream_t *os, const char *header_encoding, const char *path1, const char *path2, - apr_pool_t *result_pool) + apr_pool_t *scratch_pool) { - SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool, + SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool, "diff --git a/%s b/%s%s", path1, path2, APR_EOL_STR)); return SVN_NO_ERROR; } +/* Helper function for print_git_diff_header */ +static svn_error_t * +maybe_print_mode_change(svn_stream_t *os, + const char *header_encoding, + svn_boolean_t exec_bit1, + svn_boolean_t exec_bit2, + svn_boolean_t symlink_bit1, + svn_boolean_t symlink_bit2, + const char *git_index_shas, + apr_pool_t *scratch_pool) +{ + int old_mode = (exec_bit1 ? exec_mode : noexec_mode) + | (symlink_bit1 ? kind_symlink_mode : kind_file_mode); + int new_mode = (exec_bit2 ? exec_mode : noexec_mode) + | (symlink_bit2 ? kind_symlink_mode : kind_file_mode); + if (old_mode == new_mode) + { + if (git_index_shas) + SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool, + "index %s %06o" APR_EOL_STR, + git_index_shas, old_mode)); + return SVN_NO_ERROR; + } + + SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool, + "old mode %06o" APR_EOL_STR, old_mode)); + SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool, + "new mode %06o" APR_EOL_STR, new_mode)); + return SVN_NO_ERROR; +} + /* Print a git diff header showing the OPERATION to the stream OS using * HEADER_ENCODING. Return suitable diff labels for the git diff in *LABEL1 * and *LABEL2. REPOS_RELPATH1 and REPOS_RELPATH2 are relative to reposroot. @@ -354,17 +399,31 @@ print_git_diff_header(svn_stream_t *os, svn_revnum_t rev2, const char *copyfrom_path, svn_revnum_t copyfrom_rev, + apr_hash_t *left_props, + apr_hash_t *right_props, + const char *git_index_shas, const char *header_encoding, apr_pool_t *scratch_pool) { + svn_boolean_t exec_bit1 = (svn_prop_get_value(left_props, + SVN_PROP_EXECUTABLE) != NULL); + svn_boolean_t exec_bit2 = (svn_prop_get_value(right_props, + SVN_PROP_EXECUTABLE) != NULL); + svn_boolean_t symlink_bit1 = (svn_prop_get_value(left_props, + SVN_PROP_SPECIAL) != NULL); + svn_boolean_t symlink_bit2 = (svn_prop_get_value(right_props, + SVN_PROP_SPECIAL) != NULL); + if (operation == svn_diff_op_deleted) { SVN_ERR(print_git_diff_header_deleted(os, header_encoding, repos_relpath1, repos_relpath2, + exec_bit1, symlink_bit1, scratch_pool)); *label1 = diff_label(apr_psprintf(scratch_pool, "a/%s", repos_relpath1), rev1, scratch_pool); - *label2 = diff_label("/dev/null", rev2, scratch_pool); + *label2 = diff_label(apr_psprintf(scratch_pool, "b/%s", repos_relpath2), + rev2, scratch_pool); } else if (operation == svn_diff_op_copied) @@ -377,13 +436,20 @@ print_git_diff_header(svn_stream_t *os, rev1, scratch_pool); *label2 = diff_label(apr_psprintf(scratch_pool, "b/%s", repos_relpath2), rev2, scratch_pool); + SVN_ERR(maybe_print_mode_change(os, header_encoding, + exec_bit1, exec_bit2, + symlink_bit1, symlink_bit2, + git_index_shas, + scratch_pool)); } else if (operation == svn_diff_op_added) { SVN_ERR(print_git_diff_header_added(os, header_encoding, repos_relpath1, repos_relpath2, + exec_bit2, symlink_bit2, scratch_pool)); - *label1 = diff_label("/dev/null", rev1, scratch_pool); + *label1 = diff_label(apr_psprintf(scratch_pool, "a/%s", repos_relpath1), + rev1, scratch_pool); *label2 = diff_label(apr_psprintf(scratch_pool, "b/%s", repos_relpath2), rev2, scratch_pool); } @@ -396,6 +462,11 @@ print_git_diff_header(svn_stream_t *os, rev1, scratch_pool); *label2 = diff_label(apr_psprintf(scratch_pool, "b/%s", repos_relpath2), rev2, scratch_pool); + SVN_ERR(maybe_print_mode_change(os, header_encoding, + exec_bit1, exec_bit2, + symlink_bit1, symlink_bit2, + git_index_shas, + scratch_pool)); } else if (operation == svn_diff_op_moved) { @@ -406,6 +477,11 @@ print_git_diff_header(svn_stream_t *os, rev1, scratch_pool); *label2 = diff_label(apr_psprintf(scratch_pool, "b/%s", repos_relpath2), rev2, scratch_pool); + SVN_ERR(maybe_print_mode_change(os, header_encoding, + exec_bit1, exec_bit2, + symlink_bit1, symlink_bit2, + git_index_shas, + scratch_pool)); } return SVN_NO_ERROR; @@ -425,7 +501,8 @@ print_git_diff_header(svn_stream_t *os, ANCHOR is the local path where the diff editor is anchored. */ static svn_error_t * display_prop_diffs(const apr_array_header_t *propchanges, - apr_hash_t *original_props, + apr_hash_t *left_props, + apr_hash_t *right_props, const char *diff_relpath, const char *anchor, const char *orig_path1, @@ -487,6 +564,9 @@ display_prop_diffs(const apr_array_header_t *propchanges, repos_relpath1, repos_relpath2, rev1, rev2, NULL, SVN_INVALID_REVNUM, + left_props, + right_props, + NULL, encoding, scratch_pool)); /* --- label1 @@ -496,18 +576,18 @@ display_prop_diffs(const apr_array_header_t *propchanges, } SVN_ERR(svn_stream_printf_from_utf8(outstream, encoding, scratch_pool, - _("%sProperty changes on: %s%s"), + APR_EOL_STR + "Property changes on: %s" APR_EOL_STR, use_git_diff_format ? repos_relpath1 - : index_path, - APR_EOL_STR)); + : index_path)); SVN_ERR(svn_stream_printf_from_utf8(outstream, encoding, scratch_pool, SVN_DIFF__UNDER_STRING APR_EOL_STR)); SVN_ERR(svn_diff__display_prop_diffs( - outstream, encoding, propchanges, original_props, + outstream, encoding, propchanges, left_props, TRUE /* pretty_print_mergeinfo */, -1 /* context_size */, cancel_func, cancel_baton, scratch_pool)); @@ -606,7 +686,8 @@ diff_props_changed(const char *diff_relpath, svn_revnum_t rev1, svn_revnum_t rev2, const apr_array_header_t *propchanges, - apr_hash_t *original_props, + apr_hash_t *left_props, + apr_hash_t *right_props, svn_boolean_t show_diff_header, diff_writer_info_t *dwi, apr_pool_t *scratch_pool) @@ -625,7 +706,7 @@ diff_props_changed(const char *diff_relpath, /* We're using the revnums from the dwi since there's * no revision argument to the svn_wc_diff_callback_t * dir_props_changed(). */ - SVN_ERR(display_prop_diffs(props, original_props, + SVN_ERR(display_prop_diffs(props, left_props, right_props, diff_relpath, dwi->ddi.anchor, dwi->ddi.orig_path_1, @@ -647,6 +728,62 @@ diff_props_changed(const char *diff_relpath, return SVN_NO_ERROR; } +/* Given a file ORIG_TMPFILE, return a path to a temporary file that lives at + * least as long as RESULT_POOL, containing the git-like represention of + * ORIG_TMPFILE */ +static svn_error_t * +transform_link_to_git(const char **new_tmpfile, + const char **git_sha1, + const char *orig_tmpfile, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + apr_file_t *orig; + apr_file_t *gitlike; + svn_stringbuf_t *line; + + *git_sha1 = NULL; + + SVN_ERR(svn_io_file_open(&orig, orig_tmpfile, APR_READ, APR_OS_DEFAULT, + scratch_pool)); + SVN_ERR(svn_io_open_unique_file3(&gitlike, new_tmpfile, NULL, + svn_io_file_del_on_pool_cleanup, + result_pool, scratch_pool)); + + SVN_ERR(svn_io_file_readline(orig, &line, NULL, NULL, 2 * APR_PATH_MAX + 2, + scratch_pool, scratch_pool)); + + if (line->len > 5 && !strncmp(line->data, "link ", 5)) + { + const char *sz_str; + svn_checksum_t *checksum; + + svn_stringbuf_remove(line, 0, 5); + + SVN_ERR(svn_io_file_write_full(gitlike, line->data, line->len, + NULL, scratch_pool)); + + /* git calculates the sha over "blob X\0" + the actual data, + where X is the decimal size of the blob. */ + sz_str = apr_psprintf(scratch_pool, "blob %u", (unsigned int)line->len); + svn_stringbuf_insert(line, 0, sz_str, strlen(sz_str) + 1); + + SVN_ERR(svn_checksum(&checksum, svn_checksum_sha1, + line->data, line->len, scratch_pool)); + + *git_sha1 = svn_checksum_to_cstring(checksum, result_pool); + } + else + { + /* Not a link... so can't convert */ + *new_tmpfile = apr_pstrdup(result_pool, orig_tmpfile); + } + + SVN_ERR(svn_io_file_close(orig, scratch_pool)); + SVN_ERR(svn_io_file_close(gitlike, scratch_pool)); + return SVN_NO_ERROR; +} + /* Show differences between TMPFILE1 and TMPFILE2. DIFF_RELPATH, REV1, and REV2 are used in the headers to indicate the file and revisions. If either MIMETYPE1 or MIMETYPE2 indicate binary content, don't show a diff, @@ -662,8 +799,8 @@ diff_content_changed(svn_boolean_t *wrote_header, const char *tmpfile2, svn_revnum_t rev1, svn_revnum_t rev2, - const char *mimetype1, - const char *mimetype2, + apr_hash_t *left_props, + apr_hash_t *right_props, svn_diff_operation_kind_t operation, svn_boolean_t force_diff, const char *copyfrom_path, @@ -678,6 +815,9 @@ diff_content_changed(svn_boolean_t *wrote_header, const char *index_path = diff_relpath; const char *path1 = dwi->ddi.orig_path_1; const char *path2 = dwi->ddi.orig_path_2; + const char *mimetype1 = svn_prop_get_value(left_props, SVN_PROP_MIME_TYPE); + const char *mimetype2 = svn_prop_get_value(right_props, SVN_PROP_MIME_TYPE); + const char *index_shas = NULL; /* If only property differences are shown, there's nothing to do. */ if (dwi->properties_only) @@ -699,6 +839,33 @@ diff_content_changed(svn_boolean_t *wrote_header, if (mimetype2) mt2_binary = svn_mime_type_is_binary(mimetype2); + if (dwi->use_git_diff_format) + { + const char *l_hash = NULL; + const char *r_hash = NULL; + + /* Change symlinks to their 'git like' plain format */ + if (svn_prop_get_value(left_props, SVN_PROP_SPECIAL)) + SVN_ERR(transform_link_to_git(&tmpfile1, &l_hash, tmpfile1, + scratch_pool, scratch_pool)); + if (svn_prop_get_value(right_props, SVN_PROP_SPECIAL)) + SVN_ERR(transform_link_to_git(&tmpfile2, &r_hash, tmpfile2, + scratch_pool, scratch_pool)); + + if (l_hash && r_hash) + { + /* The symlink has changed. But we can't tell the user of the + diff whether we are writing git diffs or svn diffs of the + symlink... except when we add a git-like index line */ + + l_hash = apr_pstrndup(scratch_pool, l_hash, 8); + r_hash = apr_pstrndup(scratch_pool, r_hash, 8); + + index_shas = apr_psprintf(scratch_pool, "%8s..%8s", + l_hash, r_hash); + } + } + if (! dwi->force_binary && (mt1_binary || mt2_binary)) { /* Print out the diff header. */ @@ -708,6 +875,8 @@ diff_content_changed(svn_boolean_t *wrote_header, SVN_DIFF__EQUAL_STRING APR_EOL_STR, index_path)); + *wrote_header = TRUE; + /* ### Print git diff headers. */ if (dwi->use_git_diff_format) @@ -716,6 +885,7 @@ diff_content_changed(svn_boolean_t *wrote_header, svn_stream_t *right_stream; const char *repos_relpath1; const char *repos_relpath2; + const char *copyfrom_repos_relpath = NULL; SVN_ERR(make_repos_relpath(&repos_relpath1, diff_relpath, dwi->ddi.orig_path_1, @@ -729,12 +899,22 @@ diff_content_changed(svn_boolean_t *wrote_header, dwi->wc_ctx, dwi->ddi.anchor, scratch_pool, scratch_pool)); + if (copyfrom_path) + SVN_ERR(make_repos_relpath(©from_repos_relpath, copyfrom_path, + dwi->ddi.orig_path_2, + dwi->ddi.session_relpath, + dwi->wc_ctx, + dwi->ddi.anchor, + scratch_pool, scratch_pool)); SVN_ERR(print_git_diff_header(outstream, &label1, &label2, operation, repos_relpath1, repos_relpath2, rev1, rev2, - copyfrom_path, + copyfrom_repos_relpath, copyfrom_rev, + left_props, + right_props, + index_shas, dwi->header_encoding, scratch_pool)); @@ -878,6 +1058,8 @@ diff_content_changed(svn_boolean_t *wrote_header, { const char *repos_relpath1; const char *repos_relpath2; + const char *copyfrom_repos_relpath = NULL; + SVN_ERR(make_repos_relpath(&repos_relpath1, diff_relpath, dwi->ddi.orig_path_1, dwi->ddi.session_relpath, @@ -890,12 +1072,23 @@ diff_content_changed(svn_boolean_t *wrote_header, dwi->wc_ctx, dwi->ddi.anchor, scratch_pool, scratch_pool)); + if (copyfrom_path) + SVN_ERR(make_repos_relpath(©from_repos_relpath, + copyfrom_path, + dwi->ddi.orig_path_2, + dwi->ddi.session_relpath, + dwi->wc_ctx, + dwi->ddi.anchor, + scratch_pool, scratch_pool)); SVN_ERR(print_git_diff_header(outstream, &label1, &label2, operation, repos_relpath1, repos_relpath2, rev1, rev2, - copyfrom_path, + copyfrom_repos_relpath, copyfrom_rev, + left_props, + right_props, + index_shas, dwi->header_encoding, scratch_pool)); } @@ -916,10 +1109,6 @@ diff_content_changed(svn_boolean_t *wrote_header, } } - /* ### todo: someday we'll need to worry about whether we're going - to need to write a diff plug-in mechanism that makes use of the - two paths, instead of just blindly running SVN_CLIENT_DIFF. */ - return SVN_NO_ERROR; } @@ -946,10 +1135,7 @@ diff_file_changed(const char *relpath, left_file, right_file, left_source->revision, right_source->revision, - svn_prop_get_value(left_props, - SVN_PROP_MIME_TYPE), - svn_prop_get_value(right_props, - SVN_PROP_MIME_TYPE), + left_props, right_props, svn_diff_op_modified, FALSE, NULL, SVN_INVALID_REVNUM, dwi, @@ -958,7 +1144,7 @@ diff_file_changed(const char *relpath, SVN_ERR(diff_props_changed(relpath, left_source->revision, right_source->revision, prop_changes, - left_props, !wrote_header, + left_props, right_props, !wrote_header, dwi, scratch_pool)); return SVN_NO_ERROR; } @@ -986,6 +1172,23 @@ diff_file_added(const char *relpath, apr_hash_t *left_props; apr_array_header_t *prop_changes; + if (dwi->no_diff_added) + { + const char *index_path = relpath; + + if (dwi->ddi.anchor) + index_path = svn_dirent_join(dwi->ddi.anchor, relpath, + scratch_pool); + + SVN_ERR(svn_stream_printf_from_utf8(dwi->outstream, + dwi->header_encoding, scratch_pool, + "Index: %s (added)" APR_EOL_STR + SVN_DIFF__EQUAL_STRING APR_EOL_STR, + index_path)); + wrote_header = TRUE; + return SVN_NO_ERROR; + } + /* During repos->wc diff of a copy revision numbers obtained * from the working copy are always SVN_INVALID_REVNUM. */ if (copyfrom_source && !dwi->show_copies_as_adds) @@ -1009,33 +1212,19 @@ diff_file_added(const char *relpath, SVN_ERR(svn_prop_diffs(&prop_changes, right_props, left_props, scratch_pool)); - if (dwi->no_diff_added) - { - const char *index_path = relpath; - - if (dwi->ddi.anchor) - index_path = svn_dirent_join(dwi->ddi.anchor, relpath, - scratch_pool); - - SVN_ERR(svn_stream_printf_from_utf8(dwi->outstream, - dwi->header_encoding, scratch_pool, - "Index: %s (added)" APR_EOL_STR - SVN_DIFF__EQUAL_STRING APR_EOL_STR, - index_path)); - wrote_header = TRUE; - } - else if (copyfrom_source && right_file) + if (copyfrom_source && right_file) SVN_ERR(diff_content_changed(&wrote_header, relpath, left_file, right_file, copyfrom_source->revision, right_source->revision, - svn_prop_get_value(left_props, - SVN_PROP_MIME_TYPE), - svn_prop_get_value(right_props, - SVN_PROP_MIME_TYPE), - svn_diff_op_copied, + left_props, right_props, + copyfrom_source->moved_from_relpath + ? svn_diff_op_moved + : svn_diff_op_copied, TRUE /* force diff output */, - copyfrom_source->repos_relpath, + copyfrom_source->moved_from_relpath + ? copyfrom_source->moved_from_relpath + : copyfrom_source->repos_relpath, copyfrom_source->revision, dwi, scratch_pool)); else if (right_file) @@ -1043,10 +1232,7 @@ diff_file_added(const char *relpath, left_file, right_file, DIFF_REVNUM_NONEXISTENT, right_source->revision, - svn_prop_get_value(left_props, - SVN_PROP_MIME_TYPE), - svn_prop_get_value(right_props, - SVN_PROP_MIME_TYPE), + left_props, right_props, svn_diff_op_added, TRUE /* force diff output */, NULL, SVN_INVALID_REVNUM, @@ -1058,8 +1244,8 @@ diff_file_added(const char *relpath, : DIFF_REVNUM_NONEXISTENT, right_source->revision, prop_changes, - left_props, ! wrote_header, - dwi, scratch_pool)); + left_props, right_props, + ! wrote_header, dwi, scratch_pool)); return SVN_NO_ERROR; } @@ -1104,8 +1290,7 @@ diff_file_deleted(const char *relpath, left_file, dwi->empty_file, left_source->revision, DIFF_REVNUM_NONEXISTENT, - svn_prop_get_value(left_props, - SVN_PROP_MIME_TYPE), + left_props, NULL, svn_diff_op_deleted, FALSE, NULL, SVN_INVALID_REVNUM, @@ -1123,8 +1308,8 @@ diff_file_deleted(const char *relpath, left_source->revision, DIFF_REVNUM_NONEXISTENT, prop_changes, - left_props, ! wrote_header, - dwi, scratch_pool)); + left_props, NULL, + ! wrote_header, dwi, scratch_pool)); } } @@ -1149,7 +1334,7 @@ diff_dir_changed(const char *relpath, left_source->revision, right_source->revision, prop_changes, - left_props, + left_props, right_props, TRUE /* show_diff_header */, dwi, scratch_pool)); @@ -1194,7 +1379,7 @@ diff_dir_added(const char *relpath, : DIFF_REVNUM_NONEXISTENT, right_source->revision, prop_changes, - left_props, + left_props, right_props, TRUE /* show_diff_header */, dwi, scratch_pool)); @@ -1211,19 +1396,20 @@ diff_dir_deleted(const char *relpath, { diff_writer_info_t *dwi = processor->baton; apr_array_header_t *prop_changes; + apr_hash_t *right_props; if (dwi->no_diff_deleted) return SVN_NO_ERROR; - - SVN_ERR(svn_prop_diffs(&prop_changes, apr_hash_make(scratch_pool), + right_props = apr_hash_make(scratch_pool); + SVN_ERR(svn_prop_diffs(&prop_changes, right_props, left_props, scratch_pool)); SVN_ERR(diff_props_changed(relpath, left_source->revision, DIFF_REVNUM_NONEXISTENT, prop_changes, - left_props, + left_props, right_props, TRUE /* show_diff_header */, dwi, scratch_pool)); @@ -1852,11 +2038,15 @@ diff_repos_repos(const char **root_relpath, /* Perform a diff between a repository path and a working-copy path. PATH_OR_URL1 may be either a URL or a working copy path. PATH2 is a - working copy path. REVISION1 and REVISION2 are their respective - revisions. If REVERSE is TRUE, the diff will be done in reverse. - If PEG_REVISION is specified, then PATH_OR_URL1 is the path in the peg - revision, and the actual repository path to be compared is - determined by following copy history. + working copy path. REVISION1 is the revision of URL1. If PEG_REVISION1 + is specified, then PATH_OR_URL1 is the path in the peg revision, and the + actual repository path to be compared is determined by following copy + history. + + REVISION_KIND2 specifies which revision should be reported from the + working copy (BASE or WORKING) + + If REVERSE is TRUE, the diff will be reported in reverse. All other options are the same as those passed to svn_client_diff6(). */ static svn_error_t * @@ -1865,9 +2055,9 @@ diff_repos_wc(const char **root_relpath, struct diff_driver_info_t *ddi, const char *path_or_url1, const svn_opt_revision_t *revision1, - const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *peg_revision1, const char *path2, - const svn_opt_revision_t *revision2, + enum svn_opt_revision_kind revision2_kind, svn_boolean_t reverse, svn_depth_t depth, svn_boolean_t ignore_ancestry, @@ -1884,7 +2074,7 @@ diff_repos_wc(const char **root_relpath, void *reporter_baton; const svn_delta_editor_t *diff_editor; void *diff_edit_baton; - svn_boolean_t rev2_is_base = (revision2->kind == svn_opt_revision_base); + svn_boolean_t rev2_is_base = (revision2_kind == svn_opt_revision_base); svn_boolean_t server_supports_depth; const char *abspath_or_url1; const char *abspath2; @@ -1924,10 +2114,10 @@ diff_repos_wc(const char **root_relpath, SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &loc1, path_or_url1, abspath2, - peg_revision, revision1, + peg_revision1, revision1, ctx, scratch_pool)); - if (revision2->kind == svn_opt_revision_base || !is_copy) + if (revision2_kind == svn_opt_revision_base || !is_copy) { /* Convert path_or_url1 to a URL to feed to do_diff. */ SVN_ERR(svn_wc_get_actual_target2(&anchor, &target, ctx->wc_ctx, path2, @@ -2069,22 +2259,20 @@ diff_repos_wc(const char **root_relpath, else diff_depth = svn_depth_unknown; + /* Tell the RA layer we want a delta to change our txn to URL1 */ + SVN_ERR(svn_ra_do_diff3(ra_session, + &reporter, &reporter_baton, + loc1->rev, + target, + diff_depth, + ignore_ancestry, + TRUE, /* text_deltas */ + loc1->url, + diff_editor, diff_edit_baton, + scratch_pool)); - - if (is_copy && revision2->kind != svn_opt_revision_base) + if (is_copy && revision2_kind != svn_opt_revision_base) { - /* Tell the RA layer we want a delta to change our txn to URL1 */ - SVN_ERR(svn_ra_do_diff3(ra_session, - &reporter, &reporter_baton, - loc1->rev, - target, - diff_depth, - ignore_ancestry, - TRUE, /* text_deltas */ - loc1->url, - diff_editor, diff_edit_baton, - scratch_pool)); - /* Report the copy source. */ if (cf_depth == svn_depth_unknown) cf_depth = svn_depth_infinity; @@ -2108,18 +2296,6 @@ diff_repos_wc(const char **root_relpath, } else { - /* Tell the RA layer we want a delta to change our txn to URL1 */ - SVN_ERR(svn_ra_do_diff3(ra_session, - &reporter, &reporter_baton, - loc1->rev, - target, - diff_depth, - ignore_ancestry, - TRUE, /* text_deltas */ - loc1->url, - diff_editor, diff_edit_baton, - scratch_pool)); - /* Create a txn mirror of path2; the diff editor will print diffs in reverse. :-) */ SVN_ERR(svn_wc_crawl_revisions5(ctx->wc_ctx, abspath2, @@ -2146,6 +2322,7 @@ do_diff(const char **root_relpath, const svn_opt_revision_t *revision1, const svn_opt_revision_t *revision2, const svn_opt_revision_t *peg_revision, + svn_boolean_t no_peg_revision, svn_depth_t depth, svn_boolean_t ignore_ancestry, const apr_array_header_t *changelists, @@ -2166,7 +2343,7 @@ do_diff(const char **root_relpath, { if (is_repos2) { - /* ### Ignores 'show_copies_as_adds'. */ + /* Ignores changelists. */ SVN_ERR(diff_repos_repos(root_relpath, root_is_dir, ddi, path_or_url1, path_or_url2, @@ -2179,8 +2356,11 @@ do_diff(const char **root_relpath, else /* path_or_url2 is a working copy path */ { SVN_ERR(diff_repos_wc(root_relpath, root_is_dir, ddi, - path_or_url1, revision1, peg_revision, - path_or_url2, revision2, FALSE, depth, + path_or_url1, revision1, + no_peg_revision ? revision1 + : peg_revision, + path_or_url2, revision2->kind, + FALSE, depth, ignore_ancestry, changelists, diff_processor, ctx, result_pool, scratch_pool)); @@ -2191,8 +2371,12 @@ do_diff(const char **root_relpath, if (is_repos2) { SVN_ERR(diff_repos_wc(root_relpath, root_is_dir, ddi, - path_or_url2, revision2, peg_revision, - path_or_url1, revision1, TRUE, depth, + path_or_url2, revision2, + no_peg_revision ? revision2 + : peg_revision, + path_or_url1, + revision1->kind, + TRUE, depth, ignore_ancestry, changelists, diff_processor, ctx, result_pool, scratch_pool)); @@ -2211,7 +2395,7 @@ do_diff(const char **root_relpath, scratch_pool)); /* ### What about ddi? */ - + /* Ignores changelists, ignore_ancestry */ SVN_ERR(svn_client__arbitrary_nodes_diff(root_relpath, root_is_dir, abspath1, abspath2, depth, @@ -2415,7 +2599,8 @@ svn_client_diff6(const apr_array_header_t *options, return svn_error_trace(do_diff(NULL, NULL, &dwi.ddi, path_or_url1, path_or_url2, - revision1, revision2, &peg_revision, + revision1, revision2, + &peg_revision, TRUE /* no_peg_revision */, depth, ignore_ancestry, changelists, TRUE /* text_deltas */, diff_processor, ctx, pool, pool)); @@ -2498,7 +2683,8 @@ svn_client_diff_peg6(const apr_array_header_t *options, return svn_error_trace(do_diff(NULL, NULL, &dwi.ddi, path_or_url, path_or_url, - start_revision, end_revision, peg_revision, + start_revision, end_revision, + peg_revision, FALSE /* no_peg_revision */, depth, ignore_ancestry, changelists, TRUE /* text_deltas */, diff_processor, ctx, pool, pool)); @@ -2531,7 +2717,8 @@ svn_client_diff_summarize2(const char *path_or_url1, return svn_error_trace(do_diff(p_root_relpath, NULL, NULL, path_or_url1, path_or_url2, - revision1, revision2, &peg_revision, + revision1, revision2, + &peg_revision, TRUE /* no_peg_revision */, depth, ignore_ancestry, changelists, FALSE /* text_deltas */, diff_processor, ctx, pool, pool)); @@ -2560,7 +2747,8 @@ svn_client_diff_summarize_peg2(const char *path_or_url, return svn_error_trace(do_diff(p_root_relpath, NULL, NULL, path_or_url, path_or_url, - start_revision, end_revision, peg_revision, + start_revision, end_revision, + peg_revision, FALSE /* no_peg_revision */, depth, ignore_ancestry, changelists, FALSE /* text_deltas */, diff_processor, ctx, pool, pool)); diff --git a/subversion/libsvn_client/diff_local.c b/subversion/libsvn_client/diff_local.c index df6bc0a8c009..056ee53e8f28 100644 --- a/subversion/libsvn_client/diff_local.c +++ b/subversion/libsvn_client/diff_local.c @@ -179,7 +179,7 @@ inner_dir_diff(const char *left_abspath, { svn_error_clear(err); right_dirents = apr_hash_make(scratch_pool); - right_only = TRUE; + left_only = TRUE; } else SVN_ERR(err); @@ -669,9 +669,6 @@ svn_client__arbitrary_nodes_diff(const char **root_relpath, SVN_ERR(svn_io_check_resolved_path(left_abspath, &left_kind, scratch_pool)); SVN_ERR(svn_io_check_resolved_path(right_abspath, &right_kind, scratch_pool)); - if (depth == svn_depth_unknown) - depth = svn_depth_infinity; - if (left_kind == svn_node_dir && right_kind == svn_node_dir) { left_root_abspath = left_abspath; diff --git a/subversion/libsvn_client/export.c b/subversion/libsvn_client/export.c index 63cd87a921b0..2fc2dc8ffd53 100644 --- a/subversion/libsvn_client/export.c +++ b/subversion/libsvn_client/export.c @@ -432,7 +432,7 @@ export_node(void *baton, scratch_pool)); /* Now that dst_tmp contains the translated data, do the atomic rename. */ - SVN_ERR(svn_io_file_rename(dst_tmp, to_abspath, scratch_pool)); + SVN_ERR(svn_io_file_rename2(dst_tmp, to_abspath, FALSE, scratch_pool)); if (eib->notify_func) { @@ -816,7 +816,7 @@ close_file(void *file_baton, if ((! fb->eol_style_val) && (! fb->keywords_val) && (! fb->special)) { - SVN_ERR(svn_io_file_rename(fb->tmppath, fb->path, pool)); + SVN_ERR(svn_io_file_rename2(fb->tmppath, fb->path, FALSE, pool)); } else { @@ -1035,7 +1035,7 @@ add_file_ev2(void *baton, eb->cancel_baton, scratch_pool)); /* Move the file into place. */ - SVN_ERR(svn_io_file_rename(tmppath, full_path, scratch_pool)); + SVN_ERR(svn_io_file_rename2(tmppath, full_path, FALSE, scratch_pool)); } if (executable_val) @@ -1148,7 +1148,7 @@ get_editor_ev2(const svn_delta_editor_t **export_editor, } static svn_error_t * -export_file_ev2(const char *from_path_or_url, +export_file_ev2(const char *from_url, const char *to_path, struct edit_baton *eb, svn_client__pathrev_t *loc, @@ -1156,23 +1156,21 @@ export_file_ev2(const char *from_path_or_url, svn_boolean_t overwrite, apr_pool_t *scratch_pool) { - svn_boolean_t from_is_url = svn_path_is_url(from_path_or_url); apr_hash_t *props; svn_stream_t *tmp_stream; svn_node_kind_t to_kind; + SVN_ERR_ASSERT(svn_path_is_url(from_url)); + if (svn_path_is_empty(to_path)) { - if (from_is_url) - to_path = svn_uri_basename(from_path_or_url, scratch_pool); - else - to_path = svn_dirent_basename(from_path_or_url, NULL); + to_path = svn_uri_basename(from_url, scratch_pool); eb->root_path = to_path; } else { - SVN_ERR(append_basename_if_dir(&to_path, from_path_or_url, - from_is_url, scratch_pool)); + SVN_ERR(append_basename_if_dir(&to_path, from_url, + TRUE, scratch_pool)); eb->root_path = to_path; } @@ -1204,7 +1202,7 @@ export_file_ev2(const char *from_path_or_url, } static svn_error_t * -export_file(const char *from_path_or_url, +export_file(const char *from_url, const char *to_path, struct edit_baton *eb, svn_client__pathrev_t *loc, @@ -1216,20 +1214,18 @@ export_file(const char *from_path_or_url, apr_hash_index_t *hi; struct file_baton *fb = apr_pcalloc(scratch_pool, sizeof(*fb)); svn_node_kind_t to_kind; - svn_boolean_t from_is_url = svn_path_is_url(from_path_or_url); + + SVN_ERR_ASSERT(svn_path_is_url(from_url)); if (svn_path_is_empty(to_path)) { - if (from_is_url) - to_path = svn_uri_basename(from_path_or_url, scratch_pool); - else - to_path = svn_dirent_basename(from_path_or_url, NULL); + to_path = svn_uri_basename(from_url, scratch_pool); eb->root_path = to_path; } else { - SVN_ERR(append_basename_if_dir(&to_path, from_path_or_url, - from_is_url, scratch_pool)); + SVN_ERR(append_basename_if_dir(&to_path, from_url, + TRUE, scratch_pool)); eb->root_path = to_path; } @@ -1288,7 +1284,7 @@ export_file(const char *from_path_or_url, } static svn_error_t * -export_directory(const char *from_path_or_url, +export_directory(const char *from_url, const char *to_path, struct edit_baton *eb, svn_client__pathrev_t *loc, @@ -1307,6 +1303,8 @@ export_directory(const char *from_path_or_url, void *report_baton; svn_node_kind_t kind; + SVN_ERR_ASSERT(svn_path_is_url(from_url)); + if (!ENABLE_EV2_IMPL) SVN_ERR(get_editor_ev1(&export_editor, &edit_baton, eb, ctx, scratch_pool, scratch_pool)); @@ -1355,7 +1353,7 @@ export_directory(const char *from_path_or_url, SVN_ERR(svn_dirent_get_absolute(&to_abspath, to_path, scratch_pool)); SVN_ERR(svn_client__export_externals(eb->externals, - from_path_or_url, + from_url, to_abspath, eb->repos_root_url, depth, native_eol, ignore_keywords, @@ -1402,8 +1400,12 @@ svn_client_export5(svn_revnum_t *result_rev, svn_client__pathrev_t *loc; svn_ra_session_t *ra_session; svn_node_kind_t kind; + const char *from_url; struct edit_baton *eb = apr_pcalloc(pool, sizeof(*eb)); + SVN_ERR(svn_client_url_from_path2(&from_url, from_path_or_url, + ctx, pool, pool)); + /* Get the RA connection. */ SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &loc, from_path_or_url, NULL, @@ -1428,15 +1430,15 @@ svn_client_export5(svn_revnum_t *result_rev, if (kind == svn_node_file) { if (!ENABLE_EV2_IMPL) - SVN_ERR(export_file(from_path_or_url, to_path, eb, loc, ra_session, + SVN_ERR(export_file(from_url, to_path, eb, loc, ra_session, overwrite, pool)); else - SVN_ERR(export_file_ev2(from_path_or_url, to_path, eb, loc, + SVN_ERR(export_file_ev2(from_url, to_path, eb, loc, ra_session, overwrite, pool)); } else if (kind == svn_node_dir) { - SVN_ERR(export_directory(from_path_or_url, to_path, + SVN_ERR(export_directory(from_url, to_path, eb, loc, ra_session, overwrite, ignore_externals, ignore_keywords, depth, native_eol, ctx, pool)); @@ -1508,7 +1510,7 @@ svn_client_export5(svn_revnum_t *result_rev, eib.ignore_keywords = ignore_keywords; eib.wc_ctx = ctx->wc_ctx; eib.native_eol = native_eol; - eib.notify_func = ctx->notify_func2;; + eib.notify_func = ctx->notify_func2; eib.notify_baton = ctx->notify_baton2; eib.origin_abspath = from_path_or_url; eib.exported = FALSE; diff --git a/subversion/libsvn_client/externals.c b/subversion/libsvn_client/externals.c index 851b260dec4c..7ff1ed25d80d 100644 --- a/subversion/libsvn_client/externals.c +++ b/subversion/libsvn_client/externals.c @@ -120,7 +120,7 @@ relegate_dir_external(svn_wc_context_t *wc_ctx, /* And if it is no longer a working copy, we should just rename it */ - err = svn_io_file_rename(local_abspath, new_path, scratch_pool); + err = svn_io_file_rename2(local_abspath, new_path, FALSE, scratch_pool); } /* ### TODO: We should notify the user about the rename */ @@ -534,7 +534,7 @@ switch_file_external(const char *local_abspath, SVN_ERR(svn_io_check_path(local_abspath, &disk_kind, scratch_pool)); - if (kind == svn_node_file || kind == svn_node_dir) + if (disk_kind == svn_node_file || disk_kind == svn_node_dir) return svn_error_createf(SVN_ERR_WC_PATH_FOUND, NULL, _("The file external '%s' can not be " "created because the node exists."), @@ -574,6 +574,8 @@ switch_file_external(const char *local_abspath, record_url, record_peg_revision, record_revision, + ctx->conflict_func2, + ctx->conflict_baton2, ctx->cancel_func, ctx->cancel_baton, ctx->notify_func2, diff --git a/subversion/libsvn_client/import.c b/subversion/libsvn_client/import.c index b5ee0776def7..ae67e9ad43b5 100644 --- a/subversion/libsvn_client/import.c +++ b/subversion/libsvn_client/import.c @@ -73,32 +73,59 @@ typedef struct import_ctx_t apr_hash_t *autoprops; } import_ctx_t; +typedef struct open_txdelta_stream_baton_t +{ + svn_boolean_t need_reset; + svn_stream_t *stream; +} open_txdelta_stream_baton_t; + +/* Implements svn_txdelta_stream_open_func_t */ +static svn_error_t * +open_txdelta_stream(svn_txdelta_stream_t **txdelta_stream_p, + void *baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + open_txdelta_stream_baton_t *b = baton; + + if (b->need_reset) + { + /* Under rare circumstances, we can be restarted and would need to + * supply the delta stream again. In this case, reset the base + * stream. */ + SVN_ERR(svn_stream_reset(b->stream)); + } + + /* Get the delta stream (delta against the empty string). */ + svn_txdelta2(txdelta_stream_p, svn_stream_empty(result_pool), + b->stream, FALSE, result_pool); + b->need_reset = TRUE; + return SVN_NO_ERROR; +} /* Apply LOCAL_ABSPATH's contents (as a delta against the empty string) to FILE_BATON in EDITOR. Use POOL for any temporary allocation. PROPERTIES is the set of node properties set on this file. - Fill DIGEST with the md5 checksum of the sent file; DIGEST must be - at least APR_MD5_DIGESTSIZE bytes long. */ + Return the resulting checksum in *RESULT_MD5_CHECKSUM_P. */ /* ### how does this compare against svn_wc_transmit_text_deltas2() ??? */ static svn_error_t * -send_file_contents(const char *local_abspath, +send_file_contents(svn_checksum_t **result_md5_checksum_p, + const char *local_abspath, void *file_baton, const svn_delta_editor_t *editor, apr_hash_t *properties, - unsigned char *digest, apr_pool_t *pool) { svn_stream_t *contents; - svn_txdelta_window_handler_t handler; - void *handler_baton; const svn_string_t *eol_style_val = NULL, *keywords_val = NULL; svn_boolean_t special = FALSE; svn_subst_eol_style_t eol_style; const char *eol; apr_hash_t *keywords; + open_txdelta_stream_baton_t baton = { 0 }; /* If there are properties, look for EOL-style and keywords ones. */ if (properties) @@ -111,10 +138,6 @@ send_file_contents(const char *local_abspath, special = TRUE; } - /* Get an editor func that wants to consume the delta stream. */ - SVN_ERR(editor->apply_textdelta(file_baton, NULL, pool, - &handler, &handler_baton)); - if (eol_style_val) svn_subst_eol_style_from_value(&eol_style, &eol, eol_style_val->data); else @@ -168,10 +191,17 @@ send_file_contents(const char *local_abspath, } } - /* Send the file's contents to the delta-window handler. */ - return svn_error_trace(svn_txdelta_send_stream(contents, handler, - handler_baton, digest, - pool)); + /* Arrange the stream to calculate the resulting MD5. */ + contents = svn_stream_checksummed2(contents, result_md5_checksum_p, NULL, + svn_checksum_md5, TRUE, pool); + /* Send the contents. */ + baton.need_reset = FALSE; + baton.stream = svn_stream_disown(contents, pool); + SVN_ERR(editor->apply_textdelta_stream(editor, file_baton, NULL, + open_txdelta_stream, &baton, pool)); + SVN_ERR(svn_stream_close(contents)); + + return SVN_NO_ERROR; } @@ -198,7 +228,7 @@ import_file(const svn_delta_editor_t *editor, { void *file_baton; const char *mimetype = NULL; - unsigned char digest[APR_MD5_DIGESTSIZE]; + svn_checksum_t *result_md5_checksum; const char *text_checksum; apr_hash_t* properties; apr_hash_index_t *hi; @@ -262,13 +292,11 @@ import_file(const svn_delta_editor_t *editor, } /* Now, transmit the file contents. */ - SVN_ERR(send_file_contents(local_abspath, file_baton, editor, - properties, digest, pool)); + SVN_ERR(send_file_contents(&result_md5_checksum, local_abspath, + file_baton, editor, properties, pool)); /* Finally, close the file. */ - text_checksum = - svn_checksum_to_cstring(svn_checksum__from_digest_md5(digest, pool), pool); - + text_checksum = svn_checksum_to_cstring(result_md5_checksum, pool); return svn_error_trace(editor->close_file(file_baton, text_checksum, pool)); } @@ -577,26 +605,26 @@ import_dir(const svn_delta_editor_t *editor, } -/* Recursively import PATH to a repository using EDITOR and - * EDIT_BATON. PATH can be a file or directory. +/* Recursively import LOCAL_ABSPATH to a repository using EDITOR and + * EDIT_BATON. LOCAL_ABSPATH can be a file or directory. * * Sets *UPDATED_REPOSITORY to TRUE when the repository was modified by * a successfull commit, otherwise to FALSE. * - * DEPTH is the depth at which to import PATH; it behaves as for - * svn_client_import4(). + * DEPTH is the depth at which to import LOCAL_ABSPATH; it behaves as for + * svn_client_import5(). * * BASE_REV is the revision to use for the root of the commit. We * checked the preconditions against this revision. * * NEW_ENTRIES is an ordered array of path components that must be * created in the repository (where the ordering direction is - * parent-to-child). If PATH is a directory, NEW_ENTRIES may be empty + * parent-to-child). If LOCAL_ABSPATH is a directory, NEW_ENTRIES may be empty * -- the result is an import which creates as many new entries in the * top repository target directory as there are importable entries in - * the top of PATH; but if NEW_ENTRIES is not empty, its last item is + * the top of LOCAL_ABSPATH; but if NEW_ENTRIES is not empty, its last item is * the name of a new subdirectory in the repository to hold the - * import. If PATH is a file, NEW_ENTRIES may not be empty, and its + * import. If LOCAL_ABSPATH is a file, NEW_ENTRIES may not be empty, and its * last item is the name used for the file in the repository. If * NEW_ENTRIES contains more than one item, all but the last item are * the names of intermediate directories that are created before the @@ -624,6 +652,8 @@ import_dir(const svn_delta_editor_t *editor, * If CTX->NOTIFY_FUNC is non-null, invoke it with CTX->NOTIFY_BATON for * each imported path, passing actions svn_wc_notify_commit_added. * + * URL is used only in the 'commit_finalizing' notification. + * * Use POOL for any temporary allocation. * * Note: the repository directory receiving the import was specified diff --git a/subversion/libsvn_client/info.c b/subversion/libsvn_client/info.c index 39b5eb112bab..3331647c9587 100644 --- a/subversion/libsvn_client/info.c +++ b/subversion/libsvn_client/info.c @@ -253,17 +253,17 @@ same_resource_in_head(svn_boolean_t *same_p, apr_pool_t *pool) { svn_error_t *err; - svn_opt_revision_t start_rev, peg_rev; + svn_opt_revision_t operative_rev, peg_rev; const char *head_url; - start_rev.kind = svn_opt_revision_head; - peg_rev.kind = svn_opt_revision_number; - peg_rev.value.number = rev; + peg_rev.kind = svn_opt_revision_head; + operative_rev.kind = svn_opt_revision_number; + operative_rev.value.number = rev; err = svn_client__repos_locations(&head_url, NULL, NULL, NULL, ra_session, url, &peg_rev, - &start_rev, NULL, + &operative_rev, NULL, ctx, pool); if (err && ((err->apr_err == SVN_ERR_CLIENT_UNRELATED_RESOURCES) || diff --git a/subversion/libsvn_client/list.c b/subversion/libsvn_client/list.c index c29b8bd68dc4..78433c337e58 100644 --- a/subversion/libsvn_client/list.c +++ b/subversion/libsvn_client/list.c @@ -21,6 +21,8 @@ * ==================================================================== */ +#include + #include "svn_client.h" #include "svn_dirent_uri.h" #include "svn_hash.h" @@ -35,12 +37,14 @@ #include "private/svn_fspath.h" #include "private/svn_ra_private.h" #include "private/svn_sorts_private.h" +#include "private/svn_utf_private.h" #include "private/svn_wc_private.h" #include "svn_private_config.h" /* Prototypes for referencing before declaration */ static svn_error_t * list_externals(apr_hash_t *externals, + const apr_array_header_t *patterns, svn_depth_t depth, apr_uint32_t dirent_fields, svn_boolean_t fetch_locks, @@ -53,6 +57,7 @@ static svn_error_t * list_internal(const char *path_or_url, const svn_opt_revision_t *peg_revision, const svn_opt_revision_t *revision, + const apr_array_header_t *patterns, svn_depth_t depth, apr_uint32_t dirent_fields, svn_boolean_t fetch_locks, @@ -64,6 +69,18 @@ list_internal(const char *path_or_url, svn_client_ctx_t *ctx, apr_pool_t *pool); +/* Return TRUE if S matches any of the const char * in PATTERNS. + * Note that any S will match if PATTERNS is empty. + * Use SCRATCH_BUFFER for temporary string contents. */ +static svn_boolean_t +match_patterns(const char *s, + const apr_array_header_t *patterns, + svn_membuf_t *scratch_buffer) +{ + return patterns + ? svn_utf__fuzzy_glob_match(s, patterns, scratch_buffer) + : TRUE; +} /* Get the directory entries of DIR at REV (relative to the root of RA_SESSION), getting at least the fields specified by DIRENT_FIELDS. @@ -75,6 +92,10 @@ list_internal(const char *path_or_url, if svn_depth_infinity, invoke it on file and directory entries and recurse into the directory entries with the same depth. + If PATTERNS is not empty, the last path segments must match at least + one of const char * patterns in it or the respective dirent will not + be reported. + LOCKS, if non-NULL, is a hash mapping const char * paths to svn_lock_t objects and FS_PATH is the absolute filesystem path of the RA session. Use SCRATCH_POOL for temporary allocations. @@ -86,6 +107,8 @@ list_internal(const char *path_or_url, EXTERNAL_PARENT_URL and EXTERNAL_TARGET are set when external items are listed, otherwise both are set to NULL by the caller. + + Use SCRATCH_BUFFER for temporary string contents. */ static svn_error_t * get_dir_contents(apr_uint32_t dirent_fields, @@ -94,6 +117,7 @@ get_dir_contents(apr_uint32_t dirent_fields, svn_ra_session_t *ra_session, apr_hash_t *locks, const char *fs_path, + const apr_array_header_t *patterns, svn_depth_t depth, svn_client_ctx_t *ctx, apr_hash_t *externals, @@ -101,6 +125,7 @@ get_dir_contents(apr_uint32_t dirent_fields, const char *external_target, svn_client_list_func2_t list_func, void *baton, + svn_membuf_t *scratch_buffer, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { @@ -175,23 +200,71 @@ get_dir_contents(apr_uint32_t dirent_fields, if (the_ent->kind == svn_node_file || depth == svn_depth_immediates || depth == svn_depth_infinity) - SVN_ERR(list_func(baton, path, the_ent, lock, fs_path, - external_parent_url, external_target, iterpool)); + if (match_patterns(item->key, patterns, scratch_buffer)) + SVN_ERR(list_func(baton, path, the_ent, lock, fs_path, + external_parent_url, external_target, iterpool)); /* If externals is non-NULL, populate the externals hash table recursively for all directory entries. */ if (depth == svn_depth_infinity && the_ent->kind == svn_node_dir) - SVN_ERR(get_dir_contents(dirent_fields, path, rev, - ra_session, locks, fs_path, depth, ctx, + SVN_ERR(get_dir_contents(dirent_fields, path, rev, ra_session, + locks, fs_path, patterns, depth, ctx, externals, external_parent_url, external_target, list_func, baton, - result_pool, iterpool)); + scratch_buffer, result_pool, iterpool)); } svn_pool_destroy(iterpool); return SVN_NO_ERROR; } +/* Baton type to be used with list_receiver. */ +typedef struct receiver_baton_t +{ + /* Wrapped callback function to invoke. */ + svn_client_list_func2_t list_func; + + /* Baton to be used with LIST_FUNC. */ + void *list_baton; + + /* Client context providing cancellation support. */ + svn_client_ctx_t *ctx; + + /* All locks found for the whole tree; pick yours. */ + apr_hash_t *locks; + + /* Start path of the operation. */ + const char *fs_base_path; +} receiver_baton_t; + +/* Implement svn_ra_dirent_receiver_t. + The BATON type must be a receiver_baton_t. */ +static svn_error_t * +list_receiver(const char *rel_path, + svn_dirent_t *dirent, + void *baton, + apr_pool_t *pool) +{ + receiver_baton_t *b = baton; + const svn_lock_t *lock = NULL; + + /* We only report the path relative to the start path. */ + rel_path = svn_dirent_skip_ancestor(b->fs_base_path, rel_path); + + if (b->locks) + { + const char *abs_path = svn_dirent_join(b->fs_base_path, rel_path, pool); + lock = svn_hash_gets(b->locks, abs_path); + } + + if (b->ctx->cancel_func) + SVN_ERR(b->ctx->cancel_func(b->ctx->cancel_baton)); + + SVN_ERR(b->list_func(b->list_baton, rel_path, dirent, lock, + b->fs_base_path, NULL, NULL, pool)); + + return SVN_NO_ERROR; +} /* List the file/directory entries for PATH_OR_URL at REVISION. The actual node revision selected is determined by the path as @@ -204,6 +277,10 @@ get_dir_contents(apr_uint32_t dirent_fields, subdirectories (at svn_depth_empty). Else if DEPTH is svn_depth_empty, just list PATH_OR_URL with none of its entries. + If PATTERNS is not NULL, the last path segments must match at least + one of const char * patterns in it or the respective dirent will not + be reported. + DIRENT_FIELDS controls which fields in the svn_dirent_t's are filled in. To have them totally filled in use SVN_DIRENT_ALL, otherwise simply bitwise OR together the combination of SVN_DIRENT_* @@ -230,6 +307,7 @@ static svn_error_t * list_internal(const char *path_or_url, const svn_opt_revision_t *peg_revision, const svn_opt_revision_t *revision, + const apr_array_header_t *patterns, svn_depth_t depth, apr_uint32_t dirent_fields, svn_boolean_t fetch_locks, @@ -248,6 +326,7 @@ list_internal(const char *path_or_url, svn_error_t *err; apr_hash_t *locks; apr_hash_t *externals; + svn_membuf_t scratch_buffer; if (include_externals) externals = apr_hash_make(pool); @@ -266,12 +345,6 @@ list_internal(const char *path_or_url, fs_path = svn_client__pathrev_fspath(loc, pool); - SVN_ERR(svn_ra_stat(ra_session, "", loc->rev, &dirent, pool)); - if (! dirent) - return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL, - _("URL '%s' non-existent in revision %ld"), - loc->url, loc->rev); - /* Maybe get all locks under url. */ if (fetch_locks) { @@ -290,20 +363,52 @@ list_internal(const char *path_or_url, else locks = NULL; + /* Try to use the efficient and fully authz-filtered code path. */ + if (!include_externals) + { + receiver_baton_t receiver_baton; + receiver_baton.list_baton = baton; + receiver_baton.ctx = ctx; + receiver_baton.list_func = list_func; + receiver_baton.locks = locks; + receiver_baton.fs_base_path = fs_path; + + err = svn_ra_list(ra_session, "", loc->rev, patterns, depth, + dirent_fields, list_receiver, &receiver_baton, pool); + + if (svn_error_find_cause(err, SVN_ERR_UNSUPPORTED_FEATURE)) + svn_error_clear(err); + else + return svn_error_trace(err); + } + + /* Stat for the file / directory node itself. */ + SVN_ERR(svn_ra_stat(ra_session, "", loc->rev, &dirent, pool)); + if (! dirent) + return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL, + _("URL '%s' non-existent in revision %ld"), + loc->url, loc->rev); + + /* We need a scratch buffer for temporary string data. + * Create one with a reasonable initial size. */ + svn_membuf__create(&scratch_buffer, 256, pool); + /* Report the dirent for the target. */ - SVN_ERR(list_func(baton, "", dirent, locks - ? (svn_hash_gets(locks, fs_path)) - : NULL, fs_path, external_parent_url, - external_target, pool)); + if (match_patterns(svn_dirent_dirname(fs_path, pool), patterns, + &scratch_buffer)) + SVN_ERR(list_func(baton, "", dirent, locks + ? (svn_hash_gets(locks, fs_path)) + : NULL, fs_path, external_parent_url, + external_target, pool)); if (dirent->kind == svn_node_dir && (depth == svn_depth_files || depth == svn_depth_immediates || depth == svn_depth_infinity)) SVN_ERR(get_dir_contents(dirent_fields, "", loc->rev, ra_session, locks, - fs_path, depth, ctx, externals, + fs_path, patterns, depth, ctx, externals, external_parent_url, external_target, list_func, - baton, pool, pool)); + baton, &scratch_buffer, pool, pool)); /* We handle externals after listing entries under path_or_url, so that handling external items (and any errors therefrom) doesn't delay @@ -312,7 +417,7 @@ list_internal(const char *path_or_url, { /* The 'externals' hash populated by get_dir_contents() is processed here. */ - SVN_ERR(list_externals(externals, depth, dirent_fields, + SVN_ERR(list_externals(externals, patterns, depth, dirent_fields, fetch_locks, list_func, baton, ctx, pool)); } @@ -349,6 +454,7 @@ wrap_list_error(const svn_client_ctx_t *ctx, static svn_error_t * list_external_items(apr_array_header_t *external_items, const char *externals_parent_url, + const apr_array_header_t *patterns, svn_depth_t depth, apr_uint32_t dirent_fields, svn_boolean_t fetch_locks, @@ -389,6 +495,7 @@ list_external_items(apr_array_header_t *external_items, list_internal(resolved_url, &item->peg_revision, &item->revision, + patterns, depth, dirent_fields, fetch_locks, TRUE, @@ -411,6 +518,7 @@ list_external_items(apr_array_header_t *external_items, passed to svn_client_list(). */ static svn_error_t * list_externals(apr_hash_t *externals, + const apr_array_header_t *patterns, svn_depth_t depth, apr_uint32_t dirent_fields, svn_boolean_t fetch_locks, @@ -440,9 +548,10 @@ list_externals(apr_hash_t *externals, if (! external_items->nelts) continue; - SVN_ERR(list_external_items(external_items, externals_parent_url, depth, - dirent_fields, fetch_locks, list_func, - baton, ctx, iterpool)); + SVN_ERR(list_external_items(external_items, externals_parent_url, + patterns, depth, dirent_fields, + fetch_locks, list_func, baton, ctx, + iterpool)); } svn_pool_destroy(iterpool); @@ -452,9 +561,10 @@ list_externals(apr_hash_t *externals, svn_error_t * -svn_client_list3(const char *path_or_url, +svn_client_list4(const char *path_or_url, const svn_opt_revision_t *peg_revision, const svn_opt_revision_t *revision, + const apr_array_header_t *patterns, svn_depth_t depth, apr_uint32_t dirent_fields, svn_boolean_t fetch_locks, @@ -462,14 +572,14 @@ svn_client_list3(const char *path_or_url, svn_client_list_func2_t list_func, void *baton, svn_client_ctx_t *ctx, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { return svn_error_trace(list_internal(path_or_url, peg_revision, - revision, + revision, patterns, depth, dirent_fields, fetch_locks, include_externals, NULL, NULL, list_func, - baton, ctx, pool)); + baton, ctx, scratch_pool)); } diff --git a/subversion/libsvn_client/merge.c b/subversion/libsvn_client/merge.c index aaab4e002cf5..21341b9b0a7b 100644 --- a/subversion/libsvn_client/merge.c +++ b/subversion/libsvn_client/merge.c @@ -215,32 +215,6 @@ /*** Repos-Diff Editor Callbacks ***/ -/* */ -typedef struct merge_source_t -{ - /* "left" side URL and revision (inclusive iff youngest) */ - const svn_client__pathrev_t *loc1; - - /* "right" side URL and revision (inclusive iff youngest) */ - const svn_client__pathrev_t *loc2; - - /* True iff LOC1 is an ancestor of LOC2 or vice-versa (history-wise). */ - svn_boolean_t ancestral; -} merge_source_t; - -/* Description of the merge target root node (a WC working node) */ -typedef struct merge_target_t -{ - /* Absolute path to the WC node */ - const char *abspath; - - /* The repository location of the base node of the target WC. If the node - * is locally added, then URL & REV are NULL & SVN_INVALID_REVNUM. - * REPOS_ROOT_URL and REPOS_UUID are always valid. */ - svn_client__pathrev_t loc; - -} merge_target_t; - typedef struct merge_cmd_baton_t { svn_boolean_t force_delete; /* Delete a file/dir even if modified */ svn_boolean_t dry_run; @@ -1236,7 +1210,7 @@ struct merge_file_baton_t /* If a tree conflict will be installed once edited, it's reason. If a skip should be produced its reason. Some special values are defined. See the - merge_tree_baton_t for an explanation. */ + merge_dir_baton_t for an explanation. */ svn_wc_conflict_reason_t tree_conflict_reason; svn_wc_conflict_action_t tree_conflict_action; svn_node_kind_t tree_conflict_local_node_kind; @@ -2266,13 +2240,9 @@ merge_file_added(const char *relpath, Otherwise, we'll use a pure add. */ if (merge_b->same_repos) { - const char *child = - svn_dirent_skip_ancestor(merge_b->target->abspath, - local_abspath); - SVN_ERR_ASSERT(child != NULL); copyfrom_url = svn_path_url_add_component2( merge_b->merge_source.loc2->url, - child, scratch_pool); + relpath, scratch_pool); copyfrom_rev = right_source->revision; SVN_ERR(check_repos_match(merge_b->target, local_abspath, copyfrom_url, scratch_pool)); @@ -5524,29 +5494,16 @@ single_range_conflict_report_create(const merge_source_t *conflicted_range, return report; } -/* Data for reporting when a merge aborted because of raising conflicts. - * - * ### TODO: More info, including the ranges (or other parameters) the user - * needs to complete the merge. - */ -typedef struct conflict_report_t -{ - const char *target_abspath; - /* The revision range during which conflicts were raised */ - const merge_source_t *conflicted_range; - /* Was the conflicted range the last range in the whole requested merge? */ - svn_boolean_t was_last_range; -} conflict_report_t; - -/* Return a new conflict_report_t containing deep copies of the parameters, - * allocated in RESULT_POOL. */ -static conflict_report_t * +/* Return a new svn_client__conflict_report_t containing deep copies of the + * parameters, allocated in RESULT_POOL. */ +static svn_client__conflict_report_t * conflict_report_create(const char *target_abspath, const merge_source_t *conflicted_range, svn_boolean_t was_last_range, apr_pool_t *result_pool) { - conflict_report_t *report = apr_palloc(result_pool, sizeof(*report)); + svn_client__conflict_report_t *report = apr_palloc(result_pool, + sizeof(*report)); report->target_abspath = apr_pstrdup(result_pool, target_abspath); report->conflicted_range = merge_source_dup(conflicted_range, result_pool); @@ -5555,11 +5512,12 @@ conflict_report_create(const char *target_abspath, } /* Return a deep copy of REPORT, allocated in RESULT_POOL. */ -static conflict_report_t * -conflict_report_dup(const conflict_report_t *report, +static svn_client__conflict_report_t * +conflict_report_dup(const svn_client__conflict_report_t *report, apr_pool_t *result_pool) { - conflict_report_t *new = apr_pmemdup(result_pool, report, sizeof(*new)); + svn_client__conflict_report_t *new = apr_pmemdup(result_pool, report, + sizeof(*new)); new->target_abspath = apr_pstrdup(result_pool, report->target_abspath); new->conflicted_range = merge_source_dup(report->conflicted_range, @@ -5567,11 +5525,9 @@ conflict_report_dup(const conflict_report_t *report, return new; } -/* Create and return an error structure appropriate for the unmerged - revisions range(s). */ -static APR_INLINE svn_error_t * -make_merge_conflict_error(conflict_report_t *report, - apr_pool_t *scratch_pool) +svn_error_t * +svn_client__make_merge_conflict_error(svn_client__conflict_report_t *report, + apr_pool_t *scratch_pool) { assert(!report || svn_dirent_is_absolute(report->target_abspath)); @@ -6512,10 +6468,7 @@ get_mergeinfo_paths(apr_array_header_t *children_with_mergeinfo, /* Sort CHILDREN_WITH_MERGEINFO by each child's path (i.e. as per compare_merge_path_t_as_paths). Any subsequent insertions of new children with insert_child_to_merge() require this ordering. */ - qsort(children_with_mergeinfo->elts, - children_with_mergeinfo->nelts, - children_with_mergeinfo->elt_size, - compare_merge_path_t_as_paths); + svn_sort__array(children_with_mergeinfo, compare_merge_path_t_as_paths); } svn_pool_destroy(swmi_pool); @@ -7125,8 +7078,7 @@ combine_range_with_segments(apr_array_header_t **merge_source_ts_p, /* If this was a subtractive merge, and we created more than one merge source, we need to reverse the sort ordering of our sources. */ if (subtractive && (merge_source_ts->nelts > 1)) - qsort(merge_source_ts->elts, merge_source_ts->nelts, - merge_source_ts->elt_size, compare_merge_source_ts); + svn_sort__array(merge_source_ts, compare_merge_source_ts); *merge_source_ts_p = merge_source_ts; return SVN_NO_ERROR; @@ -9814,7 +9766,7 @@ ensure_ra_session_url(svn_ra_session_t **ra_session, static svn_error_t * do_merge(apr_hash_t **modified_subtrees, svn_mergeinfo_catalog_t result_catalog, - conflict_report_t **conflict_report, + svn_client__conflict_report_t **conflict_report, svn_boolean_t *use_sleep, const apr_array_header_t *merge_sources, const merge_target_t *target, @@ -10137,23 +10089,24 @@ do_merge(apr_hash_t **modified_subtrees, SCRATCH_POOL is used for all temporary allocations. */ static svn_error_t * -merge_cousins_and_supplement_mergeinfo(conflict_report_t **conflict_report, - svn_boolean_t *use_sleep, - const merge_target_t *target, - svn_ra_session_t *URL1_ra_session, - svn_ra_session_t *URL2_ra_session, - const merge_source_t *source, - const svn_client__pathrev_t *yca, - svn_boolean_t same_repos, - svn_depth_t depth, - svn_boolean_t diff_ignore_ancestry, - svn_boolean_t force_delete, - svn_boolean_t record_only, - svn_boolean_t dry_run, - const apr_array_header_t *merge_options, - svn_client_ctx_t *ctx, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) +merge_cousins_and_supplement_mergeinfo( + svn_client__conflict_report_t **conflict_report, + svn_boolean_t *use_sleep, + const merge_target_t *target, + svn_ra_session_t *URL1_ra_session, + svn_ra_session_t *URL2_ra_session, + const merge_source_t *source, + const svn_client__pathrev_t *yca, + svn_boolean_t same_repos, + svn_depth_t depth, + svn_boolean_t diff_ignore_ancestry, + svn_boolean_t force_delete, + svn_boolean_t record_only, + svn_boolean_t dry_run, + const apr_array_header_t *merge_options, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { apr_array_header_t *remove_sources, *add_sources; apr_hash_t *modified_subtrees = NULL; @@ -10477,24 +10430,24 @@ open_target_wc(merge_target_t **target_p, * * IGNORE_MERGEINFO and DIFF_IGNORE_ANCESTRY are as in do_merge(). */ -static svn_error_t * -merge_locked(conflict_report_t **conflict_report, - const char *source1, - const svn_opt_revision_t *revision1, - const char *source2, - const svn_opt_revision_t *revision2, - const char *target_abspath, - svn_depth_t depth, - svn_boolean_t ignore_mergeinfo, - svn_boolean_t diff_ignore_ancestry, - svn_boolean_t force_delete, - svn_boolean_t record_only, - svn_boolean_t dry_run, - svn_boolean_t allow_mixed_rev, - const apr_array_header_t *merge_options, - svn_client_ctx_t *ctx, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) +svn_error_t * +svn_client__merge_locked(svn_client__conflict_report_t **conflict_report, + const char *source1, + const svn_opt_revision_t *revision1, + const char *source2, + const svn_opt_revision_t *revision2, + const char *target_abspath, + svn_depth_t depth, + svn_boolean_t ignore_mergeinfo, + svn_boolean_t diff_ignore_ancestry, + svn_boolean_t force_delete, + svn_boolean_t record_only, + svn_boolean_t dry_run, + svn_boolean_t allow_mixed_rev, + const apr_array_header_t *merge_options, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { merge_target_t *target; svn_client__pathrev_t *source1_loc, *source2_loc; @@ -10691,7 +10644,7 @@ svn_client_merge5(const char *source1, apr_pool_t *pool) { const char *target_abspath, *lock_abspath; - conflict_report_t *conflict_report; + svn_client__conflict_report_t *conflict_report; /* Sanity check our input -- we require specified revisions, * and either 2 paths or 2 URLs. */ @@ -10714,22 +10667,23 @@ svn_client_merge5(const char *source1, if (!dry_run) SVN_WC__CALL_WITH_WRITE_LOCK( - merge_locked(&conflict_report, - source1, revision1, source2, revision2, - target_abspath, depth, ignore_mergeinfo, - diff_ignore_ancestry, - force_delete, record_only, dry_run, - allow_mixed_rev, merge_options, ctx, pool, pool), + svn_client__merge_locked(&conflict_report, + source1, revision1, source2, revision2, + target_abspath, depth, ignore_mergeinfo, + diff_ignore_ancestry, + force_delete, record_only, dry_run, + allow_mixed_rev, merge_options, ctx, pool, pool), ctx->wc_ctx, lock_abspath, FALSE /* lock_anchor */, pool); else - SVN_ERR(merge_locked(&conflict_report, - source1, revision1, source2, revision2, - target_abspath, depth, ignore_mergeinfo, - diff_ignore_ancestry, - force_delete, record_only, dry_run, - allow_mixed_rev, merge_options, ctx, pool, pool)); + SVN_ERR(svn_client__merge_locked(&conflict_report, + source1, revision1, source2, revision2, + target_abspath, depth, ignore_mergeinfo, + diff_ignore_ancestry, + force_delete, record_only, dry_run, + allow_mixed_rev, merge_options, ctx, pool, + pool)); - SVN_ERR(make_merge_conflict_error(conflict_report, pool)); + SVN_ERR(svn_client__make_merge_conflict_error(conflict_report, pool)); return SVN_NO_ERROR; } @@ -11756,7 +11710,7 @@ open_reintegrate_source_and_target(svn_ra_session_t **source_ra_session_p, /* The body of svn_client_merge_reintegrate(), which see for details. */ static svn_error_t * -merge_reintegrate_locked(conflict_report_t **conflict_report, +merge_reintegrate_locked(svn_client__conflict_report_t **conflict_report, const char *source_path_or_url, const svn_opt_revision_t *source_peg_revision, const char *target_abspath, @@ -11831,7 +11785,7 @@ svn_client_merge_reintegrate(const char *source_path_or_url, apr_pool_t *pool) { const char *target_abspath, *lock_abspath; - conflict_report_t *conflict_report; + svn_client__conflict_report_t *conflict_report; SVN_ERR(get_target_and_lock_abspath(&target_abspath, &lock_abspath, target_wcpath, ctx, pool)); @@ -11851,7 +11805,7 @@ svn_client_merge_reintegrate(const char *source_path_or_url, FALSE /*diff_ignore_ancestry*/, dry_run, merge_options, ctx, pool, pool)); - SVN_ERR(make_merge_conflict_error(conflict_report, pool)); + SVN_ERR(svn_client__make_merge_conflict_error(conflict_report, pool)); return SVN_NO_ERROR; } @@ -11861,7 +11815,7 @@ svn_client_merge_reintegrate(const char *source_path_or_url, * IGNORE_MERGEINFO and DIFF_IGNORE_ANCESTRY are as in do_merge(). */ static svn_error_t * -merge_peg_locked(conflict_report_t **conflict_report, +merge_peg_locked(svn_client__conflict_report_t **conflict_report, const char *source_path_or_url, const svn_opt_revision_t *source_peg_revision, const svn_rangelist_t *ranges_to_merge, @@ -11913,6 +11867,21 @@ merge_peg_locked(conflict_report_t **conflict_report, /* Do the real merge! (We say with confidence that our merge sources are both ancestral and related.) */ + if (getenv("SVN_ELEMENT_MERGE") + && same_repos + && (depth == svn_depth_infinity || depth == svn_depth_unknown) + && ignore_mergeinfo + && !record_only) + { + err = svn_client__merge_elements(&use_sleep, + merge_sources, target, ra_session, + diff_ignore_ancestry, force_delete, + dry_run, merge_options, + ctx, result_pool, scratch_pool); + /* ### Currently this merge just errors out on any conflicts */ + *conflict_report = NULL; + } + else err = do_merge(NULL, NULL, conflict_report, &use_sleep, merge_sources, target, ra_session, TRUE /*sources_related*/, same_repos, ignore_mergeinfo, @@ -11951,7 +11920,7 @@ client_find_automatic_merge(automatic_merge_t **merge_p, apr_pool_t *scratch_pool); static svn_error_t * -do_automatic_merge_locked(conflict_report_t **conflict_report, +do_automatic_merge_locked(svn_client__conflict_report_t **conflict_report, const automatic_merge_t *merge, const char *target_abspath, svn_depth_t depth, @@ -11981,7 +11950,7 @@ svn_client_merge_peg5(const char *source_path_or_url, apr_pool_t *pool) { const char *target_abspath, *lock_abspath; - conflict_report_t *conflict_report; + svn_client__conflict_report_t *conflict_report; /* No ranges to merge? No problem. */ if (ranges_to_merge != NULL && ranges_to_merge->nelts == 0) @@ -12046,7 +12015,7 @@ svn_client_merge_peg5(const char *source_path_or_url, force_delete, record_only, dry_run, allow_mixed_rev, merge_options, ctx, pool, pool)); - SVN_ERR(make_merge_conflict_error(conflict_report, pool)); + SVN_ERR(svn_client__make_merge_conflict_error(conflict_report, pool)); return SVN_NO_ERROR; } @@ -12731,7 +12700,7 @@ client_find_automatic_merge(automatic_merge_t **merge_p, * eliminate already-cherry-picked revisions from the source. */ static svn_error_t * -do_automatic_merge_locked(conflict_report_t **conflict_report, +do_automatic_merge_locked(svn_client__conflict_report_t **conflict_report, const automatic_merge_t *merge, const char *target_abspath, svn_depth_t depth, diff --git a/subversion/libsvn_client/merge_elements.c b/subversion/libsvn_client/merge_elements.c new file mode 100644 index 000000000000..66c21b640593 --- /dev/null +++ b/subversion/libsvn_client/merge_elements.c @@ -0,0 +1,248 @@ +/* + * merge_elements.c: element-based merging + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#include +#include +#include +#include +#include "svn_types.h" +#include "svn_error.h" +#include "svn_pools.h" +#include "svn_hash.h" +#include "svn_wc.h" +#include "svn_client.h" +#include "svn_dirent_uri.h" + +#include "client.h" +#include "private/svn_element.h" + +#include "svn_private_config.h" + + +/* Print a notification. + * ### TODO: Send notifications through ctx->notify_func2(). + * ### TODO: Only when 'verbose' output is requested. + */ +static +__attribute__((format(printf, 1, 2))) +void +verbose_notify(const char *fmt, + ...) +{ + va_list ap; + + va_start(ap, fmt); + vprintf(fmt, ap); + if (fmt[strlen(fmt) - 1] != '\n') + printf("\n"); + va_end(ap); +} + +/* Return a string representation of PATHREV. */ +static const char * +pathrev_str(const svn_client__pathrev_t *pathrev, + apr_pool_t *pool) +{ + const char *rrpath + = svn_uri_skip_ancestor(pathrev->repos_root_url, pathrev->url, pool); + + return apr_psprintf(pool, "^/%s@%ld", rrpath, pathrev->rev); +} + +/* Element matching info. + */ +typedef struct element_matching_info_t +{ + void *info; +} element_matching_info_t; + +/* Return a string representation of INFO. */ +static const char * +element_matching_info_str(const element_matching_info_t *info, + apr_pool_t *result_pool) +{ + /* ### */ + const char *str = "{...}"; + + return str; +} + +/* Assign EIDs (in memory) to the source-left, source-right and target + * trees. + */ +static svn_error_t * +assign_eids_to_trees(svn_element__tree_t **tree_left_p, + svn_element__tree_t **tree_right_p, + svn_element__tree_t **tree_target_p, + const svn_client__pathrev_t *src_left, + const svn_client__pathrev_t *src_right, + merge_target_t *target, + svn_ra_session_t *ra_session, + element_matching_info_t *element_matching_info, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + verbose_notify("--- Assigning EIDs to trees"); + + /* ### */ + return SVN_NO_ERROR; +} + +/* Perform a three-way tree merge. Write the result to *MERGE_RESULT_P. + * + * Set *CONFLICTS_P to describe any conflicts, or set *CONFLICTS_P to + * null if there are none. + */ +static svn_error_t * +merge_trees(svn_element__tree_t **merge_result_p, + void **conflicts_p, + svn_element__tree_t *tree_left, + svn_element__tree_t *tree_right, + svn_element__tree_t *tree_target, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + verbose_notify("--- Merging trees"); + + /* ### */ + *merge_result_p = NULL; + *conflicts_p = NULL; + return SVN_NO_ERROR; +} + +/* Convert the MERGE_RESULT to a series of WC edits and apply those to + * the WC described in TARGET. + */ +static svn_error_t * +apply_merge_result_to_wc(merge_target_t *target, + svn_element__tree_t *merge_result, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + verbose_notify("--- Writing merge result to WC"); + + return SVN_NO_ERROR; +} + +/* Do a three-way element-based merge for one merge source range, + * SRC_LEFT:SRC_RIGHT. If there are no conflicts, write the result to the + * WC described in TARGET. + */ +static svn_error_t * +merge_elements_one_source(svn_boolean_t *use_sleep, + const svn_client__pathrev_t *src_left, + const svn_client__pathrev_t *src_right, + merge_target_t *target, + svn_ra_session_t *ra_session, + element_matching_info_t *element_matching_info, + svn_boolean_t diff_ignore_ancestry, + svn_boolean_t force_delete, + svn_boolean_t dry_run, + const apr_array_header_t *merge_options, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + svn_element__tree_t *tree_left, *tree_right, *tree_target; + svn_element__tree_t *merge_result; + void *conflicts; + + verbose_notify("--- Merging by elements: " + "left=%s, right=%s, matching=%s", + pathrev_str(src_left, scratch_pool), + pathrev_str(src_right, scratch_pool), + element_matching_info_str(element_matching_info, + scratch_pool)); + + /* assign EIDs (in memory) to the source-left, source-right and target + trees */ + SVN_ERR(assign_eids_to_trees(&tree_left, &tree_right, &tree_target, + src_left, src_right, target, ra_session, + element_matching_info, + ctx, scratch_pool, scratch_pool)); + + /* perform a tree merge, creating a temporary result (in memory) */ + SVN_ERR(merge_trees(&merge_result, &conflicts, + tree_left, tree_right, tree_target, + scratch_pool, scratch_pool)); + + /* check for (new style) conflicts in the result; if any, bail out */ + if (conflicts) + { + return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, + _("Merge had conflicts; " + "this is not yet supported")); + } + + /* convert the result to a series of WC edits and apply those to the WC */ + if (dry_run) + { + verbose_notify("--- Dry run; not writing merge result to WC"); + } + else + { + SVN_ERR(apply_merge_result_to_wc(target, merge_result, + ctx, scratch_pool)); + *use_sleep = TRUE; + } + + /* forget all the EID metadata */ + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client__merge_elements(svn_boolean_t *use_sleep, + apr_array_header_t *merge_sources, + merge_target_t *target, + svn_ra_session_t *ra_session, + svn_boolean_t diff_ignore_ancestry, + svn_boolean_t force_delete, + svn_boolean_t dry_run, + const apr_array_header_t *merge_options, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + int i; + + /* Merge each source range in turn */ + for (i = 0; i < merge_sources->nelts; i++) + { + merge_source_t *source + = APR_ARRAY_IDX(merge_sources, i, void *); + element_matching_info_t *element_matching_info; + + /* ### TODO: get element matching info from the user */ + element_matching_info = NULL; + + SVN_ERR(merge_elements_one_source(use_sleep, + source->loc1, source->loc2, + target, ra_session, + element_matching_info, + diff_ignore_ancestry, + force_delete, dry_run, merge_options, + ctx, scratch_pool)); + } + + return SVN_NO_ERROR; +} diff --git a/subversion/libsvn_client/mergeinfo.c b/subversion/libsvn_client/mergeinfo.c index 622dbbca2261..f4f5acd6c850 100644 --- a/subversion/libsvn_client/mergeinfo.c +++ b/subversion/libsvn_client/mergeinfo.c @@ -1946,12 +1946,12 @@ svn_client__mergeinfo_log(svn_boolean_t finding_merged, SVN_ERR(svn_mergeinfo__add_suffix_to_mergeinfo( &subtree_source_history, source_history, - subtree_rel_path, scratch_pool, scratch_pool)); + subtree_rel_path, scratch_pool, iterpool)); if (!finding_merged) SVN_ERR(svn_mergeinfo__add_suffix_to_mergeinfo( &subtree_history, target_history, - subtree_rel_path, scratch_pool, scratch_pool)); + subtree_rel_path, scratch_pool, iterpool)); } else { @@ -1969,7 +1969,7 @@ svn_client__mergeinfo_log(svn_boolean_t finding_merged, scratch_pool, iterpool)); SVN_ERR(svn_mergeinfo_merge2(subtree_mergeinfo, merged_via_history, - scratch_pool, scratch_pool)); + scratch_pool, iterpool)); } SVN_ERR(svn_mergeinfo_inheritable2(&subtree_inheritable_mergeinfo, @@ -1995,7 +1995,7 @@ svn_client__mergeinfo_log(svn_boolean_t finding_merged, subtree_source_history, FALSE, scratch_pool, iterpool)); svn_mergeinfo__set_inheritance(merged_noninheritable, FALSE, - scratch_pool); + iterpool); /* Keep track of all ranges partially merged to any and all subtrees. */ diff --git a/subversion/libsvn_client/mtcc.c b/subversion/libsvn_client/mtcc.c index e0fc1e9441b0..75889cad2746 100644 --- a/subversion/libsvn_client/mtcc.c +++ b/subversion/libsvn_client/mtcc.c @@ -568,10 +568,44 @@ svn_client__mtcc_add_copy(const char *src_relpath, return SVN_NO_ERROR; } -svn_error_t * -svn_client__mtcc_add_delete(const char *relpath, - svn_client__mtcc_t *mtcc, - apr_pool_t *scratch_pool) +/* Check if this operation contains at least one change that is not a + plain delete */ +static svn_boolean_t +mtcc_op_contains_non_delete(const mtcc_op_t *op) +{ + if (op->kind != OP_OPEN_DIR && op->kind != OP_OPEN_FILE + && op->kind != OP_DELETE) + { + return TRUE; + } + + if (op->prop_mods && op->prop_mods->nelts) + return TRUE; + + if (op->src_stream) + return TRUE; + + if (op->children) + { + int i; + + for (i = 0; i < op->children->nelts; i++) + { + const mtcc_op_t *c_op = APR_ARRAY_IDX(op->children, i, + const mtcc_op_t *); + + if (mtcc_op_contains_non_delete(c_op)) + return TRUE; + } + } + return FALSE; +} + +static svn_error_t * +mtcc_add_delete(const char *relpath, + svn_boolean_t for_move, + svn_client__mtcc_t *mtcc, + apr_pool_t *scratch_pool) { mtcc_op_t *op; svn_boolean_t created; @@ -598,6 +632,20 @@ svn_client__mtcc_add_delete(const char *relpath, SVN_ERR(mtcc_op_find(&op, &created, relpath, mtcc->root_op, FALSE, TRUE, TRUE, mtcc->pool, scratch_pool)); + if (!for_move && !op && !created) + { + /* Allow deleting directories, that are unmodified except for + one or more deleted descendants */ + + SVN_ERR(mtcc_op_find(&op, &created, relpath, mtcc->root_op, TRUE, + FALSE, FALSE, mtcc->pool, scratch_pool)); + + if (op && mtcc_op_contains_non_delete(op)) + op = NULL; + else + created = TRUE; + } + if (!op || !created) { return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL, @@ -613,6 +661,14 @@ svn_client__mtcc_add_delete(const char *relpath, return SVN_NO_ERROR; } +svn_error_t * +svn_client__mtcc_add_delete(const char *relpath, + svn_client__mtcc_t *mtcc, + apr_pool_t *scratch_pool) +{ + return svn_error_trace(mtcc_add_delete(relpath, FALSE, mtcc, scratch_pool)); +} + svn_error_t * svn_client__mtcc_add_mkdir(const char *relpath, svn_client__mtcc_t *mtcc, @@ -662,7 +718,7 @@ svn_client__mtcc_add_move(const char *src_relpath, SVN_ERR(svn_client__mtcc_add_copy(src_relpath, mtcc->base_revision, dst_relpath, mtcc, scratch_pool)); - SVN_ERR(svn_client__mtcc_add_delete(src_relpath, mtcc, scratch_pool)); + SVN_ERR(mtcc_add_delete(src_relpath, TRUE, mtcc, scratch_pool)); return SVN_NO_ERROR; } @@ -712,6 +768,7 @@ mtcc_prop_getter(const svn_string_t **mime_type, { *mime_type = svn_string_dup(mod->value, pool); mime_type = NULL; + break; } } } diff --git a/subversion/libsvn_client/patch.c b/subversion/libsvn_client/patch.c index 6d8d0a4632c8..1b2d86b1da94 100644 --- a/subversion/libsvn_client/patch.c +++ b/subversion/libsvn_client/patch.c @@ -46,6 +46,7 @@ #include "private/svn_eol_private.h" #include "private/svn_wc_private.h" #include "private/svn_dep_compat.h" +#include "private/svn_diff_private.h" #include "private/svn_string_private.h" #include "private/svn_subr_private.h" #include "private/svn_sorts_private.h" @@ -66,7 +67,10 @@ typedef struct hunk_info_t { /* The fuzz factor used when matching this hunk, i.e. how many * lines of leading and trailing context to ignore during matching. */ - svn_linenum_t fuzz; + svn_linenum_t match_fuzz; + + /* match_fuzz + the penalty caused by bad patch files */ + svn_linenum_t report_fuzz; } hunk_info_t; /* A struct carrying information related to the patched and unpatched @@ -152,6 +156,9 @@ typedef struct prop_patch_target_t { * ### Should we use flags instead since we're not using all enum values? */ svn_diff_operation_kind_t operation; + /* When true the property change won't be applied */ + svn_boolean_t skipped; + /* ### Here we'll add flags telling if the prop was added, deleted, * ### had_rejects, had_local_mods prior to patching and so on. */ } prop_patch_target_t; @@ -190,8 +197,8 @@ typedef struct patch_target_t { /* Path to the patched file. */ const char *patched_path; - /* Hunks that are rejected will be written to this file. */ - apr_file_t *reject_file; + /* Hunks that are rejected will be written to this stream. */ + svn_stream_t *reject_stream; /* Path to the reject file. */ const char *reject_path; @@ -209,15 +216,23 @@ typedef struct patch_target_t { /* True if the target had to be skipped for some reason. */ svn_boolean_t skipped; + /* True if the reason for skipping is a local obstruction */ + svn_boolean_t obstructed; + /* True if at least one hunk was rejected. */ svn_boolean_t had_rejects; /* True if at least one property hunk was rejected. */ svn_boolean_t had_prop_rejects; - /* True if the target file had local modifications before the - * patch was applied to it. */ - svn_boolean_t local_mods; + /* True if at least one hunk was handled as already applied */ + svn_boolean_t had_already_applied; + + /* True if at least one property hunk was handled as already applied */ + svn_boolean_t had_prop_already_applied; + + /* The operation on the target as set in the patch file */ + svn_diff_operation_kind_t operation; /* True if the target was added by the patch, which means that it did * not exist on disk before patching and has content after patching. */ @@ -226,10 +241,6 @@ typedef struct patch_target_t { /* True if the target ended up being deleted by the patch. */ svn_boolean_t deleted; - /* True if the target ended up being replaced by the patch - * (i.e. a new file was added on top locally deleted node). */ - svn_boolean_t replaced; - /* Set if the target is supposed to be moved by the patch. * This applies to --git diffs which carry "rename from/to" headers. */ const char *move_target_abspath; @@ -252,6 +263,10 @@ typedef struct patch_target_t { /* A hash table of prop_patch_target_t objects keyed by property names. */ apr_hash_t *prop_targets; + /* When TRUE, this patch uses the raw git symlink format instead of the + Subversion internal style format where links start with 'link '. */ + svn_boolean_t git_symlink_format; + } patch_target_t; @@ -261,8 +276,58 @@ typedef struct patch_target_t { typedef struct patch_target_info_t { const char *local_abspath; svn_boolean_t deleted; + svn_boolean_t added; } patch_target_info_t; +/* Check if LOCAL_ABSPATH is recorded as added in TARGETS_INFO */ +static svn_boolean_t +target_is_added(const apr_array_header_t *targets_info, + const char *local_abspath, + apr_pool_t *scratch_pool) +{ + int i; + + for (i = targets_info->nelts - 1; i >= 0; i--) + { + const patch_target_info_t *target_info = + APR_ARRAY_IDX(targets_info, i, const patch_target_info_t *); + + const char *info = svn_dirent_skip_ancestor(target_info->local_abspath, + local_abspath); + + if (info && !*info) + return target_info->added; + else if (info) + return FALSE; + } + + return FALSE; +} + +/* Check if LOCAL_ABSPATH or an ancestor is recorded as deleted in + TARGETS_INFO */ +static svn_boolean_t +target_is_deleted(const apr_array_header_t *targets_info, + const char *local_abspath, + apr_pool_t *scratch_pool) +{ + int i; + + for (i = targets_info->nelts - 1; i >= 0; i--) + { + const patch_target_info_t *target_info = + APR_ARRAY_IDX(targets_info, i, const patch_target_info_t *); + + const char *info = svn_dirent_skip_ancestor(target_info->local_abspath, + local_abspath); + + if (info) + return target_info->deleted; + } + + return FALSE; +} + /* Strip STRIP_COUNT components from the front of PATH, returning * the result in *RESULT, allocated in RESULT_POOL. @@ -368,18 +433,20 @@ obtain_eol_and_keywords_for_file(apr_hash_t **keywords, * Indicate in TARGET->SKIPPED whether the target should be skipped. * STRIP_COUNT specifies the number of leading path components * which should be stripped from target paths in the patch. - * PROP_CHANGES_ONLY specifies whether the target path is allowed to have - * only property changes, and no content changes (in which case the target - * must be a directory). + * HAS_TEXT_CHANGES specifies whether the target path will have some text + * changes applied, implying that the target should be a file and not a + * directory. * Use RESULT_POOL for allocations of fields in TARGET. * Use SCRATCH_POOL for all other allocations. */ static svn_error_t * resolve_target_path(patch_target_t *target, const char *path_from_patchfile, - const char *wcroot_abspath, + const char *root_abspath, int strip_count, - svn_boolean_t prop_changes_only, + svn_boolean_t has_text_changes, + svn_boolean_t follow_moves, svn_wc_context_t *wc_ctx, + const apr_array_header_t *targets_info, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { @@ -391,8 +458,8 @@ resolve_target_path(patch_target_t *target, target->canon_path_from_patchfile = svn_dirent_internal_style( path_from_patchfile, result_pool); - /* We allow properties to be set on the wc root dir. */ - if (! prop_changes_only && target->canon_path_from_patchfile[0] == '\0') + /* We can't handle text changes on the patch root dir. */ + if (has_text_changes && target->canon_path_from_patchfile[0] == '\0') { /* An empty patch target path? What gives? Skip this. */ target->skipped = TRUE; @@ -409,14 +476,14 @@ resolve_target_path(patch_target_t *target, if (svn_dirent_is_absolute(stripped_path)) { - target->local_relpath = svn_dirent_is_child(wcroot_abspath, + target->local_relpath = svn_dirent_is_child(root_abspath, stripped_path, result_pool); if (! target->local_relpath) { /* The target path is either outside of the working copy - * or it is the working copy itself. Skip it. */ + * or it is the patch root itself. Skip it. */ target->skipped = TRUE; target->local_abspath = NULL; target->local_relpath = stripped_path; @@ -429,9 +496,9 @@ resolve_target_path(patch_target_t *target, } /* Make sure the path is secure to use. We want the target to be inside - * of the working copy and not be fooled by symlinks it might contain. */ + * the locked tree and not be fooled by symlinks it might contain. */ SVN_ERR(svn_dirent_is_under_root(&under_root, - &target->local_abspath, wcroot_abspath, + &target->local_abspath, root_abspath, target->local_relpath, result_pool)); if (! under_root) @@ -442,6 +509,13 @@ resolve_target_path(patch_target_t *target, return SVN_NO_ERROR; } + if (target_is_deleted(targets_info, target->local_abspath, scratch_pool)) + { + target->locally_deleted = TRUE; + target->db_kind = svn_node_none; + return SVN_NO_ERROR; + } + /* Skip things we should not be messing with. */ err = svn_wc_status3(&status, wc_ctx, target->local_abspath, result_pool, scratch_pool); @@ -463,6 +537,7 @@ resolve_target_path(patch_target_t *target, status->conflicted) { target->skipped = TRUE; + target->obstructed = TRUE; return SVN_NO_ERROR; } else if (status->node_status == svn_wc_status_deleted) @@ -481,20 +556,29 @@ resolve_target_path(patch_target_t *target, if (target->locally_deleted) { - const char *moved_to_abspath; + const char *moved_to_abspath = NULL; + + if (follow_moves + && !target_is_added(targets_info, target->local_abspath, + scratch_pool)) + { + SVN_ERR(svn_wc__node_was_moved_away(&moved_to_abspath, NULL, + wc_ctx, target->local_abspath, + result_pool, scratch_pool)); + } - SVN_ERR(svn_wc__node_was_moved_away(&moved_to_abspath, NULL, - wc_ctx, target->local_abspath, - result_pool, scratch_pool)); - /* ### BUG: moved_to_abspath contains the target where the op-root was - ### moved to... not the target itself! */ if (moved_to_abspath) { target->local_abspath = moved_to_abspath; - target->local_relpath = svn_dirent_skip_ancestor(wcroot_abspath, - moved_to_abspath); - SVN_ERR_ASSERT(target->local_relpath && - target->local_relpath[0] != '\0'); + target->local_relpath = svn_dirent_skip_ancestor(root_abspath, + moved_to_abspath); + + if (!target->local_relpath || target->local_relpath[0] == '\0') + { + /* The target path is outside of the patch area. Skip it. */ + target->skipped = TRUE; + return SVN_NO_ERROR; + } /* As far as we are concerned this target is not locally deleted. */ target->locally_deleted = FALSE; @@ -511,6 +595,22 @@ resolve_target_path(patch_target_t *target, } } +#ifndef HAVE_SYMLINK + if (target->kind_on_disk == svn_node_file + && !target->is_symlink + && !target->locally_deleted + && status->prop_status != svn_wc_status_none) + { + const svn_string_t *value; + + SVN_ERR(svn_wc_prop_get2(&value, wc_ctx, target->local_abspath, + SVN_PROP_SPECIAL, scratch_pool, scratch_pool)); + + if (value) + target->is_symlink = TRUE; + } +#endif + return SVN_NO_ERROR; } @@ -540,7 +640,7 @@ readline_prop(void *baton, svn_stringbuf_t **line, const char **eol_str, svn_boolean_t *eof, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - prop_read_baton_t *b = (prop_read_baton_t *)baton; + prop_read_baton_t *b = baton; svn_stringbuf_t *str = NULL; const char *c; svn_boolean_t found_eof; @@ -593,7 +693,7 @@ readline_prop(void *baton, svn_stringbuf_t **line, const char **eol_str, while (c < b->value->data + b->value->len); if (eof) - *eof = found_eof; + *eof = found_eof && !(str && str->len > 0); *line = str; return SVN_NO_ERROR; @@ -605,7 +705,8 @@ readline_prop(void *baton, svn_stringbuf_t **line, const char **eol_str, static svn_error_t * tell_prop(void *baton, apr_off_t *offset, apr_pool_t *scratch_pool) { - prop_read_baton_t *b = (prop_read_baton_t *)baton; + prop_read_baton_t *b = baton; + *offset = b->offset; return SVN_NO_ERROR; } @@ -615,7 +716,8 @@ tell_prop(void *baton, apr_off_t *offset, apr_pool_t *scratch_pool) static svn_error_t * seek_prop(void *baton, apr_off_t offset, apr_pool_t *scratch_pool) { - prop_read_baton_t *b = (prop_read_baton_t *)baton; + prop_read_baton_t *b = baton; + b->offset = offset; return SVN_NO_ERROR; } @@ -626,7 +728,8 @@ static svn_error_t * write_prop(void *baton, const char *buf, apr_size_t len, apr_pool_t *scratch_pool) { - svn_stringbuf_t *patched_value = (svn_stringbuf_t *)baton; + svn_stringbuf_t *patched_value = baton; + svn_stringbuf_appendbytes(patched_value, buf, len); return SVN_NO_ERROR; } @@ -638,6 +741,7 @@ write_prop(void *baton, const char *buf, apr_size_t len, * Use SCRATCH_POOL for temporary allocations. */ static svn_error_t * init_prop_target(prop_patch_target_t **prop_target, + const patch_target_t *target, const char *prop_name, svn_diff_operation_kind_t operation, svn_wc_context_t *wc_ctx, @@ -647,7 +751,6 @@ init_prop_target(prop_patch_target_t **prop_target, prop_patch_target_t *new_prop_target; target_content_t *content; const svn_string_t *value; - svn_error_t *err; prop_read_baton_t *prop_read_baton; content = apr_pcalloc(result_pool, sizeof(*content)); @@ -664,18 +767,12 @@ init_prop_target(prop_patch_target_t **prop_target, new_prop_target->operation = operation; new_prop_target->content = content; - err = svn_wc_prop_get2(&value, wc_ctx, local_abspath, prop_name, - result_pool, scratch_pool); - if (err) - { - if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND) - { - svn_error_clear(err); - value = NULL; - } - else - return svn_error_trace(err); - } + if (!(target->deleted || target->db_kind == svn_node_none)) + SVN_ERR(svn_wc_prop_get2(&value, wc_ctx, local_abspath, prop_name, + result_pool, scratch_pool)); + else + value = NULL; + content->existed = (value != NULL); new_prop_target->value = value; new_prop_target->patched_value = svn_stringbuf_create_empty(result_pool); @@ -716,71 +813,15 @@ readline_file(void *baton, svn_stringbuf_t **line, const char **eol_str, svn_boolean_t *eof, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - apr_file_t *file = (apr_file_t *)baton; - svn_stringbuf_t *str = NULL; - apr_size_t numbytes; - char c; - svn_boolean_t found_eof; + apr_file_t *file = baton; - /* Read bytes into STR up to and including, but not storing, - * the next EOL sequence. */ - *eol_str = NULL; - numbytes = 1; - found_eof = FALSE; - while (!found_eof) - { - SVN_ERR(svn_io_file_read_full2(file, &c, sizeof(c), &numbytes, - &found_eof, scratch_pool)); - if (numbytes != 1) - { - found_eof = TRUE; - break; - } + SVN_ERR(svn_io_file_readline(file, line, eol_str, eof, APR_SIZE_MAX, + result_pool, scratch_pool)); - if (c == '\n') - { - *eol_str = "\n"; - } - else if (c == '\r') - { - *eol_str = "\r"; - - if (!found_eof) - { - apr_off_t pos; - - /* Check for "\r\n" by peeking at the next byte. */ - pos = 0; - SVN_ERR(svn_io_file_seek(file, APR_CUR, &pos, scratch_pool)); - SVN_ERR(svn_io_file_read_full2(file, &c, sizeof(c), &numbytes, - &found_eof, scratch_pool)); - if (numbytes == 1 && c == '\n') - { - *eol_str = "\r\n"; - } - else - { - /* Pretend we never peeked. */ - SVN_ERR(svn_io_file_seek(file, APR_SET, &pos, scratch_pool)); - found_eof = FALSE; - numbytes = 1; - } - } - } - else - { - if (str == NULL) - str = svn_stringbuf_create_ensure(80, result_pool); - svn_stringbuf_appendbyte(str, c); - } - - if (*eol_str) - break; - } - - if (eof) - *eof = found_eof; - *line = str; + if (!(*line)->len) + *line = NULL; + else + *eof = FALSE; return SVN_NO_ERROR; } @@ -791,9 +832,9 @@ readline_file(void *baton, svn_stringbuf_t **line, const char **eol_str, static svn_error_t * tell_file(void *baton, apr_off_t *offset, apr_pool_t *scratch_pool) { - apr_file_t *file = (apr_file_t *)baton; - *offset = 0; - SVN_ERR(svn_io_file_seek(file, APR_CUR, offset, scratch_pool)); + apr_file_t *file = baton; + + SVN_ERR(svn_io_file_get_offset(offset, file, scratch_pool)); return SVN_NO_ERROR; } @@ -802,7 +843,8 @@ tell_file(void *baton, apr_off_t *offset, apr_pool_t *scratch_pool) static svn_error_t * seek_file(void *baton, apr_off_t offset, apr_pool_t *scratch_pool) { - apr_file_t *file = (apr_file_t *)baton; + apr_file_t *file = baton; + SVN_ERR(svn_io_file_seek(file, APR_SET, &offset, scratch_pool)); return SVN_NO_ERROR; } @@ -813,27 +855,15 @@ static svn_error_t * write_file(void *baton, const char *buf, apr_size_t len, apr_pool_t *scratch_pool) { - apr_file_t *file = (apr_file_t *)baton; + apr_file_t *file = baton; + SVN_ERR(svn_io_file_write_full(file, buf, len, &len, scratch_pool)); return SVN_NO_ERROR; } -/* Handling symbolic links: - * - * In Subversion, symlinks can be represented on disk in two distinct ways. - * On systems which support symlinks, a symlink is created on disk. - * On systems which do not support symlink, a file is created on disk - * which contains the "normal form" of the symlink, which looks like: - * link TARGET - * where TARGET is the file the symlink points to. - * - * When reading symlinks (i.e. the link itself, not the file the symlink - * is pointing to) through the svn_subst_create_specialfile() function - * into a buffer, the buffer always contains the "normal form" of the symlink. - * Due to this representation symlinks always contain a single line of text. - * - * The functions below are needed to deal with the case where a patch - * wants to change the TARGET that a symlink points to. +/* Symlinks appear in patches in their repository normal form, abstracted by + * the svn_subst_* module. The functions below enable patches to change the + * targets of symlinks. */ /* Baton for the (readline|tell|seek|write)_symlink functions. */ @@ -869,16 +899,36 @@ readline_symlink(void *baton, svn_stringbuf_t **line, const char **eol_str, } else { - svn_string_t *dest; + svn_stream_t *stream; + const apr_size_t len_hint = 64; /* arbitrary */ - SVN_ERR(svn_io_read_link(&dest, sb->local_abspath, scratch_pool)); - *line = svn_stringbuf_createf(result_pool, "link %s", dest->data); + SVN_ERR(svn_subst_read_specialfile(&stream, sb->local_abspath, + scratch_pool, scratch_pool)); + SVN_ERR(svn_stringbuf_from_stream(line, stream, len_hint, result_pool)); + *eof = FALSE; sb->at_eof = TRUE; } return SVN_NO_ERROR; } +/* Identical to readline_symlink(), but returns symlink in raw format to + * allow patching links in git-style. + */ +static svn_error_t * +readline_symlink_git(void *baton, svn_stringbuf_t **line, const char **eol_str, + svn_boolean_t *eof, apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + SVN_ERR(readline_symlink(baton, line, eol_str, eof, + result_pool, scratch_pool)); + + if (*line && (*line)->len > 5 && !strncmp((*line)->data, "link ", 5)) + svn_stringbuf_remove(*line, 0, 5); /* Skip "link " */ + + return SVN_NO_ERROR; +} + /* Set *OFFSET to 1 or 0 depending on whether the "normal form" of * the symlink has already been read. */ static svn_error_t * @@ -901,35 +951,6 @@ seek_symlink(void *baton, apr_off_t offset, apr_pool_t *scratch_pool) return SVN_NO_ERROR; } - -/* Set the target of the symlink accessed via BATON. - * The contents of BUF must be a valid "normal form" of a symlink. */ -static svn_error_t * -write_symlink(void *baton, const char *buf, apr_size_t len, - apr_pool_t *scratch_pool) -{ - const char *target_abspath = baton; - const char *new_name; - const char *link = apr_pstrndup(scratch_pool, buf, len); - - if (strncmp(link, "link ", 5) != 0) - return svn_error_create(SVN_ERR_IO_WRITE_ERROR, NULL, - _("Invalid link representation")); - - link += 5; /* Skip "link " */ - - /* We assume the entire symlink is written at once, as the patch - format is line based */ - - SVN_ERR(svn_io_create_unique_link(&new_name, target_abspath, link, - ".tmp", scratch_pool)); - - SVN_ERR(svn_io_file_rename(new_name, target_abspath, scratch_pool)); - - return SVN_NO_ERROR; -} - - /* Return a suitable filename for the target of PATCH. * Examine the ``old'' and ``new'' file names, and choose the file name * with the fewest path components, the shortest basename, and the shortest @@ -987,32 +1008,19 @@ choose_target_filename(const svn_patch_t *patch) static svn_error_t * init_patch_target(patch_target_t **patch_target, const svn_patch_t *patch, - const char *wcroot_abspath, + const char *root_abspath, svn_wc_context_t *wc_ctx, int strip_count, svn_boolean_t remove_tempfiles, + const apr_array_header_t *targets_info, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { patch_target_t *target; target_content_t *content; - svn_boolean_t has_prop_changes = FALSE; - svn_boolean_t prop_changes_only = FALSE; + svn_boolean_t has_text_changes = FALSE; + svn_boolean_t follow_moves; - { - apr_hash_index_t *hi; - - for (hi = apr_hash_first(scratch_pool, patch->prop_patches); - hi; - hi = apr_hash_next(hi)) - { - svn_prop_patch_t *prop_patch = apr_hash_this_val(hi); - if (! has_prop_changes) - has_prop_changes = prop_patch->hunks->nelts > 0; - else - break; - } - } - - prop_changes_only = has_prop_changes && patch->hunks->nelts == 0; + has_text_changes = ((patch->hunks && patch->hunks->nelts > 0) + || patch->binary_patch); content = apr_pcalloc(result_pool, sizeof(*content)); @@ -1030,15 +1038,148 @@ init_patch_target(patch_target_t **patch_target, target->kind_on_disk = svn_node_none; target->content = content; target->prop_targets = apr_hash_make(result_pool); + target->operation = patch->operation; + + if (patch->operation == svn_diff_op_added /* Allow replacing */ + || patch->operation == svn_diff_op_moved) + { + follow_moves = FALSE; + } + else if (patch->operation == svn_diff_op_unchanged + && patch->hunks && patch->hunks->nelts == 1) + { + svn_diff_hunk_t *hunk = APR_ARRAY_IDX(patch->hunks, 0, + svn_diff_hunk_t *); + + follow_moves = (svn_diff_hunk_get_original_start(hunk) != 0); + } + else + follow_moves = TRUE; SVN_ERR(resolve_target_path(target, choose_target_filename(patch), - wcroot_abspath, strip_count, prop_changes_only, - wc_ctx, result_pool, scratch_pool)); + root_abspath, strip_count, has_text_changes, + follow_moves, wc_ctx, targets_info, + result_pool, scratch_pool)); *patch_target = target; if (! target->skipped) { - const char *diff_header; - apr_size_t len; + if (patch->old_symlink_bit == svn_tristate_true + || patch->new_symlink_bit == svn_tristate_true) + { + target->git_symlink_format = TRUE; + } + + /* ### Is it ok to set the operation of the target already here? Isn't + * ### the target supposed to be marked with an operation after we have + * ### determined that the changes will apply cleanly to the WC? Maybe + * ### we should have kept the patch field in patch_target_t to be + * ### able to distinguish between 'what the patch says we should do' + * ### and 'what we can do with the given state of our WC'. */ + if (patch->operation == svn_diff_op_added) + target->added = TRUE; + else if (patch->operation == svn_diff_op_deleted) + target->deleted = TRUE; + else if (patch->operation == svn_diff_op_moved) + { + const char *move_target_path; + const char *move_target_relpath; + svn_boolean_t under_root; + svn_boolean_t is_special; + svn_node_kind_t kind_on_disk; + svn_node_kind_t wc_kind; + + move_target_path = svn_dirent_internal_style(patch->new_filename, + scratch_pool); + + if (strip_count > 0) + SVN_ERR(strip_path(&move_target_path, move_target_path, + strip_count, scratch_pool, scratch_pool)); + + if (svn_dirent_is_absolute(move_target_path)) + { + move_target_relpath = svn_dirent_is_child(root_abspath, + move_target_path, + scratch_pool); + if (! move_target_relpath) + { + /* The move target path is either outside of the working + * copy or it is the working copy itself. Skip it. */ + target->skipped = TRUE; + return SVN_NO_ERROR; + } + } + else + move_target_relpath = move_target_path; + + /* Make sure the move target path is secure to use. */ + SVN_ERR(svn_dirent_is_under_root(&under_root, + &target->move_target_abspath, + root_abspath, + move_target_relpath, result_pool)); + if (! under_root) + { + /* The target path is outside of the working copy. Skip it. */ + target->skipped = TRUE; + target->move_target_abspath = NULL; + return SVN_NO_ERROR; + } + + SVN_ERR(svn_io_check_special_path(target->move_target_abspath, + &kind_on_disk, &is_special, + scratch_pool)); + SVN_ERR(svn_wc_read_kind2(&wc_kind, wc_ctx, + target->move_target_abspath, + FALSE, FALSE, scratch_pool)); + if (wc_kind == svn_node_file || wc_kind == svn_node_dir) + { + /* The move target path already exists on disk. */ + svn_error_t *err; + const char *moved_from_abspath; + + err = svn_wc__node_was_moved_here(&moved_from_abspath, NULL, + wc_ctx, + target->move_target_abspath, + scratch_pool, scratch_pool); + + if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND) + { + svn_error_clear(err); + err = NULL; + moved_from_abspath = NULL; + } + else + SVN_ERR(err); + + if (moved_from_abspath && (strcmp(moved_from_abspath, + target->local_abspath) == 0)) + { + target->local_abspath = target->move_target_abspath; + target->move_target_abspath = NULL; + target->operation = svn_diff_op_modified; + target->locally_deleted = FALSE; + target->db_kind = wc_kind; + target->kind_on_disk = kind_on_disk; + target->is_special = is_special; + + target->had_already_applied = TRUE; /* Make sure we notify */ + } + else + { + target->skipped = TRUE; + target->move_target_abspath = NULL; + return SVN_NO_ERROR; + } + + } + else if (kind_on_disk != svn_node_none + || target_is_added(targets_info, target->move_target_abspath, + scratch_pool)) + { + target->skipped = TRUE; + target->move_target_abspath = NULL; + return SVN_NO_ERROR; + } + } /* Create a temporary file to write the patched result to. * Also grab various bits of information about the file. */ @@ -1052,7 +1193,8 @@ init_patch_target(patch_target_t **patch_target, /* Wire up the read callbacks. */ content->read_baton = sb; - content->readline = readline_symlink; + content->readline = target->git_symlink_format ? readline_symlink_git + : readline_symlink; content->seek = seek_symlink; content->tell = tell_symlink; } @@ -1061,9 +1203,6 @@ init_patch_target(patch_target_t **patch_target, SVN_ERR(svn_io_file_open(&target->file, target->local_abspath, APR_READ | APR_BUFFERED, APR_OS_DEFAULT, result_pool)); - SVN_ERR(svn_wc_text_modified_p2(&target->local_mods, wc_ctx, - target->local_abspath, FALSE, - scratch_pool)); SVN_ERR(svn_io_is_file_executable(&target->executable, target->local_abspath, scratch_pool)); @@ -1083,121 +1222,25 @@ init_patch_target(patch_target_t **patch_target, content->read_baton = target->file; } - /* ### Is it ok to set the operation of the target already here? Isn't - * ### the target supposed to be marked with an operation after we have - * ### determined that the changes will apply cleanly to the WC? Maybe - * ### we should have kept the patch field in patch_target_t to be - * ### able to distinguish between 'what the patch says we should do' - * ### and 'what we can do with the given state of our WC'. */ - if (patch->operation == svn_diff_op_added) - target->added = TRUE; - else if (patch->operation == svn_diff_op_deleted) - target->deleted = TRUE; - else if (patch->operation == svn_diff_op_moved) - { - const char *move_target_path; - const char *move_target_relpath; - svn_boolean_t under_root; - svn_node_kind_t kind_on_disk; - svn_node_kind_t wc_kind; - - move_target_path = svn_dirent_internal_style(patch->new_filename, - scratch_pool); - - if (strip_count > 0) - SVN_ERR(strip_path(&move_target_path, move_target_path, - strip_count, scratch_pool, scratch_pool)); - - if (svn_dirent_is_absolute(move_target_path)) - { - move_target_relpath = svn_dirent_is_child(wcroot_abspath, - move_target_path, - scratch_pool); - if (! move_target_relpath) - { - /* The move target path is either outside of the working - * copy or it is the working copy itself. Skip it. */ - target->skipped = TRUE; - target->local_abspath = NULL; - return SVN_NO_ERROR; - } - } - else - move_target_relpath = move_target_path; - - /* Make sure the move target path is secure to use. */ - SVN_ERR(svn_dirent_is_under_root(&under_root, - &target->move_target_abspath, - wcroot_abspath, - move_target_relpath, result_pool)); - if (! under_root) - { - /* The target path is outside of the working copy. Skip it. */ - target->skipped = TRUE; - target->local_abspath = NULL; - return SVN_NO_ERROR; - } - - SVN_ERR(svn_io_check_path(target->move_target_abspath, - &kind_on_disk, scratch_pool)); - SVN_ERR(svn_wc_read_kind2(&wc_kind, wc_ctx, - target->move_target_abspath, - FALSE, FALSE, scratch_pool)); - if (kind_on_disk != svn_node_none || wc_kind != svn_node_none) - { - /* The move target path already exists on disk. Skip target. */ - target->skipped = TRUE; - target->move_target_abspath = NULL; - return SVN_NO_ERROR; - } - } - - if (! target->is_symlink) - { - /* Open a temporary file to write the patched result to. */ - SVN_ERR(svn_io_open_unique_file3(&target->patched_file, - &target->patched_path, NULL, - remove_tempfiles ? - svn_io_file_del_on_pool_cleanup : - svn_io_file_del_none, - result_pool, scratch_pool)); - - /* Put the write callback in place. */ - content->write = write_file; - content->write_baton = target->patched_file; - } - else - { - /* Put the write callback in place. */ - SVN_ERR(svn_io_open_unique_file3(NULL, - &target->patched_path, NULL, - remove_tempfiles ? - svn_io_file_del_on_pool_cleanup : - svn_io_file_del_none, - result_pool, scratch_pool)); - - content->write_baton = (void*)target->patched_path; - - content->write = write_symlink; - } - - /* Open a temporary file to write rejected hunks to. */ - SVN_ERR(svn_io_open_unique_file3(&target->reject_file, - &target->reject_path, NULL, + /* Open a temporary file to write the patched result to. */ + SVN_ERR(svn_io_open_unique_file3(&target->patched_file, + &target->patched_path, NULL, remove_tempfiles ? svn_io_file_del_on_pool_cleanup : svn_io_file_del_none, result_pool, scratch_pool)); - /* The reject file needs a diff header. */ - diff_header = apr_psprintf(scratch_pool, "--- %s%s+++ %s%s", - target->canon_path_from_patchfile, - APR_EOL_STR, - target->canon_path_from_patchfile, - APR_EOL_STR); - len = strlen(diff_header); - SVN_ERR(svn_io_file_write_full(target->reject_file, diff_header, len, - &len, scratch_pool)); + /* Put the write callback in place. */ + content->write = write_file; + content->write_baton = target->patched_file; + + /* Open a temporary stream to write rejected hunks to. */ + SVN_ERR(svn_stream_open_unique(&target->reject_stream, + &target->reject_path, NULL, + remove_tempfiles ? + svn_io_file_del_on_pool_cleanup : + svn_io_file_del_none, + result_pool, scratch_pool)); /* Handle properties. */ if (! target->skipped) @@ -1213,15 +1256,187 @@ init_patch_target(patch_target_t **patch_target, prop_patch_target_t *prop_target; SVN_ERR(init_prop_target(&prop_target, - prop_name, + target, prop_name, prop_patch->operation, wc_ctx, target->local_abspath, result_pool, scratch_pool)); svn_hash_sets(target->prop_targets, prop_name, prop_target); } + + /* Now, check for out-of-band mode changes and convert these in + their Subversion equivalent properties. */ + if (patch->new_executable_bit != svn_tristate_unknown + && patch->new_executable_bit != patch->old_executable_bit) + { + svn_diff_operation_kind_t operation; + + if (patch->new_executable_bit == svn_tristate_true) + operation = svn_diff_op_added; + else if (patch->new_executable_bit == svn_tristate_false) + { + /* Made non-executable. */ + if (patch->old_executable_bit == svn_tristate_true) + operation = svn_diff_op_deleted; + else + operation = svn_diff_op_unchanged; + } + else + operation = svn_diff_op_unchanged; + + if (operation != svn_diff_op_unchanged) + { + prop_patch_target_t *prop_target; + + prop_target = svn_hash_gets(target->prop_targets, + SVN_PROP_EXECUTABLE); + + if (prop_target && operation != prop_target->operation) + { + return svn_error_createf(SVN_ERR_INVALID_INPUT, NULL, + _("Invalid patch: specifies " + "contradicting mode changes and " + "%s changes (for '%s')"), + SVN_PROP_EXECUTABLE, + target->local_abspath); + } + else if (!prop_target) + { + SVN_ERR(init_prop_target(&prop_target, + target, SVN_PROP_EXECUTABLE, + operation, + wc_ctx, target->local_abspath, + result_pool, scratch_pool)); + svn_hash_sets(target->prop_targets, SVN_PROP_EXECUTABLE, + prop_target); + } + } + } + + if (patch->new_symlink_bit != svn_tristate_unknown + && patch->new_symlink_bit != patch->old_symlink_bit) + { + svn_diff_operation_kind_t operation; + + if (patch->new_symlink_bit == svn_tristate_true) + operation = svn_diff_op_added; + else if (patch->new_symlink_bit == svn_tristate_false) + { + /* Made non-symlink. */ + if (patch->old_symlink_bit == svn_tristate_true) + operation = svn_diff_op_deleted; + else + operation = svn_diff_op_unchanged; + } + else + operation = svn_diff_op_unchanged; + + if (operation != svn_diff_op_unchanged) + { + prop_patch_target_t *prop_target; + prop_target = svn_hash_gets(target->prop_targets, + SVN_PROP_SPECIAL); + + if (prop_target && operation != prop_target->operation) + { + return svn_error_createf(SVN_ERR_INVALID_INPUT, NULL, + _("Invalid patch: specifies " + "contradicting mode changes and " + "%s changes (for '%s')"), + SVN_PROP_SPECIAL, + target->local_abspath); + } + else if (!prop_target) + { + SVN_ERR(init_prop_target(&prop_target, + target, SVN_PROP_SPECIAL, + operation, + wc_ctx, target->local_abspath, + result_pool, scratch_pool)); + svn_hash_sets(target->prop_targets, SVN_PROP_SPECIAL, + prop_target); + } + } + } } } + if ((target->locally_deleted || target->db_kind == svn_node_none) + && !target->added + && target->operation == svn_diff_op_unchanged) + { + svn_boolean_t maybe_add = FALSE; + + if (patch->hunks && patch->hunks->nelts == 1) + { + svn_diff_hunk_t *hunk = APR_ARRAY_IDX(patch->hunks, 0, + svn_diff_hunk_t *); + + if (svn_diff_hunk_get_original_start(hunk) == 0) + maybe_add = TRUE; + } + else if (patch->prop_patches && apr_hash_count(patch->prop_patches)) + { + apr_hash_index_t *hi; + svn_boolean_t all_add = TRUE; + + for (hi = apr_hash_first(result_pool, patch->prop_patches); + hi; + hi = apr_hash_next(hi)) + { + svn_prop_patch_t *prop_patch = apr_hash_this_val(hi); + + if (prop_patch->operation != svn_diff_op_added) + { + all_add = FALSE; + break; + } + } + + maybe_add = all_add; + } + /* Other implied types */ + + if (maybe_add) + target->added = TRUE; + } + else if (!target->deleted && !target->added + && target->operation == svn_diff_op_unchanged) + { + svn_boolean_t maybe_delete = FALSE; + + if (patch->hunks && patch->hunks->nelts == 1) + { + svn_diff_hunk_t *hunk = APR_ARRAY_IDX(patch->hunks, 0, + svn_diff_hunk_t *); + + if (svn_diff_hunk_get_modified_start(hunk) == 0) + maybe_delete = TRUE; + } + + /* Other implied types */ + + if (maybe_delete) + target->deleted = TRUE; + } + + if (target->reject_stream != NULL) + { + /* The reject file needs a diff header. */ + const char *left_src = target->canon_path_from_patchfile; + const char *right_src = target->canon_path_from_patchfile; + + /* Handle moves specifically? */ + if (target->added) + left_src = "/dev/null"; + if (target->deleted) + right_src = "/dev/null"; + + SVN_ERR(svn_stream_printf(target->reject_stream, scratch_pool, + "--- %s" APR_EOL_STR + "+++ %s" APR_EOL_STR, + left_src, right_src)); + } + return SVN_NO_ERROR; } @@ -1354,12 +1569,20 @@ match_hunk(svn_boolean_t *matched, target_content_t *content, svn_linenum_t hunk_length; svn_linenum_t leading_context; svn_linenum_t trailing_context; + svn_linenum_t fuzz_penalty; *matched = FALSE; if (content->eof) return SVN_NO_ERROR; + fuzz_penalty = svn_diff_hunk__get_fuzz_penalty(hunk); + + if (fuzz_penalty > fuzz) + return SVN_NO_ERROR; + else + fuzz -= fuzz_penalty; + saved_line = content->current_line; lines_read = 0; lines_matched = FALSE; @@ -1568,14 +1791,14 @@ match_existing_target(svn_boolean_t *match, *match = FALSE; return SVN_NO_ERROR; } - } - while (lines_matched && ! content->eof && ! hunk_eof); - svn_pool_destroy(iterpool); + } + while (lines_matched && ! content->eof && ! hunk_eof); + svn_pool_destroy(iterpool); - *match = (lines_matched && content->eof == hunk_eof); - SVN_ERR(seek_to_line(content, saved_line, scratch_pool)); + *match = (lines_matched && content->eof == hunk_eof); + SVN_ERR(seek_to_line(content, saved_line, scratch_pool)); - return SVN_NO_ERROR; + return SVN_NO_ERROR; } /* Determine the line at which a HUNK applies to CONTENT of the TARGET @@ -1636,8 +1859,6 @@ get_hunk_info(hunk_info_t **hi, patch_target_t *target, { svn_boolean_t file_matches; - /* ### I can't reproduce anything but a no-match here. - The content is already at eof, so any hunk fails */ SVN_ERR(match_existing_target(&file_matches, content, hunk, scratch_pool)); if (file_matches) @@ -1682,8 +1903,11 @@ get_hunk_info(hunk_info_t **hi, patch_target_t *target, } else if (original_start > 0 && content->existed) { + svn_linenum_t modified_start; svn_linenum_t saved_line = content->current_line; + modified_start = svn_diff_hunk_get_modified_start(hunk); + /* Scan for a match at the line where the hunk thinks it * should be going. */ SVN_ERR(seek_to_line(content, original_start, scratch_pool)); @@ -1707,20 +1931,24 @@ get_hunk_info(hunk_info_t **hi, patch_target_t *target, * check would be ambiguous. */ if (fuzz == 0) { - svn_linenum_t modified_start; - - modified_start = svn_diff_hunk_get_modified_start(hunk); - if (modified_start == 0) + if (modified_start == 0 + && (target->operation == svn_diff_op_unchanged + || target->operation == svn_diff_op_deleted)) { - /* Patch wants to delete the file. + /* Patch wants to delete the file. */ - ### locally_deleted is always false here? */ already_applied = target->locally_deleted; } else { - SVN_ERR(seek_to_line(content, modified_start, - scratch_pool)); + svn_linenum_t seek_to; + + if (modified_start == 0) + seek_to = 1; /* Empty file case */ + else + seek_to = modified_start; + + SVN_ERR(seek_to_line(content, seek_to, scratch_pool)); SVN_ERR(scan_for_match(&matched_line, content, hunk, TRUE, modified_start + 1, @@ -1817,12 +2045,42 @@ get_hunk_info(hunk_info_t **hi, patch_target_t *target, } } } + else if (matched_line > 0 + && fuzz == 0 + && (svn_diff_hunk_get_leading_context(hunk) == 0 + || svn_diff_hunk_get_trailing_context(hunk) == 0) + && (svn_diff_hunk_get_modified_length(hunk) > + svn_diff_hunk_get_original_length(hunk))) + { + /* Check that we are not applying the same change that just adds some + lines again, when we don't have enough context to see the + difference */ + svn_linenum_t reverse_matched_line; + + SVN_ERR(seek_to_line(content, modified_start, scratch_pool)); + SVN_ERR(scan_for_match(&reverse_matched_line, content, + hunk, TRUE, + modified_start + 1, + fuzz, ignore_whitespace, TRUE, + cancel_func, cancel_baton, + scratch_pool)); + + /* We might want to check that we are actually at the start or the + end of the file. Having no context implies that we should be. */ + already_applied = (reverse_matched_line == modified_start); + } SVN_ERR(seek_to_line(content, saved_line, scratch_pool)); } + else if (!content->existed && svn_diff_hunk_get_modified_start(hunk) == 0) + { + /* The hunk wants to delete a file or property which doesn't exist. */ + matched_line = 0; + already_applied = TRUE; + } else { - /* The hunk wants to modify a file which doesn't exist. */ + /* The hunk wants to modify a file or property which doesn't exist. */ matched_line = 0; } @@ -1831,7 +2089,8 @@ get_hunk_info(hunk_info_t **hi, patch_target_t *target, (*hi)->matched_line = matched_line; (*hi)->rejected = (matched_line == 0); (*hi)->already_applied = already_applied; - (*hi)->fuzz = fuzz; + (*hi)->report_fuzz = fuzz; + (*hi)->match_fuzz = fuzz - svn_diff_hunk__get_fuzz_penalty(hunk); return SVN_NO_ERROR; } @@ -1877,8 +2136,6 @@ reject_hunk(patch_target_t *target, target_content_t *content, svn_diff_hunk_t *hunk, const char *prop_name, apr_pool_t *pool) { - const char *hunk_header; - apr_size_t len; svn_boolean_t eof; static const char * const text_atat = "@@"; static const char * const prop_atat = "##"; @@ -1887,14 +2144,9 @@ reject_hunk(patch_target_t *target, target_content_t *content, if (prop_name) { - const char *prop_header; - - /* ### Print 'Added', 'Deleted' or 'Modified' instead of 'Property'. - */ - prop_header = apr_psprintf(pool, "Property: %s\n", prop_name); - len = strlen(prop_header); - SVN_ERR(svn_io_file_write_full(target->reject_file, prop_header, - len, &len, pool)); + /* ### Print 'Added', 'Deleted' or 'Modified' instead of 'Property'. */ + svn_stream_printf(target->reject_stream, + pool, "Property: %s" APR_EOL_STR, prop_name); atat = prop_atat; } else @@ -1902,17 +2154,14 @@ reject_hunk(patch_target_t *target, target_content_t *content, atat = text_atat; } - hunk_header = apr_psprintf(pool, "%s -%lu,%lu +%lu,%lu %s%s", - atat, - svn_diff_hunk_get_original_start(hunk), - svn_diff_hunk_get_original_length(hunk), - svn_diff_hunk_get_modified_start(hunk), - svn_diff_hunk_get_modified_length(hunk), - atat, - APR_EOL_STR); - len = strlen(hunk_header); - SVN_ERR(svn_io_file_write_full(target->reject_file, hunk_header, len, - &len, pool)); + SVN_ERR(svn_stream_printf(target->reject_stream, pool, + "%s -%lu,%lu +%lu,%lu %s" APR_EOL_STR, + atat, + svn_diff_hunk_get_original_start(hunk), + svn_diff_hunk_get_original_length(hunk), + svn_diff_hunk_get_modified_start(hunk), + svn_diff_hunk_get_modified_length(hunk), + atat)); iterpool = svn_pool_create(pool); do @@ -1928,17 +2177,15 @@ reject_hunk(patch_target_t *target, target_content_t *content, { if (hunk_line->len >= 1) { - len = hunk_line->len; - SVN_ERR(svn_io_file_write_full(target->reject_file, - hunk_line->data, len, &len, - iterpool)); + apr_size_t len = hunk_line->len; + + SVN_ERR(svn_stream_write(target->reject_stream, + hunk_line->data, &len)); } if (eol_str) { - len = strlen(eol_str); - SVN_ERR(svn_io_file_write_full(target->reject_file, eol_str, - len, &len, iterpool)); + SVN_ERR(svn_stream_puts(target->reject_stream, eol_str)); } } } @@ -1965,6 +2212,7 @@ apply_hunk(patch_target_t *target, target_content_t *content, svn_linenum_t lines_read; svn_boolean_t eof; apr_pool_t *iterpool; + svn_linenum_t fuzz = hi->match_fuzz; /* ### Is there a cleaner way to describe if we have an existing target? */ @@ -1976,13 +2224,13 @@ apply_hunk(patch_target_t *target, target_content_t *content, * Also copy leading lines of context which matched with fuzz. * The target has changed on the fuzzy-matched lines, * so we should retain the target's version of those lines. */ - SVN_ERR(copy_lines_to_target(content, hi->matched_line + hi->fuzz, + SVN_ERR(copy_lines_to_target(content, hi->matched_line + fuzz, pool)); /* Skip the target's version of the hunk. * Don't skip trailing lines which matched with fuzz. */ line = content->current_line + - svn_diff_hunk_get_original_length(hi->hunk) - (2 * hi->fuzz); + svn_diff_hunk_get_original_length(hi->hunk) - (2 * fuzz); SVN_ERR(seek_to_line(content, line, pool)); if (content->current_line != line && ! content->eof) { @@ -2009,8 +2257,8 @@ apply_hunk(patch_target_t *target, target_content_t *content, &eol_str, &eof, iterpool, iterpool)); lines_read++; - if (lines_read > hi->fuzz && - lines_read <= svn_diff_hunk_get_modified_length(hi->hunk) - hi->fuzz) + if (lines_read > fuzz && + lines_read <= svn_diff_hunk_get_modified_length(hi->hunk) - fuzz) { apr_size_t len; @@ -2079,7 +2327,7 @@ send_hunk_notification(const hunk_info_t *hi, notify->hunk_modified_length = svn_diff_hunk_get_modified_length(hi->hunk); notify->hunk_matched_line = hi->matched_line; - notify->hunk_fuzz = hi->fuzz; + notify->hunk_fuzz = hi->report_fuzz; notify->prop_name = prop_name; ctx->notify_func2(ctx->notify_baton2, notify, pool); @@ -2092,7 +2340,7 @@ send_hunk_notification(const hunk_info_t *hi, static svn_error_t * send_patch_notification(const patch_target_t *target, const svn_client_ctx_t *ctx, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { svn_wc_notify_t *notify; svn_wc_notify_action_t action; @@ -2105,7 +2353,7 @@ send_patch_notification(const patch_target_t *target, action = svn_wc_notify_skip; else if (target->deleted) action = svn_wc_notify_delete; - else if (target->added || target->replaced || target->move_target_abspath) + else if (target->added || target->move_target_abspath) action = svn_wc_notify_add; else action = svn_wc_notify_patch; @@ -2116,16 +2364,17 @@ send_patch_notification(const patch_target_t *target, notify_path = target->local_abspath ? target->local_abspath : target->local_relpath; - notify = svn_wc_create_notify(notify_path, action, pool); - notify->kind = svn_node_file; + notify = svn_wc_create_notify(notify_path, action, scratch_pool); + notify->kind = (target->db_kind == svn_node_dir) ? svn_node_dir + : svn_node_file; if (action == svn_wc_notify_skip) { - if (target->db_kind == svn_node_none || - target->db_kind == svn_node_unknown) - notify->content_state = svn_wc_notify_state_missing; - else if (target->db_kind == svn_node_dir) + if (target->obstructed) notify->content_state = svn_wc_notify_state_obstructed; + else if (target->db_kind == svn_node_none || + target->db_kind == svn_node_unknown) + notify->content_state = svn_wc_notify_state_missing; else notify->content_state = svn_wc_notify_state_unknown; } @@ -2133,26 +2382,32 @@ send_patch_notification(const patch_target_t *target, { if (target->had_rejects) notify->content_state = svn_wc_notify_state_conflicted; - else if (target->local_mods) - notify->content_state = svn_wc_notify_state_merged; else if (target->has_text_changes) notify->content_state = svn_wc_notify_state_changed; + else if (target->had_already_applied) + notify->content_state = svn_wc_notify_state_merged; + else + notify->content_state = svn_wc_notify_state_unchanged; if (target->had_prop_rejects) notify->prop_state = svn_wc_notify_state_conflicted; else if (target->has_prop_changes) notify->prop_state = svn_wc_notify_state_changed; + else if (target->had_prop_already_applied) + notify->prop_state = svn_wc_notify_state_merged; + else + notify->prop_state = svn_wc_notify_state_unchanged; } - ctx->notify_func2(ctx->notify_baton2, notify, pool); + ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool); if (action == svn_wc_notify_patch) { int i; apr_pool_t *iterpool; - apr_hash_index_t *hash_index; + apr_array_header_t *prop_targets; - iterpool = svn_pool_create(pool); + iterpool = svn_pool_create(scratch_pool); for (i = 0; i < target->content->hunks->nelts; i++) { const hunk_info_t *hi; @@ -2165,26 +2420,30 @@ send_patch_notification(const patch_target_t *target, ctx, iterpool)); } - for (hash_index = apr_hash_first(pool, target->prop_targets); - hash_index; - hash_index = apr_hash_next(hash_index)) + prop_targets = svn_sort__hash(target->prop_targets, + svn_sort_compare_items_lexically, + scratch_pool); + for (i = 0; i < prop_targets->nelts; i++) { - prop_patch_target_t *prop_target; + int j; + svn_sort__item_t item = APR_ARRAY_IDX(prop_targets, i, + svn_sort__item_t); - prop_target = apr_hash_this_val(hash_index); + prop_patch_target_t *prop_target = item.value; - for (i = 0; i < prop_target->content->hunks->nelts; i++) + for (j = 0; j < prop_target->content->hunks->nelts; j++) { const hunk_info_t *hi; svn_pool_clear(iterpool); - hi = APR_ARRAY_IDX(prop_target->content->hunks, i, + hi = APR_ARRAY_IDX(prop_target->content->hunks, j, hunk_info_t *); /* Don't notify on the hunk level for added or deleted props. */ - if (prop_target->operation != svn_diff_op_added && + if ((prop_target->operation != svn_diff_op_added && prop_target->operation != svn_diff_op_deleted) + || hi->rejected || hi->already_applied) SVN_ERR(send_hunk_notification(hi, target, prop_target->name, ctx, iterpool)); } @@ -2192,13 +2451,13 @@ send_patch_notification(const patch_target_t *target, svn_pool_destroy(iterpool); } - if (target->move_target_abspath) + if (!target->skipped && target->move_target_abspath) { /* Notify about deletion of move source. */ notify = svn_wc_create_notify(target->local_abspath, - svn_wc_notify_delete, pool); + svn_wc_notify_delete, scratch_pool); notify->kind = svn_node_file; - ctx->notify_func2(ctx->notify_baton2, notify, pool); + ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool); } return SVN_NO_ERROR; @@ -2252,7 +2511,8 @@ sort_matched_hunks(const void *a, const void *b) * in RESULT_POOL. Use WC_CTX as the working copy context. * STRIP_COUNT specifies the number of leading path components * which should be stripped from target paths in the patch. - * REMOVE_TEMPFILES, PATCH_FUNC, and PATCH_BATON as in svn_client_patch(). + * REMOVE_TEMPFILES is as in svn_client_patch(). + * TARGETS_INFO is for preserving info across calls. * IGNORE_WHITESPACE tells whether whitespace should be considered when * doing the matching. * Call cancel CANCEL_FUNC with baton CANCEL_BATON to trigger cancellation. @@ -2263,6 +2523,7 @@ apply_one_patch(patch_target_t **patch_target, svn_patch_t *patch, int strip_count, svn_boolean_t ignore_whitespace, svn_boolean_t remove_tempfiles, + const apr_array_header_t *targets_info, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *result_pool, apr_pool_t *scratch_pool) @@ -2273,9 +2534,11 @@ apply_one_patch(patch_target_t **patch_target, svn_patch_t *patch, static const svn_linenum_t MAX_FUZZ = 2; apr_hash_index_t *hash_index; svn_linenum_t previous_offset = 0; + apr_array_header_t *prop_targets; SVN_ERR(init_patch_target(&target, patch, abs_wc_path, wc_ctx, strip_count, - remove_tempfiles, result_pool, scratch_pool)); + remove_tempfiles, targets_info, + result_pool, scratch_pool)); if (target->skipped) { *patch_target = target; @@ -2283,79 +2546,196 @@ apply_one_patch(patch_target_t **patch_target, svn_patch_t *patch, } iterpool = svn_pool_create(scratch_pool); - /* Match hunks. */ - for (i = 0; i < patch->hunks->nelts; i++) + + if (patch->hunks && patch->hunks->nelts) { - svn_diff_hunk_t *hunk; - hunk_info_t *hi; - svn_linenum_t fuzz = 0; - - svn_pool_clear(iterpool); - - if (cancel_func) - SVN_ERR(cancel_func(cancel_baton)); - - hunk = APR_ARRAY_IDX(patch->hunks, i, svn_diff_hunk_t *); - - /* Determine the line the hunk should be applied at. - * If no match is found initially, try with fuzz. */ - do + /* Match hunks. */ + for (i = 0; i < patch->hunks->nelts; i++) { - SVN_ERR(get_hunk_info(&hi, target, target->content, hunk, fuzz, - previous_offset, - ignore_whitespace, - FALSE /* is_prop_hunk */, - cancel_func, cancel_baton, - result_pool, iterpool)); - fuzz++; + svn_diff_hunk_t *hunk; + hunk_info_t *hi; + svn_linenum_t fuzz = 0; + + svn_pool_clear(iterpool); + + if (cancel_func) + SVN_ERR(cancel_func(cancel_baton)); + + hunk = APR_ARRAY_IDX(patch->hunks, i, svn_diff_hunk_t *); + + /* Determine the line the hunk should be applied at. + * If no match is found initially, try with fuzz. */ + do + { + SVN_ERR(get_hunk_info(&hi, target, target->content, hunk, fuzz, + previous_offset, + ignore_whitespace, + FALSE /* is_prop_hunk */, + cancel_func, cancel_baton, + result_pool, iterpool)); + fuzz++; + } + while (hi->rejected && fuzz <= MAX_FUZZ && ! hi->already_applied); + + if (hi->matched_line) + previous_offset + = hi->matched_line - svn_diff_hunk_get_original_start(hunk); + + APR_ARRAY_PUSH(target->content->hunks, hunk_info_t *) = hi; } - while (hi->rejected && fuzz <= MAX_FUZZ && ! hi->already_applied); - if (hi->matched_line) - previous_offset - = hi->matched_line - svn_diff_hunk_get_original_start(hunk); + /* Hunks are applied in the order determined by the matched line and + this may be different from the order of the original lines. */ + svn_sort__array(target->content->hunks, sort_matched_hunks); - APR_ARRAY_PUSH(target->content->hunks, hunk_info_t *) = hi; + /* Apply or reject hunks. */ + for (i = 0; i < target->content->hunks->nelts; i++) + { + hunk_info_t *hi; + + svn_pool_clear(iterpool); + + if (cancel_func) + SVN_ERR(cancel_func(cancel_baton)); + + hi = APR_ARRAY_IDX(target->content->hunks, i, hunk_info_t *); + if (hi->already_applied) + { + target->had_already_applied = TRUE; + continue; + } + else if (hi->rejected) + SVN_ERR(reject_hunk(target, target->content, hi->hunk, + NULL /* prop_name */, + iterpool)); + else + SVN_ERR(apply_hunk(target, target->content, hi, + NULL /* prop_name */, iterpool)); + } + + if (target->kind_on_disk == svn_node_file) + { + /* Copy any remaining lines to target. */ + SVN_ERR(copy_lines_to_target(target->content, 0, scratch_pool)); + if (! target->content->eof) + { + /* We could not copy the entire target file to the temporary + * file, and would truncate the target if we copied the + * temporary file on top of it. Skip this target. */ + target->skipped = TRUE; + } + } } - - /* Hunks are applied in the order determined by the matched line and - this may be different from the order of the original lines. */ - svn_sort__array(target->content->hunks, sort_matched_hunks); - - /* Apply or reject hunks. */ - for (i = 0; i < target->content->hunks->nelts; i++) + else if (patch->binary_patch) { - hunk_info_t *hi; + svn_stream_t *orig_stream; + svn_boolean_t same; + if (target->file) + orig_stream = svn_stream_from_aprfile2(target->file, TRUE, iterpool); + else + orig_stream = svn_stream_empty(iterpool); + + SVN_ERR(svn_stream_contents_same2( + &same, orig_stream, + svn_diff_get_binary_diff_original_stream(patch->binary_patch, + iterpool), + iterpool)); svn_pool_clear(iterpool); - if (cancel_func) - SVN_ERR(cancel_func(cancel_baton)); - - hi = APR_ARRAY_IDX(target->content->hunks, i, hunk_info_t *); - if (hi->already_applied) - continue; - else if (hi->rejected) - SVN_ERR(reject_hunk(target, target->content, hi->hunk, - NULL /* prop_name */, - iterpool)); - else - SVN_ERR(apply_hunk(target, target->content, hi, - NULL /* prop_name */, iterpool)); - } - - if (target->kind_on_disk == svn_node_file) - { - /* Copy any remaining lines to target. */ - SVN_ERR(copy_lines_to_target(target->content, 0, scratch_pool)); - if (! target->content->eof) + if (same) { - /* We could not copy the entire target file to the temporary file, - * and would truncate the target if we copied the temporary file - * on top of it. Skip this target. */ + /* The file in the working copy is identical to the one expected by + the patch... So we can write the result stream; no fuzz, + just a 100% match */ + + target->has_text_changes = TRUE; + } + else + { + /* Perhaps the file is identical to the resulting version, implying + that the patch has already been applied */ + if (target->file) + { + apr_off_t start = 0; + + SVN_ERR(svn_io_file_seek(target->file, APR_SET, &start, iterpool)); + + orig_stream = svn_stream_from_aprfile2(target->file, TRUE, iterpool); + } + else + orig_stream = svn_stream_empty(iterpool); + + SVN_ERR(svn_stream_contents_same2( + &same, orig_stream, + svn_diff_get_binary_diff_result_stream(patch->binary_patch, + iterpool), + iterpool)); + svn_pool_clear(iterpool); + + if (same) + target->had_already_applied = TRUE; + } + + if (same) + { + SVN_ERR(svn_stream_copy3( + svn_diff_get_binary_diff_result_stream(patch->binary_patch, + iterpool), + svn_stream_from_aprfile2(target->patched_file, TRUE, + iterpool), + cancel_func, cancel_baton, + iterpool)); + } + else + { + /* ### TODO: Implement a proper reject of a binary patch + + This should at least setup things for a proper notification, + and perhaps install a normal text conflict. Unlike normal unified + diff based patches we have all the versions we would need for + that in a much easier format than can be obtained from the patch + file. */ target->skipped = TRUE; } } + else if (target->move_target_abspath) + { + /* ### Why do we do this? + BH: I don't know, but if we don't do this some tests + on git style patches break. + + ### It would be much better to really move the actual file instead + of copying to a temporary file; move that to target and then + delete the original file + + ### BH: I have absolutely no idea if moving directories would work. + */ + if (target->kind_on_disk == svn_node_file) + { + /* Copy any remaining lines to target. (read: all lines) */ + SVN_ERR(copy_lines_to_target(target->content, 0, scratch_pool)); + if (!target->content->eof) + { + /* We could not copy the entire target file to the temporary + * file, and would truncate the target if we copied the + * temporary file on top of it. Skip this target. */ + target->skipped = TRUE; + } + } + } + + if (target->had_rejects || target->locally_deleted) + target->deleted = FALSE; + + if (target->added + && !(target->locally_deleted || target->db_kind == svn_node_none)) + { + target->added = FALSE; + } + + /* Assume nothing changed. Will be updated via property hunks */ + target->is_special = target->is_symlink; /* Match property hunks. */ for (hash_index = apr_hash_first(scratch_pool, patch->prop_patches); @@ -2369,8 +2749,8 @@ apply_one_patch(patch_target_t **patch_target, svn_patch_t *patch, prop_name = apr_hash_this_key(hash_index); prop_patch = apr_hash_this_val(hash_index); - if (! strcmp(prop_name, SVN_PROP_SPECIAL)) - target->is_special = TRUE; + if (!strcmp(prop_name, SVN_PROP_SPECIAL)) + target->is_special = (prop_patch->operation != svn_diff_op_deleted); /* We'll store matched hunks in prop_content. */ prop_target = svn_hash_gets(target->prop_targets, prop_name); @@ -2406,48 +2786,174 @@ apply_one_patch(patch_target_t **patch_target, svn_patch_t *patch, } } - /* Apply or reject property hunks. */ - for (hash_index = apr_hash_first(scratch_pool, target->prop_targets); - hash_index; - hash_index = apr_hash_next(hash_index)) + /* Match implied property hunks. */ + if (patch->new_executable_bit != svn_tristate_unknown + && patch->new_executable_bit != patch->old_executable_bit + && svn_hash_gets(target->prop_targets, SVN_PROP_EXECUTABLE) + && !svn_hash_gets(patch->prop_patches, SVN_PROP_EXECUTABLE)) { - prop_patch_target_t *prop_target; + hunk_info_t *hi; + svn_diff_hunk_t *hunk; + prop_patch_target_t *prop_target = svn_hash_gets(target->prop_targets, + SVN_PROP_EXECUTABLE); - prop_target = apr_hash_this_val(hash_index); + if (patch->new_executable_bit == svn_tristate_true) + SVN_ERR(svn_diff_hunk__create_adds_single_line( + &hunk, + SVN_PROP_EXECUTABLE_VALUE, + patch, + result_pool, + iterpool)); + else + SVN_ERR(svn_diff_hunk__create_deletes_single_line( + &hunk, + SVN_PROP_EXECUTABLE_VALUE, + patch, + result_pool, + iterpool)); - for (i = 0; i < prop_target->content->hunks->nelts; i++) + /* Derive a hunk_info from hunk. */ + SVN_ERR(get_hunk_info(&hi, target, prop_target->content, + hunk, 0 /* fuzz */, 0 /* previous_offset */, + ignore_whitespace, + TRUE /* is_prop_hunk */, + cancel_func, cancel_baton, + result_pool, iterpool)); + APR_ARRAY_PUSH(prop_target->content->hunks, hunk_info_t *) = hi; + } + + if (patch->new_symlink_bit != svn_tristate_unknown + && patch->new_symlink_bit != patch->old_symlink_bit + && svn_hash_gets(target->prop_targets, SVN_PROP_SPECIAL) + && !svn_hash_gets(patch->prop_patches, SVN_PROP_SPECIAL)) + { + hunk_info_t *hi; + svn_diff_hunk_t *hunk; + + prop_patch_target_t *prop_target = svn_hash_gets(target->prop_targets, + SVN_PROP_SPECIAL); + + if (patch->new_symlink_bit == svn_tristate_true) + { + SVN_ERR(svn_diff_hunk__create_adds_single_line( + &hunk, + SVN_PROP_SPECIAL_VALUE, + patch, + result_pool, + iterpool)); + target->is_special = TRUE; + } + else + { + SVN_ERR(svn_diff_hunk__create_deletes_single_line( + &hunk, + SVN_PROP_SPECIAL_VALUE, + patch, + result_pool, + iterpool)); + target->is_special = FALSE; + } + + /* Derive a hunk_info from hunk. */ + SVN_ERR(get_hunk_info(&hi, target, prop_target->content, + hunk, 0 /* fuzz */, 0 /* previous_offset */, + ignore_whitespace, + TRUE /* is_prop_hunk */, + cancel_func, cancel_baton, + result_pool, iterpool)); + APR_ARRAY_PUSH(prop_target->content->hunks, hunk_info_t *) = hi; + } + + /* When the node is deleted or does not exist after the patch is applied + we should reject a few more property hunks that can't be applied even + though the source matched */ + if (target->deleted + || (!target->added && + (target->locally_deleted || target->db_kind == svn_node_none))) + { + for (hash_index = apr_hash_first(scratch_pool, target->prop_targets); + hash_index; + hash_index = apr_hash_next(hash_index)) + { + prop_patch_target_t *prop_target = apr_hash_this_val(hash_index); + + if (prop_target->operation == svn_diff_op_deleted) + continue; + + for (i = 0; i < prop_target->content->hunks->nelts; i++) + { + hunk_info_t *hi; + + hi = APR_ARRAY_IDX(prop_target->content->hunks, i, hunk_info_t*); + + if (hi->already_applied || hi->rejected) + continue; + else + { + hi->rejected = TRUE; + prop_target->skipped = TRUE; + + if (!target->deleted && !target->added) + target->skipped = TRUE; + } + } + } + } + + /* Apply or reject property hunks. */ + + prop_targets = svn_sort__hash(target->prop_targets, + svn_sort_compare_items_lexically, + scratch_pool); + for (i = 0; i < prop_targets->nelts; i++) + { + svn_sort__item_t item = APR_ARRAY_IDX(prop_targets, i, svn_sort__item_t); + prop_patch_target_t *prop_target = item.value; + svn_boolean_t applied_one = FALSE; + int j; + + for (j = 0; j < prop_target->content->hunks->nelts; j++) { hunk_info_t *hi; svn_pool_clear(iterpool); - hi = APR_ARRAY_IDX(prop_target->content->hunks, i, + hi = APR_ARRAY_IDX(prop_target->content->hunks, j, hunk_info_t *); if (hi->already_applied) - continue; + { + target->had_prop_already_applied = TRUE; + continue; + } else if (hi->rejected) SVN_ERR(reject_hunk(target, prop_target->content, hi->hunk, prop_target->name, iterpool)); else - SVN_ERR(apply_hunk(target, prop_target->content, hi, - prop_target->name, - iterpool)); + { + SVN_ERR(apply_hunk(target, prop_target->content, hi, + prop_target->name, + iterpool)); + applied_one = TRUE; + } } - if (prop_target->content->existed) - { - /* Copy any remaining lines to target. */ - SVN_ERR(copy_lines_to_target(prop_target->content, 0, - scratch_pool)); - if (! prop_target->content->eof) - { - /* We could not copy the entire target property to the - * temporary file, and would truncate the target if we - * copied the temporary file on top of it. Skip this target. */ - target->skipped = TRUE; - } - } + if (!applied_one) + prop_target->skipped = TRUE; + + if (applied_one && prop_target->content->existed) + { + /* Copy any remaining lines to target. */ + SVN_ERR(copy_lines_to_target(prop_target->content, 0, + scratch_pool)); + if (! prop_target->content->eof) + { + /* We could not copy the entire target property to the + * temporary stream, and would truncate the target if we + * copied the temporary stream on top of it. Skip this target. */ + prop_target->skipped = TRUE; + } + } } svn_pool_destroy(iterpool); @@ -2460,57 +2966,9 @@ apply_one_patch(patch_target_t **patch_target, svn_patch_t *patch, * will be closed later in write_out_rejected_hunks(). */ if (target->kind_on_disk == svn_node_file) SVN_ERR(svn_io_file_close(target->file, scratch_pool)); - - SVN_ERR(svn_io_file_close(target->patched_file, scratch_pool)); } - if (! target->skipped) - { - apr_finfo_t working_file; - apr_finfo_t patched_file; - - /* Get sizes of the patched temporary file and the working file. - * We'll need those to figure out whether we should delete the - * patched file. */ - SVN_ERR(svn_io_stat(&patched_file, target->patched_path, - APR_FINFO_SIZE | APR_FINFO_LINK, scratch_pool)); - if (target->kind_on_disk == svn_node_file) - SVN_ERR(svn_io_stat(&working_file, target->local_abspath, - APR_FINFO_SIZE | APR_FINFO_LINK, scratch_pool)); - else - working_file.size = 0; - - if (patched_file.size == 0 && working_file.size > 0) - { - /* If a unidiff removes all lines from a file, that usually - * means deletion, so we can confidently schedule the target - * for deletion. In the rare case where the unidiff was really - * meant to replace a file with an empty one, this may not - * be desirable. But the deletion can easily be reverted and - * creating an empty file manually is not exactly hard either. */ - target->deleted = (target->db_kind == svn_node_file); - } - else if (patched_file.size == 0 && working_file.size == 0) - { - /* The target was empty or non-existent to begin with - * and no content was changed by patching. - * Report this as skipped if it didn't exist, unless in the special - * case of adding an empty file which has properties set on it or - * adding an empty file with a 'git diff' */ - if (target->kind_on_disk == svn_node_none - && ! target->has_prop_changes - && ! target->added) - target->skipped = TRUE; - } - else if (patched_file.size > 0 && working_file.size == 0) - { - /* The patch has created a file. */ - if (target->locally_deleted) - target->replaced = TRUE; - else if (target->db_kind == svn_node_none) - target->added = TRUE; - } - } + SVN_ERR(svn_io_file_close(target->patched_file, scratch_pool)); *patch_target = target; @@ -2520,6 +2978,9 @@ apply_one_patch(patch_target_t **patch_target, svn_patch_t *patch, /* Try to create missing parent directories for TARGET in the working copy * rooted at ABS_WC_PATH, and add the parents to version control. * If the parents cannot be created, mark the target as skipped. + * + * In dry run mode record missing parents in ALREADY_ADDED + * * Use client context CTX. If DRY_RUN is true, do not create missing * parents but issue notifications only. * Use SCRATCH_POOL for temporary allocations. */ @@ -2528,6 +2989,7 @@ create_missing_parents(patch_target_t *target, const char *abs_wc_path, svn_client_ctx_t *ctx, svn_boolean_t dry_run, + apr_array_header_t *targets_info, apr_pool_t *scratch_pool) { const char *local_abspath; @@ -2608,12 +3070,28 @@ create_missing_parents(patch_target_t *target, for (i = present_components; i < components->nelts - 1; i++) { const char *component; + patch_target_info_t *pti; svn_pool_clear(iterpool); + if (ctx->cancel_func) + SVN_ERR(ctx->cancel_func(ctx->cancel_baton)); + component = APR_ARRAY_IDX(components, i, const char *); local_abspath = svn_dirent_join(local_abspath, component, scratch_pool); + + if (target_is_added(targets_info, local_abspath, iterpool)) + continue; + + pti = apr_pcalloc(targets_info->pool, sizeof(*pti)); + + pti->local_abspath = apr_pstrdup(targets_info->pool, + local_abspath); + pti->added = TRUE; + + APR_ARRAY_PUSH(targets_info, patch_target_info_t *) = pti; + if (dry_run) { if (ctx->notify_func2) @@ -2634,10 +3112,6 @@ create_missing_parents(patch_target_t *target, * to version control. Allow cancellation since we * have not modified the working copy yet for this * target. */ - - if (ctx->cancel_func) - SVN_ERR(ctx->cancel_func(ctx->cancel_baton)); - SVN_ERR(svn_wc_add_from_disk3(ctx->wc_ctx, local_abspath, NULL /*props*/, FALSE /* skip checks */, @@ -2653,11 +3127,17 @@ create_missing_parents(patch_target_t *target, /* Install a patched TARGET into the working copy at ABS_WC_PATH. * Use client context CTX to retrieve WC_CTX, and possibly doing - * notifications. If DRY_RUN is TRUE, don't modify the working copy. + * notifications. + * + * Pass on ALREADY_ADDED to allow recording already added ancestors + * in dry-run mode. + * + * If DRY_RUN is TRUE, don't modify the working copy. * Do temporary allocations in POOL. */ static svn_error_t * install_patched_target(patch_target_t *target, const char *abs_wc_path, svn_client_ctx_t *ctx, svn_boolean_t dry_run, + apr_array_header_t *targets_info, apr_pool_t *pool) { if (target->deleted) @@ -2671,13 +3151,15 @@ install_patched_target(patch_target_t *target, const char *abs_wc_path, * notify about what we did before aborting. */ SVN_ERR(svn_wc_delete4(ctx->wc_ctx, target->local_abspath, FALSE /* keep_local */, FALSE, - NULL, NULL, NULL, NULL, pool)); + ctx->cancel_func, ctx->cancel_baton, + NULL, NULL /* notify */, + pool)); } } else { svn_node_kind_t parent_db_kind; - if (target->added || target->replaced) + if (target->added) { const char *parent_abspath; @@ -2707,7 +3189,7 @@ install_patched_target(patch_target_t *target, const char *abs_wc_path, } else SVN_ERR(create_missing_parents(target, abs_wc_path, ctx, - dry_run, pool)); + dry_run, targets_info, pool)); } else @@ -2723,6 +3205,8 @@ install_patched_target(patch_target_t *target, const char *abs_wc_path, || wc_kind != target->kind_on_disk) { target->skipped = TRUE; + if (wc_kind != target->kind_on_disk) + target->obstructed = TRUE; } } @@ -2739,6 +3223,8 @@ install_patched_target(patch_target_t *target, const char *abs_wc_path, SVN_ERR(svn_subst_create_specialfile(&stream, target->local_abspath, pool, pool)); + if (target->git_symlink_format) + SVN_ERR(svn_stream_puts(stream, "link ")); SVN_ERR(svn_stream_copy3(patched_stream, stream, ctx->cancel_func, ctx->cancel_baton, pool)); @@ -2766,7 +3252,7 @@ install_patched_target(patch_target_t *target, const char *abs_wc_path, ctx->cancel_func, ctx->cancel_baton, pool)); } - if (target->added || target->replaced) + if (target->added) { /* The target file didn't exist previously, * so add it to version control. @@ -2800,7 +3286,8 @@ install_patched_target(patch_target_t *target, const char *abs_wc_path, target->move_target_abspath, TRUE, /* metadata_only */ FALSE, /* allow_mixed_revisions */ - NULL, NULL, NULL, NULL, + ctx->cancel_func, ctx->cancel_baton, + NULL, NULL, pool)); /* Delete the patch target's old location from disk. */ @@ -2818,20 +3305,54 @@ install_patched_target(patch_target_t *target, const char *abs_wc_path, */ static svn_error_t * write_out_rejected_hunks(patch_target_t *target, + const char *root_abspath, svn_boolean_t dry_run, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { - SVN_ERR(svn_io_file_close(target->reject_file, pool)); - if (! dry_run && (target->had_rejects || target->had_prop_rejects)) { /* Write out rejected hunks, if any. */ - SVN_ERR(svn_io_copy_file(target->reject_path, - apr_psprintf(pool, "%s.svnpatch.rej", - target->local_abspath), - FALSE, pool)); + apr_file_t *reject_file; + svn_error_t *err; + + err = svn_io_open_uniquely_named(&reject_file, NULL, + svn_dirent_dirname(target->local_abspath, + scratch_pool), + svn_dirent_basename( + target->local_abspath, + NULL), + ".svnpatch.rej", + svn_io_file_del_none, + scratch_pool, scratch_pool); + if (err && APR_STATUS_IS_ENOENT(err->apr_err)) + { + /* The hunk applies to a file in a directory which does not exist. + * Put the reject file into the working copy root instead. */ + svn_error_clear(err); + SVN_ERR(svn_io_open_uniquely_named(&reject_file, NULL, + root_abspath, + svn_dirent_basename( + target->local_abspath, + NULL), + ".svnpatch.rej", + svn_io_file_del_none, + scratch_pool, scratch_pool)); + } + else + SVN_ERR(err); + + SVN_ERR(svn_stream_reset(target->reject_stream)); + + /* svn_stream_copy3() closes the files for us */ + SVN_ERR(svn_stream_copy3(target->reject_stream, + svn_stream_from_aprfile2(reject_file, FALSE, + scratch_pool), + NULL, NULL, scratch_pool)); /* ### TODO mark file as conflicted. */ } + else + SVN_ERR(svn_stream_close(target->reject_stream)); + return SVN_NO_ERROR; } @@ -2845,6 +3366,13 @@ install_patched_prop_targets(patch_target_t *target, { apr_hash_index_t *hi; apr_pool_t *iterpool; + const char *local_abspath; + + /* Apply properties to a move target if there is one */ + if (target->move_target_abspath) + local_abspath = target->move_target_abspath; + else + local_abspath = target->local_abspath; iterpool = svn_pool_create(scratch_pool); @@ -2861,11 +3389,14 @@ install_patched_prop_targets(patch_target_t *target, if (ctx->cancel_func) SVN_ERR(ctx->cancel_func(ctx->cancel_baton)); + if (prop_target->skipped) + continue; + /* For a deleted prop we only set the value to NULL. */ if (prop_target->operation == svn_diff_op_deleted) { if (! dry_run) - SVN_ERR(svn_wc_prop_set4(ctx->wc_ctx, target->local_abspath, + SVN_ERR(svn_wc_prop_set4(ctx->wc_ctx, local_abspath, prop_target->name, NULL, svn_depth_empty, TRUE /* skip_checks */, NULL /* changelist_filter */, @@ -2875,31 +3406,6 @@ install_patched_prop_targets(patch_target_t *target, continue; } - /* If the patch target doesn't exist yet, the patch wants to add an - * empty file with properties set on it. So create an empty file and - * add it to version control. But if the patch was in the 'git format' - * then the file has already been added. - * - * ### How can we tell whether the patch really wanted to create - * ### an empty directory? */ - if (! target->has_text_changes - && target->kind_on_disk == svn_node_none - && ! target->added) - { - if (! dry_run) - { - SVN_ERR(svn_io_file_create_empty(target->local_abspath, - scratch_pool)); - SVN_ERR(svn_wc_add_from_disk3(ctx->wc_ctx, target->local_abspath, - NULL /*props*/, - FALSE /* skip checks */, - /* suppress notification */ - NULL, NULL, - iterpool)); - } - target->added = TRUE; - } - /* Attempt to set the property, and reject all hunks if this fails. If the property had a non-empty value, but now has an empty one, we'll just delete the property altogether. */ @@ -2915,7 +3421,7 @@ install_patched_prop_targets(patch_target_t *target, err = svn_wc_canonicalize_svn_prop(&canon_propval, prop_target->name, - prop_val, target->local_abspath, + prop_val, local_abspath, target->db_kind, TRUE, /* ### Skipping checks */ NULL, NULL, @@ -2923,7 +3429,7 @@ install_patched_prop_targets(patch_target_t *target, } else { - err = svn_wc_prop_set4(ctx->wc_ctx, target->local_abspath, + err = svn_wc_prop_set4(ctx->wc_ctx, local_abspath, prop_target->name, prop_val, svn_depth_empty, TRUE /* skip_checks */, NULL /* changelist_filter */, @@ -3105,7 +3611,7 @@ static svn_error_t * apply_patches(/* The path to the patch file. */ const char *patch_abspath, /* The abspath to the working copy the patch should be applied to. */ - const char *abs_wc_path, + const char *root_abspath, /* Indicates whether we're doing a dry run. */ svn_boolean_t dry_run, /* Number of leading components to strip from patch target paths. */ @@ -3150,9 +3656,10 @@ apply_patches(/* The path to the patch file. */ patch_target_t *target; svn_boolean_t filtered = FALSE; - SVN_ERR(apply_one_patch(&target, patch, abs_wc_path, + SVN_ERR(apply_one_patch(&target, patch, root_abspath, ctx->wc_ctx, strip_count, ignore_whitespace, remove_tempfiles, + targets_info, ctx->cancel_func, ctx->cancel_baton, iterpool, iterpool)); @@ -3172,31 +3679,34 @@ apply_patches(/* The path to the patch file. */ target_info->local_abspath = apr_pstrdup(scratch_pool, target->local_abspath); target_info->deleted = target->deleted; + target_info->added = target->added; if (! target->skipped) { - APR_ARRAY_PUSH(targets_info, - patch_target_info_t *) = target_info; - if (target->has_text_changes || target->added || target->move_target_abspath || target->deleted) - SVN_ERR(install_patched_target(target, abs_wc_path, - ctx, dry_run, iterpool)); + SVN_ERR(install_patched_target(target, root_abspath, + ctx, dry_run, + targets_info, iterpool)); if (target->has_prop_changes && (!target->deleted)) SVN_ERR(install_patched_prop_targets(target, ctx, dry_run, iterpool)); - SVN_ERR(write_out_rejected_hunks(target, dry_run, iterpool)); - } + SVN_ERR(write_out_rejected_hunks(target, root_abspath, + dry_run, iterpool)); + + APR_ARRAY_PUSH(targets_info, + patch_target_info_t *) = target_info; + } SVN_ERR(send_patch_notification(target, ctx, iterpool)); if (target->deleted && !target->skipped) { SVN_ERR(check_ancestor_delete(target_info->local_abspath, - targets_info, abs_wc_path, + targets_info, root_abspath, dry_run, ctx, scratch_pool, iterpool)); } diff --git a/subversion/libsvn_client/ra.c b/subversion/libsvn_client/ra.c index f98b4b0708ee..d50e720bd0f1 100644 --- a/subversion/libsvn_client/ra.c +++ b/subversion/libsvn_client/ra.c @@ -727,7 +727,7 @@ repos_locations(const char **start_url, /* We'd better have all the paths we were looking for! */ if (start_url) { - start_path = apr_hash_get(rev_locs, &start_revnum, sizeof(svn_revnum_t)); + start_path = apr_hash_get(rev_locs, &start_revnum, sizeof(start_revnum)); if (! start_path) return svn_error_createf (SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL, @@ -739,7 +739,7 @@ repos_locations(const char **start_url, if (end_url) { - end_path = apr_hash_get(rev_locs, &end_revnum, sizeof(svn_revnum_t)); + end_path = apr_hash_get(rev_locs, &end_revnum, sizeof(end_revnum)); if (! end_path) return svn_error_createf (SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL, diff --git a/subversion/libsvn_client/relocate.c b/subversion/libsvn_client/relocate.c index dcd9017c75ca..2e5c1170f1ae 100644 --- a/subversion/libsvn_client/relocate.c +++ b/subversion/libsvn_client/relocate.c @@ -141,6 +141,8 @@ svn_client_relocate2(const char *wcroot_dir, apr_hash_index_t *hi; apr_pool_t *iterpool = NULL; const char *old_repos_root_url, *new_repos_root_url; + char *sig_from_prefix, *sig_to_prefix; + apr_size_t index_from, index_to; /* Populate our validator callback baton, and call the relocate code. */ vb.ctx = ctx; @@ -183,6 +185,21 @@ svn_client_relocate2(const char *wcroot_dir, if (! apr_hash_count(externals_hash)) return SVN_NO_ERROR; + /* A valid prefix for the main working copy may be too long to be + valid for an external. Trim any common trailing characters to + leave the significant part that changes. */ + sig_from_prefix = apr_pstrdup(pool, from_prefix); + sig_to_prefix = apr_pstrdup(pool, to_prefix); + index_from = strlen(sig_from_prefix); + index_to = strlen(sig_to_prefix); + while (index_from && index_to + && sig_from_prefix[index_from] == sig_to_prefix[index_to]) + { + sig_from_prefix[index_from] = sig_to_prefix[index_to] = '\0'; + --index_from; + --index_to; + } + iterpool = svn_pool_create(pool); for (hi = apr_hash_first(pool, externals_hash); @@ -218,7 +235,8 @@ svn_client_relocate2(const char *wcroot_dir, SVN_ERR(err); if (strcmp(old_repos_root_url, this_repos_root_url) == 0) - SVN_ERR(svn_client_relocate2(this_abspath, from_prefix, to_prefix, + SVN_ERR(svn_client_relocate2(this_abspath, + sig_from_prefix, sig_to_prefix, FALSE /* ignore_externals */, ctx, iterpool)); } diff --git a/subversion/libsvn_client/resolved.c b/subversion/libsvn_client/resolved.c index 8b94707ec89b..6cb5caef54b9 100644 --- a/subversion/libsvn_client/resolved.c +++ b/subversion/libsvn_client/resolved.c @@ -1,5 +1,5 @@ /* - * resolved.c: wrapper around wc resolved functionality. + * resolved.c: wrapper around Subversion <=1.9 wc resolved functionality * * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one @@ -41,6 +41,7 @@ #include "private/svn_wc_private.h" #include "svn_private_config.h" + /*** Code. ***/ diff --git a/subversion/libsvn_client/revisions.c b/subversion/libsvn_client/revisions.c index e61e7d475f86..4bfbfc3fc32a 100644 --- a/subversion/libsvn_client/revisions.c +++ b/subversion/libsvn_client/revisions.c @@ -89,7 +89,9 @@ svn_client__get_revision_number(svn_revnum_t *revnum, /* The BASE, COMMITTED, and PREV revision keywords do not apply to URLs. */ if (svn_path_is_url(local_abspath)) - goto invalid_rev_arg; + return svn_error_create(SVN_ERR_CLIENT_BAD_REVISION, NULL, + _("PREV, BASE, or COMMITTED revision " + "keywords are invalid for URL")); err = svn_wc__node_get_origin(NULL, revnum, NULL, NULL, NULL, NULL, NULL, @@ -129,7 +131,9 @@ svn_client__get_revision_number(svn_revnum_t *revnum, /* The BASE, COMMITTED, and PREV revision keywords do not apply to URLs. */ if (svn_path_is_url(local_abspath)) - goto invalid_rev_arg; + return svn_error_create(SVN_ERR_CLIENT_BAD_REVISION, NULL, + _("PREV, BASE, or COMMITTED revision " + "keywords are invalid for URL")); SVN_ERR(svn_wc__node_get_changed_info(revnum, NULL, NULL, wc_ctx, local_abspath, @@ -183,10 +187,4 @@ svn_client__get_revision_number(svn_revnum_t *revnum, *revnum = *youngest_rev; return SVN_NO_ERROR; - - invalid_rev_arg: - return svn_error_create( - SVN_ERR_CLIENT_BAD_REVISION, NULL, - _("PREV, BASE, or COMMITTED revision keywords are invalid for URL")); - } diff --git a/subversion/libsvn_client/shelve.c b/subversion/libsvn_client/shelve.c new file mode 100644 index 000000000000..af8dd67bc605 --- /dev/null +++ b/subversion/libsvn_client/shelve.c @@ -0,0 +1,552 @@ +/* + * shelve.c: implementation of the 'shelve' commands + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +/* ==================================================================== */ + +/* We define this here to remove any further warnings about the usage of + experimental functions in this file. */ +#define SVN_EXPERIMENTAL + +#include "svn_client.h" +#include "svn_wc.h" +#include "svn_pools.h" +#include "svn_dirent_uri.h" +#include "svn_path.h" +#include "svn_hash.h" +#include "svn_utf.h" +#include "svn_ctype.h" + +#include "client.h" +#include "private/svn_client_private.h" +#include "private/svn_wc_private.h" +#include "svn_private_config.h" + + +static svn_error_t * +shelf_name_encode(char **encoded_name_p, + const char *name, + apr_pool_t *result_pool) +{ + char *encoded_name + = apr_palloc(result_pool, strlen(name) * 2 + 1); + char *out_pos = encoded_name; + + if (name[0] == '\0') + return svn_error_create(SVN_ERR_BAD_CHANGELIST_NAME, NULL, + _("Shelf name cannot be the empty string")); + + while (*name) + { + apr_snprintf(out_pos, 3, "%02x", (unsigned char)(*name++)); + out_pos += 2; + } + *encoded_name_p = encoded_name; + return SVN_NO_ERROR; +} + +static svn_error_t * +shelf_name_decode(char **decoded_name_p, + const char *codename, + apr_pool_t *result_pool) +{ + svn_stringbuf_t *sb + = svn_stringbuf_create_ensure(strlen(codename) / 2, result_pool); + const char *input = codename; + + while (*input) + { + int c; + int nchars; + int nitems = sscanf(input, "%02x%n", &c, &nchars); + + if (nitems != 1 || nchars != 2) + return svn_error_createf(SVN_ERR_BAD_CHANGELIST_NAME, NULL, + _("Shelve: Bad encoded name '%s'"), codename); + svn_stringbuf_appendbyte(sb, c); + input += 2; + } + *decoded_name_p = sb->data; + return SVN_NO_ERROR; +} + +/* Set *NAME to the shelf name from FILENAME. */ +static svn_error_t * +shelf_name_from_filename(char **name, + const char *filename, + apr_pool_t *result_pool) +{ + size_t len = strlen(filename); + + if (len > 6 && strcmp(filename + len - 6, ".patch") == 0) + { + char *codename = apr_pstrndup(result_pool, filename, len - 6); + SVN_ERR(shelf_name_decode(name, codename, result_pool)); + } + return SVN_NO_ERROR; +} + +/* Set *PATCH_ABSPATH to the abspath of the patch file for shelved change + * NAME, no matter whether it exists. + */ +static svn_error_t * +get_patch_abspath(char **patch_abspath, + const char *name, + const char *wc_root_abspath, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + char *dir; + char *filename; + + SVN_ERR(svn_wc__get_shelves_dir(&dir, ctx->wc_ctx, wc_root_abspath, + scratch_pool, scratch_pool)); + SVN_ERR(shelf_name_encode(&filename, name, scratch_pool)); + filename = apr_pstrcat(scratch_pool, filename, ".patch", SVN_VA_NULL); + *patch_abspath = svn_dirent_join(dir, filename, result_pool); + return SVN_NO_ERROR; +} + +/** Write local changes to a patch file for shelved change @a name. + * + * @a message: An optional log message. + * + * @a wc_root_abspath: The WC root dir. + * + * @a overwrite_existing: If a file at @a patch_abspath exists, overwrite it. + * + * @a paths, @a depth, @a changelists: The selection of local paths to diff. + */ +static svn_error_t * +shelf_write_patch(const char *name, + const char *message, + const char *wc_root_abspath, + svn_boolean_t overwrite_existing, + const apr_array_header_t *paths, + svn_depth_t depth, + const apr_array_header_t *changelists, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + char *patch_abspath; + apr_int32_t flag; + apr_file_t *outfile; + svn_stream_t *outstream; + svn_stream_t *errstream; + apr_pool_t *iterpool = svn_pool_create(scratch_pool); + int i; + svn_opt_revision_t peg_revision = {svn_opt_revision_unspecified, {0}}; + svn_opt_revision_t start_revision = {svn_opt_revision_base, {0}}; + svn_opt_revision_t end_revision = {svn_opt_revision_working, {0}}; + + SVN_ERR(get_patch_abspath(&patch_abspath, name, wc_root_abspath, + ctx, scratch_pool, scratch_pool)); + + /* Get streams for the output and any error output of the diff. */ + /* ### svn_stream_open_writable() doesn't work here: the buffering + goes wrong so that diff headers appear after their hunks. + For now, fix by opening the file without APR_BUFFERED. */ + flag = APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_TRUNCATE; + if (! overwrite_existing) + flag |= APR_FOPEN_EXCL; + SVN_ERR(svn_io_file_open(&outfile, patch_abspath, + flag, APR_FPROT_OS_DEFAULT, scratch_pool)); + outstream = svn_stream_from_aprfile2(outfile, FALSE /*disown*/, scratch_pool); + SVN_ERR(svn_stream_for_stderr(&errstream, scratch_pool)); + + /* Write the patch file header (log message, etc.) */ + if (message) + { + SVN_ERR(svn_stream_printf(outstream, scratch_pool, "%s\n", + message)); + } + SVN_ERR(svn_stream_printf(outstream, scratch_pool, + "--This line, and those below, will be ignored--\n\n")); + SVN_ERR(svn_stream_printf(outstream, scratch_pool, + "--This patch was generated by 'svn shelve'--\n\n")); + + for (i = 0; i < paths->nelts; i++) + { + const char *path = APR_ARRAY_IDX(paths, i, const char *); + + if (svn_path_is_url(path)) + return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL, + _("'%s' is not a local path"), path); + SVN_ERR(svn_dirent_get_absolute(&path, path, scratch_pool)); + + SVN_ERR(svn_client_diff_peg6( + NULL /*options*/, + path, + &peg_revision, + &start_revision, + &end_revision, + wc_root_abspath, + depth, + TRUE /*notice_ancestry*/, + FALSE /*no_diff_added*/, + FALSE /*no_diff_deleted*/, + TRUE /*show_copies_as_adds*/, + FALSE /*ignore_content_type: FALSE -> omit binary files*/, + FALSE /*ignore_properties*/, + FALSE /*properties_only*/, + FALSE /*use_git_diff_format*/, + SVN_APR_LOCALE_CHARSET, + outstream, + errstream, + changelists, + ctx, iterpool)); + } + SVN_ERR(svn_stream_close(outstream)); + SVN_ERR(svn_stream_close(errstream)); + + return SVN_NO_ERROR; +} + +/** Apply the patch file for shelved change @a name to the WC. + * + * @a wc_root_abspath: The WC root dir. + * + * @a reverse: Apply the patch in reverse. + * + * @a dry_run: Don't really apply the changes, just notify what would be done. + */ +static svn_error_t * +shelf_apply_patch(const char *name, + const char *wc_root_abspath, + svn_boolean_t reverse, + svn_boolean_t dry_run, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + char *patch_abspath; + + SVN_ERR(get_patch_abspath(&patch_abspath, name, wc_root_abspath, + ctx, scratch_pool, scratch_pool)); + SVN_ERR(svn_client_patch(patch_abspath, wc_root_abspath, + dry_run, 0 /*strip*/, + reverse, + FALSE /*ignore_whitespace*/, + TRUE /*remove_tempfiles*/, NULL, NULL, + ctx, scratch_pool)); + + return SVN_NO_ERROR; +} + +/** Delete the patch file for shelved change @a name. + * + * @a wc_root_abspath: The WC root dir. + */ +static svn_error_t * +shelf_delete_patch(const char *name, + const char *wc_root_abspath, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + char *patch_abspath, *to_abspath; + + SVN_ERR(get_patch_abspath(&patch_abspath, name, wc_root_abspath, + ctx, scratch_pool, scratch_pool)); + to_abspath = apr_pstrcat(scratch_pool, patch_abspath, ".bak", SVN_VA_NULL); + + /* remove any previous backup */ + SVN_ERR(svn_io_remove_file2(to_abspath, TRUE /*ignore_enoent*/, + scratch_pool)); + + /* move the patch to a backup file */ + SVN_ERR(svn_io_file_rename2(patch_abspath, to_abspath, FALSE /*flush_to_disk*/, + scratch_pool)); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_shelve(const char *name, + const apr_array_header_t *paths, + svn_depth_t depth, + const apr_array_header_t *changelists, + svn_boolean_t keep_local, + svn_boolean_t dry_run, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + const char *local_abspath; + const char *wc_root_abspath; + const char *message = ""; + svn_error_t *err; + + /* ### TODO: check all paths are in same WC; for now use first path */ + SVN_ERR(svn_dirent_get_absolute(&local_abspath, + APR_ARRAY_IDX(paths, 0, char *), pool)); + SVN_ERR(svn_client_get_wc_root(&wc_root_abspath, + local_abspath, ctx, pool, pool)); + + /* Fetch the log message and any other revprops */ + if (SVN_CLIENT__HAS_LOG_MSG_FUNC(ctx)) + { + const char *tmp_file; + apr_array_header_t *commit_items = apr_array_make(pool, 1, sizeof(void *)); + + SVN_ERR(svn_client__get_log_msg(&message, &tmp_file, commit_items, + ctx, pool)); + if (! message) + return SVN_NO_ERROR; + } + + err = shelf_write_patch(name, message, wc_root_abspath, + FALSE /*overwrite_existing*/, + paths, depth, changelists, + ctx, pool); + if (err && APR_STATUS_IS_EEXIST(err->apr_err)) + { + return svn_error_quick_wrapf(err, + "Shelved change '%s' already exists", + name); + } + else + SVN_ERR(err); + + if (!keep_local) + { + /* Reverse-apply the patch. This should be a safer way to remove those + changes from the WC than running a 'revert' operation. */ + SVN_ERR(shelf_apply_patch(name, wc_root_abspath, + TRUE /*reverse*/, dry_run, + ctx, pool)); + } + + if (dry_run) + { + SVN_ERR(shelf_delete_patch(name, wc_root_abspath, + ctx, pool)); + } + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_unshelve(const char *name, + const char *local_abspath, + svn_boolean_t keep, + svn_boolean_t dry_run, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + const char *wc_root_abspath; + svn_error_t *err; + + SVN_ERR(svn_client_get_wc_root(&wc_root_abspath, + local_abspath, ctx, pool, pool)); + + /* Apply the patch. */ + err = shelf_apply_patch(name, wc_root_abspath, + FALSE /*reverse*/, dry_run, + ctx, pool); + if (err && err->apr_err == SVN_ERR_ILLEGAL_TARGET) + { + return svn_error_quick_wrapf(err, + "Shelved change '%s' not found", + name); + } + else + SVN_ERR(err); + + /* Remove the patch. */ + if (! keep && ! dry_run) + { + SVN_ERR(shelf_delete_patch(name, wc_root_abspath, + ctx, pool)); + } + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_shelves_delete(const char *name, + const char *local_abspath, + svn_boolean_t dry_run, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + const char *wc_root_abspath; + + SVN_ERR(svn_client_get_wc_root(&wc_root_abspath, + local_abspath, ctx, pool, pool)); + + /* Remove the patch. */ + if (! dry_run) + { + svn_error_t *err; + + err = shelf_delete_patch(name, wc_root_abspath, + ctx, pool); + if (err && APR_STATUS_IS_ENOENT(err->apr_err)) + { + return svn_error_quick_wrapf(err, + "Shelved change '%s' not found", + name); + } + else + SVN_ERR(err); + } + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_shelf_get_paths(apr_hash_t **affected_paths, + const char *name, + const char *local_abspath, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + const char *wc_root_abspath; + char *patch_abspath; + svn_patch_file_t *patch_file; + apr_pool_t *iterpool = svn_pool_create(scratch_pool); + apr_hash_t *paths = apr_hash_make(result_pool); + + SVN_ERR(svn_client_get_wc_root(&wc_root_abspath, + local_abspath, ctx, scratch_pool, scratch_pool)); + SVN_ERR(get_patch_abspath(&patch_abspath, name, wc_root_abspath, + ctx, scratch_pool, scratch_pool)); + SVN_ERR(svn_diff_open_patch_file(&patch_file, patch_abspath, result_pool)); + + while (1) + { + svn_patch_t *patch; + + svn_pool_clear(iterpool); + SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file, + FALSE /*reverse*/, + FALSE /*ignore_whitespace*/, + iterpool, iterpool)); + if (! patch) + break; + svn_hash_sets(paths, + apr_pstrdup(result_pool, patch->old_filename), + apr_pstrdup(result_pool, patch->new_filename)); + } + SVN_ERR(svn_diff_close_patch_file(patch_file, iterpool)); + svn_pool_destroy(iterpool); + + *affected_paths = paths; + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_shelf_has_changes(svn_boolean_t *has_changes, + const char *name, + const char *local_abspath, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + apr_hash_t *patch_paths; + + SVN_ERR(svn_client_shelf_get_paths(&patch_paths, name, local_abspath, + ctx, scratch_pool, scratch_pool)); + *has_changes = (apr_hash_count(patch_paths) != 0); + return SVN_NO_ERROR; +} + +/* Set *LOGMSG to the log message stored in the file PATCH_ABSPATH. + * + * ### Currently just reads the first line. + */ +static svn_error_t * +read_logmsg_from_patch(const char **logmsg, + const char *patch_abspath, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + apr_file_t *file; + svn_stream_t *stream; + svn_boolean_t eof; + svn_stringbuf_t *line; + + SVN_ERR(svn_io_file_open(&file, patch_abspath, + APR_FOPEN_READ, APR_FPROT_OS_DEFAULT, scratch_pool)); + stream = svn_stream_from_aprfile2(file, FALSE /*disown*/, scratch_pool); + SVN_ERR(svn_stream_readline(stream, &line, "\n", &eof, result_pool)); + SVN_ERR(svn_stream_close(stream)); + *logmsg = line->data; + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_shelves_list(apr_hash_t **shelved_patch_infos, + const char *local_abspath, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + char *shelves_dir; + apr_hash_t *dirents; + apr_hash_index_t *hi; + + SVN_ERR(svn_wc__get_shelves_dir(&shelves_dir, ctx->wc_ctx, local_abspath, + scratch_pool, scratch_pool)); + SVN_ERR(svn_io_get_dirents3(&dirents, shelves_dir, FALSE /*only_check_type*/, + result_pool, scratch_pool)); + + *shelved_patch_infos = apr_hash_make(result_pool); + + /* Remove non-shelves */ + for (hi = apr_hash_first(scratch_pool, dirents); hi; hi = apr_hash_next(hi)) + { + const char *filename = apr_hash_this_key(hi); + svn_io_dirent2_t *dirent = apr_hash_this_val(hi); + char *name = NULL; + + svn_error_clear(shelf_name_from_filename(&name, filename, result_pool)); + if (name && dirent->kind == svn_node_file) + { + svn_client_shelved_patch_info_t *info + = apr_palloc(result_pool, sizeof(*info)); + + info->dirent = dirent; + info->mtime = info->dirent->mtime; + info->patch_path + = svn_dirent_join(shelves_dir, filename, result_pool); + SVN_ERR(read_logmsg_from_patch(&info->message, info->patch_path, + result_pool, scratch_pool)); + + svn_hash_sets(*shelved_patch_infos, name, info); + } + } + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_shelves_any(svn_boolean_t *any_shelved, + const char *local_abspath, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + apr_hash_t *shelved_patch_infos; + + SVN_ERR(svn_client_shelves_list(&shelved_patch_infos, local_abspath, + ctx, scratch_pool, scratch_pool)); + *any_shelved = apr_hash_count(shelved_patch_infos) != 0; + return SVN_NO_ERROR; +} diff --git a/subversion/libsvn_client/upgrade.c b/subversion/libsvn_client/upgrade.c index 5677b1cf59b1..741443af2ddc 100644 --- a/subversion/libsvn_client/upgrade.c +++ b/subversion/libsvn_client/upgrade.c @@ -179,6 +179,122 @@ svn_client_upgrade(const char *path, return SVN_NO_ERROR; } +/* Helper for upgrade_externals_from_properties: upgrades one external ITEM + in EXTERNALS_PARENT. Uses SCRATCH_POOL for temporary allocations. */ +static svn_error_t * +upgrade_external_item(svn_client_ctx_t *ctx, + const char *externals_parent_abspath, + const char *externals_parent_url, + const char *externals_parent_repos_root_url, + svn_wc_external_item2_t *item, + struct repos_info_baton *info_baton, + apr_pool_t *scratch_pool) +{ + const char *resolved_url; + const char *external_abspath; + const char *repos_relpath; + const char *repos_root_url; + const char *repos_uuid; + svn_node_kind_t external_kind; + svn_revnum_t peg_revision; + svn_revnum_t revision; + svn_error_t *err; + + external_abspath = svn_dirent_join(externals_parent_abspath, + item->target_dir, + scratch_pool); + + SVN_ERR(svn_wc__resolve_relative_external_url( + &resolved_url, + item, + externals_parent_repos_root_url, + externals_parent_url, + scratch_pool, scratch_pool)); + + /* This is a hack. We only need to call svn_wc_upgrade() on external + * dirs, as file externals are upgraded along with their defining + * WC. Reading the kind will throw an exception on an external dir, + * saying that the wc must be upgraded. If it's a file, the lookup + * is done in an adm_dir belonging to the defining wc (which has + * already been upgraded) and no error is returned. If it doesn't + * exist (external that isn't checked out yet), we'll just get + * svn_node_none. */ + err = svn_wc_read_kind2(&external_kind, ctx->wc_ctx, + external_abspath, TRUE, FALSE, scratch_pool); + if (err && err->apr_err == SVN_ERR_WC_UPGRADE_REQUIRED) + { + svn_error_clear(err); + + SVN_ERR(svn_client_upgrade(external_abspath, ctx, scratch_pool)); + } + else if (err) + return svn_error_trace(err); + + /* The upgrade of any dir should be done now, get the now reliable + * kind. */ + SVN_ERR(svn_wc_read_kind2(&external_kind, ctx->wc_ctx, external_abspath, + TRUE, FALSE, scratch_pool)); + + /* Update the EXTERNALS table according to the root URL, + * relpath and uuid known in the upgraded external WC. */ + + /* We should probably have a function that provides all three + * of root URL, repos relpath and uuid at once, but here goes... */ + + /* First get the relpath, as that returns SVN_ERR_WC_PATH_NOT_FOUND + * when the node is not present in the file system. + * svn_wc__node_get_repos_info() would try to derive the URL. */ + SVN_ERR(svn_wc__node_get_repos_info(NULL, + &repos_relpath, + &repos_root_url, + &repos_uuid, + ctx->wc_ctx, + external_abspath, + scratch_pool, scratch_pool)); + + /* If we haven't got any information from the checked out external, + * or if the URL information mismatches the external's definition, + * ask fetch_repos_info() to find out the repos root. */ + if (0 != strcmp(resolved_url, + svn_path_url_add_component2(repos_root_url, + repos_relpath, + scratch_pool))) + { + SVN_ERR(fetch_repos_info(&repos_root_url, &repos_uuid, info_baton, + resolved_url, scratch_pool, scratch_pool)); + + repos_relpath = svn_uri_skip_ancestor(repos_root_url, + resolved_url, + scratch_pool); + + /* There's just the URL, no idea what kind the external is. + * That's fine, as the external isn't even checked out yet. + * The kind will be set during the next 'update'. */ + external_kind = svn_node_unknown; + } + + peg_revision = (item->peg_revision.kind == svn_opt_revision_number + ? item->peg_revision.value.number + : SVN_INVALID_REVNUM); + + revision = (item->revision.kind == svn_opt_revision_number + ? item->revision.value.number + : SVN_INVALID_REVNUM); + + SVN_ERR(svn_wc__upgrade_add_external_info(ctx->wc_ctx, + external_abspath, + external_kind, + externals_parent_abspath, + repos_relpath, + repos_root_url, + repos_uuid, + peg_revision, + revision, + scratch_pool)); + + return SVN_NO_ERROR; +} + static svn_error_t * upgrade_externals_from_properties(svn_client_ctx_t *ctx, const char *local_abspath, @@ -207,34 +323,32 @@ upgrade_externals_from_properties(svn_client_ctx_t *ctx, hi = apr_hash_next(hi)) { int i; - const char *externals_parent_abspath; const char *externals_parent_url; const char *externals_parent_repos_root_url; const char *externals_parent_repos_relpath; - const char *externals_parent = apr_hash_this_key(hi); + const char *externals_parent_abspath = apr_hash_this_key(hi); svn_string_t *external_desc = apr_hash_this_val(hi); apr_array_header_t *externals_p; svn_error_t *err; svn_pool_clear(iterpool); + + /* svn_client_propget5() has API promise to return absolute paths. */ + SVN_ERR_ASSERT(svn_dirent_is_absolute(externals_parent_abspath)); + externals_p = apr_array_make(iterpool, 1, sizeof(svn_wc_external_item2_t*)); /* In this loop, an error causes the respective externals definition, or * the external (inner loop), to be skipped, so that upgrade carries on * with the other externals. */ - - err = svn_dirent_get_absolute(&externals_parent_abspath, - externals_parent, iterpool); - - if (!err) - err = svn_wc__node_get_repos_info(NULL, - &externals_parent_repos_relpath, - &externals_parent_repos_root_url, - NULL, - ctx->wc_ctx, - externals_parent_abspath, - iterpool, iterpool); + err = svn_wc__node_get_repos_info(NULL, + &externals_parent_repos_relpath, + &externals_parent_repos_root_url, + NULL, + ctx->wc_ctx, + externals_parent_abspath, + iterpool, iterpool); if (!err) externals_parent_url = svn_path_url_add_component2( @@ -248,7 +362,7 @@ upgrade_externals_from_properties(svn_client_ctx_t *ctx, if (err) { svn_wc_notify_t *notify = - svn_wc_create_notify(externals_parent, + svn_wc_create_notify(externals_parent_abspath, svn_wc_notify_failed_external, scratch_pool); notify->err = err; @@ -265,130 +379,21 @@ upgrade_externals_from_properties(svn_client_ctx_t *ctx, for (i = 0; i < externals_p->nelts; i++) { svn_wc_external_item2_t *item; - const char *resolved_url; - const char *external_abspath; - const char *repos_relpath; - const char *repos_root_url; - const char *repos_uuid; - svn_node_kind_t external_kind; - svn_revnum_t peg_revision; - svn_revnum_t revision; item = APR_ARRAY_IDX(externals_p, i, svn_wc_external_item2_t*); svn_pool_clear(iterpool2); - external_abspath = svn_dirent_join(externals_parent_abspath, - item->target_dir, - iterpool2); + err = upgrade_external_item(ctx, externals_parent_abspath, + externals_parent_url, + externals_parent_repos_root_url, + item, info_baton, iterpool2); - err = svn_wc__resolve_relative_external_url( - &resolved_url, - item, - externals_parent_repos_root_url, - externals_parent_url, - scratch_pool, scratch_pool); - if (err) - goto handle_error; - - /* This is a hack. We only need to call svn_wc_upgrade() on external - * dirs, as file externals are upgraded along with their defining - * WC. Reading the kind will throw an exception on an external dir, - * saying that the wc must be upgraded. If it's a file, the lookup - * is done in an adm_dir belonging to the defining wc (which has - * already been upgraded) and no error is returned. If it doesn't - * exist (external that isn't checked out yet), we'll just get - * svn_node_none. */ - err = svn_wc_read_kind2(&external_kind, ctx->wc_ctx, - external_abspath, TRUE, FALSE, iterpool2); - if (err && err->apr_err == SVN_ERR_WC_UPGRADE_REQUIRED) - { - svn_error_clear(err); - - err = svn_client_upgrade(external_abspath, ctx, iterpool2); - if (err) - goto handle_error; - } - else if (err) - goto handle_error; - - /* The upgrade of any dir should be done now, get the now reliable - * kind. */ - err = svn_wc_read_kind2(&external_kind, ctx->wc_ctx, external_abspath, - TRUE, FALSE, iterpool2); - if (err) - goto handle_error; - - /* Update the EXTERNALS table according to the root URL, - * relpath and uuid known in the upgraded external WC. */ - - /* We should probably have a function that provides all three - * of root URL, repos relpath and uuid at once, but here goes... */ - - /* First get the relpath, as that returns SVN_ERR_WC_PATH_NOT_FOUND - * when the node is not present in the file system. - * svn_wc__node_get_repos_info() would try to derive the URL. */ - err = svn_wc__node_get_repos_info(NULL, - &repos_relpath, - &repos_root_url, - &repos_uuid, - ctx->wc_ctx, - external_abspath, - iterpool2, iterpool2); - if (err) - goto handle_error; - - /* If we haven't got any information from the checked out external, - * or if the URL information mismatches the external's definition, - * ask fetch_repos_info() to find out the repos root. */ - if (0 != strcmp(resolved_url, - svn_path_url_add_component2(repos_root_url, - repos_relpath, - scratch_pool))) - { - err = fetch_repos_info(&repos_root_url, - &repos_uuid, - info_baton, - resolved_url, - scratch_pool, scratch_pool); - if (err) - goto handle_error; - - repos_relpath = svn_uri_skip_ancestor(repos_root_url, - resolved_url, - iterpool2); - - /* There's just the URL, no idea what kind the external is. - * That's fine, as the external isn't even checked out yet. - * The kind will be set during the next 'update'. */ - external_kind = svn_node_unknown; - } - - if (err) - goto handle_error; - - peg_revision = (item->peg_revision.kind == svn_opt_revision_number - ? item->peg_revision.value.number - : SVN_INVALID_REVNUM); - - revision = (item->revision.kind == svn_opt_revision_number - ? item->revision.value.number - : SVN_INVALID_REVNUM); - - err = svn_wc__upgrade_add_external_info(ctx->wc_ctx, - external_abspath, - external_kind, - externals_parent, - repos_relpath, - repos_root_url, - repos_uuid, - peg_revision, - revision, - iterpool2); -handle_error: if (err) { svn_wc_notify_t *notify = - svn_wc_create_notify(external_abspath, + svn_wc_create_notify(svn_dirent_join(externals_parent_abspath, + item->target_dir, + iterpool2), svn_wc_notify_failed_external, scratch_pool); notify->err = err; diff --git a/subversion/libsvn_delta/branch.c b/subversion/libsvn_delta/branch.c new file mode 100644 index 000000000000..95355d44650d --- /dev/null +++ b/subversion/libsvn_delta/branch.c @@ -0,0 +1,1699 @@ +/* + * branch.c : Element-Based Branching and Move Tracking. + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#include + +#include "svn_types.h" +#include "svn_error.h" +#include "svn_dirent_uri.h" +#include "svn_hash.h" +#include "svn_iter.h" +#include "svn_pools.h" + +#include "private/svn_element.h" +#include "private/svn_branch.h" +#include "private/svn_branch_impl.h" +#include "private/svn_sorts_private.h" + +#include "svn_private_config.h" + + +/* Is EID allocated (no matter whether an element with this id exists)? */ +#define EID_IS_ALLOCATED(branch, eid) \ + ((eid) >= (branch)->txn->priv->first_eid \ + && (eid) < (branch)->txn->priv->next_eid) + +#define IS_BRANCH_ROOT_EID(branch, eid) \ + ((eid) == (branch)->priv->element_tree->root_eid) + +/* Is BRANCH1 the same branch as BRANCH2? Compare by full branch-ids; don't + require identical branch objects. */ +#define BRANCH_IS_SAME_BRANCH(branch1, branch2, scratch_pool) \ + (strcmp(svn_branch__get_id(branch1, scratch_pool), \ + svn_branch__get_id(branch2, scratch_pool)) == 0) + +struct svn_branch__txn_priv_t +{ + /* All branches. */ + apr_array_header_t *branches; + + /* The range of element ids assigned. */ + /* EIDs local to the txn are negative, assigned by decrementing FIRST_EID + * (skipping -1). */ + int first_eid, next_eid; + +}; + +struct svn_branch__state_priv_t +{ + /* EID -> svn_element__content_t mapping. */ + svn_element__tree_t *element_tree; + + /* Merge history for this branch state. */ + svn_branch__history_t *history; + + svn_boolean_t is_flat; + +}; + +static svn_branch__state_t * +branch_state_create(const char *bid, + int root_eid, + svn_branch__txn_t *txn, + apr_pool_t *result_pool); + +static svn_error_t * +branch_instantiate_elements(svn_branch__state_t *to_branch, + const svn_element__tree_t *elements, + apr_pool_t *scratch_pool); + +static svn_error_t * +svn_branch__map_add_subtree(svn_branch__state_t *to_branch, + int to_eid, + svn_branch__eid_t new_parent_eid, + const char *new_name, + svn_element__tree_t *new_subtree, + apr_pool_t *scratch_pool); + +/* */ +static apr_pool_t * +branch_state_pool_get(svn_branch__state_t *branch) +{ + return apr_hash_pool_get(branch->priv->element_tree->e_map); +} + +/* ### Layering: we didn't want to look at the whole repos in here, but + copying seems to require it. */ +svn_error_t * +svn_branch__repos_get_branch_by_id(svn_branch__state_t **branch_p, + const svn_branch__repos_t *repos, + svn_revnum_t revnum, + const char *branch_id, + apr_pool_t *scratch_pool); + +/* */ +static svn_error_t * +branch_in_rev_or_txn(svn_branch__state_t **src_branch, + const svn_branch__rev_bid_eid_t *src_el_rev, + svn_branch__txn_t *txn, + apr_pool_t *result_pool) +{ + if (SVN_IS_VALID_REVNUM(src_el_rev->rev)) + { + SVN_ERR(svn_branch__repos_get_branch_by_id(src_branch, + txn->repos, + src_el_rev->rev, + src_el_rev->bid, + result_pool)); + } + else + { + *src_branch + = svn_branch__txn_get_branch_by_id(txn, src_el_rev->bid, result_pool); + } + + return SVN_NO_ERROR; +} + +/* An #svn_branch__txn_t method. */ +static apr_array_header_t * +branch_txn_get_branches(const svn_branch__txn_t *txn, + apr_pool_t *result_pool) +{ + return apr_array_copy(result_pool, txn->priv->branches); +} + +/* An #svn_branch__txn_t method. */ +static svn_error_t * +branch_txn_delete_branch(svn_branch__txn_t *txn, + const char *bid, + apr_pool_t *scratch_pool) +{ + int i; + + for (i = 0; i < txn->priv->branches->nelts; i++) + { + svn_branch__state_t *b = APR_ARRAY_IDX(txn->priv->branches, i, void *); + + if (strcmp(b->bid, bid) == 0) + { + svn_sort__array_delete(txn->priv->branches, i, 1); + break; + } + } + return SVN_NO_ERROR; +} + +/* An #svn_branch__txn_t method. */ +static svn_error_t * +branch_txn_get_num_new_eids(const svn_branch__txn_t *txn, + int *num_new_eids_p, + apr_pool_t *scratch_pool) +{ + if (num_new_eids_p) + *num_new_eids_p = -1 - txn->priv->first_eid; + return SVN_NO_ERROR; +} + +/* An #svn_branch__txn_t method. */ +static svn_error_t * +branch_txn_new_eid(svn_branch__txn_t *txn, + svn_branch__eid_t *eid_p, + apr_pool_t *scratch_pool) +{ + int eid = (txn->priv->first_eid < 0) ? txn->priv->first_eid - 1 : -2; + + txn->priv->first_eid = eid; + if (eid_p) + *eid_p = eid; + return SVN_NO_ERROR; +} + +/* An #svn_branch__txn_t method. */ +static svn_error_t * +branch_txn_open_branch(svn_branch__txn_t *txn, + svn_branch__state_t **new_branch_p, + const char *branch_id, + int root_eid, + svn_branch__rev_bid_eid_t *tree_ref, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_branch__state_t *new_branch; + + /* if the branch already exists, just return it, else create it */ + new_branch + = svn_branch__txn_get_branch_by_id(txn, branch_id, scratch_pool); + if (new_branch) + { + SVN_ERR_ASSERT(root_eid == svn_branch__root_eid(new_branch)); + } + else + { + SVN_ERR_ASSERT_NO_RETURN(root_eid != -1); + + new_branch = branch_state_create(branch_id, root_eid, txn, + txn->priv->branches->pool); + APR_ARRAY_PUSH(txn->priv->branches, void *) = new_branch; + } + + if (tree_ref) + { + svn_branch__state_t *from_branch; + svn_element__tree_t *tree; + + SVN_ERR(branch_in_rev_or_txn(&from_branch, tree_ref, txn, scratch_pool)); + /* Source branch must exist */ + if (! from_branch) + { + return svn_error_createf(SVN_BRANCH__ERR, NULL, + _("Cannot branch from r%ld %s e%d: " + "branch does not exist"), + tree_ref->rev, tree_ref->bid, tree_ref->eid); + } + + SVN_ERR_ASSERT(from_branch->priv->is_flat); + + SVN_ERR(svn_branch__state_get_elements(from_branch, &tree, + scratch_pool)); + tree = svn_element__tree_get_subtree_at_eid(tree, tree_ref->eid, + scratch_pool); + /* Source element must exist */ + if (! tree) + { + return svn_error_createf(SVN_BRANCH__ERR, NULL, + _("Cannot branch from r%ld %s e%d: " + "element does not exist"), + tree_ref->rev, tree_ref->bid, tree_ref->eid); + } + + /* Populate the tree from the 'from' source */ + SVN_ERR(branch_instantiate_elements(new_branch, tree, scratch_pool)); + } + + if (new_branch_p) + *new_branch_p = new_branch; + return SVN_NO_ERROR; +} + +/* An #svn_branch__txn_t method. */ +static svn_error_t * +branch_txn_sequence_point(svn_branch__txn_t *txn, + apr_pool_t *scratch_pool) +{ + int i; + + /* purge elements in each branch */ + for (i = 0; i < txn->priv->branches->nelts; i++) + { + svn_branch__state_t *b + = APR_ARRAY_IDX(txn->priv->branches, i, void *); + + SVN_ERR(svn_branch__state_purge(b, scratch_pool)); + } + + return SVN_NO_ERROR; +} + +/* An #svn_branch__txn_t method. */ +static svn_error_t * +branch_txn_complete(svn_branch__txn_t *txn, + apr_pool_t *scratch_pool) +{ + return SVN_NO_ERROR; +} + +/* An #svn_branch__txn_t method. */ +static svn_error_t * +branch_txn_abort(svn_branch__txn_t *txn, + apr_pool_t *scratch_pool) +{ + return SVN_NO_ERROR; +} + +/* + * ======================================================================== + * Branch Txn Object + * ======================================================================== + */ + +apr_array_header_t * +svn_branch__txn_get_branches(const svn_branch__txn_t *txn, + apr_pool_t *result_pool) +{ + apr_array_header_t *branches + = txn->vtable->get_branches(txn, + result_pool); + return branches; +} + +svn_error_t * +svn_branch__txn_delete_branch(svn_branch__txn_t *txn, + const char *bid, + apr_pool_t *scratch_pool) +{ + SVN_ERR(txn->vtable->delete_branch(txn, + bid, + scratch_pool)); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_branch__txn_get_num_new_eids(const svn_branch__txn_t *txn, + int *num_new_eids_p, + apr_pool_t *scratch_pool) +{ + SVN_ERR(txn->vtable->get_num_new_eids(txn, + num_new_eids_p, + scratch_pool)); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_branch__txn_new_eid(svn_branch__txn_t *txn, + int *new_eid_p, + apr_pool_t *scratch_pool) +{ + SVN_ERR(txn->vtable->new_eid(txn, + new_eid_p, + scratch_pool)); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_branch__txn_open_branch(svn_branch__txn_t *txn, + svn_branch__state_t **new_branch_p, + const char *branch_id, + int root_eid, + svn_branch__rev_bid_eid_t *tree_ref, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + SVN_ERR(txn->vtable->open_branch(txn, + new_branch_p, + branch_id, + root_eid, tree_ref, result_pool, + scratch_pool)); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_branch__txn_finalize_eids(svn_branch__txn_t *txn, + apr_pool_t *scratch_pool) +{ + SVN_ERR(txn->vtable->finalize_eids(txn, + scratch_pool)); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_branch__txn_serialize(svn_branch__txn_t *txn, + svn_stream_t *stream, + apr_pool_t *scratch_pool) +{ + SVN_ERR(txn->vtable->serialize(txn, + stream, + scratch_pool)); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_branch__txn_sequence_point(svn_branch__txn_t *txn, + apr_pool_t *scratch_pool) +{ + SVN_ERR(txn->vtable->sequence_point(txn, + scratch_pool)); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_branch__txn_complete(svn_branch__txn_t *txn, + apr_pool_t *scratch_pool) +{ + SVN_ERR(txn->vtable->complete(txn, + scratch_pool)); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_branch__txn_abort(svn_branch__txn_t *txn, + apr_pool_t *scratch_pool) +{ + SVN_ERR(txn->vtable->abort(txn, + scratch_pool)); + return SVN_NO_ERROR; +} + +svn_branch__txn_t * +svn_branch__txn_create(const svn_branch__txn_vtable_t *vtable, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *result_pool) +{ + svn_branch__txn_t *txn = apr_pcalloc(result_pool, sizeof(*txn)); + + txn->vtable = apr_pmemdup(result_pool, vtable, sizeof(*vtable)); + + txn->vtable->vpriv.cancel_func = cancel_func; + txn->vtable->vpriv.cancel_baton = cancel_baton; + +#ifdef ENABLE_ORDERING_CHECK + txn->vtable->vpriv.within_callback = FALSE; + txn->vtable->vpriv.finished = FALSE; + txn->vtable->vpriv.state_pool = result_pool; +#endif + + return txn; +} + +/* + * ======================================================================== + */ + +/* */ +static const char * +branch_finalize_bid(const char *bid, + int mapping_offset, + apr_pool_t *result_pool) +{ + const char *outer_bid; + int outer_eid; + + svn_branch__id_unnest(&outer_bid, &outer_eid, bid, result_pool); + + if (outer_bid) + { + outer_bid = branch_finalize_bid(outer_bid, mapping_offset, result_pool); + } + + if (outer_eid < -1) + { + outer_eid = mapping_offset - outer_eid; + } + + return svn_branch__id_nest(outer_bid, outer_eid, result_pool); +} + +/* Change txn-local EIDs (negative integers) in BRANCH to revision EIDs, by + * assigning a new revision-EID (positive integer) for each one. + */ +static svn_error_t * +branch_finalize_eids(svn_branch__state_t *branch, + int mapping_offset, + apr_pool_t *scratch_pool) +{ + apr_hash_index_t *hi; + + branch->bid = branch_finalize_bid(branch->bid, mapping_offset, + branch_state_pool_get(branch)); + if (branch->priv->element_tree->root_eid < -1) + { + branch->priv->element_tree->root_eid + = mapping_offset - branch->priv->element_tree->root_eid; + } + + for (hi = apr_hash_first(scratch_pool, branch->priv->element_tree->e_map); + hi; hi = apr_hash_next(hi)) + { + int old_eid = svn_eid__hash_this_key(hi); + svn_element__content_t *element = apr_hash_this_val(hi); + + if (old_eid < -1) + { + int new_eid = mapping_offset - old_eid; + + svn_element__tree_set(branch->priv->element_tree, old_eid, NULL); + svn_element__tree_set(branch->priv->element_tree, new_eid, element); + } + if (element->parent_eid < -1) + { + element->parent_eid = mapping_offset - element->parent_eid; + } + } + return SVN_NO_ERROR; +} + +/* An #svn_branch__txn_t method. */ +static svn_error_t * +branch_txn_finalize_eids(svn_branch__txn_t *txn, + apr_pool_t *scratch_pool) +{ + int n_txn_eids = (-1) - txn->priv->first_eid; + int mapping_offset; + apr_array_header_t *branches = branch_txn_get_branches(txn, scratch_pool); + int i; + + if (txn->priv->first_eid == 0) + return SVN_NO_ERROR; + + /* mapping from txn-local (negative) EID to committed (positive) EID is: + txn_local_eid == -2 => committed_eid := (txn.next_eid + 0) + txn_local_eid == -3 => committed_eid := (txn.next_eid + 1) ... */ + mapping_offset = txn->priv->next_eid - 2; + + for (i = 0; i < branches->nelts; i++) + { + svn_branch__state_t *b = APR_ARRAY_IDX(branches, i, void *); + + SVN_ERR(branch_finalize_eids(b, mapping_offset, scratch_pool)); + } + + txn->priv->next_eid += n_txn_eids; + txn->priv->first_eid = 0; + return SVN_NO_ERROR; +} + +/* + * ======================================================================== + */ + +static svn_error_t * +branch_txn_serialize(svn_branch__txn_t *txn, + svn_stream_t *stream, + apr_pool_t *scratch_pool) +{ + apr_array_header_t *branches = branch_txn_get_branches(txn, scratch_pool); + int i; + + SVN_ERR(svn_stream_printf(stream, scratch_pool, + "r%ld: eids %d %d " + "branches %d\n", + txn->rev, + txn->priv->first_eid, txn->priv->next_eid, + branches->nelts)); + + for (i = 0; i < branches->nelts; i++) + { + svn_branch__state_t *branch = APR_ARRAY_IDX(branches, i, void *); + + SVN_ERR(svn_branch__state_serialize(stream, branch, scratch_pool)); + } + return SVN_NO_ERROR; +} + +/* + * ======================================================================== + */ + +svn_branch__state_t * +svn_branch__txn_get_branch_by_id(const svn_branch__txn_t *txn, + const char *branch_id, + apr_pool_t *scratch_pool) +{ + apr_array_header_t *branches = svn_branch__txn_get_branches(txn, scratch_pool); + int i; + svn_branch__state_t *branch = NULL; + + for (i = 0; i < branches->nelts; i++) + { + svn_branch__state_t *b = APR_ARRAY_IDX(branches, i, void *); + + if (strcmp(svn_branch__get_id(b, scratch_pool), branch_id) == 0) + { + branch = b; + break; + } + } + return branch; +} + +/* + * ======================================================================== + */ + +/* Create a new branch txn object. + * + * It will have no branches. + */ +static svn_branch__txn_t * +branch_txn_create(svn_branch__repos_t *repos, + svn_revnum_t rev, + svn_revnum_t base_rev, + apr_pool_t *result_pool) +{ + static const svn_branch__txn_vtable_t vtable = { + {0}, + branch_txn_get_branches, + branch_txn_delete_branch, + branch_txn_get_num_new_eids, + branch_txn_new_eid, + branch_txn_open_branch, + branch_txn_finalize_eids, + branch_txn_serialize, + branch_txn_sequence_point, + branch_txn_complete, + branch_txn_abort, + }; + svn_branch__txn_t *txn + = svn_branch__txn_create(&vtable, NULL, NULL, result_pool); + + txn->priv = apr_pcalloc(result_pool, sizeof(*txn->priv)); + txn->repos = repos; + txn->rev = rev; + txn->base_rev = base_rev; + txn->priv->branches = apr_array_make(result_pool, 0, sizeof(void *)); + return txn; +} + +/* + * ======================================================================== + */ + +static void +branch_validate_element(const svn_branch__state_t *branch, + int eid, + const svn_element__content_t *element); + +/* Assert BRANCH satisfies all its invariants. + */ +static void +assert_branch_state_invariants(const svn_branch__state_t *branch, + apr_pool_t *scratch_pool) +{ + apr_hash_index_t *hi; + + assert(branch->bid); + assert(branch->txn); + assert(branch->priv->element_tree); + assert(branch->priv->element_tree->e_map); + + /* Validate elements in the map */ + for (hi = apr_hash_first(scratch_pool, branch->priv->element_tree->e_map); + hi; hi = apr_hash_next(hi)) + { + branch_validate_element(branch, svn_eid__hash_this_key(hi), + apr_hash_this_val(hi)); + } +} + +/* An #svn_branch__state_t method. */ +static svn_error_t * +branch_state_copy_one(svn_branch__state_t *branch, + const svn_branch__rev_bid_eid_t *src_el_rev, + svn_branch__eid_t eid, + svn_branch__eid_t new_parent_eid, + const char *new_name, + const svn_element__payload_t *new_payload, + apr_pool_t *scratch_pool) +{ + /* New payload shall be the same as the source if NEW_PAYLOAD is null. */ + /* ### if (! new_payload) + { + new_payload = branch_map_get(branch, eid)->payload; + } + */ + + return SVN_NO_ERROR; +} + +/* Copy a subtree. + * + * Adjust TO_BRANCH and its subbranches (recursively), to reflect a copy + * of a subtree from FROM_EL_REV to TO_PARENT_EID:TO_NAME. + * + * FROM_EL_REV must be an existing element. (It may be a branch root.) + * + * ### TODO: + * If FROM_EL_REV is the root of a subbranch and/or contains nested + * subbranches, also copy them ... + * ### What shall we do with a subbranch? Make plain copies of its raw + * elements; make a subbranch by branching the source subbranch? + * + * TO_PARENT_EID must be a directory element in TO_BRANCH, and TO_NAME a + * non-existing path in it. + */ +static svn_error_t * +copy_subtree(const svn_branch__el_rev_id_t *from_el_rev, + svn_branch__state_t *to_branch, + svn_branch__eid_t to_parent_eid, + const char *to_name, + apr_pool_t *scratch_pool) +{ + svn_element__tree_t *new_subtree; + + SVN_ERR_ASSERT(from_el_rev->branch->priv->is_flat); + + SVN_ERR(svn_branch__state_get_elements(from_el_rev->branch, &new_subtree, + scratch_pool)); + new_subtree = svn_element__tree_get_subtree_at_eid(new_subtree, + from_el_rev->eid, + scratch_pool); + + /* copy the subtree, assigning new EIDs */ + SVN_ERR(svn_branch__map_add_subtree(to_branch, -1 /*to_eid*/, + to_parent_eid, to_name, + new_subtree, + scratch_pool)); + + return SVN_NO_ERROR; +} + +/* An #svn_branch__state_t method. */ +static svn_error_t * +branch_state_copy_tree(svn_branch__state_t *to_branch, + const svn_branch__rev_bid_eid_t *src_el_rev, + svn_branch__eid_t new_parent_eid, + const char *new_name, + apr_pool_t *scratch_pool) +{ + svn_branch__txn_t *txn = to_branch->txn; + svn_branch__state_t *src_branch; + svn_branch__el_rev_id_t *from_el_rev; + + SVN_ERR(branch_in_rev_or_txn(&src_branch, src_el_rev, txn, scratch_pool)); + from_el_rev = svn_branch__el_rev_id_create(src_branch, src_el_rev->eid, + src_el_rev->rev, scratch_pool); + SVN_ERR(copy_subtree(from_el_rev, + to_branch, new_parent_eid, new_name, + scratch_pool)); + + return SVN_NO_ERROR; +} + +const char * +svn_branch__get_id(const svn_branch__state_t *branch, + apr_pool_t *result_pool) +{ + return branch->bid; +} + +int +svn_branch__root_eid(const svn_branch__state_t *branch) +{ + svn_element__tree_t *elements; + + svn_error_clear(svn_branch__state_get_elements(branch, &elements, + NULL/*scratch_pool*/)); + return elements->root_eid; +} + +svn_branch__el_rev_id_t * +svn_branch__el_rev_id_create(svn_branch__state_t *branch, + int eid, + svn_revnum_t rev, + apr_pool_t *result_pool) +{ + svn_branch__el_rev_id_t *id = apr_palloc(result_pool, sizeof(*id)); + + id->branch = branch; + id->eid = eid; + id->rev = rev; + return id; +} + +svn_branch__el_rev_id_t * +svn_branch__el_rev_id_dup(const svn_branch__el_rev_id_t *old_id, + apr_pool_t *result_pool) +{ + if (! old_id) + return NULL; + + return svn_branch__el_rev_id_create(old_id->branch, + old_id->eid, + old_id->rev, + result_pool); +} + +svn_branch__rev_bid_eid_t * +svn_branch__rev_bid_eid_create(svn_revnum_t rev, + const char *branch_id, + int eid, + apr_pool_t *result_pool) +{ + svn_branch__rev_bid_eid_t *id = apr_palloc(result_pool, sizeof(*id)); + + id->bid = apr_pstrdup(result_pool, branch_id); + id->eid = eid; + id->rev = rev; + return id; +} + +svn_branch__rev_bid_eid_t * +svn_branch__rev_bid_eid_dup(const svn_branch__rev_bid_eid_t *old_id, + apr_pool_t *result_pool) +{ + svn_branch__rev_bid_eid_t *id; + + if (! old_id) + return NULL; + + id = apr_pmemdup(result_pool, old_id, sizeof(*id)); + id->bid = apr_pstrdup(result_pool, old_id->bid); + return id; +} + +svn_branch__rev_bid_t * +svn_branch__rev_bid_create(svn_revnum_t rev, + const char *branch_id, + apr_pool_t *result_pool) +{ + svn_branch__rev_bid_t *id = apr_palloc(result_pool, sizeof(*id)); + + id->bid = apr_pstrdup(result_pool, branch_id); + id->rev = rev; + return id; +} + +svn_branch__rev_bid_t * +svn_branch__rev_bid_dup(const svn_branch__rev_bid_t *old_id, + apr_pool_t *result_pool) +{ + svn_branch__rev_bid_t *id; + + if (! old_id) + return NULL; + + id = apr_pmemdup(result_pool, old_id, sizeof(*id)); + id->bid = apr_pstrdup(result_pool, old_id->bid); + return id; +} + +svn_boolean_t +svn_branch__rev_bid_equal(const svn_branch__rev_bid_t *id1, + const svn_branch__rev_bid_t *id2) +{ + return (id1->rev == id2->rev + && strcmp(id1->bid, id2->bid) == 0); +} + +svn_branch__history_t * +svn_branch__history_create_empty(apr_pool_t *result_pool) +{ + svn_branch__history_t *history + = svn_branch__history_create(NULL, result_pool); + + return history; +} + +svn_branch__history_t * +svn_branch__history_create(apr_hash_t *parents, + apr_pool_t *result_pool) +{ + svn_branch__history_t *history + = apr_pcalloc(result_pool, sizeof(*history)); + + history->parents = apr_hash_make(result_pool); + if (parents) + { + apr_hash_index_t *hi; + + for (hi = apr_hash_first(result_pool, parents); + hi; hi = apr_hash_next(hi)) + { + const char *bid = apr_hash_this_key(hi); + svn_branch__rev_bid_t *val = apr_hash_this_val(hi); + + svn_hash_sets(history->parents, + apr_pstrdup(result_pool, bid), + svn_branch__rev_bid_dup(val, result_pool)); + } + } + return history; +} + +svn_branch__history_t * +svn_branch__history_dup(const svn_branch__history_t *old, + apr_pool_t *result_pool) +{ + svn_branch__history_t *history = NULL; + + if (old) + { + history + = svn_branch__history_create(old->parents, result_pool); + } + return history; +} + + +/* + * ======================================================================== + * Branch mappings + * ======================================================================== + */ + +/* Validate that ELEMENT is suitable for a mapping of BRANCH:EID. + * ELEMENT->payload may be null. + */ +static void +branch_validate_element(const svn_branch__state_t *branch, + int eid, + const svn_element__content_t *element) +{ + SVN_ERR_ASSERT_NO_RETURN(element); + + /* Parent EID must be valid and different from this element's EID, or -1 + iff this is the branch root element. */ + SVN_ERR_ASSERT_NO_RETURN( + IS_BRANCH_ROOT_EID(branch, eid) + ? (element->parent_eid == -1) + : (element->parent_eid != eid + && EID_IS_ALLOCATED(branch, element->parent_eid))); + + /* Element name must be given, and empty iff EID is the branch root. */ + SVN_ERR_ASSERT_NO_RETURN( + element->name + && IS_BRANCH_ROOT_EID(branch, eid) == (*element->name == '\0')); + + SVN_ERR_ASSERT_NO_RETURN(svn_element__payload_invariants(element->payload)); + if (element->payload->is_subbranch_root) + { + /* a subbranch root element must not be the branch root element */ + SVN_ERR_ASSERT_NO_RETURN(! IS_BRANCH_ROOT_EID(branch, eid)); + } +} + +static svn_error_t * +branch_state_get_elements(const svn_branch__state_t *branch, + svn_element__tree_t **element_tree_p, + apr_pool_t *result_pool) +{ + *element_tree_p = branch->priv->element_tree; + return SVN_NO_ERROR; +} + +static svn_element__content_t * +branch_get_element(const svn_branch__state_t *branch, + int eid) +{ + svn_element__content_t *element; + + element = svn_element__tree_get(branch->priv->element_tree, eid); + + if (element) + branch_validate_element(branch, eid, element); + return element; +} + +static svn_error_t * +branch_state_get_element(const svn_branch__state_t *branch, + svn_element__content_t **element_p, + int eid, + apr_pool_t *result_pool) +{ + *element_p = branch_get_element(branch, eid); + return SVN_NO_ERROR; +} + +/* In BRANCH, set element EID to ELEMENT. + * + * If ELEMENT is null, delete element EID. + * + * Assume ELEMENT is already allocated with sufficient lifetime. + */ +static void +branch_map_set(svn_branch__state_t *branch, + int eid, + const svn_element__content_t *element) +{ + apr_pool_t *map_pool = apr_hash_pool_get(branch->priv->element_tree->e_map); + + SVN_ERR_ASSERT_NO_RETURN(EID_IS_ALLOCATED(branch, eid)); + if (element) + branch_validate_element(branch, eid, element); + + svn_element__tree_set(branch->priv->element_tree, eid, element); + branch->priv->is_flat = FALSE; + assert_branch_state_invariants(branch, map_pool); +} + +/* An #svn_branch__state_t method. */ +static svn_error_t * +branch_state_set_element(svn_branch__state_t *branch, + svn_branch__eid_t eid, + const svn_element__content_t *element, + apr_pool_t *scratch_pool) +{ + apr_pool_t *map_pool = apr_hash_pool_get(branch->priv->element_tree->e_map); + + /* EID must be a valid element id */ + SVN_ERR_ASSERT(EID_IS_ALLOCATED(branch, eid)); + + if (element) + { + element = svn_element__content_dup(element, map_pool); + + /* NEW_PAYLOAD must be specified, either in full or by reference */ + SVN_ERR_ASSERT(element->payload); + + if ((element->parent_eid == -1) != IS_BRANCH_ROOT_EID(branch, eid) + || (*element->name == '\0') != IS_BRANCH_ROOT_EID(branch, eid)) + { + return svn_error_createf(SVN_BRANCH__ERR, NULL, + _("Cannot set e%d to (parent=e%d, name='%s'): " + "branch root is e%d"), + eid, element->parent_eid, element->name, + branch->priv->element_tree->root_eid); + } + } + + /* Insert the new version */ + branch_map_set(branch, eid, element); + return SVN_NO_ERROR; +} + +/* An #svn_branch__state_t method. */ +static svn_error_t * +branch_state_purge(svn_branch__state_t *branch, + apr_pool_t *scratch_pool) +{ + svn_element__tree_purge_orphans(branch->priv->element_tree->e_map, + branch->priv->element_tree->root_eid, + scratch_pool); + branch->priv->is_flat = TRUE; + return SVN_NO_ERROR; +} + +/* An #svn_branch__state_t method. */ +static svn_error_t * +branch_state_get_history(svn_branch__state_t *branch, + svn_branch__history_t **history_p, + apr_pool_t *result_pool) +{ + if (history_p) + { + *history_p + = svn_branch__history_dup(branch->priv->history, result_pool); + } + return SVN_NO_ERROR; +} + +/* An #svn_branch__state_t method. */ +static svn_error_t * +branch_state_set_history(svn_branch__state_t *branch, + const svn_branch__history_t *history, + apr_pool_t *scratch_pool) +{ + apr_pool_t *branch_pool = branch_state_pool_get(branch); + + branch->priv->history + = svn_branch__history_dup(history, branch_pool); + return SVN_NO_ERROR; +} + +const char * +svn_branch__get_path_by_eid(const svn_branch__state_t *branch, + int eid, + apr_pool_t *result_pool) +{ + svn_element__tree_t *elements; + + SVN_ERR_ASSERT_NO_RETURN(EID_IS_ALLOCATED(branch, eid)); + /*SVN_ERR_ASSERT_NO_RETURN(branch->priv->is_flat);*/ + + svn_error_clear(svn_branch__state_get_elements(branch, &elements, result_pool)); + return svn_element__tree_get_path_by_eid(elements, eid, result_pool); +} + +int +svn_branch__get_eid_by_path(const svn_branch__state_t *branch, + const char *path, + apr_pool_t *scratch_pool) +{ + svn_element__tree_t *elements; + apr_hash_index_t *hi; + + /*SVN_ERR_ASSERT_NO_RETURN(branch->priv->is_flat);*/ + + /* ### This is a crude, linear search */ + svn_error_clear(svn_branch__state_get_elements(branch, &elements, scratch_pool)); + for (hi = apr_hash_first(scratch_pool, elements->e_map); + hi; hi = apr_hash_next(hi)) + { + int eid = svn_eid__hash_this_key(hi); + const char *this_path = svn_element__tree_get_path_by_eid(elements, eid, + scratch_pool); + + if (! this_path) + { + /* Mapping is not complete; this element is in effect not present. */ + continue; + } + if (strcmp(path, this_path) == 0) + { + return eid; + } + } + + return -1; +} + +/* Create a copy of NEW_SUBTREE in TO_BRANCH. + * + * For each non-root element in NEW_SUBTREE, create a new element with + * a new EID, no matter what EID is used to represent it in NEW_SUBTREE. + * + * For the new subtree root element, if TO_EID is -1, generate a new EID, + * otherwise alter (if it exists) or instantiate the element TO_EID. + * + * Set the new subtree root element's parent to NEW_PARENT_EID and name to + * NEW_NAME. + */ +static svn_error_t * +svn_branch__map_add_subtree(svn_branch__state_t *to_branch, + int to_eid, + svn_branch__eid_t new_parent_eid, + const char *new_name, + svn_element__tree_t *new_subtree, + apr_pool_t *scratch_pool) +{ + apr_hash_index_t *hi; + svn_element__content_t *new_root_content; + + /* Get a new EID for the root element, if not given. */ + if (to_eid == -1) + { + SVN_ERR(svn_branch__txn_new_eid(to_branch->txn, &to_eid, + scratch_pool)); + } + + /* Create the new subtree root element */ + new_root_content = svn_element__tree_get(new_subtree, new_subtree->root_eid); + new_root_content = svn_element__content_create(new_parent_eid, new_name, + new_root_content->payload, + scratch_pool); + SVN_ERR(branch_state_set_element(to_branch, to_eid, new_root_content, + scratch_pool)); + + /* Process its immediate children */ + for (hi = apr_hash_first(scratch_pool, new_subtree->e_map); + hi; hi = apr_hash_next(hi)) + { + int this_from_eid = svn_eid__hash_this_key(hi); + svn_element__content_t *from_element = apr_hash_this_val(hi); + + if (from_element->parent_eid == new_subtree->root_eid) + { + svn_element__tree_t *this_subtree; + + /* Recurse. (We don't try to check whether it's a directory node, + as we might not have the node kind in the map.) */ + this_subtree + = svn_element__tree_create(new_subtree->e_map, this_from_eid, + scratch_pool); + SVN_ERR(svn_branch__map_add_subtree(to_branch, -1 /*to_eid*/, + to_eid, from_element->name, + this_subtree, scratch_pool)); + } + } + + return SVN_NO_ERROR; +} + +/* Instantiate elements in a branch. + * + * In TO_BRANCH, instantiate (or alter, if existing) each element of + * ELEMENTS, each with its given tree structure (parent, name) and payload. + */ +static svn_error_t * +branch_instantiate_elements(svn_branch__state_t *to_branch, + const svn_element__tree_t *elements, + apr_pool_t *scratch_pool) +{ + apr_hash_index_t *hi; + + for (hi = apr_hash_first(scratch_pool, elements->e_map); + hi; hi = apr_hash_next(hi)) + { + int this_eid = svn_eid__hash_this_key(hi); + svn_element__content_t *this_element = apr_hash_this_val(hi); + + branch_map_set(to_branch, this_eid, + svn_element__content_dup( + this_element, + apr_hash_pool_get(to_branch->priv->element_tree->e_map))); + } + + return SVN_NO_ERROR; +} + +/* + * ======================================================================== + * Branch State Object + * ======================================================================== + */ + +svn_error_t * +svn_branch__state_get_elements(const svn_branch__state_t *branch, + svn_element__tree_t **element_tree_p, + apr_pool_t *result_pool) +{ + SVN_ERR(branch->vtable->get_elements(branch, + element_tree_p, + result_pool)); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_branch__state_get_element(const svn_branch__state_t *branch, + svn_element__content_t **element_p, + int eid, + apr_pool_t *result_pool) +{ + SVN_ERR(branch->vtable->get_element(branch, + element_p, eid, result_pool)); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_branch__state_set_element(svn_branch__state_t *branch, + int eid, + const svn_element__content_t *element, + apr_pool_t *scratch_pool) +{ + SVN_ERR(branch->vtable->set_element(branch, + eid, element, + scratch_pool)); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_branch__state_alter_one(svn_branch__state_t *branch, + svn_branch__eid_t eid, + svn_branch__eid_t new_parent_eid, + const char *new_name, + const svn_element__payload_t *new_payload, + apr_pool_t *scratch_pool) +{ + svn_element__content_t *element + = svn_element__content_create(new_parent_eid, new_name, new_payload, + scratch_pool); + + SVN_ERR(svn_branch__state_set_element(branch, eid, element, scratch_pool)); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_branch__state_copy_tree(svn_branch__state_t *branch, + const svn_branch__rev_bid_eid_t *src_el_rev, + svn_branch__eid_t new_parent_eid, + const char *new_name, + apr_pool_t *scratch_pool) +{ + SVN_ERR(branch->vtable->copy_tree(branch, + src_el_rev, new_parent_eid, new_name, + scratch_pool)); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_branch__state_delete_one(svn_branch__state_t *branch, + svn_branch__eid_t eid, + apr_pool_t *scratch_pool) +{ + SVN_ERR(svn_branch__state_set_element(branch, eid, NULL, scratch_pool)); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_branch__state_purge(svn_branch__state_t *branch, + apr_pool_t *scratch_pool) +{ + SVN_ERR(branch->vtable->purge(branch, + scratch_pool)); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_branch__state_get_history(svn_branch__state_t *branch, + svn_branch__history_t **history_p, + apr_pool_t *result_pool) +{ + SVN_ERR(branch->vtable->get_history(branch, + history_p, + result_pool)); + SVN_ERR_ASSERT(*history_p); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_branch__state_set_history(svn_branch__state_t *branch, + const svn_branch__history_t *history, + apr_pool_t *scratch_pool) +{ + SVN_ERR_ASSERT(history); + SVN_ERR(branch->vtable->set_history(branch, + history, + scratch_pool)); + return SVN_NO_ERROR; +} + +svn_branch__state_t * +svn_branch__state_create(const svn_branch__state_vtable_t *vtable, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *result_pool) +{ + svn_branch__state_t *b = apr_pcalloc(result_pool, sizeof(*b)); + + b->vtable = apr_pmemdup(result_pool, vtable, sizeof(*vtable)); + + b->vtable->vpriv.cancel_func = cancel_func; + b->vtable->vpriv.cancel_baton = cancel_baton; + +#ifdef ENABLE_ORDERING_CHECK + b->vtable->vpriv.within_callback = FALSE; + b->vtable->vpriv.finished = FALSE; + b->vtable->vpriv.state_pool = result_pool; +#endif + + return b; +} + +/* Create a new branch state object. + * + * It will have no elements (not even a root element). + */ +static svn_branch__state_t * +branch_state_create(const char *bid, + int root_eid, + svn_branch__txn_t *txn, + apr_pool_t *result_pool) +{ + static const svn_branch__state_vtable_t vtable = { + {0}, + branch_state_get_elements, + branch_state_get_element, + branch_state_set_element, + branch_state_copy_one, + branch_state_copy_tree, + branch_state_purge, + branch_state_get_history, + branch_state_set_history, + }; + svn_branch__state_t *b + = svn_branch__state_create(&vtable, NULL, NULL, result_pool); + + b->priv = apr_pcalloc(result_pool, sizeof(*b->priv)); + b->bid = apr_pstrdup(result_pool, bid); + b->txn = txn; + b->priv->element_tree = svn_element__tree_create(NULL, root_eid, result_pool); + assert_branch_state_invariants(b, result_pool); + b->priv->is_flat = TRUE; + b->priv->history = svn_branch__history_create_empty(result_pool); + return b; +} + +/* + * ======================================================================== + * Parsing and Serializing + * ======================================================================== + */ + +svn_string_t * +svn_branch__get_default_r0_metadata(apr_pool_t *result_pool) +{ + static const char *default_repos_info + = "r0: eids 0 1 branches 1\n" + "B0 root-eid 0 num-eids 1\n" + "history: parents 0\n" + "e0: normal -1 .\n"; + + return svn_string_create(default_repos_info, result_pool); +} + +/* */ +static svn_error_t * +parse_branch_line(char *bid_p, + int *root_eid_p, + int *num_eids_p, + svn_stream_t *stream, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_stringbuf_t *line; + svn_boolean_t eof; + int n; + + /* Read a line */ + SVN_ERR(svn_stream_readline(stream, &line, "\n", &eof, scratch_pool)); + SVN_ERR_ASSERT(!eof); + + n = sscanf(line->data, "%s root-eid %d num-eids %d", + bid_p, root_eid_p, num_eids_p); + SVN_ERR_ASSERT(n == 3); + + return SVN_NO_ERROR; +} + +/* Parse the history metadata for BRANCH. + */ +static svn_error_t * +history_parse(svn_branch__history_t **history_p, + svn_stream_t *stream, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_branch__history_t *history + = svn_branch__history_create_empty(result_pool); + svn_stringbuf_t *line; + svn_boolean_t eof; + int n; + int num_parents; + int i; + + /* Read a line */ + SVN_ERR(svn_stream_readline(stream, &line, "\n", &eof, scratch_pool)); + SVN_ERR_ASSERT(!eof); + + n = sscanf(line->data, "history: parents %d", + &num_parents); + SVN_ERR_ASSERT(n == 1); + + for (i = 0; i < num_parents; i++) + { + svn_revnum_t rev; + char bid[100]; + + SVN_ERR(svn_stream_readline(stream, &line, "\n", &eof, scratch_pool)); + SVN_ERR_ASSERT(!eof); + + n = sscanf(line->data, "parent: r%ld.%99s", + &rev, bid); + SVN_ERR_ASSERT(n == 2); + + svn_hash_sets(history->parents, + apr_pstrdup(result_pool, bid), + svn_branch__rev_bid_create(rev, bid, result_pool)); + } + + if (history_p) + *history_p = history; + return SVN_NO_ERROR; +} + +/* Parse the mapping for one element. + */ +static svn_error_t * +parse_element_line(int *eid_p, + svn_boolean_t *is_subbranch_p, + int *parent_eid_p, + const char **name_p, + svn_stream_t *stream, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_stringbuf_t *line; + svn_boolean_t eof; + char kind[10]; + int n; + int offset; + + /* Read a line */ + SVN_ERR(svn_stream_readline(stream, &line, "\n", &eof, scratch_pool)); + SVN_ERR_ASSERT(!eof); + + n = sscanf(line->data, "e%d: %9s %d%n", + eid_p, + kind, parent_eid_p, &offset); + SVN_ERR_ASSERT(n >= 3); /* C std is unclear on whether '%n' counts */ + SVN_ERR_ASSERT(line->data[offset] == ' '); + + *name_p = apr_pstrdup(result_pool, line->data + offset + 1); + *is_subbranch_p = (strcmp(kind, "subbranch") == 0); + + if (strcmp(*name_p, "(null)") == 0) + *name_p = NULL; + else if (strcmp(*name_p, ".") == 0) + *name_p = ""; + + return SVN_NO_ERROR; +} + +const char * +svn_branch__id_nest(const char *outer_bid, + int outer_eid, + apr_pool_t *result_pool) +{ + if (!outer_bid) + return apr_psprintf(result_pool, "B%d", outer_eid); + + return apr_psprintf(result_pool, "%s.%d", outer_bid, outer_eid); +} + +void +svn_branch__id_unnest(const char **outer_bid, + int *outer_eid, + const char *bid, + apr_pool_t *result_pool) +{ + char *last_dot = strrchr(bid, '.'); + + if (last_dot) /* BID looks like "B3.11" or "B3.11.22" etc. */ + { + *outer_bid = apr_pstrndup(result_pool, bid, last_dot - bid); + *outer_eid = atoi(last_dot + 1); + } + else /* looks like "B0" or B22" (with no dot) */ + { + *outer_bid = NULL; + *outer_eid = atoi(bid + 1); + } +} + +/* Create a new branch *NEW_BRANCH, initialized + * with info parsed from STREAM, allocated in RESULT_POOL. + */ +static svn_error_t * +svn_branch__state_parse(svn_branch__state_t **new_branch, + svn_branch__txn_t *txn, + svn_stream_t *stream, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + char bid[1000]; + int root_eid, num_eids; + svn_branch__state_t *branch_state; + int i; + + SVN_ERR(parse_branch_line(bid, &root_eid, &num_eids, + stream, scratch_pool, scratch_pool)); + + branch_state = branch_state_create(bid, root_eid, txn, + result_pool); + + /* Read in the merge history. */ + SVN_ERR(history_parse(&branch_state->priv->history, + stream, result_pool, scratch_pool)); + + /* Read in the structure. Set the payload of each normal element to a + (branch-relative) reference. */ + for (i = 0; i < num_eids; i++) + { + int eid, this_parent_eid; + const char *this_name; + svn_boolean_t is_subbranch; + + SVN_ERR(parse_element_line(&eid, + &is_subbranch, &this_parent_eid, &this_name, + stream, scratch_pool, scratch_pool)); + + if (this_name) + { + svn_element__payload_t *payload; + svn_element__content_t *element; + + if (! is_subbranch) + { + payload = svn_element__payload_create_ref(txn->rev, bid, eid, + result_pool); + } + else + { + payload + = svn_element__payload_create_subbranch(result_pool); + } + element = svn_element__content_create(this_parent_eid, + this_name, payload, + scratch_pool); + SVN_ERR(branch_state_set_element(branch_state, eid, element, + scratch_pool)); + } + } + + branch_state->priv->is_flat = TRUE; + *new_branch = branch_state; + return SVN_NO_ERROR; +} + +svn_error_t * +svn_branch__txn_parse(svn_branch__txn_t **txn_p, + svn_branch__repos_t *repos, + svn_stream_t *stream, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_branch__txn_t *txn; + svn_revnum_t rev; + int first_eid, next_eid; + int num_branches; + svn_stringbuf_t *line; + svn_boolean_t eof; + int n; + int j; + + SVN_ERR(svn_stream_readline(stream, &line, "\n", &eof, scratch_pool)); + SVN_ERR_ASSERT(! eof); + n = sscanf(line->data, "r%ld: eids %d %d " + "branches %d", + &rev, + &first_eid, &next_eid, + &num_branches); + SVN_ERR_ASSERT(n == 4); + + txn = branch_txn_create(repos, rev, rev - 1, result_pool); + txn->priv->first_eid = first_eid; + txn->priv->next_eid = next_eid; + + /* parse the branches */ + for (j = 0; j < num_branches; j++) + { + svn_branch__state_t *branch; + + SVN_ERR(svn_branch__state_parse(&branch, txn, stream, + result_pool, scratch_pool)); + APR_ARRAY_PUSH(txn->priv->branches, void *) = branch; + } + + *txn_p = txn; + return SVN_NO_ERROR; +} + +/* Serialize the history metadata for BRANCH. + */ +static svn_error_t * +history_serialize(svn_stream_t *stream, + svn_branch__history_t *history, + apr_pool_t *scratch_pool) +{ + apr_array_header_t *ancestors_sorted; + int i; + + /* Write entries in sorted order for stability -- so that for example + we can test parse-then-serialize by expecting identical output. */ + ancestors_sorted = svn_sort__hash(history->parents, + svn_sort_compare_items_lexically, + scratch_pool); + SVN_ERR(svn_stream_printf(stream, scratch_pool, + "history: parents %d\n", + ancestors_sorted->nelts)); + for (i = 0; i < ancestors_sorted->nelts; i++) + { + svn_sort__item_t *item + = &APR_ARRAY_IDX(ancestors_sorted, i, svn_sort__item_t); + svn_branch__rev_bid_t *rev_bid = item->value; + + SVN_ERR(svn_stream_printf(stream, scratch_pool, + "parent: r%ld.%s\n", + rev_bid->rev, rev_bid->bid)); + } + + return SVN_NO_ERROR; +} + +/* Write to STREAM a parseable representation of BRANCH. + */ +svn_error_t * +svn_branch__state_serialize(svn_stream_t *stream, + svn_branch__state_t *branch, + apr_pool_t *scratch_pool) +{ + svn_eid__hash_iter_t *ei; + + SVN_ERR_ASSERT(branch->priv->is_flat); + + SVN_ERR(svn_stream_printf(stream, scratch_pool, + "%s root-eid %d num-eids %d\n", + svn_branch__get_id(branch, scratch_pool), + branch->priv->element_tree->root_eid, + apr_hash_count(branch->priv->element_tree->e_map))); + + SVN_ERR(history_serialize(stream, branch->priv->history, + scratch_pool)); + + for (SVN_EID__HASH_ITER_SORTED_BY_EID(ei, branch->priv->element_tree->e_map, + scratch_pool)) + { + int eid = ei->eid; + svn_element__content_t *element = branch_get_element(branch, eid); + int parent_eid; + const char *name; + + SVN_ERR_ASSERT(element); + parent_eid = element->parent_eid; + name = element->name[0] ? element->name : "."; + SVN_ERR(svn_stream_printf(stream, scratch_pool, + "e%d: %s %d %s\n", + eid, + element ? ((! element->payload->is_subbranch_root) + ? "normal" : "subbranch") + : "none", + parent_eid, name)); + } + return SVN_NO_ERROR; +} + +/* + * ======================================================================== + */ + diff --git a/subversion/libsvn_delta/branch_compat.c b/subversion/libsvn_delta/branch_compat.c new file mode 100644 index 000000000000..dac0e191cf24 --- /dev/null +++ b/subversion/libsvn_delta/branch_compat.c @@ -0,0 +1,2070 @@ +/* + * branch_compat.c : Branching compatibility layer. + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#include "svn_types.h" +#include "svn_error.h" +#include "svn_delta.h" +#include "svn_dirent_uri.h" +#include "svn_path.h" +#include "svn_hash.h" +#include "svn_iter.h" +#include "svn_props.h" +#include "svn_pools.h" + +#include "private/svn_branch_impl.h" +#include "private/svn_branch_repos.h" +#include "private/svn_branch_nested.h" +#include "private/svn_delta_private.h" +#include "private/svn_branch_compat.h" + +#include "svn_private_config.h" + + +/* Verify EXPR is true; raise an error if not. */ +#define VERIFY(expr) SVN_ERR_ASSERT(expr) + + +/* + * =================================================================== + * Minor data types + * =================================================================== + */ + +/** A location in a committed revision. + * + * @a rev shall not be #SVN_INVALID_REVNUM unless the interface using this + * type specifically allows it and defines its meaning. */ +typedef struct svn_pathrev_t +{ + svn_revnum_t rev; + const char *relpath; +} svn_pathrev_t; + +/* Return true iff PEG_PATH1 and PEG_PATH2 are both the same location. + */ +static svn_boolean_t +pathrev_equal(const svn_pathrev_t *p1, + const svn_pathrev_t *p2) +{ + if (p1->rev != p2->rev) + return FALSE; + if (strcmp(p1->relpath, p2->relpath) != 0) + return FALSE; + + return TRUE; +} + +#if 0 +/* Return a human-readable string representation of LOC. */ +static const char * +pathrev_str(const svn_pathrev_t *loc, + apr_pool_t *result_pool) +{ + if (! loc) + return ""; + return apr_psprintf(result_pool, "%s@%ld", + loc->relpath, loc->rev); +} + +/* Return a string representation of the (string) keys of HASH. */ +static const char * +hash_keys_str(apr_hash_t *hash) +{ + const char *str = NULL; + apr_pool_t *pool; + apr_hash_index_t *hi; + + if (! hash) + return ""; + + pool = apr_hash_pool_get(hash); + for (hi = apr_hash_first(pool, hash); hi; hi = apr_hash_next(hi)) + { + const char *key = apr_hash_this_key(hi); + + if (!str) + str = key; + else + str = apr_psprintf(pool, "%s, %s", str, key); + } + return apr_psprintf(pool, "{%s}", str); +} +#endif + +/** + * Merge two hash tables into one new hash table. The values of the overlay + * hash override the values of the base if both have the same key. + * + * Unlike apr_hash_overlay(), this doesn't care whether the input hashes use + * the same hash function, nor about the relationship between the three pools. + * + * @param p The pool to use for the new hash table + * @param overlay The table to add to the initial table + * @param base The table that represents the initial values of the new table + * @return A new hash table containing all of the data from the two passed in + * @remark Makes a shallow copy: keys and values are not copied + */ +static apr_hash_t * +hash_overlay(apr_hash_t *overlay, + apr_hash_t *base) +{ + apr_pool_t *pool = apr_hash_pool_get(base); + apr_hash_t *result = apr_hash_copy(pool, base); + apr_hash_index_t *hi; + + for (hi = apr_hash_first(pool, overlay); hi; hi = apr_hash_next(hi)) + { + svn_hash_sets(result, apr_hash_this_key(hi), apr_hash_this_val(hi)); + } + return result; +} + + +/* + * ======================================================================== + * Configuration Options + * ======================================================================== + */ + +/* Features that are not wanted for this commit editor shim but may be + * wanted in a similar but different shim such as for an update editor. */ +/* #define SHIM_WITH_ADD_ABSENT */ +/* #define SHIM_WITH_UNLOCK */ + +/* Whether to support switching from relative to absolute paths in the + * Ev1 methods. */ +/* #define SHIM_WITH_ABS_PATHS */ + + +/* + * ======================================================================== + * Shim Connector + * ======================================================================== + * + * The shim connector enables a more exact round-trip conversion from an + * Ev1 drive to Ev3 and back to Ev1. + */ +struct svn_branch__compat_shim_connector_t +{ + /* Set to true if and when an Ev1 receiving shim receives an absolute + * path (prefixed with '/') from the delta edit, and causes the Ev1 + * sending shim to send absolute paths. + * ### NOT IMPLEMENTED + */ +#ifdef SHIM_WITH_ABS_PATHS + svn_boolean_t *ev1_absolute_paths; +#endif + + /* The Ev1 set_target_revision and start_edit methods, respectively, will + * call the TARGET_REVISION_FUNC and START_EDIT_FUNC callbacks, if non-null. + * Otherwise, default calls will be used. + * + * (Possibly more useful for update editors than for commit editors?) */ + svn_branch__compat_set_target_revision_func_t target_revision_func; + + /* If not null, a callback that the Ev3 driver may call to + * provide the "base revision" of the root directory, even if it is not + * going to modify that directory. (If it does modify it, then it will + * pass in the appropriate base revision at that time.) If null + * or if the driver does not call it, then the Ev1 + * open_root() method will be called with SVN_INVALID_REVNUM as the base + * revision parameter. + */ + svn_delta__start_edit_func_t start_edit_func; + +#ifdef SHIM_WITH_UNLOCK + /* A callback which will be called when an unlocking action is received. + (For update editors?) */ + svn_delta__unlock_func_t unlock_func; +#endif + + void *baton; +}; + +svn_error_t * +svn_branch__compat_insert_shims( + const svn_delta_editor_t **new_deditor, + void **new_dedit_baton, + const svn_delta_editor_t *old_deditor, + void *old_dedit_baton, + const char *repos_root, + const char *base_relpath, + svn_branch__compat_fetch_func_t fetch_func, + void *fetch_baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ +#if 0 + svn_branch__txn_t *edit_txn; + svn_branch__compat_shim_connector_t *shim_connector; + +#ifdef SVN_DEBUG + /*SVN_ERR(svn_delta__get_debug_editor(&old_deditor, &old_dedit_baton, + old_deditor, old_dedit_baton, + "[OUT] ", result_pool));*/ +#endif + SVN_ERR(svn_branch__compat_txn_from_delta_for_commit( + &edit_txn, + &shim_connector, + old_deditor, old_dedit_baton, + branching_txn, + repos_root, + fetch_func, fetch_baton, + NULL, NULL /*cancel*/, + result_pool, scratch_pool)); + SVN_ERR(svn_branch__compat_delta_from_txn_for_commit( + new_deditor, new_dedit_baton, + edit_txn, + repos_root, base_relpath, + fetch_func, fetch_baton, + shim_connector, + result_pool, scratch_pool)); +#ifdef SVN_DEBUG + /*SVN_ERR(svn_delta__get_debug_editor(new_deditor, new_dedit_baton, + *new_deditor, *new_dedit_baton, + "[IN] ", result_pool));*/ +#endif +#else + *new_deditor = old_deditor; + *new_dedit_baton = old_dedit_baton; +#endif + return SVN_NO_ERROR; +} + + +/* + * ======================================================================== + * Buffering the Delta Editor Changes + * ======================================================================== + */ + +/* The kind of Ev1 restructuring operation on a particular path. For each + * visited path we use exactly one restructuring action. */ +enum restructure_action_t +{ + RESTRUCTURE_NONE = 0, + RESTRUCTURE_ADD, /* add the node, maybe replacing. maybe copy */ +#ifdef SHIM_WITH_ADD_ABSENT + RESTRUCTURE_ADD_ABSENT, /* add an absent node, possibly replacing */ +#endif + RESTRUCTURE_DELETE /* delete this node */ +}; + +/* Records everything about how this node is to be changed, from an Ev1 + * point of view. */ +typedef struct change_node_t +{ + /* what kind of (tree) restructure is occurring at this node? */ + enum restructure_action_t action; + + svn_node_kind_t kind; /* the NEW kind of this node */ + + /* We may need to specify the revision we are altering or the revision + to delete or replace. These are mutually exclusive, but are separate + for clarity. */ + /* CHANGING_REV is the base revision of the change if ACTION is 'none', + else is SVN_INVALID_REVNUM. (If ACTION is 'add' and COPYFROM_PATH + is non-null, then COPYFROM_REV serves the equivalent purpose for the + copied node.) */ + /* ### Can also be SVN_INVALID_REVNUM for a pre-existing file/dir, + meaning the base is the youngest revision. This is probably not + a good idea -- it is at least confusing -- and we should instead + resolve to a real revnum when Ev1 passes in SVN_INVALID_REVNUM + in such cases. */ + svn_revnum_t changing_rev; + /* If ACTION is 'delete' or if ACTION is 'add' and it is a replacement, + DELETING is TRUE and DELETING_REV is the revision to delete. */ + /* ### Can also be SVN_INVALID_REVNUM for a pre-existing file/dir, + meaning the base is the youngest revision. This is probably not + a good idea -- it is at least confusing -- and we should instead + resolve to a real revnum when Ev1 passes in SVN_INVALID_REVNUM + in such cases. */ + svn_boolean_t deleting; + svn_revnum_t deleting_rev; + + /* new/final set of props to apply; null => no *change*, not no props */ + apr_hash_t *props; + + /* new fulltext; null => no change */ + svn_boolean_t contents_changed; + svn_stringbuf_t *contents_text; + + /* If COPYFROM_PATH is not NULL, then copy PATH@REV to this node. + RESTRUCTURE must be RESTRUCTURE_ADD. */ + const char *copyfrom_path; + svn_revnum_t copyfrom_rev; + +#ifdef SHIM_WITH_UNLOCK + /* Record whether an incoming propchange unlocked this node. */ + svn_boolean_t unlock; +#endif +} change_node_t; + +#if 0 +/* Return a string representation of CHANGE. */ +static const char * +change_node_str(change_node_t *change, + apr_pool_t *result_pool) +{ + const char *copyfrom = ""; + const char *str; + + if (change->copyfrom_path) + copyfrom = apr_psprintf(result_pool, "'%s'@%ld", + change->copyfrom_path, change->copyfrom_rev); + str = apr_psprintf(result_pool, + "action=%d, kind=%s, changing_rev=%ld, " + "deleting=%d, deleting_rev=%ld, ..., " + "copyfrom=%s", + change->action, + svn_node_kind_to_word(change->kind), + change->changing_rev, + change->deleting, change->deleting_rev, + copyfrom); + return str; +} +#endif + +/* Check whether RELPATH is known to exist, known to not exist, or unknown. */ +static svn_tristate_t +check_existence(apr_hash_t *changes, + const char *relpath) +{ + apr_pool_t *changes_pool = apr_hash_pool_get(changes); + apr_pool_t *scratch_pool = changes_pool; + change_node_t *change = svn_hash_gets(changes, relpath); + svn_tristate_t exists = svn_tristate_unknown; + + if (change && change->action != RESTRUCTURE_DELETE) + exists = svn_tristate_true; + else if (change && change->action == RESTRUCTURE_DELETE) + exists = svn_tristate_false; + else + { + const char *parent_path = relpath; + + /* Find the nearest parent change. If that's a delete or a simple + (non-recursive) add, this path cannot exist, else we don't know. */ + while ((parent_path = svn_relpath_dirname(parent_path, scratch_pool)), + *parent_path) + { + change = svn_hash_gets(changes, parent_path); + if (change) + { + if ((change->action == RESTRUCTURE_ADD && !change->copyfrom_path) + || change->action == RESTRUCTURE_DELETE) + exists = svn_tristate_false; + break; + } + } + } + + return exists; +} + +/* Insert a new Ev1-style change for RELPATH, or return an existing one. + * + * Verify Ev3 rules. Primary differences from Ev1 rules are ... + * + * If ACTION is 'delete', elide any previous explicit deletes inside + * that subtree. (Other changes inside that subtree are not allowed.) We + * do not store multiple change records per path even with nested moves + * -- the most complex change is delete + copy which all fits in one + * record with action='add'. + */ +static svn_error_t * +insert_change(change_node_t **change_p, apr_hash_t *changes, + const char *relpath, + enum restructure_action_t action) +{ + apr_pool_t *changes_pool = apr_hash_pool_get(changes); + change_node_t *change = svn_hash_gets(changes, relpath); + + /* Check whether this op is allowed. */ + switch (action) + { + case RESTRUCTURE_NONE: + if (change) + { + /* A no-restructure change is allowed after add, but not allowed + * (in Ev3) after another no-restructure change, nor a delete. */ + VERIFY(change->action == RESTRUCTURE_ADD); + } + break; + + case RESTRUCTURE_ADD: + if (change) + { + /* Add or copy is allowed after delete (and replaces the delete), + * but not allowed after an add or a no-restructure change. */ + VERIFY(change->action == RESTRUCTURE_DELETE); + change->action = action; + } + break; + +#ifdef SHIM_WITH_ADD_ABSENT + case RESTRUCTURE_ADD_ABSENT: + /* ### */ + break; +#endif + + case RESTRUCTURE_DELETE: + SVN_ERR_MALFUNCTION(); + } + + if (change) + { + if (action != RESTRUCTURE_NONE) + { + change->action = action; + } + } + else + { + /* Create a new change. Callers will set the other fields as needed. */ + change = apr_pcalloc(changes_pool, sizeof(*change)); + change->action = action; + change->changing_rev = SVN_INVALID_REVNUM; + + svn_hash_sets(changes, apr_pstrdup(changes_pool, relpath), change); + } + + *change_p = change; + return SVN_NO_ERROR; +} + +/* Modify CHANGES so as to delete the subtree at RELPATH. + * + * Insert a new Ev1-style change record for RELPATH (or perhaps remove + * the existing record if this would have the same effect), and remove + * any change records for sub-paths under RELPATH. + * + * Follow Ev3 rules, although without knowing whether this delete is + * part of a move. Ev3 (incremental) "rm" operation says each node to + * be removed "MAY be a child of a copy but otherwise SHOULD NOT have + * been created or modified in this edit". "mv" operation says ... + */ +static svn_error_t * +delete_subtree(apr_hash_t *changes, + const char *relpath, + svn_revnum_t deleting_rev) +{ + apr_pool_t *changes_pool = apr_hash_pool_get(changes); + apr_pool_t *scratch_pool = changes_pool; + change_node_t *change = svn_hash_gets(changes, relpath); + + if (change) + { + /* If this previous change was a non-replacing addition, there + is no longer any change to be made at this path. If it was + a replacement or a modification, it now becomes a delete. + (If it was a delete, this attempt to delete is an error.) */ + VERIFY(change->action != RESTRUCTURE_DELETE); + if (change->action == RESTRUCTURE_ADD && !change->deleting) + { + svn_hash_sets(changes, relpath, NULL); + change = NULL; + } + else + { + change->action = RESTRUCTURE_DELETE; + } + } + else + { + /* There was no change recorded at this path. Record a delete. */ + change = apr_pcalloc(changes_pool, sizeof(*change)); + change->action = RESTRUCTURE_DELETE; + change->changing_rev = SVN_INVALID_REVNUM; + change->deleting = TRUE; + change->deleting_rev = deleting_rev; + + svn_hash_sets(changes, apr_pstrdup(changes_pool, relpath), change); + } + + /* Elide all child ops. */ + { + apr_hash_index_t *hi; + + for (hi = apr_hash_first(scratch_pool, changes); + hi; hi = apr_hash_next(hi)) + { + const char *this_relpath = apr_hash_this_key(hi); + const char *r = svn_relpath_skip_ancestor(relpath, this_relpath); + + if (r && r[0]) + { + svn_hash_sets(changes, this_relpath, NULL); + } + } + } + + return SVN_NO_ERROR; +} + + +/* + * =================================================================== + * Commit Editor converter to join a v1 driver to a v3 consumer + * =================================================================== + * + * ... + */ + +svn_error_t * +svn_branch__compat_delta_from_txn_for_commit( + const svn_delta_editor_t **deditor, + void **dedit_baton, + svn_branch__txn_t *edit_txn, + const char *repos_root_url, + const char *base_relpath, + svn_branch__compat_fetch_func_t fetch_func, + void *fetch_baton, + const svn_branch__compat_shim_connector_t *shim_connector, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + /* ### ... */ + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_branch__compat_delta_from_txn_for_update( + const svn_delta_editor_t **deditor, + void **dedit_baton, + svn_branch__compat_update_editor3_t *update_editor, + const char *repos_root_url, + const char *base_repos_relpath, + svn_branch__compat_fetch_func_t fetch_func, + void *fetch_baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_branch__compat_shim_connector_t *shim_connector + = apr_pcalloc(result_pool, sizeof(*shim_connector)); + + shim_connector->target_revision_func = update_editor->set_target_revision_func; + shim_connector->baton = update_editor->set_target_revision_baton; +#ifdef SHIM_WITH_ABS_PATHS + shim_connector->ev1_absolute_paths /*...*/; +#endif + + SVN_ERR(svn_branch__compat_delta_from_txn_for_commit( + deditor, dedit_baton, + update_editor->edit_txn, + repos_root_url, base_repos_relpath, + fetch_func, fetch_baton, + shim_connector, + result_pool, scratch_pool)); + /*SVN_ERR(svn_delta__get_debug_editor(deditor, dedit_baton, + *deditor, *dedit_baton, + "[UP>1] ", result_pool));*/ + + return SVN_NO_ERROR; +} + + +/* + * =================================================================== + * Commit Editor converter to join a v3 driver to a v1 consumer + * =================================================================== + * + * This editor buffers all the changes before driving the Ev1 at the end, + * since it needs to do a single depth-first traversal of the path space + * and this cannot be started until all moves are known. + * + * Moves are converted to copy-and-delete, with the copy being from + * the source peg rev. (### Should it request copy-from revision "-1"?) + * + * It works like this: + * + * +------+--------+ + * | path | change | + * Ev3 --> +------+--------+ --> Ev1 + * | ... | ... | + * | ... | ... | + * + * 1. Ev3 changes are accumulated in a per-path table, EB->changes. + * + * 2. On Ev3 close-edit, walk through the table in a depth-first order, + * sending the equivalent Ev1 action for each change. + * + * TODO + * + * ### For changes inside a copied subtree, the calls to the "open dir" + * and "open file" Ev1 methods may be passing the wrong revision + * number: see comment in apply_change(). + * + * ### Have we got our rel-paths in order? Ev1, Ev3 and callbacks may + * all expect different paths. Are they relative to repos root or to + * some base path? Leading slash (unimplemented 'send_abs_paths' + * feature), etc. + * + * ### May be tidier for OPEN_ROOT_FUNC callback (see open_root_ev3()) + * not to actually open the root in advance, but instead just to + * remember the base revision that the driver wants us to specify + * when we do open it. + */ + + + +/* + * ======================================================================== + * Driving the Delta Editor + * ======================================================================== + */ + +/* Information needed for driving the delta editor. */ +struct svn_branch__txn_priv_t +{ + /* The Ev1 "delta editor" */ + const svn_delta_editor_t *deditor; + void *dedit_baton; + + /* Callbacks */ + svn_branch__compat_fetch_func_t fetch_func; + void *fetch_baton; + + /* The Ev1 root directory baton if we have opened the root, else null. */ + void *ev1_root_dir_baton; + +#ifdef SHIM_WITH_ABS_PATHS + const svn_boolean_t *make_abs_paths; +#endif + + /* Repository root URL + ### Some code allows this to be null -- but is that valid? */ + const char *repos_root_url; + + /* Ev1 changes recorded so far: REPOS_RELPATH -> change_node_ev3_t */ + apr_hash_t *changes; + + /* The branching state on which the per-element API is working */ + svn_branch__txn_t *txn; + + apr_pool_t *edit_pool; +}; + +/* Get all the (Ev1) paths that have changes. + */ +static const apr_array_header_t * +get_unsorted_paths(apr_hash_t *changes, + apr_pool_t *scratch_pool) +{ + apr_array_header_t *paths = apr_array_make(scratch_pool, 0, sizeof(void *)); + apr_hash_index_t *hi; + + for (hi = apr_hash_first(scratch_pool, changes); hi; hi = apr_hash_next(hi)) + { + const char *this_path = apr_hash_this_key(hi); + APR_ARRAY_PUSH(paths, const char *) = this_path; + } + + return paths; +} + +#if 0 /* needed only for shim connector */ +/* */ +static svn_error_t * +set_target_revision_ev3(void *edit_baton, + svn_revnum_t target_revision, + apr_pool_t *scratch_pool) +{ + svn_branch__txn_priv_t *eb = edit_baton; + + SVN_ERR(eb->deditor->set_target_revision(eb->dedit_baton, target_revision, + scratch_pool)); + + return SVN_NO_ERROR; +} +#endif + +/* */ +static svn_error_t * +open_root_ev3(void *baton, + svn_revnum_t base_revision) +{ + svn_branch__txn_priv_t *eb = baton; + + SVN_ERR(eb->deditor->open_root(eb->dedit_baton, base_revision, + eb->edit_pool, &eb->ev1_root_dir_baton)); + return SVN_NO_ERROR; +} + +/* If RELPATH is a child of a copy, return the path of the copy root, + * else return NULL. + */ +static const char * +find_enclosing_copy(apr_hash_t *changes, + const char *relpath, + apr_pool_t *result_pool) +{ + while (*relpath) + { + const change_node_t *change = svn_hash_gets(changes, relpath); + + if (change) + { + if (change->copyfrom_path) + return relpath; + if (change->action != RESTRUCTURE_NONE) + return NULL; + } + relpath = svn_relpath_dirname(relpath, result_pool); + } + + return NULL; +} + +/* Set *BASE_PROPS to the 'base' properties, against which any changes + * will be described, for the changed path described in CHANGES at + * REPOS_RELPATH. + * + * For a copied path, including a copy child path, fetch from the copy + * source path. For a plain add, return an empty set. For a delete, + * return NULL. + */ +static svn_error_t * +fetch_base_props(apr_hash_t **base_props, + apr_hash_t *changes, + const char *repos_relpath, + svn_branch__compat_fetch_func_t fetch_func, + void *fetch_baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + const change_node_t *change = svn_hash_gets(changes, repos_relpath); + const char *source_path = NULL; + svn_revnum_t source_rev; + + if (change->action == RESTRUCTURE_DELETE) + { + *base_props = NULL; + } + + else if (change->action == RESTRUCTURE_ADD && ! change->copyfrom_path) + { + *base_props = apr_hash_make(result_pool); + } + else if (change->copyfrom_path) + { + source_path = change->copyfrom_path; + source_rev = change->copyfrom_rev; + } + else /* RESTRUCTURE_NONE */ + { + /* It's an edit, but possibly to a copy child. Discover if it's a + copy child, & find the copy-from source. */ + + const char *copy_path + = find_enclosing_copy(changes, repos_relpath, scratch_pool); + + if (copy_path) + { + const change_node_t *enclosing_copy + = svn_hash_gets(changes, copy_path); + const char *remainder + = svn_relpath_skip_ancestor(copy_path, repos_relpath); + + source_path = svn_relpath_join(enclosing_copy->copyfrom_path, + remainder, scratch_pool); + source_rev = enclosing_copy->copyfrom_rev; + } + else + { + /* It's a plain edit (not a copy child path). */ + source_path = repos_relpath; + source_rev = change->changing_rev; + } + } + + if (source_path) + { + SVN_ERR(fetch_func(NULL, base_props, NULL, NULL, + fetch_baton, source_path, source_rev, + result_pool, scratch_pool)); + } + + return SVN_NO_ERROR; +} + +/* Send property changes to Ev1 for the CHANGE at REPOS_RELPATH. + * + * Ev1 requires exactly one prop-change call for each prop whose value + * has changed. Therefore we *have* to fetch the original props from the + * repository, provide them as OLD_PROPS, and calculate the changes. + */ +static svn_error_t * +drive_ev1_props(const char *repos_relpath, + const change_node_t *change, + apr_hash_t *old_props, + const svn_delta_editor_t *deditor, + void *node_baton, + apr_pool_t *scratch_pool) +{ + apr_pool_t *iterpool = svn_pool_create(scratch_pool); + apr_array_header_t *propdiffs; + int i; + + SVN_ERR_ASSERT(change->action != RESTRUCTURE_DELETE); + + /* If there are no property changes, then just exit. */ + if (change->props == NULL) + return SVN_NO_ERROR; + + SVN_ERR(svn_prop_diffs(&propdiffs, change->props, old_props, scratch_pool)); + + /* Apply property changes. These should be changes against the empty set + for a new node, or changes against the source node for a copied node. */ + for (i = 0; i < propdiffs->nelts; i++) + { + const svn_prop_t *prop = &APR_ARRAY_IDX(propdiffs, i, svn_prop_t); + + svn_pool_clear(iterpool); + + if (change->kind == svn_node_dir) + SVN_ERR(deditor->change_dir_prop(node_baton, + prop->name, prop->value, + iterpool)); + else + SVN_ERR(deditor->change_file_prop(node_baton, + prop->name, prop->value, + iterpool)); + } + +#ifdef SHIM_WITH_UNLOCK + /* Handle the funky unlock protocol. Note: only possibly on files. */ + if (change->unlock) + { + SVN_ERR_ASSERT(change->kind == svn_node_file); + SVN_ERR(deditor->change_file_prop(node_baton, + SVN_PROP_ENTRY_LOCK_TOKEN, NULL, + iterpool)); + } +#endif + + svn_pool_destroy(iterpool); + return SVN_NO_ERROR; +} + +/* Drive the Ev1 editor with the change recorded in EB->changes for the + * path EV1_RELPATH. + * + * Conforms to svn_delta_path_driver_cb_func_t. + */ +static svn_error_t * +apply_change(void **dir_baton, + void *parent_baton, + void *callback_baton, + const char *ev1_relpath, + apr_pool_t *result_pool) +{ + apr_pool_t *scratch_pool = result_pool; + const svn_branch__txn_priv_t *eb = callback_baton; + const change_node_t *change = svn_hash_gets(eb->changes, ev1_relpath); + void *file_baton = NULL; + apr_hash_t *base_props; + + /* The callback should only be called for paths in CHANGES. */ + SVN_ERR_ASSERT(change != NULL); + + /* Typically, we are not creating new directory batons. */ + *dir_baton = NULL; + + SVN_ERR(fetch_base_props(&base_props, eb->changes, ev1_relpath, + eb->fetch_func, eb->fetch_baton, + scratch_pool, scratch_pool)); + + /* Are we editing the root of the tree? */ + if (parent_baton == NULL) + { + /* The root dir was already opened. */ + *dir_baton = eb->ev1_root_dir_baton; + + /* Only property edits are allowed on the root. */ + SVN_ERR_ASSERT(change->action == RESTRUCTURE_NONE); + SVN_ERR(drive_ev1_props(ev1_relpath, change, base_props, + eb->deditor, *dir_baton, scratch_pool)); + + /* No further action possible for the root. */ + return SVN_NO_ERROR; + } + + if (change->action == RESTRUCTURE_DELETE) + { + SVN_ERR(eb->deditor->delete_entry(ev1_relpath, change->deleting_rev, + parent_baton, scratch_pool)); + + /* No futher action possible for this node. */ + return SVN_NO_ERROR; + } + + /* If we're not deleting this node, then we should know its kind. */ + SVN_ERR_ASSERT(change->kind != svn_node_unknown); + +#ifdef SHIM_WITH_ADD_ABSENT + if (change->action == RESTRUCTURE_ADD_ABSENT) + { + if (change->kind == svn_node_dir) + SVN_ERR(eb->deditor->absent_directory(ev1_relpath, parent_baton, + scratch_pool)); + else if (change->kind == svn_node_file) + SVN_ERR(eb->deditor->absent_file(ev1_relpath, parent_baton, + scratch_pool)); + else + SVN_ERR_MALFUNCTION(); + + /* No further action possible for this node. */ + return SVN_NO_ERROR; + } +#endif + /* RESTRUCTURE_NONE or RESTRUCTURE_ADD */ + + if (change->action == RESTRUCTURE_ADD) + { + const char *copyfrom_url = NULL; + svn_revnum_t copyfrom_rev = SVN_INVALID_REVNUM; + + /* Do we have an old node to delete first? If so, delete it. */ + if (change->deleting) + SVN_ERR(eb->deditor->delete_entry(ev1_relpath, change->deleting_rev, + parent_baton, scratch_pool)); + + /* If it's a copy, determine the copy source location. */ + if (change->copyfrom_path) + { + /* ### What's this about URL vs. fspath? REPOS_ROOT_URL isn't + optional, is it, at least in a commit editor? */ + if (eb->repos_root_url) + copyfrom_url = svn_path_url_add_component2(eb->repos_root_url, + change->copyfrom_path, + scratch_pool); + else + { + copyfrom_url = change->copyfrom_path; + + /* Make this an FS path by prepending "/" */ + if (copyfrom_url[0] != '/') + copyfrom_url = apr_pstrcat(scratch_pool, "/", + copyfrom_url, SVN_VA_NULL); + } + + copyfrom_rev = change->copyfrom_rev; + } + + if (change->kind == svn_node_dir) + SVN_ERR(eb->deditor->add_directory(ev1_relpath, parent_baton, + copyfrom_url, copyfrom_rev, + result_pool, dir_baton)); + else if (change->kind == svn_node_file) + SVN_ERR(eb->deditor->add_file(ev1_relpath, parent_baton, + copyfrom_url, copyfrom_rev, + result_pool, &file_baton)); + else + SVN_ERR_MALFUNCTION(); + } + else /* RESTRUCTURE_NONE */ + { + /* ### The code that inserts a "plain edit" change record sets + 'changing_rev' to the peg rev of the pegged part of the path, + even when the full path refers to a child of a copy. Should we + instead be using the copy source rev here, in that case? (Like + when we fetch the base properties.) */ + + if (change->kind == svn_node_dir) + SVN_ERR(eb->deditor->open_directory(ev1_relpath, parent_baton, + change->changing_rev, + result_pool, dir_baton)); + else if (change->kind == svn_node_file) + SVN_ERR(eb->deditor->open_file(ev1_relpath, parent_baton, + change->changing_rev, + result_pool, &file_baton)); + else + SVN_ERR_MALFUNCTION(); + } + + /* Apply any properties in CHANGE to the node. */ + if (change->kind == svn_node_dir) + SVN_ERR(drive_ev1_props(ev1_relpath, change, base_props, + eb->deditor, *dir_baton, scratch_pool)); + else + SVN_ERR(drive_ev1_props(ev1_relpath, change, base_props, + eb->deditor, file_baton, scratch_pool)); + + /* Send the text content delta, if new text content is provided. */ + if (change->contents_text) + { + svn_stream_t *read_stream; + svn_txdelta_window_handler_t handler; + void *handler_baton; + + read_stream = svn_stream_from_stringbuf(change->contents_text, + scratch_pool); + /* ### would be nice to have a BASE_CHECKSUM, but hey: this is the + ### shim code... */ + SVN_ERR(eb->deditor->apply_textdelta(file_baton, NULL, scratch_pool, + &handler, &handler_baton)); + /* ### it would be nice to send a true txdelta here, but whatever. */ + SVN_ERR(svn_txdelta_send_stream(read_stream, handler, handler_baton, + NULL, scratch_pool)); + SVN_ERR(svn_stream_close(read_stream)); + } + + if (file_baton) + { + SVN_ERR(eb->deditor->close_file(file_baton, NULL, scratch_pool)); + } + + return SVN_NO_ERROR; +} + +/* + * ======================================================================== + * Old-repository storage paths for branch elements + * ======================================================================== + * + * To support top-level branches, we map each top-level branch to its own + * directory in the old repository, with each nested branch in a subdirectory: + * + * B0 => ^/top0/... + * ^/top0/.../trunk/... <= B0.12 + * B1 => ^/top1/... + * + * It may be better to put each branch in its own directory: + * + * B0 => ^/B0/... + * B0.12 => ^/B0.12/... + * B1 => ^/B1/... + * + * (A branch root is not necessarily a directory, it could be a file.) + */ + +/* Get the old-repository path for the storage of the root element of BRANCH. + * + * Currently, this is the same as the nested-branching hierarchical path + * (and thus assumes there is only one top-level branch). + */ +static const char * +branch_get_storage_root_rrpath(const svn_branch__state_t *branch, + apr_pool_t *result_pool) +{ + int top_branch_num = atoi(branch->bid + 1); + const char *top_path = apr_psprintf(result_pool, "top%d", top_branch_num); + const char *nested_path = svn_branch__get_root_rrpath(branch, result_pool); + + return svn_relpath_join(top_path, nested_path, result_pool); +} + +/* Get the old-repository path for the storage of element EID of BRANCH. + * + * If the element EID doesn't exist in BRANCH, return NULL. + */ +static const char * +branch_get_storage_rrpath_by_eid(const svn_branch__state_t *branch, + int eid, + apr_pool_t *result_pool) +{ + const char *path = svn_branch__get_path_by_eid(branch, eid, result_pool); + const char *rrpath = NULL; + + if (path) + { + rrpath = svn_relpath_join(branch_get_storage_root_rrpath(branch, + result_pool), + path, result_pool); + } + return rrpath; +} + +/* Return, in *STORAGE_PATHREV_P, the storage-rrpath-rev for BRANCH_REF. + */ +static svn_error_t * +storage_pathrev_from_branch_ref(svn_pathrev_t *storage_pathrev_p, + svn_element__branch_ref_t branch_ref, + svn_branch__repos_t *repos, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_branch__el_rev_id_t *el_rev; + + SVN_ERR(svn_branch__repos_find_el_rev_by_id(&el_rev, + repos, + branch_ref.rev, + branch_ref.branch_id, + branch_ref.eid, + scratch_pool, scratch_pool)); + + storage_pathrev_p->rev = el_rev->rev; + storage_pathrev_p->relpath + = branch_get_storage_rrpath_by_eid(el_rev->branch, el_rev->eid, + result_pool); + + return SVN_NO_ERROR; +} + +/* + * ======================================================================== + * Editor for Commit (independent per-element changes; element-id addressing) + * ======================================================================== + */ + +/* */ +#define PAYLOAD_IS_ONLY_BY_REFERENCE(payload) \ + ((payload)->kind == svn_node_unknown) + +/* Fetch a payload as *PAYLOAD_P from its storage-pathrev PATH_REV. + * Fetch names of immediate children of PATH_REV as *CHILDREN_NAMES. + * Either of the outputs may be null if not wanted. + */ +static svn_error_t * +payload_fetch(svn_element__payload_t **payload_p, + apr_hash_t **children_names, + svn_branch__txn_priv_t *eb, + const svn_pathrev_t *path_rev, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_element__payload_t *payload + = apr_pcalloc(result_pool, sizeof (*payload)); + + SVN_ERR(eb->fetch_func(&payload->kind, + &payload->props, + &payload->text, + children_names, + eb->fetch_baton, + path_rev->relpath, path_rev->rev, + result_pool, scratch_pool)); + + SVN_ERR_ASSERT(svn_element__payload_invariants(payload)); + SVN_ERR_ASSERT(payload->kind == svn_node_dir + || payload->kind == svn_node_file); + if (payload_p) + *payload_p = payload; + return SVN_NO_ERROR; +} + +/* Return the storage-pathrev of PAYLOAD as *STORAGE_PATHREV_P. + * + * Find the storage-pathrev from PAYLOAD->branch_ref. + */ +static svn_error_t * +payload_get_storage_pathrev(svn_pathrev_t *storage_pathrev_p, + svn_element__payload_t *payload, + svn_branch__repos_t *repos, + apr_pool_t *result_pool) +{ + SVN_ERR_ASSERT(payload->branch_ref.branch_id /* && ... */); + + SVN_ERR(storage_pathrev_from_branch_ref(storage_pathrev_p, + payload->branch_ref, repos, + result_pool, result_pool)); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_branch__compat_fetch(svn_element__payload_t **payload_p, + svn_branch__txn_t *txn, + svn_element__branch_ref_t branch_ref, + svn_branch__compat_fetch_func_t fetch_func, + void *fetch_baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_branch__txn_priv_t eb; + svn_pathrev_t storage_pathrev; + + /* Simulate the existence of /top0 in r0. */ + if (branch_ref.rev == 0 && branch_ref.eid == 0) + { + *payload_p = svn_element__payload_create_dir(apr_hash_make(result_pool), + result_pool); + return SVN_NO_ERROR; + } + + eb.txn = txn; + eb.fetch_func = fetch_func; + eb.fetch_baton = fetch_baton; + + SVN_ERR(storage_pathrev_from_branch_ref(&storage_pathrev, + branch_ref, txn->repos, + scratch_pool, scratch_pool)); + + SVN_ERR(payload_fetch(payload_p, NULL, + &eb, &storage_pathrev, result_pool, scratch_pool)); + (*payload_p)->branch_ref = branch_ref; + return SVN_NO_ERROR; +} + +/* Fill in the actual payload, from its reference, if not already done. + */ +static svn_error_t * +payload_resolve(svn_element__payload_t *payload, + svn_branch__txn_priv_t *eb, + apr_pool_t *scratch_pool) +{ + svn_pathrev_t storage; + + SVN_ERR_ASSERT(svn_element__payload_invariants(payload)); + + if (! PAYLOAD_IS_ONLY_BY_REFERENCE(payload)) + return SVN_NO_ERROR; + + SVN_ERR(payload_get_storage_pathrev(&storage, payload, + eb->txn->repos, + scratch_pool)); + + SVN_ERR(eb->fetch_func(&payload->kind, + &payload->props, + &payload->text, + NULL, + eb->fetch_baton, + storage.relpath, storage.rev, + payload->pool, scratch_pool)); + + SVN_ERR_ASSERT(svn_element__payload_invariants(payload)); + SVN_ERR_ASSERT(! PAYLOAD_IS_ONLY_BY_REFERENCE(payload)); + return SVN_NO_ERROR; +} + +/* Update *PATHS, a hash of (storage_rrpath -> svn_branch__el_rev_id_t), + * creating or filling in entries for all elements in BRANCH. + */ +static svn_error_t * +convert_branch_to_paths(apr_hash_t *paths, + svn_branch__state_t *branch, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + apr_hash_index_t *hi; + svn_element__tree_t *elements; + + /* assert(branch is at a sequence point); */ + + SVN_ERR(svn_branch__state_get_elements(branch, &elements, scratch_pool)); + for (hi = apr_hash_first(scratch_pool, elements->e_map); + hi; hi = apr_hash_next(hi)) + { + int eid = svn_eid__hash_this_key(hi); + svn_element__content_t *element = apr_hash_this_val(hi); + const char *rrpath + = branch_get_storage_rrpath_by_eid(branch, eid, result_pool); + svn_branch__el_rev_id_t *ba; + + /* A subbranch-root element carries no payload; the corresponding + inner branch root element will provide the payload for this path. */ + if (element->payload->is_subbranch_root) + continue; + + /* No other element should exist at this path, given that we avoid + storing anything for a subbranch-root element. */ + SVN_ERR_ASSERT(! svn_hash_gets(paths, rrpath)); + + /* Fill in the details. */ + ba = svn_branch__el_rev_id_create(branch, eid, branch->txn->rev, + result_pool); + svn_hash_sets(paths, rrpath, ba); + /*SVN_DBG(("branch-to-path[%d]: b%s e%d -> %s", + i, svn_branch__get_id(branch, scratch_pool), eid, rrpath));*/ + } + return SVN_NO_ERROR; +} + +/* Produce a mapping from paths to element ids, covering all elements in + * BRANCH and all its sub-branches, recursively. + * + * Update *PATHS_UNION, a hash of (storage_rrpath -> svn_branch__el_rev_id_t), + * creating or filling in entries for all elements in all branches at and + * under BRANCH, recursively. + */ +static svn_error_t * +convert_branch_to_paths_r(apr_hash_t *paths_union, + svn_branch__state_t *branch, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + apr_array_header_t *subbranches; + int i; + + /*SVN_DBG(("[%d] branch={b%s e%d at '%s'}", idx, + svn_branch__get_id(branch, scratch_pool), branch->root_eid, + svn_branch__get_root_rrpath(branch, scratch_pool)));*/ + SVN_ERR(convert_branch_to_paths(paths_union, branch, + result_pool, scratch_pool)); + + SVN_ERR(svn_branch__get_immediate_subbranches(branch, &subbranches, + scratch_pool, scratch_pool)); + /* Rercurse into sub-branches */ + for (i = 0; i < subbranches->nelts; i++) + { + svn_branch__state_t *b = APR_ARRAY_IDX(subbranches, i, void *); + + SVN_ERR(convert_branch_to_paths_r(paths_union, b, result_pool, + scratch_pool)); + } + return SVN_NO_ERROR; +} + +/* Return TRUE iff INITIAL_PAYLOAD and FINAL_PAYLOAD are both non-null + * and have the same properties. + */ +static svn_boolean_t +props_equal(svn_element__payload_t *initial_payload, + svn_element__payload_t *final_payload, + apr_pool_t *scratch_pool) +{ + apr_array_header_t *prop_diffs; + + if (!initial_payload || !final_payload) + return FALSE; + + svn_error_clear(svn_prop_diffs(&prop_diffs, + initial_payload->props, + final_payload->props, + scratch_pool)); + return (prop_diffs->nelts == 0); +} + +/* Return TRUE iff INITIAL_PAYLOAD and FINAL_PAYLOAD are both file payload + * and have the same text. + */ +static svn_boolean_t +text_equal(svn_element__payload_t *initial_payload, + svn_element__payload_t *final_payload) +{ + if (!initial_payload || !final_payload + || initial_payload->kind != svn_node_file + || final_payload->kind != svn_node_file) + { + return FALSE; + } + + return svn_stringbuf_compare(initial_payload->text, + final_payload->text); +} + +/* Return the copy-from location to be used if this is to be a copy; + * otherwise return NULL. + * + * ### Currently this is indicated by payload-by-reference, which is + * an inadequate indication. + */ +static svn_error_t * +get_copy_from(svn_pathrev_t *copyfrom_pathrev_p, + svn_element__payload_t *final_payload, + svn_branch__txn_priv_t *eb, + apr_pool_t *result_pool) +{ + if (final_payload->branch_ref.branch_id) + { + SVN_ERR(payload_get_storage_pathrev(copyfrom_pathrev_p, final_payload, + eb->txn->repos, + result_pool)); + } + else + { + copyfrom_pathrev_p->relpath = NULL; + copyfrom_pathrev_p->rev = SVN_INVALID_REVNUM; + } + + return SVN_NO_ERROR; +} + +/* Return a hash whose keys are the names of the immediate children of + * RRPATH in PATHS. + */ +static apr_hash_t * +get_immediate_children_names(apr_hash_t *paths, + const char *parent_rrpath, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + apr_hash_t *children = apr_hash_make(result_pool); + apr_hash_index_t *hi; + + for (hi = apr_hash_first(scratch_pool, paths); hi; hi = apr_hash_next(hi)) + { + const char *this_rrpath = apr_hash_this_key(hi); + + if (this_rrpath[0] + && strcmp(parent_rrpath, svn_relpath_dirname(this_rrpath, + scratch_pool)) == 0) + { + svn_hash_sets(children, + svn_relpath_basename(this_rrpath, result_pool), ""); + } + } + + return children; +} + +/* Generate Ev1 instructions to edit from a current state to a final state + * at RRPATH, recursing for child paths of RRPATH. + * + * The current state at RRPATH might not be the initial state because, + * although neither RRPATH nor any sub-paths have been explicitly visited + * before, the current state at RRPATH and its sub-paths might be the + * result of a copy. + * + * PRED_LOC is the predecessor location of the node currently at RRPATH in + * the Ev1 transaction, or NULL if there is no node currently at RRPATH. + * If the node is copied, including a child of a copy, this is its copy-from + * location, otherwise this is its location in the txn base revision. + * (The current node cannot be a plain added node on entry to this function, + * as the function must be called only once for each path and there is no + * recursive add operation.) PRED_LOC identifies the node content that the + * that the Ev1 edit needs to delete, replace, update or leave unchanged. + * + * Process a single hierarchy of nested branches, rooted in the top-level + * branch TOP_BRANCH_NUM. + */ +static svn_error_t * +drive_changes_r(const char *rrpath, + svn_pathrev_t *pred_loc, + apr_hash_t *paths_final, + const char *top_branch_id, + svn_branch__txn_priv_t *eb, + apr_pool_t *scratch_pool) +{ + /* The el-rev-id of the element that will finally exist at RRPATH. */ + svn_branch__el_rev_id_t *final_el_rev = svn_hash_gets(paths_final, rrpath); + svn_element__payload_t *final_payload; + svn_pathrev_t final_copy_from; + svn_boolean_t succession; + + /*SVN_DBG(("rrpath '%s' current=%s, final=e%d)", + rrpath, + pred_loc ? pathrev_str(*pred_loc, scratch_pool) : "", + final_el_rev ? final_el_rev->eid : -1));*/ + + SVN_ERR_ASSERT(!pred_loc + || (pred_loc->relpath && SVN_IS_VALID_REVNUM(pred_loc->rev))); + + if (final_el_rev) + { + svn_element__content_t *final_element; + + SVN_ERR(svn_branch__state_get_element(final_el_rev->branch, &final_element, + final_el_rev->eid, scratch_pool)); + /* A non-null FINAL address means an element exists there. */ + SVN_ERR_ASSERT(final_element); + + final_payload = final_element->payload; + + /* Decide whether the state at this path should be a copy (incl. a + copy-child) */ + SVN_ERR(get_copy_from(&final_copy_from, final_payload, eb, scratch_pool)); + /* It doesn't make sense to have a non-copy inside a copy */ + /*SVN_ERR_ASSERT(!(parent_is_copy && !final_copy_from));*/ + } + else + { + final_payload = NULL; + final_copy_from.relpath = NULL; + } + + /* Succession means: + for a copy (inc. child) -- copy-from same place as natural predecessor + otherwise -- it's succession if it's the same element + (which also implies the same kind) */ + if (pred_loc && final_copy_from.relpath) + { + succession = pathrev_equal(pred_loc, &final_copy_from); + } + else if (pred_loc && final_el_rev) + { + svn_branch__el_rev_id_t *pred_el_rev; + + SVN_ERR(svn_branch__repos_find_el_rev_by_path_rev(&pred_el_rev, + eb->txn->repos, + pred_loc->rev, + top_branch_id, + pred_loc->relpath, + scratch_pool, scratch_pool)); + + succession = (pred_el_rev->eid == final_el_rev->eid); + } + else + { + succession = FALSE; + } + + /* If there's an initial node that isn't also going to be the final + node at this path, then it's being deleted or replaced: delete it. */ + if (pred_loc && !succession) + { + /* Issue an Ev1 delete unless this path is inside a path at which + we've already issued a delete. */ + if (check_existence(eb->changes, rrpath) != svn_tristate_false) + { + /*SVN_DBG(("ev1:del(%s)", rrpath));*/ + /* ### We don't need "delete_subtree", we only need to insert a + single delete operation, as we know we haven't + inserted any changes inside this subtree. */ + SVN_ERR(delete_subtree(eb->changes, rrpath, pred_loc->rev)); + } + else + { + /*SVN_DBG(("ev1:del(%s): parent is already deleted", rrpath))*/ + } + } + + /* If there's a final node, it's being added or modified. + Or it's unchanged -- we do nothing in that case. */ + if (final_el_rev) + { + svn_element__payload_t *current_payload = NULL; + apr_hash_t *current_children = NULL; + change_node_t *change = NULL; + + /* Get the full payload of the final node. If we have + only a reference to the payload, fetch it in full. */ + SVN_ERR_ASSERT(final_payload); + SVN_ERR(payload_resolve(final_payload, eb, scratch_pool)); + + /* If the final node was also the initial node, it's being + modified, otherwise it's being added (perhaps a replacement). */ + if (succession) + { + /* Get full payload of the current node */ + SVN_ERR(payload_fetch(¤t_payload, ¤t_children, + eb, pred_loc, + scratch_pool, scratch_pool)); + + /* If no changes to make, then skip this path */ + if (svn_element__payload_equal(current_payload, + final_payload, scratch_pool)) + { + /*SVN_DBG(("ev1:no-op(%s)", rrpath));*/ + } + else + { + /*SVN_DBG(("ev1:mod(%s)", rrpath));*/ + SVN_ERR(insert_change(&change, eb->changes, rrpath, + RESTRUCTURE_NONE)); + change->changing_rev = pred_loc->rev; + } + } + else /* add or copy/move */ + { + /*SVN_DBG(("ev1:add(%s)", rrpath));*/ + SVN_ERR(insert_change(&change, eb->changes, rrpath, + RESTRUCTURE_ADD)); + + /* If the node is to be copied (and possibly modified) ... */ + if (final_copy_from.relpath) + { + change->copyfrom_rev = final_copy_from.rev; + change->copyfrom_path = final_copy_from.relpath; + + /* Get full payload of the copy source node */ + SVN_ERR(payload_fetch(¤t_payload, ¤t_children, + eb, &final_copy_from, + scratch_pool, scratch_pool)); + } + } + + if (change) + { + /* Copy the required content into the change record. Avoid no-op + changes of props / text, not least to minimize clutter when + debugging Ev1 operations. */ + SVN_ERR_ASSERT(final_payload->kind == svn_node_dir + || final_payload->kind == svn_node_file); + change->kind = final_payload->kind; + if (!props_equal(current_payload, final_payload, scratch_pool)) + { + change->props = final_payload->props; + } + if (final_payload->kind == svn_node_file + && !text_equal(current_payload, final_payload)) + { + change->contents_text = final_payload->text; + } + } + + /* Recurse to process this directory's children */ + if (final_payload->kind == svn_node_dir) + { + apr_hash_t *final_children; + apr_hash_t *union_children; + apr_hash_index_t *hi; + + final_children = get_immediate_children_names(paths_final, rrpath, + scratch_pool, + scratch_pool); + union_children = (current_children + ? hash_overlay(current_children, final_children) + : final_children); + for (hi = apr_hash_first(scratch_pool, union_children); + hi; hi = apr_hash_next(hi)) + { + const char *name = apr_hash_this_key(hi); + const char *this_rrpath = svn_relpath_join(rrpath, name, + scratch_pool); + svn_boolean_t child_in_current + = current_children && svn_hash_gets(current_children, name); + svn_pathrev_t *child_pred = NULL; + + if (child_in_current) + { + /* If the parent dir is copied, then this child has been + copied along with it: predecessor is parent's copy-from + location extended by the child's name. */ + child_pred = apr_palloc(scratch_pool, sizeof(*child_pred)); + if (final_copy_from.relpath) + { + child_pred->rev = final_copy_from.rev; + child_pred->relpath + = svn_relpath_join(final_copy_from.relpath, name, + scratch_pool); + } + else + { + child_pred->rev = pred_loc->rev; + child_pred->relpath = this_rrpath; + } + } + + SVN_ERR(drive_changes_r(this_rrpath, + child_pred, + paths_final, top_branch_id, + eb, scratch_pool)); + } + } + } + + return SVN_NO_ERROR; +} + +/* + * Drive svn_delta_editor_t (actions: add/copy/delete/modify) from + * a before-and-after element mapping. + */ +static svn_error_t * +drive_changes(svn_branch__txn_priv_t *eb, + apr_pool_t *scratch_pool) +{ + apr_array_header_t *branches; + int i; + const apr_array_header_t *paths; + + /* Convert the element mappings to an svn_delta_editor_t traversal. + + 1. find union of paths in initial and final states, across all branches. + 2. traverse paths in depth-first order. + 3. modify/delete/add/replace as needed at each path. + */ + + /* Process one hierarchy of nested branches at a time. */ + branches = svn_branch__txn_get_branches(eb->txn, scratch_pool); + for (i = 0; i < branches->nelts; i++) + { + svn_branch__state_t *root_branch = APR_ARRAY_IDX(branches, i, void *); + apr_hash_t *paths_final; + + const char *top_path = branch_get_storage_root_rrpath(root_branch, + scratch_pool); + svn_pathrev_t current; + svn_branch__state_t *base_root_branch; + svn_boolean_t branch_is_new; + + if (strchr(root_branch->bid, '.')) + continue; /* that's not a root branch */ + + SVN_ERR(svn_branch__repos_get_branch_by_id(&base_root_branch, + eb->txn->repos, + eb->txn->base_rev, + root_branch->bid, scratch_pool)); + branch_is_new = !base_root_branch; + + paths_final = apr_hash_make(scratch_pool); + SVN_ERR(convert_branch_to_paths_r(paths_final, + root_branch, + scratch_pool, scratch_pool)); + + current.rev = eb->txn->base_rev; + current.relpath = top_path; + + /* Create the top-level storage node if the branch is new, or if this is + the first commit to branch B0 which was created in r0 but had no + storage node there. */ + if (branch_is_new || current.rev == 0) + { + change_node_t *change; + + SVN_ERR(insert_change(&change, eb->changes, top_path, RESTRUCTURE_ADD)); + change->kind = svn_node_dir; + } + + SVN_ERR(drive_changes_r(top_path, ¤t, + paths_final, svn_branch__get_id(root_branch, + scratch_pool), + eb, scratch_pool)); + } + + /* If the driver has not explicitly opened the root directory via the + start_edit (aka open_root) callback, do so now. */ + if (eb->ev1_root_dir_baton == NULL) + SVN_ERR(open_root_ev3(eb, SVN_INVALID_REVNUM)); + + /* Make the path driver visit the root dir of the edit. Otherwise, it + will attempt an open_root() instead, which we already did. */ + if (! svn_hash_gets(eb->changes, "")) + { + change_node_t *change; + + SVN_ERR(insert_change(&change, eb->changes, "", RESTRUCTURE_NONE)); + change->kind = svn_node_dir; + } + + /* Apply the appropriate Ev1 change to each Ev1-relative path. */ + paths = get_unsorted_paths(eb->changes, scratch_pool); + SVN_ERR(svn_delta_path_driver2(eb->deditor, eb->dedit_baton, + paths, TRUE /*sort*/, + apply_change, (void *)eb, + scratch_pool)); + + return SVN_NO_ERROR; +} + +/* An #svn_branch__txn_t method. */ +static apr_array_header_t * +compat_branch_txn_get_branches(const svn_branch__txn_t *txn, + apr_pool_t *result_pool) +{ + /* Just forwarding: nothing more is needed. */ + apr_array_header_t *branches + = svn_branch__txn_get_branches(txn->priv->txn, + result_pool); + + return branches; +} + +/* An #svn_branch__txn_t method. */ +static svn_error_t * +compat_branch_txn_delete_branch(svn_branch__txn_t *txn, + const char *bid, + apr_pool_t *scratch_pool) +{ + /* Just forwarding: nothing more is needed. */ + SVN_ERR(svn_branch__txn_delete_branch(txn->priv->txn, + bid, + scratch_pool)); + return SVN_NO_ERROR; +} + +/* An #svn_branch__txn_t method. */ +static svn_error_t * +compat_branch_txn_get_num_new_eids(const svn_branch__txn_t *txn, + int *num_new_eids_p, + apr_pool_t *scratch_pool) +{ + /* Just forwarding: nothing more is needed. */ + SVN_ERR(svn_branch__txn_get_num_new_eids(txn->priv->txn, + num_new_eids_p, + scratch_pool)); + return SVN_NO_ERROR; +} + +/* An #svn_branch__txn_t method. */ +static svn_error_t * +compat_branch_txn_new_eid(svn_branch__txn_t *txn, + svn_branch__eid_t *eid_p, + apr_pool_t *scratch_pool) +{ + /* Just forwarding: nothing more is needed. */ + SVN_ERR(svn_branch__txn_new_eid(txn->priv->txn, + eid_p, + scratch_pool)); + return SVN_NO_ERROR; +} + +/* An #svn_branch__txn_t method. */ +static svn_error_t * +compat_branch_txn_finalize_eids(svn_branch__txn_t *txn, + apr_pool_t *scratch_pool) +{ + /* Just forwarding: nothing more is needed. */ + SVN_ERR(svn_branch__txn_finalize_eids(txn->priv->txn, + scratch_pool)); + return SVN_NO_ERROR; +} + +/* An #svn_branch__txn_t method. */ +static svn_error_t * +compat_branch_txn_open_branch(svn_branch__txn_t *txn, + svn_branch__state_t **new_branch_p, + const char *new_branch_id, + int root_eid, + svn_branch__rev_bid_eid_t *tree_ref, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + /* Just forwarding: nothing more is needed. */ + SVN_ERR(svn_branch__txn_open_branch(txn->priv->txn, + new_branch_p, + new_branch_id, root_eid, tree_ref, + result_pool, + scratch_pool)); + return SVN_NO_ERROR; +} + +/* An #svn_branch__txn_t method. */ +static svn_error_t * +compat_branch_txn_serialize(svn_branch__txn_t *txn, + svn_stream_t *stream, + apr_pool_t *scratch_pool) +{ + /* Just forwarding: nothing more is needed. */ + SVN_ERR(svn_branch__txn_serialize(txn->priv->txn, + stream, + scratch_pool)); + return SVN_NO_ERROR; +} + +/* An #svn_branch__txn_t method. */ +static svn_error_t * +compat_branch_txn_sequence_point(svn_branch__txn_t *txn, + apr_pool_t *scratch_pool) +{ + /* Just forwarding: nothing more is needed. */ + SVN_ERR(svn_branch__txn_sequence_point(txn->priv->txn, + scratch_pool)); + return SVN_NO_ERROR; +} + +/* An #svn_branch__txn_t method. */ +static svn_error_t * +compat_branch_txn_complete(svn_branch__txn_t *txn, + apr_pool_t *scratch_pool) +{ + svn_branch__txn_priv_t *eb = txn->priv; + svn_error_t *err; + + /* Convert the transaction to a revision */ + SVN_ERR(svn_branch__txn_sequence_point(txn->priv->txn, scratch_pool)); + SVN_ERR(svn_branch__txn_finalize_eids(txn->priv->txn, scratch_pool)); + + err = drive_changes(eb, scratch_pool); + + if (!err) + { + err = svn_error_compose_create(err, eb->deditor->close_edit( + eb->dedit_baton, + scratch_pool)); + } + + if (err) + svn_error_clear(eb->deditor->abort_edit(eb->dedit_baton, scratch_pool)); + + SVN_ERR(svn_branch__txn_complete(txn->priv->txn, scratch_pool)); + + return err; +} + +/* An #svn_branch__txn_t method. */ +static svn_error_t * +compat_branch_txn_abort(svn_branch__txn_t *txn, + apr_pool_t *scratch_pool) +{ + svn_branch__txn_priv_t *eb = txn->priv; + + SVN_ERR(eb->deditor->abort_edit(eb->dedit_baton, scratch_pool)); + + SVN_ERR(svn_branch__txn_abort(txn->priv->txn, + scratch_pool)); + return SVN_NO_ERROR; +} + +/* Baton for wrap_fetch_func. */ +typedef struct wrap_fetch_baton_t +{ + /* Wrapped fetcher */ + svn_branch__compat_fetch_func_t fetch_func; + void *fetch_baton; +} wrap_fetch_baton_t; + +/* The purpose of this fetcher-wrapper is to make it appear that B0 + * was created (as an empty dir) in r0. + */ +static svn_error_t * +wrap_fetch_func(svn_node_kind_t *kind, + apr_hash_t **props, + svn_stringbuf_t **file_text, + apr_hash_t **children_names, + void *baton, + const char *repos_relpath, + svn_revnum_t revision, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + wrap_fetch_baton_t *b = baton; + + if (revision == 0 && strcmp(repos_relpath, "top0") == 0) + { + if (kind) + *kind = svn_node_dir; + if (props) + *props = apr_hash_make(result_pool); + if (file_text) + *file_text = NULL; + if (children_names) + *children_names = apr_hash_make(result_pool); + } + else + { + SVN_ERR(b->fetch_func(kind, props, file_text, children_names, + b->fetch_baton, + repos_relpath, revision, + result_pool, scratch_pool)); + } + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_branch__compat_txn_from_delta_for_commit( + svn_branch__txn_t **txn_p, + svn_branch__compat_shim_connector_t **shim_connector, + const svn_delta_editor_t *deditor, + void *dedit_baton, + svn_branch__txn_t *branching_txn, + const char *repos_root_url, + svn_branch__compat_fetch_func_t fetch_func, + void *fetch_baton, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + static const svn_branch__txn_vtable_t vtable = { + {0}, + compat_branch_txn_get_branches, + compat_branch_txn_delete_branch, + compat_branch_txn_get_num_new_eids, + compat_branch_txn_new_eid, + compat_branch_txn_open_branch, + compat_branch_txn_finalize_eids, + compat_branch_txn_serialize, + compat_branch_txn_sequence_point, + compat_branch_txn_complete, + compat_branch_txn_abort + }; + svn_branch__txn_t *txn; + svn_branch__txn_priv_t *eb = apr_pcalloc(result_pool, sizeof(*eb)); + wrap_fetch_baton_t *wb = apr_pcalloc(result_pool, sizeof(*wb)); + + eb->deditor = deditor; + eb->dedit_baton = dedit_baton; + + eb->repos_root_url = apr_pstrdup(result_pool, repos_root_url); + + eb->changes = apr_hash_make(result_pool); + + wb->fetch_func = fetch_func; + wb->fetch_baton = fetch_baton; + eb->fetch_func = wrap_fetch_func; + eb->fetch_baton = wb; + + eb->edit_pool = result_pool; + + branching_txn = svn_branch__nested_txn_create(branching_txn, result_pool); + + eb->txn = branching_txn; + + txn = svn_branch__txn_create(&vtable, NULL, NULL, result_pool); + txn->priv = eb; + txn->repos = branching_txn->repos; + txn->rev = branching_txn->rev; + txn->base_rev = branching_txn->base_rev; + *txn_p = txn; + + if (shim_connector) + { +#if 0 + *shim_connector = apr_palloc(result_pool, sizeof(**shim_connector)); +#ifdef SHIM_WITH_ABS_PATHS + (*shim_connector)->ev1_absolute_paths + = apr_palloc(result_pool, sizeof(svn_boolean_t)); + eb->make_abs_paths = (*shim_connector)->ev1_absolute_paths; +#endif + (*shim_connector)->target_revision_func = set_target_revision_ev3; + (*shim_connector)->start_edit_func = open_root_ev3; +#ifdef SHIM_WITH_UNLOCK + (*shim_connector)->unlock_func = do_unlock; +#endif + (*shim_connector)->baton = eb; +#endif + } + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_branch__compat_txn_from_delta_for_update( + svn_branch__compat_update_editor3_t **update_editor_p, + const svn_delta_editor_t *deditor, + void *dedit_baton, + svn_branch__txn_t *branching_txn, + const char *repos_root_url, + const char *base_repos_relpath, + svn_branch__compat_fetch_func_t fetch_func, + void *fetch_baton, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_branch__compat_update_editor3_t *update_editor + = apr_pcalloc(result_pool, sizeof(*update_editor)); + svn_branch__compat_shim_connector_t *shim_connector; + + /*(("svn_delta__ev3_from_delta_for_update(base='%s')...", + base_repos_relpath));*/ + + /*SVN_ERR(svn_delta__get_debug_editor(&deditor, &dedit_baton, + deditor, dedit_baton, + "[1>UP] ", result_pool));*/ + SVN_ERR(svn_branch__compat_txn_from_delta_for_commit( + &update_editor->edit_txn, + &shim_connector, + deditor, dedit_baton, + branching_txn, repos_root_url, + fetch_func, fetch_baton, + cancel_func, cancel_baton, + result_pool, scratch_pool)); + + update_editor->set_target_revision_func = shim_connector->target_revision_func; + update_editor->set_target_revision_baton = shim_connector->baton; + /* shim_connector->start_edit_func = open_root_ev3; */ +#ifdef SHIM_WITH_ABS_PATHS + update_editor->ev1_absolute_paths /*...*/; +#endif +#ifdef SHIM_WITH_UNLOCK + update_editor->unlock_func = do_unlock; +#endif + + *update_editor_p = update_editor; + return SVN_NO_ERROR; +} diff --git a/subversion/libsvn_delta/branch_migrate.c b/subversion/libsvn_delta/branch_migrate.c new file mode 100644 index 000000000000..7b741810638d --- /dev/null +++ b/subversion/libsvn_delta/branch_migrate.c @@ -0,0 +1,366 @@ +/* + * migrate.c: Migrate history from non-move-tracking revisions + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#include "svn_types.h" +#include "svn_error.h" +#include "svn_delta.h" +#include "svn_ra.h" + +#include "private/svn_branch.h" +#include "private/svn_branch_compat.h" + +#include "svn_private_config.h" + + +struct edit_baton +{ + svn_branch__txn_t *edit_txn; + svn_ra_session_t *from_session; + svn_revnum_t revision; +}; + +struct dir_baton +{ + struct edit_baton *edit_baton; +}; + +struct file_baton +{ + struct edit_baton *edit_baton; +}; + +static svn_error_t * +set_target_revision(void *edit_baton, + svn_revnum_t target_revision, + apr_pool_t *pool) +{ + /*struct edit_baton *eb = edit_baton;*/ + + /*SVN_ERR(eb->wrapped_editor->set_target_revision(eb->wrapped_edit_baton, + target_revision, + pool));*/ + return SVN_NO_ERROR; +} + +static svn_error_t * +open_root(void *edit_baton, + svn_revnum_t base_revision, + apr_pool_t *pool, + void **root_baton) +{ + struct edit_baton *eb = edit_baton; + struct dir_baton *dir_baton = apr_palloc(pool, sizeof(*dir_baton)); + + /*SVN_ERR(eb->wrapped_editor->open_root(eb->wrapped_edit_baton, + base_revision, + pool, + &dir_baton->wrapped_dir_baton));*/ + + dir_baton->edit_baton = eb; + + *root_baton = dir_baton; + + return SVN_NO_ERROR; +} + +static svn_error_t * +delete_entry(const char *path, + svn_revnum_t base_revision, + void *parent_baton, + apr_pool_t *pool) +{ + /*struct dir_baton *pb = parent_baton; + struct edit_baton *eb = pb->edit_baton;*/ + + /*SVN_ERR(eb->wrapped_editor->delete_entry(path, + base_revision, + pb->wrapped_dir_baton, + pool);*/ + return SVN_NO_ERROR; +} + +static svn_error_t * +add_directory(const char *path, + void *parent_baton, + const char *copyfrom_path, + svn_revnum_t copyfrom_revision, + apr_pool_t *pool, + void **child_baton) +{ + struct dir_baton *pb = parent_baton; + struct edit_baton *eb = pb->edit_baton; + struct dir_baton *db = apr_palloc(pool, sizeof(*db)); + + /*SVN_ERR(eb->wrapped_editor->add_directory(path, + pb->wrapped_dir_baton, + copyfrom_path, + copyfrom_revision, + pool, + &db->wrapped_dir_baton));*/ + + db->edit_baton = eb; + *child_baton = db; + + return SVN_NO_ERROR; +} + +static svn_error_t * +open_directory(const char *path, + void *parent_baton, + svn_revnum_t base_revision, + apr_pool_t *pool, + void **child_baton) +{ + struct dir_baton *pb = parent_baton; + struct edit_baton *eb = pb->edit_baton; + struct dir_baton *db = apr_palloc(pool, sizeof(*db)); + + /*SVN_ERR(eb->wrapped_editor->open_directory(path, + pb->wrapped_dir_baton, + base_revision, + pool, + &db->wrapped_dir_baton));*/ + + db->edit_baton = eb; + *child_baton = db; + + return SVN_NO_ERROR; +} + +static svn_error_t * +add_file(const char *path, + void *parent_baton, + const char *copyfrom_path, + svn_revnum_t copyfrom_revision, + apr_pool_t *pool, + void **file_baton) +{ + struct dir_baton *pb = parent_baton; + struct edit_baton *eb = pb->edit_baton; + struct file_baton *fb = apr_palloc(pool, sizeof(*fb)); + + /*SVN_ERR(eb->wrapped_editor->add_file(path, + pb->wrapped_dir_baton, + copyfrom_path, + copyfrom_revision, + pool, + &fb->wrapped_file_baton));*/ + + fb->edit_baton = eb; + *file_baton = fb; + + return SVN_NO_ERROR; +} + +static svn_error_t * +open_file(const char *path, + void *parent_baton, + svn_revnum_t base_revision, + apr_pool_t *pool, + void **file_baton) +{ + struct dir_baton *pb = parent_baton; + struct edit_baton *eb = pb->edit_baton; + struct file_baton *fb = apr_palloc(pool, sizeof(*fb)); + + /*SVN_ERR(eb->wrapped_editor->open_file(path, + pb->wrapped_dir_baton, + base_revision, + pool, + &fb->wrapped_file_baton));*/ + + fb->edit_baton = eb; + *file_baton = fb; + + return SVN_NO_ERROR; +} + +static svn_error_t * +apply_textdelta(void *file_baton, + const char *base_checksum, + apr_pool_t *pool, + svn_txdelta_window_handler_t *handler, + void **handler_baton) +{ + /*struct file_baton *fb = file_baton; + struct edit_baton *eb = fb->edit_baton;*/ + + /*SVN_ERR(eb->wrapped_editor->apply_textdelta(fb->wrapped_file_baton, + base_checksum, + pool, + handler, + handler_baton));*/ + + return SVN_NO_ERROR; +} + +static svn_error_t * +close_file(void *file_baton, + const char *text_checksum, + apr_pool_t *pool) +{ + /*struct file_baton *fb = file_baton; + struct edit_baton *eb = fb->edit_baton;*/ + + /*SVN_ERR(eb->wrapped_editor->close_file(fb->wrapped_file_baton, + text_checksum, pool));*/ + + return SVN_NO_ERROR; +} + +static svn_error_t * +absent_file(const char *path, + void *file_baton, + apr_pool_t *pool) +{ + /*struct file_baton *fb = file_baton; + struct edit_baton *eb = fb->edit_baton;*/ + + /*SVN_ERR(eb->wrapped_editor->absent_file(path, fb->wrapped_file_baton, + pool));*/ + + return SVN_NO_ERROR; +} + +static svn_error_t * +close_directory(void *dir_baton, + apr_pool_t *pool) +{ + /*struct dir_baton *db = dir_baton; + struct edit_baton *eb = db->edit_baton;*/ + + /*SVN_ERR(eb->wrapped_editor->close_directory(db->wrapped_dir_baton, + pool));*/ + + return SVN_NO_ERROR; +} + +static svn_error_t * +absent_directory(const char *path, + void *dir_baton, + apr_pool_t *pool) +{ + /*struct dir_baton *db = dir_baton; + struct edit_baton *eb = db->edit_baton;*/ + + /*SVN_ERR(eb->wrapped_editor->absent_directory(path, db->wrapped_dir_baton, + pool));*/ + + return SVN_NO_ERROR; +} + +static svn_error_t * +change_file_prop(void *file_baton, + const char *name, + const svn_string_t *value, + apr_pool_t *pool) +{ + /*struct file_baton *fb = file_baton; + struct edit_baton *eb = fb->edit_baton;*/ + + /*SVN_ERR(eb->wrapped_editor->change_file_prop(fb->wrapped_file_baton, + name, + value, + pool));*/ + + return SVN_NO_ERROR; +} + +static svn_error_t * +change_dir_prop(void *dir_baton, + const char *name, + const svn_string_t *value, + apr_pool_t *pool) +{ + /*struct dir_baton *db = dir_baton; + struct edit_baton *eb = db->edit_baton;*/ + + /*SVN_ERR(eb->wrapped_editor->change_dir_prop(db->wrapped_dir_baton, + name, + value, + pool));*/ + + return SVN_NO_ERROR; +} + +static svn_error_t * +close_edit(void *edit_baton, + apr_pool_t *pool) +{ + /*struct edit_baton *eb = edit_baton;*/ + + /*SVN_ERR(eb->wrapped_editor->close_edit(eb->wrapped_edit_baton, pool));*/ + + return SVN_NO_ERROR; +} + +static svn_error_t * +abort_edit(void *edit_baton, + apr_pool_t *pool) +{ + /*struct edit_baton *eb = edit_baton;*/ + + /*SVN_ERR(eb->wrapped_editor->abort_edit(eb->wrapped_edit_baton, pool));*/ + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_branch__compat_get_migration_editor( + const svn_delta_editor_t **old_editor, + void **old_edit_baton, + svn_branch__txn_t *edit_txn, + svn_ra_session_t *from_session, + svn_revnum_t revision, + apr_pool_t *result_pool) +{ + static const svn_delta_editor_t editor = { + set_target_revision, + open_root, + delete_entry, + add_directory, + open_directory, + change_dir_prop, + close_directory, + absent_directory, + add_file, + open_file, + apply_textdelta, + change_file_prop, + close_file, + absent_file, + close_edit, + abort_edit + }; + struct edit_baton *eb = apr_palloc(result_pool, sizeof(*eb)); + + eb->edit_txn = edit_txn; + eb->from_session = from_session; + eb->revision = revision; + + *old_editor = &editor; + *old_edit_baton = eb; + + return SVN_NO_ERROR; +} + diff --git a/subversion/libsvn_delta/branch_nested.c b/subversion/libsvn_delta/branch_nested.c new file mode 100644 index 000000000000..191d2d3b154b --- /dev/null +++ b/subversion/libsvn_delta/branch_nested.c @@ -0,0 +1,660 @@ +/* + * branch_nested.c : Nested Branches + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#include + +#include "svn_types.h" +#include "svn_error.h" +#include "svn_dirent_uri.h" +#include "svn_hash.h" +#include "svn_iter.h" +#include "svn_pools.h" + +#include "private/svn_branch_nested.h" +#include "private/svn_branch_impl.h" +#include "private/svn_branch_repos.h" + +#include "svn_private_config.h" + + +void +svn_branch__get_outer_branch_and_eid(svn_branch__state_t **outer_branch_p, + int *outer_eid_p, + const svn_branch__state_t *branch, + apr_pool_t *scratch_pool) +{ + const char *outer_bid; + + svn_branch__id_unnest(&outer_bid, outer_eid_p, branch->bid, scratch_pool); + *outer_branch_p = NULL; + if (outer_bid) + { + *outer_branch_p + = svn_branch__txn_get_branch_by_id(branch->txn, outer_bid, + scratch_pool); + } +} + +const char * +svn_branch__get_root_rrpath(const svn_branch__state_t *branch, + apr_pool_t *result_pool) +{ + svn_branch__state_t *outer_branch; + int outer_eid; + const char *root_rrpath; + + svn_branch__get_outer_branch_and_eid(&outer_branch, &outer_eid, branch, + result_pool); + if (outer_branch) + { + root_rrpath + = svn_branch__get_rrpath_by_eid(outer_branch, outer_eid, result_pool); + } + else + { + root_rrpath = ""; + } + + SVN_ERR_ASSERT_NO_RETURN(root_rrpath); + return root_rrpath; +} + +const char * +svn_branch__get_rrpath_by_eid(const svn_branch__state_t *branch, + int eid, + apr_pool_t *result_pool) +{ + const char *path = svn_branch__get_path_by_eid(branch, eid, result_pool); + const char *rrpath = NULL; + + if (path) + { + rrpath = svn_relpath_join(svn_branch__get_root_rrpath(branch, result_pool), + path, result_pool); + } + return rrpath; +} + +svn_error_t * +svn_branch__get_subbranch_at_eid(svn_branch__state_t *branch, + svn_branch__state_t **subbranch_p, + int eid, + apr_pool_t *scratch_pool) +{ + svn_element__content_t *element; + + SVN_ERR(svn_branch__state_get_element(branch, &element, eid, scratch_pool)); + if (element && element->payload->is_subbranch_root) + { + const char *branch_id = svn_branch__get_id(branch, scratch_pool); + const char *subbranch_id = svn_branch__id_nest(branch_id, eid, + scratch_pool); + + *subbranch_p = svn_branch__txn_get_branch_by_id(branch->txn, subbranch_id, + scratch_pool); + } + else + { + *subbranch_p = NULL; + } + return SVN_NO_ERROR; +} + +/* Set *SUBBRANCH_EIDS_P an array of EIDs of the subbranch-root elements in + * BRANCH. + */ +static svn_error_t * +svn_branch__get_immediate_subbranch_eids(svn_branch__state_t *branch, + apr_array_header_t **subbranch_eids_p, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + apr_array_header_t *subbranch_eids + = apr_array_make(result_pool, 0, sizeof(int)); + svn_element__tree_t *elements; + apr_hash_index_t *hi; + + SVN_ERR(svn_branch__state_get_elements(branch, &elements, scratch_pool)); + for (hi = apr_hash_first(scratch_pool, elements->e_map); + hi; hi = apr_hash_next(hi)) + { + int eid = svn_eid__hash_this_key(hi); + svn_element__content_t *element = apr_hash_this_val(hi); + + if (element->payload->is_subbranch_root) + { + APR_ARRAY_PUSH(subbranch_eids, int) = eid; + } + } + *subbranch_eids_p = subbranch_eids; + return SVN_NO_ERROR; +} + +svn_error_t * +svn_branch__get_immediate_subbranches(svn_branch__state_t *branch, + apr_array_header_t **subbranches_p, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + apr_array_header_t *subbranch_eids; + apr_array_header_t *subbranches + = apr_array_make(result_pool, 0, sizeof(void *)); + const char *branch_id = svn_branch__get_id(branch, scratch_pool); + int i; + + SVN_ERR(svn_branch__get_immediate_subbranch_eids(branch, &subbranch_eids, + scratch_pool, scratch_pool)); + for (i = 0; i < subbranch_eids->nelts; i++) + { + int eid = APR_ARRAY_IDX(subbranch_eids, i, int); + const char *subbranch_id + = svn_branch__id_nest(branch_id, eid, scratch_pool); + svn_branch__state_t *subbranch + = svn_branch__txn_get_branch_by_id(branch->txn, subbranch_id, + scratch_pool); + + SVN_ERR_ASSERT_NO_RETURN(subbranch); + APR_ARRAY_PUSH(subbranches, void *) = subbranch; + } + *subbranches_p = subbranches; + return SVN_NO_ERROR; +} + +svn_branch__subtree_t * +svn_branch__subtree_create(apr_hash_t *e_map, + int root_eid, + apr_pool_t *result_pool) +{ + svn_branch__subtree_t *subtree = apr_pcalloc(result_pool, sizeof(*subtree)); + + subtree->tree = svn_element__tree_create(e_map, root_eid, result_pool); + subtree->subbranches = apr_hash_make(result_pool); + return subtree; +} + +svn_error_t * +svn_branch__get_subtree(svn_branch__state_t *branch, + svn_branch__subtree_t **subtree_p, + int eid, + apr_pool_t *result_pool) +{ + svn_element__tree_t *element_tree; + svn_branch__subtree_t *new_subtree; + apr_array_header_t *subbranch_eids; + int i; + apr_pool_t *iterpool = result_pool; /* ### not a proper iterpool */ + + SVN_ERR(svn_branch__state_get_elements(branch, &element_tree, result_pool)); + element_tree = svn_element__tree_get_subtree_at_eid(element_tree, eid, + result_pool); + new_subtree + = svn_branch__subtree_create(element_tree->e_map, eid, result_pool); + + /* Add subbranches */ + SVN_ERR(svn_branch__get_immediate_subbranch_eids(branch, &subbranch_eids, + result_pool, result_pool)); + for (i = 0; i < subbranch_eids->nelts; i++) + { + int outer_eid = APR_ARRAY_IDX(subbranch_eids, i, int); + const char *subbranch_relpath_in_subtree; + + subbranch_relpath_in_subtree + = svn_element__tree_get_path_by_eid(new_subtree->tree, outer_eid, + iterpool); + + /* Is it pathwise at or below EID? If so, add it into the subtree. */ + if (subbranch_relpath_in_subtree) + { + svn_branch__state_t *subbranch; + svn_branch__subtree_t *this_subtree; + + SVN_ERR(svn_branch__get_subbranch_at_eid(branch, &subbranch, + outer_eid, iterpool)); + if (subbranch) + { + SVN_ERR(svn_branch__get_subtree(subbranch, &this_subtree, + svn_branch__root_eid(subbranch), + result_pool)); + svn_eid__hash_set(new_subtree->subbranches, outer_eid, + this_subtree); + } + } + } + *subtree_p = new_subtree; + return SVN_NO_ERROR; +} + +svn_branch__subtree_t * +svn_branch__subtree_get_subbranch_at_eid(svn_branch__subtree_t *subtree, + int eid, + apr_pool_t *result_pool) +{ + subtree = svn_eid__hash_get(subtree->subbranches, eid); + + return subtree; +} + +/* Instantiate ELEMENTS in TO_BRANCH. + */ +static svn_error_t * +branch_instantiate_elements(svn_branch__state_t *to_branch, + const svn_element__tree_t *elements, + apr_pool_t *scratch_pool) +{ + apr_hash_index_t *hi; + + for (hi = apr_hash_first(scratch_pool, elements->e_map); + hi; hi = apr_hash_next(hi)) + { + int this_eid = svn_eid__hash_this_key(hi); + svn_element__content_t *this_element = apr_hash_this_val(hi); + + SVN_ERR(svn_branch__state_set_element(to_branch, this_eid, + this_element, scratch_pool)); + } + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_branch__instantiate_elements_r(svn_branch__state_t *to_branch, + svn_branch__subtree_t elements, + apr_pool_t *scratch_pool) +{ + SVN_ERR(branch_instantiate_elements(to_branch, elements.tree, + scratch_pool)); + + /* branch any subbranches */ + { + apr_hash_index_t *hi; + + for (hi = apr_hash_first(scratch_pool, elements.subbranches); + hi; hi = apr_hash_next(hi)) + { + int this_outer_eid = svn_eid__hash_this_key(hi); + svn_branch__subtree_t *this_subtree = apr_hash_this_val(hi); + const char *new_branch_id; + svn_branch__state_t *new_branch; + /*### svn_branch__history_t *history;*/ + + /* branch this subbranch into NEW_BRANCH (recursing) */ + new_branch_id = svn_branch__id_nest(to_branch->bid, this_outer_eid, + scratch_pool); + SVN_ERR(svn_branch__txn_open_branch(to_branch->txn, &new_branch, + new_branch_id, + this_subtree->tree->root_eid, + NULL /*tree_ref*/, + scratch_pool, scratch_pool)); + /*### SVN_ERR(svn_branch__state_set_history(new_branch, history, + scratch_pool));*/ + + SVN_ERR(svn_branch__instantiate_elements_r(new_branch, *this_subtree, + scratch_pool)); + } + } + + return SVN_NO_ERROR; +} + +/* + * ======================================================================== + */ + +svn_error_t * +svn_branch__find_nested_branch_element_by_relpath( + svn_branch__state_t **branch_p, + int *eid_p, + svn_branch__state_t *root_branch, + const char *relpath, + apr_pool_t *scratch_pool) +{ + /* The path we're looking for is (path-wise) in this branch. See if it + is also in a sub-branch. */ + /* Loop invariants: RELPATH is the path we're looking for, relative to + ROOT_BRANCH which is the current level of nesting that we've descended + into. */ + while (TRUE) + { + apr_array_header_t *subbranch_eids; + int i; + svn_boolean_t found = FALSE; + + SVN_ERR(svn_branch__get_immediate_subbranch_eids( + root_branch, &subbranch_eids, scratch_pool, scratch_pool)); + for (i = 0; i < subbranch_eids->nelts; i++) + { + int outer_eid = APR_ARRAY_IDX(subbranch_eids, i, int); + const char *relpath_to_subbranch; + const char *relpath_in_subbranch; + + /* Check whether the RELPATH we're looking for is within this + subbranch at OUTER_EID. If it is, recurse in the subbranch. */ + relpath_to_subbranch + = svn_branch__get_path_by_eid(root_branch, outer_eid, scratch_pool); + relpath_in_subbranch + = svn_relpath_skip_ancestor(relpath_to_subbranch, relpath); + if (relpath_in_subbranch) + { + svn_branch__state_t *subbranch; + + SVN_ERR(svn_branch__get_subbranch_at_eid( + root_branch, &subbranch, outer_eid, scratch_pool)); + /* If the branch hierarchy is not 'flat' then we might find + there is no actual branch where the subbranch-root element + says there should be one. In that case, ignore it. */ + if (subbranch) + { + root_branch = subbranch; + relpath = relpath_in_subbranch; + found = TRUE; + break; + } + } + } + if (! found) + { + break; + } + } + + *branch_p = root_branch; + if (eid_p) + *eid_p = svn_branch__get_eid_by_path(root_branch, relpath, scratch_pool); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_branch__repos_find_el_rev_by_path_rev(svn_branch__el_rev_id_t **el_rev_p, + const svn_branch__repos_t *repos, + svn_revnum_t revnum, + const char *branch_id, + const char *relpath, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_branch__el_rev_id_t *el_rev = apr_palloc(result_pool, sizeof(*el_rev)); + svn_branch__state_t *branch; + + SVN_ERR(svn_branch__repos_get_branch_by_id(&branch, + repos, revnum, branch_id, + scratch_pool)); + el_rev->rev = revnum; + SVN_ERR(svn_branch__find_nested_branch_element_by_relpath(&el_rev->branch, + &el_rev->eid, + branch, relpath, + scratch_pool)); + + /* Any relpath must at least be within the originally given branch */ + SVN_ERR_ASSERT_NO_RETURN(el_rev->branch); + *el_rev_p = el_rev; + return SVN_NO_ERROR; +} + +/* Set *BRANCH_P to the branch found in the repository of TXN, at the + * location (in a revision or in this txn) SRC_EL_REV. + * + * Return an error if REVNUM or BRANCH_ID is not found. + */ +static svn_error_t * +branch_in_rev_or_txn(svn_branch__state_t **branch_p, + const svn_branch__rev_bid_eid_t *src_el_rev, + svn_branch__txn_t *txn, + apr_pool_t *result_pool) +{ + if (SVN_IS_VALID_REVNUM(src_el_rev->rev)) + { + SVN_ERR(svn_branch__repos_get_branch_by_id(branch_p, + txn->repos, + src_el_rev->rev, + src_el_rev->bid, + result_pool)); + } + else + { + *branch_p + = svn_branch__txn_get_branch_by_id( + txn, src_el_rev->bid, result_pool); + if (! *branch_p) + return svn_error_createf(SVN_BRANCH__ERR, NULL, + _("Branch %s not found"), + src_el_rev->bid); + } + + return SVN_NO_ERROR; +} + +struct svn_branch__txn_priv_t +{ + /* The underlying branch-txn that supports only non-nested branching. */ + svn_branch__txn_t *wrapped_txn; + +}; + +/* Implements nested branching. + * An #svn_branch__txn_t method. */ +static apr_array_header_t * +nested_branch_txn_get_branches(const svn_branch__txn_t *txn, + apr_pool_t *result_pool) +{ + /* Just forwarding: nothing more is needed. */ + apr_array_header_t *branches + = svn_branch__txn_get_branches(txn->priv->wrapped_txn, + result_pool); + + return branches; +} + +/* An #svn_branch__txn_t method. */ +static svn_error_t * +nested_branch_txn_delete_branch(svn_branch__txn_t *txn, + const char *bid, + apr_pool_t *scratch_pool) +{ + /* Just forwarding: nothing more is needed. */ + SVN_ERR(svn_branch__txn_delete_branch(txn->priv->wrapped_txn, + bid, + scratch_pool)); + return SVN_NO_ERROR; +} + +/* Implements nested branching. + * An #svn_branch__txn_t method. */ +static svn_error_t * +nested_branch_txn_get_num_new_eids(const svn_branch__txn_t *txn, + int *num_new_eids_p, + apr_pool_t *scratch_pool) +{ + /* Just forwarding: nothing more is needed. */ + SVN_ERR(svn_branch__txn_get_num_new_eids(txn->priv->wrapped_txn, + num_new_eids_p, + scratch_pool)); + return SVN_NO_ERROR; +} + +/* Implements nested branching. + * An #svn_branch__txn_t method. */ +static svn_error_t * +nested_branch_txn_new_eid(svn_branch__txn_t *txn, + svn_branch__eid_t *eid_p, + apr_pool_t *scratch_pool) +{ + /* Just forwarding: nothing more is needed. */ + SVN_ERR(svn_branch__txn_new_eid(txn->priv->wrapped_txn, + eid_p, + scratch_pool)); + return SVN_NO_ERROR; +} + +/* Implements nested branching. + * An #svn_branch__txn_t method. */ +static svn_error_t * +nested_branch_txn_open_branch(svn_branch__txn_t *txn, + svn_branch__state_t **new_branch_p, + const char *new_branch_id, + int root_eid, + svn_branch__rev_bid_eid_t *tree_ref, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_branch__state_t *new_branch; + + SVN_ERR(svn_branch__txn_open_branch(txn->priv->wrapped_txn, + &new_branch, + new_branch_id, root_eid, tree_ref, + result_pool, + scratch_pool)); + + /* Recursively branch any nested branches */ + if (tree_ref) + { + svn_branch__state_t *from_branch; + svn_branch__subtree_t *from_subtree; + + /* (The way we're doing it here also redundantly re-instantiates all the + elements in NEW_BRANCH.) */ + SVN_ERR(branch_in_rev_or_txn(&from_branch, tree_ref, + txn->priv->wrapped_txn, scratch_pool)); + SVN_ERR(svn_branch__get_subtree(from_branch, &from_subtree, + tree_ref->eid, scratch_pool)); + SVN_ERR(svn_branch__instantiate_elements_r(new_branch, *from_subtree, + scratch_pool)); + } + + if (new_branch_p) + *new_branch_p = new_branch; + return SVN_NO_ERROR; +} + +/* Implements nested branching. + * An #svn_branch__txn_t method. */ +static svn_error_t * +nested_branch_txn_finalize_eids(svn_branch__txn_t *txn, + apr_pool_t *scratch_pool) +{ + /* Just forwarding: nothing more is needed. */ + SVN_ERR(svn_branch__txn_finalize_eids(txn->priv->wrapped_txn, + scratch_pool)); + return SVN_NO_ERROR; +} + +/* Implements nested branching. + * An #svn_branch__txn_t method. */ +static svn_error_t * +nested_branch_txn_serialize(svn_branch__txn_t *txn, + svn_stream_t *stream, + apr_pool_t *scratch_pool) +{ + /* Just forwarding: nothing more is needed. */ + SVN_ERR(svn_branch__txn_serialize(txn->priv->wrapped_txn, + stream, + scratch_pool)); + return SVN_NO_ERROR; +} + +/* Implements nested branching. + * An #svn_branch__txn_t method. */ +static svn_error_t * +nested_branch_txn_sequence_point(svn_branch__txn_t *txn, + apr_pool_t *scratch_pool) +{ + svn_branch__txn_t *wrapped_txn = txn->priv->wrapped_txn; + apr_array_header_t *branches; + int i; + + /* first, purge elements in each branch */ + SVN_ERR(svn_branch__txn_sequence_point(wrapped_txn, scratch_pool)); + + /* second, purge branches that are no longer nested */ + branches = svn_branch__txn_get_branches(wrapped_txn, scratch_pool); + for (i = 0; i < branches->nelts; i++) + { + svn_branch__state_t *b = APR_ARRAY_IDX(branches, i, void *); + svn_branch__state_t *outer_branch; + int outer_eid; + + svn_branch__get_outer_branch_and_eid(&outer_branch, &outer_eid, + b, scratch_pool); + if (outer_branch) + { + svn_element__content_t *element; + + SVN_ERR(svn_branch__state_get_element(outer_branch, &element, + outer_eid, scratch_pool)); + if (! element) + SVN_ERR(svn_branch__txn_delete_branch(wrapped_txn, b->bid, + scratch_pool)); + } + } + return SVN_NO_ERROR; +} + +/* An #svn_branch__txn_t method. */ +static svn_error_t * +nested_branch_txn_complete(svn_branch__txn_t *txn, + apr_pool_t *scratch_pool) +{ + /* Just forwarding: nothing more is needed. */ + SVN_ERR(svn_branch__txn_complete(txn->priv->wrapped_txn, + scratch_pool)); + return SVN_NO_ERROR; +} + +/* An #svn_branch__txn_t method. */ +static svn_error_t * +nested_branch_txn_abort(svn_branch__txn_t *txn, + apr_pool_t *scratch_pool) +{ + /* Just forwarding: nothing more is needed. */ + SVN_ERR(svn_branch__txn_abort(txn->priv->wrapped_txn, + scratch_pool)); + return SVN_NO_ERROR; +} + +svn_branch__txn_t * +svn_branch__nested_txn_create(svn_branch__txn_t *wrapped_txn, + apr_pool_t *result_pool) +{ + static const svn_branch__txn_vtable_t vtable = { + {0}, + nested_branch_txn_get_branches, + nested_branch_txn_delete_branch, + nested_branch_txn_get_num_new_eids, + nested_branch_txn_new_eid, + nested_branch_txn_open_branch, + nested_branch_txn_finalize_eids, + nested_branch_txn_serialize, + nested_branch_txn_sequence_point, + nested_branch_txn_complete, + nested_branch_txn_abort, + }; + svn_branch__txn_t *txn + = svn_branch__txn_create(&vtable, NULL, NULL, result_pool); + + txn->priv = apr_pcalloc(result_pool, sizeof(*txn->priv)); + txn->priv->wrapped_txn = wrapped_txn; + txn->repos = wrapped_txn->repos; + txn->rev = wrapped_txn->rev; + txn->base_rev = wrapped_txn->base_rev; + return txn; +} + diff --git a/subversion/libsvn_delta/branch_repos.c b/subversion/libsvn_delta/branch_repos.c new file mode 100644 index 000000000000..1ba86b193c4d --- /dev/null +++ b/subversion/libsvn_delta/branch_repos.c @@ -0,0 +1,132 @@ +/* + * branch_repos.c : Element-Based Branching and Move Tracking. + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#include + +#include "svn_types.h" +#include "svn_error.h" +#include "svn_dirent_uri.h" +#include "svn_iter.h" + +#include "private/svn_branch_repos.h" +#include "svn_private_config.h" + + +/* Per-repository branching info. + */ +struct svn_branch__repos_t +{ + /* Array of (svn_branch__txn_t *), indexed by revision number. */ + apr_array_header_t *rev_roots; + + /* The pool in which this object lives. */ + apr_pool_t *pool; +}; + + +svn_branch__repos_t * +svn_branch__repos_create(apr_pool_t *result_pool) +{ + svn_branch__repos_t *repos = apr_pcalloc(result_pool, sizeof(*repos)); + + repos->rev_roots = apr_array_make(result_pool, 0, sizeof(void *)); + repos->pool = result_pool; + return repos; +} + +svn_error_t * +svn_branch__repos_add_revision(svn_branch__repos_t *repos, + svn_branch__txn_t *rev_root) +{ + APR_ARRAY_PUSH(repos->rev_roots, void *) = rev_root; + + return SVN_NO_ERROR; +} + +struct svn_branch__txn_t * +svn_branch__repos_get_revision(const svn_branch__repos_t *repos, + svn_revnum_t revnum) +{ + assert(revnum < repos->rev_roots->nelts); + return APR_ARRAY_IDX(repos->rev_roots, revnum, void *); +} + +svn_branch__txn_t * +svn_branch__repos_get_base_revision_root(svn_branch__txn_t *rev_root) +{ + return svn_branch__repos_get_revision(rev_root->repos, rev_root->base_rev); +} + +svn_error_t * +svn_branch__repos_get_branch_by_id(svn_branch__state_t **branch_p, + const svn_branch__repos_t *repos, + svn_revnum_t revnum, + const char *branch_id, + apr_pool_t *scratch_pool) +{ + svn_branch__txn_t *rev_root; + + if (revnum < 0 || revnum >= repos->rev_roots->nelts) + return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL, + _("No such revision %ld"), revnum); + + rev_root = svn_branch__repos_get_revision(repos, revnum); + *branch_p = svn_branch__txn_get_branch_by_id(rev_root, branch_id, + scratch_pool); + if (! *branch_p) + return svn_error_createf(SVN_BRANCH__ERR, NULL, + _("Branch %s not found in r%ld"), + branch_id, revnum); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_branch__repos_find_el_rev_by_id(svn_branch__el_rev_id_t **el_rev_p, + const svn_branch__repos_t *repos, + svn_revnum_t revnum, + const char *branch_id, + int eid, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_branch__el_rev_id_t *el_rev = apr_palloc(result_pool, sizeof(*el_rev)); + svn_element__content_t *element; + + el_rev->rev = revnum; + SVN_ERR(svn_branch__repos_get_branch_by_id(&el_rev->branch, + repos, revnum, branch_id, + scratch_pool)); + SVN_ERR(svn_branch__state_get_element(el_rev->branch, &element, + eid, scratch_pool)); + if (element) + { + el_rev->eid = eid; + } + else + { + el_rev->eid = -1; + } + *el_rev_p = el_rev; + return SVN_NO_ERROR; +} + diff --git a/subversion/libsvn_delta/cancel.c b/subversion/libsvn_delta/cancel.c index 89995a85ebb6..ef245b821a35 100644 --- a/subversion/libsvn_delta/cancel.c +++ b/subversion/libsvn_delta/cancel.c @@ -221,6 +221,26 @@ apply_textdelta(void *file_baton, handler_baton); } +static svn_error_t * +apply_textdelta_stream(const svn_delta_editor_t *editor, + void *file_baton, + const char *base_checksum, + svn_txdelta_stream_open_func_t open_func, + void *open_baton, + apr_pool_t *scratch_pool) +{ + struct file_baton *fb = file_baton; + struct edit_baton *eb = fb->edit_baton; + + SVN_ERR(eb->cancel_func(eb->cancel_baton)); + + return eb->wrapped_editor->apply_textdelta_stream(eb->wrapped_editor, + fb->wrapped_file_baton, + base_checksum, + open_func, open_baton, + scratch_pool); +} + static svn_error_t * close_file(void *file_baton, const char *text_checksum, @@ -354,6 +374,7 @@ svn_delta_get_cancellation_editor(svn_cancel_func_t cancel_func, tree_editor->add_file = add_file; tree_editor->open_file = open_file; tree_editor->apply_textdelta = apply_textdelta; + tree_editor->apply_textdelta_stream = apply_textdelta_stream; tree_editor->change_file_prop = change_file_prop; tree_editor->close_file = close_file; tree_editor->absent_file = absent_file; diff --git a/subversion/libsvn_delta/compat.c b/subversion/libsvn_delta/compat.c index dfa97437b92d..c89e9367cd37 100644 --- a/subversion/libsvn_delta/compat.c +++ b/subversion/libsvn_delta/compat.c @@ -816,8 +816,9 @@ static svn_error_t * open_delta_target(svn_stream_t **stream, void *baton, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - const char **delta_target = baton; - return svn_stream_open_unique(stream, delta_target, NULL, + struct change_node *change = baton; + return svn_stream_open_unique(stream, &change->contents_abspath, + NULL, svn_io_file_del_on_pool_cleanup, result_pool, scratch_pool); } @@ -850,8 +851,7 @@ ev2_apply_textdelta(void *file_baton, FALSE, handler_pool); change->contents_changed = TRUE; - target = svn_stream_lazyopen_create(open_delta_target, - &change->contents_abspath, + target = svn_stream_lazyopen_create(open_delta_target, change, FALSE, fb->eb->edit_pool); svn_txdelta_apply(hb->source, target, @@ -1223,15 +1223,23 @@ alter_file_cb(void *baton, apr_pool_t *scratch_pool) { struct editor_baton *eb = baton; - const char *tmp_filename; svn_stream_t *tmp_stream; - svn_checksum_t *md5_checksum; struct change_node *change = insert_change(relpath, eb->changes); + /* Note: this node may already have information in CHANGE as a result + of an earlier copy/move operation. */ + /* ### should we verify the kind is truly a file? */ + change->kind = svn_node_file; + change->changing = revision; + if (props != NULL) + change->props = svn_prop_hash_dup(props, eb->edit_pool); if (contents) { + const char *tmp_filename; + svn_checksum_t *md5_checksum; + /* We may need to re-checksum these contents */ if (checksum && checksum->kind == svn_checksum_md5) md5_checksum = (svn_checksum_t *)checksum; @@ -1246,17 +1254,7 @@ alter_file_cb(void *baton, eb->edit_pool, scratch_pool)); SVN_ERR(svn_stream_copy3(contents, tmp_stream, NULL, NULL, scratch_pool)); - } - /* Note: this node may already have information in CHANGE as a result - of an earlier copy/move operation. */ - - change->kind = svn_node_file; - change->changing = revision; - if (props != NULL) - change->props = svn_prop_hash_dup(props, eb->edit_pool); - if (contents != NULL) - { change->contents_changed = TRUE; change->contents_abspath = tmp_filename; change->checksum = svn_checksum_dup(md5_checksum, eb->edit_pool); diff --git a/subversion/libsvn_delta/debug_editor.c b/subversion/libsvn_delta/debug_editor.c index 8ca7b2040137..5f26936d621b 100644 --- a/subversion/libsvn_delta/debug_editor.c +++ b/subversion/libsvn_delta/debug_editor.c @@ -23,7 +23,7 @@ #include "svn_io.h" -#include "debug_editor.h" +#include "private/svn_delta_private.h" struct edit_baton { diff --git a/subversion/libsvn_delta/default_editor.c b/subversion/libsvn_delta/default_editor.c index 2f1c9734ba6a..63cbc1599231 100644 --- a/subversion/libsvn_delta/default_editor.c +++ b/subversion/libsvn_delta/default_editor.c @@ -133,6 +133,33 @@ close_file(void *file_baton, } +static svn_error_t * +apply_textdelta_stream(const svn_delta_editor_t *editor, + void *file_baton, + const char *base_checksum, + svn_txdelta_stream_open_func_t open_func, + void *open_baton, + apr_pool_t *scratch_pool) +{ + svn_txdelta_window_handler_t handler; + void *handler_baton; + + SVN_ERR(editor->apply_textdelta(file_baton, base_checksum, + scratch_pool, &handler, + &handler_baton)); + if (handler != svn_delta_noop_window_handler) + { + svn_txdelta_stream_t *txdelta_stream; + + SVN_ERR(open_func(&txdelta_stream, open_baton, scratch_pool, + scratch_pool)); + SVN_ERR(svn_txdelta_send_txstream(txdelta_stream, handler, + handler_baton, scratch_pool)); + } + + return SVN_NO_ERROR; +} + static const svn_delta_editor_t default_editor = { @@ -151,7 +178,8 @@ static const svn_delta_editor_t default_editor = close_file, absent_xxx_func, single_baton_func, - single_baton_func + single_baton_func, + apply_textdelta_stream }; svn_delta_editor_t * diff --git a/subversion/libsvn_delta/element.c b/subversion/libsvn_delta/element.c new file mode 100644 index 000000000000..be7b2171b9b4 --- /dev/null +++ b/subversion/libsvn_delta/element.c @@ -0,0 +1,471 @@ +/* + * element.c : editing trees of versioned resources + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#include +#include + +#include "svn_types.h" +#include "svn_error.h" +#include "svn_string.h" +#include "svn_props.h" +#include "svn_dirent_uri.h" +#include "svn_iter.h" +#include "private/svn_sorts_private.h" + +#include "private/svn_element.h" +#include "svn_private_config.h" + + +void * +svn_eid__hash_get(apr_hash_t *ht, + int key) +{ + return apr_hash_get(ht, &key, sizeof(key)); +} + +void +svn_eid__hash_set(apr_hash_t *ht, + int key, + const void *val) +{ + int *id_p = apr_pmemdup(apr_hash_pool_get(ht), &key, sizeof(key)); + + apr_hash_set(ht, id_p, sizeof(key), val); +} + +int +svn_eid__hash_this_key(apr_hash_index_t *hi) +{ + return *(const int *)apr_hash_this_key(hi); +} + +svn_eid__hash_iter_t * +svn_eid__hash_sorted_first(apr_pool_t *pool, + apr_hash_t *ht, + int (*comparison_func)(const svn_sort__item_t *, + const svn_sort__item_t *)) +{ + svn_eid__hash_iter_t *hi = apr_palloc(pool, sizeof(*hi)); + + if (apr_hash_count(ht) == 0) + return NULL; + + hi->array = svn_sort__hash(ht, comparison_func, pool); + hi->i = 0; + hi->eid = *(const int *)(APR_ARRAY_IDX(hi->array, hi->i, + svn_sort__item_t).key); + hi->val = APR_ARRAY_IDX(hi->array, hi->i, svn_sort__item_t).value; + return hi; +} + +svn_eid__hash_iter_t * +svn_eid__hash_sorted_next(svn_eid__hash_iter_t *hi) +{ + hi->i++; + if (hi->i >= hi->array->nelts) + { + return NULL; + } + hi->eid = *(const int *)(APR_ARRAY_IDX(hi->array, hi->i, + svn_sort__item_t).key); + hi->val = APR_ARRAY_IDX(hi->array, hi->i, svn_sort__item_t).value; + return hi; +} + +int +svn_eid__hash_sort_compare_items_by_eid(const svn_sort__item_t *a, + const svn_sort__item_t *b) +{ + int eid_a = *(const int *)a->key; + int eid_b = *(const int *)b->key; + + return eid_a - eid_b; +} + + +/* + * =================================================================== + * Element payload + * =================================================================== + */ + +svn_boolean_t +svn_element__payload_invariants(const svn_element__payload_t *payload) +{ + if (payload->is_subbranch_root) + return TRUE; + + /* If kind is unknown, it's a reference; otherwise it has content + specified and may also have a reference. */ + if (payload->kind == svn_node_unknown) + if (SVN_IS_VALID_REVNUM(payload->branch_ref.rev) + && payload->branch_ref.branch_id + && payload->branch_ref.eid != -1) + return TRUE; + if ((payload->kind == svn_node_dir + || payload->kind == svn_node_file + || payload->kind == svn_node_symlink) + && (payload->props + && ((payload->kind == svn_node_file) == !!payload->text) + && ((payload->kind == svn_node_symlink) == !!payload->target))) + return TRUE; + return FALSE; +} + +svn_element__payload_t * +svn_element__payload_dup(const svn_element__payload_t *old, + apr_pool_t *result_pool) +{ + svn_element__payload_t *new_payload; + + assert(! old || svn_element__payload_invariants(old)); + + if (old == NULL) + return NULL; + + new_payload = apr_pmemdup(result_pool, old, sizeof(*new_payload)); + if (old->branch_ref.branch_id) + new_payload->branch_ref.branch_id + = apr_pstrdup(result_pool, old->branch_ref.branch_id); + if (old->props) + new_payload->props = svn_prop_hash_dup(old->props, result_pool); + if (old->kind == svn_node_file && old->text) + new_payload->text = svn_stringbuf_dup(old->text, result_pool); + if (old->kind == svn_node_symlink && old->target) + new_payload->target = apr_pstrdup(result_pool, old->target); + return new_payload; +} + +svn_boolean_t +svn_element__payload_equal(const svn_element__payload_t *left, + const svn_element__payload_t *right, + apr_pool_t *scratch_pool) +{ + apr_array_header_t *prop_diffs; + + assert(svn_element__payload_invariants(left)); + assert(svn_element__payload_invariants(right)); + + /* any two subbranch-root elements compare equal */ + if (left->is_subbranch_root && right->is_subbranch_root) + { + return TRUE; + } + else if (left->is_subbranch_root || right->is_subbranch_root) + { + return FALSE; + } + + /* content defined only by reference is not supported */ + SVN_ERR_ASSERT_NO_RETURN(left->kind != svn_node_unknown + && right->kind != svn_node_unknown); + + if (left->kind != right->kind) + { + return FALSE; + } + + svn_error_clear(svn_prop_diffs(&prop_diffs, + left->props, right->props, + scratch_pool)); + + if (prop_diffs->nelts != 0) + { + return FALSE; + } + switch (left->kind) + { + case svn_node_dir: + break; + case svn_node_file: + if (! svn_stringbuf_compare(left->text, right->text)) + { + return FALSE; + } + break; + case svn_node_symlink: + if (strcmp(left->target, right->target) != 0) + { + return FALSE; + } + break; + default: + break; + } + + return TRUE; +} + +svn_element__payload_t * +svn_element__payload_create_subbranch(apr_pool_t *result_pool) +{ + svn_element__payload_t *new_payload + = apr_pcalloc(result_pool, sizeof(*new_payload)); + + new_payload->pool = result_pool; + new_payload->is_subbranch_root = TRUE; + assert(svn_element__payload_invariants(new_payload)); + return new_payload; +} + +svn_element__payload_t * +svn_element__payload_create_ref(svn_revnum_t rev, + const char *branch_id, + int eid, + apr_pool_t *result_pool) +{ + svn_element__payload_t *new_payload + = apr_pcalloc(result_pool, sizeof(*new_payload)); + + new_payload->pool = result_pool; + new_payload->kind = svn_node_unknown; + new_payload->branch_ref.rev = rev; + new_payload->branch_ref.branch_id = apr_pstrdup(result_pool, branch_id); + new_payload->branch_ref.eid = eid; + assert(svn_element__payload_invariants(new_payload)); + return new_payload; +} + +svn_element__payload_t * +svn_element__payload_create_dir(apr_hash_t *props, + apr_pool_t *result_pool) +{ + svn_element__payload_t *new_payload + = apr_pcalloc(result_pool, sizeof(*new_payload)); + + new_payload->pool = result_pool; + new_payload->kind = svn_node_dir; + new_payload->props = props ? svn_prop_hash_dup(props, result_pool) : NULL; + assert(svn_element__payload_invariants(new_payload)); + return new_payload; +} + +svn_element__payload_t * +svn_element__payload_create_file(apr_hash_t *props, + svn_stringbuf_t *text, + apr_pool_t *result_pool) +{ + svn_element__payload_t *new_payload + = apr_pcalloc(result_pool, sizeof(*new_payload)); + + SVN_ERR_ASSERT_NO_RETURN(text); + + new_payload->pool = result_pool; + new_payload->kind = svn_node_file; + new_payload->props = props ? svn_prop_hash_dup(props, result_pool) : NULL; + new_payload->text = svn_stringbuf_dup(text, result_pool); + assert(svn_element__payload_invariants(new_payload)); + return new_payload; +} + +svn_element__payload_t * +svn_element__payload_create_symlink(apr_hash_t *props, + const char *target, + apr_pool_t *result_pool) +{ + svn_element__payload_t *new_payload + = apr_pcalloc(result_pool, sizeof(*new_payload)); + + SVN_ERR_ASSERT_NO_RETURN(target); + + new_payload->pool = result_pool; + new_payload->kind = svn_node_symlink; + new_payload->props = props ? svn_prop_hash_dup(props, result_pool) : NULL; + new_payload->target = apr_pstrdup(result_pool, target); + assert(svn_element__payload_invariants(new_payload)); + return new_payload; +} + +svn_element__content_t * +svn_element__content_create(int parent_eid, + const char *name, + const svn_element__payload_t *payload, + apr_pool_t *result_pool) +{ + svn_element__content_t *content + = apr_palloc(result_pool, sizeof(*content)); + + content->parent_eid = parent_eid; + content->name = apr_pstrdup(result_pool, name); + content->payload = svn_element__payload_dup(payload, result_pool); + return content; +} + +svn_element__content_t * +svn_element__content_dup(const svn_element__content_t *old, + apr_pool_t *result_pool) +{ + svn_element__content_t *content + = apr_pmemdup(result_pool, old, sizeof(*content)); + + content->name = apr_pstrdup(result_pool, old->name); + content->payload = svn_element__payload_dup(old->payload, result_pool); + return content; +} + +svn_boolean_t +svn_element__content_equal(const svn_element__content_t *content_left, + const svn_element__content_t *content_right, + apr_pool_t *scratch_pool) +{ + if (!content_left && !content_right) + { + return TRUE; + } + else if (!content_left || !content_right) + { + return FALSE; + } + + if (content_left->parent_eid != content_right->parent_eid) + { + return FALSE; + } + if (strcmp(content_left->name, content_right->name) != 0) + { + return FALSE; + } + if (! svn_element__payload_equal(content_left->payload, content_right->payload, + scratch_pool)) + { + return FALSE; + } + + return TRUE; +} + +svn_element__tree_t * +svn_element__tree_create(apr_hash_t *e_map, + int root_eid, + apr_pool_t *result_pool) +{ + svn_element__tree_t *element_tree + = apr_pcalloc(result_pool, sizeof(*element_tree)); + + element_tree->e_map = e_map ? apr_hash_copy(result_pool, e_map) + : apr_hash_make(result_pool); + element_tree->root_eid = root_eid; + return element_tree; +} + +svn_element__content_t * +svn_element__tree_get(const svn_element__tree_t *tree, + int eid) +{ + return svn_eid__hash_get(tree->e_map, eid); +} + +svn_error_t * +svn_element__tree_set(svn_element__tree_t *tree, + int eid, + const svn_element__content_t *element) +{ + svn_eid__hash_set(tree->e_map, eid, element); + + return SVN_NO_ERROR; +} + +void +svn_element__tree_purge_orphans(apr_hash_t *e_map, + int root_eid, + apr_pool_t *scratch_pool) +{ + apr_hash_index_t *hi; + svn_boolean_t changed; + + SVN_ERR_ASSERT_NO_RETURN(svn_eid__hash_get(e_map, root_eid)); + + do + { + changed = FALSE; + + for (hi = apr_hash_first(scratch_pool, e_map); + hi; hi = apr_hash_next(hi)) + { + int this_eid = svn_eid__hash_this_key(hi); + svn_element__content_t *this_element = apr_hash_this_val(hi); + + if (this_eid != root_eid) + { + svn_element__content_t *parent_element + = svn_eid__hash_get(e_map, this_element->parent_eid); + + /* Purge if parent is deleted */ + if (! parent_element) + { + svn_eid__hash_set(e_map, this_eid, NULL); + changed = TRUE; + } + else + SVN_ERR_ASSERT_NO_RETURN( + ! parent_element->payload->is_subbranch_root); + } + } + } + while (changed); +} + +const char * +svn_element__tree_get_path_by_eid(const svn_element__tree_t *tree, + int eid, + apr_pool_t *result_pool) +{ + const char *path = ""; + svn_element__content_t *element; + + for (; eid != tree->root_eid; eid = element->parent_eid) + { + element = svn_element__tree_get(tree, eid); + if (! element) + return NULL; + path = svn_relpath_join(element->name, path, result_pool); + } + SVN_ERR_ASSERT_NO_RETURN(eid == tree->root_eid); + return path; +} + +svn_element__tree_t * +svn_element__tree_get_subtree_at_eid(svn_element__tree_t *element_tree, + int eid, + apr_pool_t *result_pool) +{ + svn_element__tree_t *new_subtree; + svn_element__content_t *subtree_root_element; + + new_subtree = svn_element__tree_create(element_tree->e_map, eid, + result_pool); + + /* Purge orphans */ + svn_element__tree_purge_orphans(new_subtree->e_map, + new_subtree->root_eid, result_pool); + + /* Remove 'parent' and 'name' attributes from subtree root element */ + subtree_root_element + = svn_element__tree_get(new_subtree, new_subtree->root_eid); + svn_element__tree_set(new_subtree, new_subtree->root_eid, + svn_element__content_create( + -1, "", subtree_root_element->payload, result_pool)); + + return new_subtree; +} + diff --git a/subversion/libsvn_delta/svndiff.c b/subversion/libsvn_delta/svndiff.c index 070c638a74d6..d95dde42b199 100644 --- a/subversion/libsvn_delta/svndiff.c +++ b/subversion/libsvn_delta/svndiff.c @@ -36,6 +36,23 @@ #include "private/svn_string_private.h" #include "private/svn_dep_compat.h" +static const char SVNDIFF_V0[] = { 'S', 'V', 'N', 0 }; +static const char SVNDIFF_V1[] = { 'S', 'V', 'N', 1 }; +static const char SVNDIFF_V2[] = { 'S', 'V', 'N', 2 }; + +#define SVNDIFF_HEADER_SIZE (sizeof(SVNDIFF_V0)) + +static const char * +get_svndiff_header(int version) +{ + if (version == 2) + return SVNDIFF_V2; + else if (version == 1) + return SVNDIFF_V1; + else + return SVNDIFF_V0; +} + /* ----- Text delta to svndiff ----- */ /* We make one of these and get it passed back to us in calls to the @@ -46,7 +63,8 @@ struct encoder_baton { svn_boolean_t header_done; int version; int compression_level; - apr_pool_t *pool; + /* Pool for temporary allocations, will be cleared periodically. */ + apr_pool_t *scratch_pool; }; /* This is at least as big as the largest size for a single instruction. */ @@ -72,7 +90,7 @@ static svn_error_t * send_simple_insertion_window(svn_txdelta_window_t *window, struct encoder_baton *eb) { - unsigned char headers[4 + 5 * SVN__MAX_ENCODED_UINT_LEN + unsigned char headers[SVNDIFF_HEADER_SIZE + 5 * SVN__MAX_ENCODED_UINT_LEN + MAX_INSTRUCTION_LEN]; unsigned char ibuf[MAX_INSTRUCTION_LEN]; unsigned char *header_current; @@ -89,11 +107,8 @@ send_simple_insertion_window(svn_txdelta_window_t *window, if (!eb->header_done) { eb->header_done = TRUE; - headers[0] = 'S'; - headers[1] = 'V'; - headers[2] = 'N'; - headers[3] = (unsigned char)eb->version; - header_current = headers + 4; + memcpy(headers, get_svndiff_header(eb->version), SVNDIFF_HEADER_SIZE); + header_current = headers + SVNDIFF_HEADER_SIZE; } else { @@ -135,58 +150,28 @@ send_simple_insertion_window(svn_txdelta_window_t *window, return SVN_NO_ERROR; } +/* Encodes delta window WINDOW to svndiff-format. + The svndiff version is VERSION. COMPRESSION_LEVEL is the + compression level to use. + Returned values will be allocated in POOL or refer to *WINDOW + fields. */ static svn_error_t * -window_handler(svn_txdelta_window_t *window, void *baton) +encode_window(svn_stringbuf_t **instructions_p, + svn_stringbuf_t **header_p, + const svn_string_t **newdata_p, + svn_txdelta_window_t *window, + int version, + int compression_level, + apr_pool_t *pool) { - struct encoder_baton *eb = baton; - apr_pool_t *pool; svn_stringbuf_t *instructions; - svn_stringbuf_t *i1; svn_stringbuf_t *header; const svn_string_t *newdata; unsigned char ibuf[MAX_INSTRUCTION_LEN], *ip; const svn_txdelta_op_t *op; - apr_size_t len; - - /* use specialized code if there is no source */ - if (window && !window->src_ops && window->num_ops == 1 && !eb->version) - return svn_error_trace(send_simple_insertion_window(window, eb)); - - /* Make sure we write the header. */ - if (!eb->header_done) - { - char svnver[4] = {'S','V','N','\0'}; - len = 4; - svnver[3] = (char)eb->version; - SVN_ERR(svn_stream_write(eb->output, svnver, &len)); - eb->header_done = TRUE; - } - - if (window == NULL) - { - svn_stream_t *output = eb->output; - - /* We're done; clean up. - - We clean our pool first. Given that the output stream was passed - TO us, we'll assume it has a longer lifetime, and that it will not - be affected by our pool destruction. - - The contrary point of view (close the stream first): that could - tell our user that everything related to the output stream is done, - and a cleanup of the user pool should occur. However, that user - pool could include the subpool we created for our work (eb->pool), - which would then make our call to svn_pool_destroy() puke. - */ - svn_pool_destroy(eb->pool); - - return svn_stream_close(output); - } /* create the necessary data buffers */ - pool = svn_pool_create(eb->pool); instructions = svn_stringbuf_create_empty(pool); - i1 = svn_stringbuf_create_empty(pool); header = svn_stringbuf_create_empty(pool); /* Encode the instructions. */ @@ -213,21 +198,39 @@ window_handler(svn_txdelta_window_t *window, void *baton) append_encoded_int(header, window->sview_offset); append_encoded_int(header, window->sview_len); append_encoded_int(header, window->tview_len); - if (eb->version == 1) + if (version == 2) { - SVN_ERR(svn__compress(instructions, i1, eb->compression_level)); - instructions = i1; + svn_stringbuf_t *compressed_instructions; + compressed_instructions = svn_stringbuf_create_empty(pool); + SVN_ERR(svn__compress_lz4(instructions->data, instructions->len, + compressed_instructions)); + instructions = compressed_instructions; + } + else if (version == 1) + { + svn_stringbuf_t *compressed_instructions; + compressed_instructions = svn_stringbuf_create_empty(pool); + SVN_ERR(svn__compress_zlib(instructions->data, instructions->len, + compressed_instructions, compression_level)); + instructions = compressed_instructions; } append_encoded_int(header, instructions->len); - if (eb->version == 1) + + /* Encode the data. */ + if (version == 2) { svn_stringbuf_t *compressed = svn_stringbuf_create_empty(pool); - svn_stringbuf_t *original = svn_stringbuf_create_empty(pool); - original->data = (char *)window->new_data->data; /* won't be modified */ - original->len = window->new_data->len; - original->blocksize = window->new_data->len + 1; - SVN_ERR(svn__compress(original, compressed, eb->compression_level)); + SVN_ERR(svn__compress_lz4(window->new_data->data, window->new_data->len, + compressed)); + newdata = svn_stringbuf__morph_into_string(compressed); + } + else if (version == 1) + { + svn_stringbuf_t *compressed = svn_stringbuf_create_empty(pool); + + SVN_ERR(svn__compress_zlib(window->new_data->data, window->new_data->len, + compressed, compression_level)); newdata = svn_stringbuf__morph_into_string(compressed); } else @@ -235,6 +238,53 @@ window_handler(svn_txdelta_window_t *window, void *baton) append_encoded_int(header, newdata->len); + *instructions_p = instructions; + *header_p = header; + *newdata_p = newdata; + + return SVN_NO_ERROR; +} + +/* Note: When changing things here, check the related comment in + the svn_txdelta_to_svndiff_stream() function. */ +static svn_error_t * +window_handler(svn_txdelta_window_t *window, void *baton) +{ + struct encoder_baton *eb = baton; + apr_size_t len; + svn_stringbuf_t *instructions; + svn_stringbuf_t *header; + const svn_string_t *newdata; + + /* use specialized code if there is no source */ + if (window && !window->src_ops && window->num_ops == 1 && !eb->version) + return svn_error_trace(send_simple_insertion_window(window, eb)); + + /* Make sure we write the header. */ + if (!eb->header_done) + { + len = SVNDIFF_HEADER_SIZE; + SVN_ERR(svn_stream_write(eb->output, get_svndiff_header(eb->version), + &len)); + eb->header_done = TRUE; + } + + if (window == NULL) + { + /* We're done; clean up. */ + SVN_ERR(svn_stream_close(eb->output)); + + svn_pool_destroy(eb->scratch_pool); + + return SVN_NO_ERROR; + } + + svn_pool_clear(eb->scratch_pool); + + SVN_ERR(encode_window(&instructions, &header, &newdata, window, + eb->version, eb->compression_level, + eb->scratch_pool)); + /* Write out the window. */ len = header->len; SVN_ERR(svn_stream_write(eb->output, header->data, &len)); @@ -249,7 +299,6 @@ window_handler(svn_txdelta_window_t *window, void *baton) SVN_ERR(svn_stream_write(eb->output, newdata->data, &len)); } - svn_pool_destroy(pool); return SVN_NO_ERROR; } @@ -261,13 +310,12 @@ svn_txdelta_to_svndiff3(svn_txdelta_window_handler_t *handler, int compression_level, apr_pool_t *pool) { - apr_pool_t *subpool = svn_pool_create(pool); struct encoder_baton *eb; - eb = apr_palloc(subpool, sizeof(*eb)); + eb = apr_palloc(pool, sizeof(*eb)); eb->output = output; eb->header_done = FALSE; - eb->pool = subpool; + eb->scratch_pool = svn_pool_create(pool); eb->version = svndiff_version; eb->compression_level = compression_level; @@ -334,6 +382,17 @@ struct decode_baton /* svndiff version in use by delta. */ unsigned char version; + + /* Length of parsed delta window header. 0 if window is not parsed yet. */ + apr_size_t window_header_len; + + /* Five integer fields of parsed delta window header. Valid only if + WINDOW_HEADER_LEN > 0 */ + svn_filesize_t sview_offset; + apr_size_t sview_len; + apr_size_t tview_len; + apr_size_t inslen; + apr_size_t newlen; }; @@ -483,21 +542,6 @@ count_and_verify_instructions(int *ninst, return SVN_NO_ERROR; } -static svn_error_t * -zlib_decode(const unsigned char *in, apr_size_t inLen, svn_stringbuf_t *out, - apr_size_t limit) -{ - /* construct a fake string buffer as parameter to svn__decompress. - This is fine as that function never writes to it. */ - svn_stringbuf_t compressed; - compressed.pool = NULL; - compressed.data = (char *)in; - compressed.len = inLen; - compressed.blocksize = inLen + 1; - - return svn__decompress(&compressed, out, limit); -} - /* Given the five integer fields of a window header and a pointer to the remainder of the window contents, fill in a delta window structure *WINDOW. New allocations will be performed in POOL; @@ -513,7 +557,7 @@ decode_window(svn_txdelta_window_t *window, svn_filesize_t sview_offset, int ninst; apr_size_t npos; svn_txdelta_op_t *ops, *op; - svn_string_t *new_data = apr_palloc(pool, sizeof(*new_data)); + svn_string_t *new_data; window->sview_offset = sview_offset; window->sview_len = sview_len; @@ -521,33 +565,43 @@ decode_window(svn_txdelta_window_t *window, svn_filesize_t sview_offset, insend = data + inslen; - if (version == 1) + if (version == 2) { svn_stringbuf_t *instout = svn_stringbuf_create_empty(pool); svn_stringbuf_t *ndout = svn_stringbuf_create_empty(pool); - SVN_ERR(zlib_decode(insend, newlen, ndout, - SVN_DELTA_WINDOW_SIZE)); - SVN_ERR(zlib_decode(data, insend - data, instout, - MAX_INSTRUCTION_SECTION_LEN)); + SVN_ERR(svn__decompress_lz4(insend, newlen, ndout, + SVN_DELTA_WINDOW_SIZE)); + SVN_ERR(svn__decompress_lz4(data, insend - data, instout, + MAX_INSTRUCTION_SECTION_LEN)); newlen = ndout->len; data = (unsigned char *)instout->data; insend = (unsigned char *)instout->data + instout->len; - new_data->data = (const char *) ndout->data; - new_data->len = newlen; + new_data = svn_stringbuf__morph_into_string(ndout); + } + else if (version == 1) + { + svn_stringbuf_t *instout = svn_stringbuf_create_empty(pool); + svn_stringbuf_t *ndout = svn_stringbuf_create_empty(pool); + + SVN_ERR(svn__decompress_zlib(insend, newlen, ndout, + SVN_DELTA_WINDOW_SIZE)); + SVN_ERR(svn__decompress_zlib(data, insend - data, instout, + MAX_INSTRUCTION_SECTION_LEN)); + + newlen = ndout->len; + data = (unsigned char *)instout->data; + insend = (unsigned char *)instout->data + instout->len; + + new_data = svn_stringbuf__morph_into_string(ndout); } else { /* Copy the data because an svn_string_t must have the invariant data[len]=='\0'. */ - char *buf = apr_palloc(pool, newlen + 1); - - memcpy(buf, insend, newlen); - buf[newlen] = '\0'; - new_data->data = buf; - new_data->len = newlen; + new_data = svn_string_ncreate((const char*)insend, newlen, pool); } /* Count the instructions and make sure they are all valid. */ @@ -578,10 +632,6 @@ decode_window(svn_txdelta_window_t *window, svn_filesize_t sview_offset, return SVN_NO_ERROR; } -static const char SVNDIFF_V0[] = { 'S', 'V', 'N', 0 }; -static const char SVNDIFF_V1[] = { 'S', 'V', 'N', 1 }; -#define SVNDIFF_HEADER_SIZE (sizeof(SVNDIFF_V0)) - static svn_error_t * write_handler(void *baton, const char *buffer, @@ -589,8 +639,6 @@ write_handler(void *baton, { struct decode_baton *db = (struct decode_baton *) baton; const unsigned char *p, *end; - svn_filesize_t sview_offset; - apr_size_t sview_len, tview_len, inslen, newlen, remaining; apr_size_t buflen = *len; /* Chew up four bytes at the beginning for the header. */ @@ -603,6 +651,8 @@ write_handler(void *baton, db->version = 0; else if (memcmp(buffer, SVNDIFF_V1 + db->header_bytes, nheader) == 0) db->version = 1; + else if (memcmp(buffer, SVNDIFF_V2 + db->header_bytes, nheader) == 0) + db->version = 2; else return svn_error_create(SVN_ERR_SVNDIFF_INVALID_HEADER, NULL, _("Svndiff has invalid header")); @@ -628,92 +678,108 @@ write_handler(void *baton, while (1) { - apr_pool_t *newpool; svn_txdelta_window_t window; /* Read the header, if we have enough bytes for that. */ p = (const unsigned char *) db->buffer->data; end = (const unsigned char *) db->buffer->data + db->buffer->len; - p = decode_file_offset(&sview_offset, p, end); - if (p == NULL) - break; + if (db->window_header_len == 0) + { + svn_filesize_t sview_offset; + apr_size_t sview_len, tview_len, inslen, newlen; + const unsigned char *hdr_start = p; - p = decode_size(&sview_len, p, end); - if (p == NULL) - break; + p = decode_file_offset(&sview_offset, p, end); + if (p == NULL) + break; - p = decode_size(&tview_len, p, end); - if (p == NULL) - break; + p = decode_size(&sview_len, p, end); + if (p == NULL) + break; - p = decode_size(&inslen, p, end); - if (p == NULL) - break; + p = decode_size(&tview_len, p, end); + if (p == NULL) + break; - p = decode_size(&newlen, p, end); - if (p == NULL) - break; + p = decode_size(&inslen, p, end); + if (p == NULL) + break; - if (tview_len > SVN_DELTA_WINDOW_SIZE || - sview_len > SVN_DELTA_WINDOW_SIZE || - /* for svndiff1, newlen includes the original length */ - newlen > SVN_DELTA_WINDOW_SIZE + SVN__MAX_ENCODED_UINT_LEN || - inslen > MAX_INSTRUCTION_SECTION_LEN) - return svn_error_create(SVN_ERR_SVNDIFF_CORRUPT_WINDOW, NULL, - _("Svndiff contains a too-large window")); + p = decode_size(&newlen, p, end); + if (p == NULL) + break; - /* Check for integer overflow. */ - if (sview_offset < 0 || inslen + newlen < inslen - || sview_len + tview_len < sview_len - || (apr_size_t)sview_offset + sview_len < (apr_size_t)sview_offset) - return svn_error_create(SVN_ERR_SVNDIFF_CORRUPT_WINDOW, NULL, - _("Svndiff contains corrupt window header")); + if (tview_len > SVN_DELTA_WINDOW_SIZE || + sview_len > SVN_DELTA_WINDOW_SIZE || + /* for svndiff1, newlen includes the original length */ + newlen > SVN_DELTA_WINDOW_SIZE + SVN__MAX_ENCODED_UINT_LEN || + inslen > MAX_INSTRUCTION_SECTION_LEN) + return svn_error_create( + SVN_ERR_SVNDIFF_CORRUPT_WINDOW, NULL, + _("Svndiff contains a too-large window")); - /* Check for source windows which slide backwards. */ - if (sview_len > 0 - && (sview_offset < db->last_sview_offset - || (sview_offset + sview_len - < db->last_sview_offset + db->last_sview_len))) - return svn_error_create - (SVN_ERR_SVNDIFF_BACKWARD_VIEW, NULL, - _("Svndiff has backwards-sliding source views")); + /* Check for integer overflow. */ + if (sview_offset < 0 || inslen + newlen < inslen + || sview_len + tview_len < sview_len + || (apr_size_t)sview_offset + sview_len < (apr_size_t)sview_offset) + return svn_error_create( + SVN_ERR_SVNDIFF_CORRUPT_WINDOW, NULL, + _("Svndiff contains corrupt window header")); + + /* Check for source windows which slide backwards. */ + if (sview_len > 0 + && (sview_offset < db->last_sview_offset + || (sview_offset + sview_len + < db->last_sview_offset + db->last_sview_len))) + return svn_error_create( + SVN_ERR_SVNDIFF_BACKWARD_VIEW, NULL, + _("Svndiff has backwards-sliding source views")); + + /* Remember parsed window header. */ + db->window_header_len = p - hdr_start; + db->sview_offset = sview_offset; + db->sview_len = sview_len; + db->tview_len = tview_len; + db->inslen = inslen; + db->newlen = newlen; + } + else + { + /* Skip already parsed window header. */ + p += db->window_header_len; + } /* Wait for more data if we don't have enough bytes for the - whole window. */ - if ((apr_size_t) (end - p) < inslen + newlen) + whole window. */ + if ((apr_size_t) (end - p) < db->inslen + db->newlen) return SVN_NO_ERROR; /* Decode the window and send it off. */ - SVN_ERR(decode_window(&window, sview_offset, sview_len, tview_len, - inslen, newlen, p, db->subpool, - db->version)); + SVN_ERR(decode_window(&window, db->sview_offset, db->sview_len, + db->tview_len, db->inslen, db->newlen, p, + db->subpool, db->version)); SVN_ERR(db->consumer_func(&window, db->consumer_baton)); - /* Make a new subpool and buffer, saving aside the remaining - data in the old buffer. */ - newpool = svn_pool_create(db->pool); - p += inslen + newlen; - remaining = db->buffer->data + db->buffer->len - (const char *) p; - db->buffer = - svn_stringbuf_ncreate((const char *) p, remaining, newpool); + p += db->inslen + db->newlen; + + /* Remove processed data from the buffer. */ + svn_stringbuf_remove(db->buffer, 0, db->buffer->len - (end - p)); + + /* Reset window header length. */ + db->window_header_len = 0; /* Remember the offset and length of the source view for next time. */ - db->last_sview_offset = sview_offset; - db->last_sview_len = sview_len; + db->last_sview_offset = db->sview_offset; + db->last_sview_len = db->sview_len; - /* We've copied stuff out of the old pool. Toss that pool and use - our new pool. - ### might be nice to avoid the copy and just use svn_pool_clear - ### to get rid of whatever the "other stuff" is. future project... - */ - svn_pool_destroy(db->subpool); - db->subpool = newpool; + /* Clear subpool. */ + svn_pool_clear(db->subpool); } /* At this point we processed all integral windows and DB->BUFFER is empty or contains partially read window header. - Check that unprocessed data is not larger that theoretical maximum + Check that unprocessed data is not larger than theoretical maximum window header size. */ if (db->buffer->len > 5 * SVN__MAX_ENCODED_UINT_LEN) return svn_error_create(SVN_ERR_SVNDIFF_CORRUPT_WINDOW, NULL, @@ -757,23 +823,25 @@ svn_txdelta_parse_svndiff(svn_txdelta_window_handler_t handler, svn_boolean_t error_on_early_close, apr_pool_t *pool) { - apr_pool_t *subpool = svn_pool_create(pool); - struct decode_baton *db = apr_palloc(pool, sizeof(*db)); svn_stream_t *stream; - db->consumer_func = handler; - db->consumer_baton = handler_baton; - db->pool = subpool; - db->subpool = svn_pool_create(subpool); - db->buffer = svn_stringbuf_create_empty(db->subpool); - db->last_sview_offset = 0; - db->last_sview_len = 0; - db->header_bytes = 0; - db->error_on_early_close = error_on_early_close; - stream = svn_stream_create(db, pool); - if (handler != svn_delta_noop_window_handler) { + apr_pool_t *subpool = svn_pool_create(pool); + struct decode_baton *db = apr_palloc(pool, sizeof(*db)); + + db->consumer_func = handler; + db->consumer_baton = handler_baton; + db->pool = subpool; + db->subpool = svn_pool_create(subpool); + db->buffer = svn_stringbuf_create_empty(db->pool); + db->last_sview_offset = 0; + db->last_sview_len = 0; + db->header_bytes = 0; + db->error_on_early_close = error_on_early_close; + db->window_header_len = 0; + stream = svn_stream_create(db, pool); + svn_stream_set_write(stream, write_handler); svn_stream_set_close(stream, close_handler); } @@ -781,6 +849,7 @@ svn_txdelta_parse_svndiff(svn_txdelta_window_handler_t handler, { /* And else we just ignore everything as efficiently as we can. by only hooking a no-op handler */ + stream = svn_stream_create(NULL, pool); svn_stream_set_write(stream, noop_write_handler); } return stream; @@ -926,3 +995,107 @@ svn_txdelta__read_raw_window_len(apr_size_t *window_len, return SVN_NO_ERROR; } +typedef struct svndiff_stream_baton_t +{ + apr_pool_t *scratch_pool; + svn_txdelta_stream_t *txstream; + svn_txdelta_window_handler_t handler; + void *handler_baton; + svn_stringbuf_t *window_buffer; + apr_size_t read_pos; + svn_boolean_t hit_eof; +} svndiff_stream_baton_t; + +static svn_error_t * +svndiff_stream_write_fn(void *baton, const char *data, apr_size_t *len) +{ + svndiff_stream_baton_t *b = baton; + + /* The memory usage here is limited, as this buffer doesn't grow + beyond the (header size + max window size in svndiff format). + See the comment in svn_txdelta_to_svndiff_stream(). */ + svn_stringbuf_appendbytes(b->window_buffer, data, *len); + + return SVN_NO_ERROR; +} + +static svn_error_t * +svndiff_stream_read_fn(void *baton, char *buffer, apr_size_t *len) +{ + svndiff_stream_baton_t *b = baton; + apr_size_t left = *len; + apr_size_t read = 0; + + while (left) + { + apr_size_t chunk_size; + + if (b->read_pos == b->window_buffer->len && !b->hit_eof) + { + svn_txdelta_window_t *window; + + svn_pool_clear(b->scratch_pool); + svn_stringbuf_setempty(b->window_buffer); + SVN_ERR(svn_txdelta_next_window(&window, b->txstream, + b->scratch_pool)); + SVN_ERR(b->handler(window, b->handler_baton)); + b->read_pos = 0; + + if (!window) + b->hit_eof = TRUE; + } + + if (left > b->window_buffer->len - b->read_pos) + chunk_size = b->window_buffer->len - b->read_pos; + else + chunk_size = left; + + if (!chunk_size) + break; + + memcpy(buffer, b->window_buffer->data + b->read_pos, chunk_size); + b->read_pos += chunk_size; + buffer += chunk_size; + read += chunk_size; + left -= chunk_size; + } + + *len = read; + return SVN_NO_ERROR; +} + +svn_stream_t * +svn_txdelta_to_svndiff_stream(svn_txdelta_stream_t *txstream, + int svndiff_version, + int compression_level, + apr_pool_t *pool) +{ + svndiff_stream_baton_t *baton; + svn_stream_t *push_stream; + svn_stream_t *pull_stream; + + baton = apr_pcalloc(pool, sizeof(*baton)); + baton->scratch_pool = svn_pool_create(pool); + baton->txstream = txstream; + baton->window_buffer = svn_stringbuf_create_empty(pool); + baton->hit_eof = FALSE; + baton->read_pos = 0; + + push_stream = svn_stream_create(baton, pool); + svn_stream_set_write(push_stream, svndiff_stream_write_fn); + + /* We rely on the implementation detail of the svn_txdelta_to_svndiff3() + function, namely, on how the window_handler() function behaves. + As long as it writes one svndiff window at a time to the target + stream, the memory usage of this function (in other words, how + much data can be accumulated in the internal 'window_buffer') + is limited. */ + svn_txdelta_to_svndiff3(&baton->handler, &baton->handler_baton, + push_stream, svndiff_version, + compression_level, pool); + + pull_stream = svn_stream_create(baton, pool); + svn_stream_set_read2(pull_stream, NULL, svndiff_stream_read_fn); + + return pull_stream; +} diff --git a/subversion/libsvn_delta/text_delta.c b/subversion/libsvn_delta/text_delta.c index 04eca8afb8c1..4f834988bf38 100644 --- a/subversion/libsvn_delta/text_delta.c +++ b/subversion/libsvn_delta/text_delta.c @@ -102,7 +102,7 @@ struct apply_baton { char *tbuf; /* Target buffer */ apr_size_t tbuf_size; /* Allocated target buffer space */ - apr_md5_ctx_t md5_context; /* Leads to result_digest below. */ + svn_checksum_ctx_t *md5_context; /* Leads to result_digest below. */ unsigned char *result_digest; /* MD5 digest of resultant fulltext; must point to at least APR_MD5_DIGESTSIZE bytes of storage. */ @@ -180,8 +180,7 @@ svn_txdelta_window_dup(const svn_txdelta_window_t *window, build_baton.num_ops = window->num_ops; build_baton.src_ops = window->src_ops; build_baton.ops_size = window->num_ops; - build_baton.ops = apr_palloc(pool, ops_size); - memcpy(build_baton.ops, window->ops, ops_size); + build_baton.ops = apr_pmemdup(pool, window->ops, ops_size); build_baton.new_data = svn_stringbuf_create_from_string(window->new_data, pool); @@ -721,15 +720,23 @@ apply_window(svn_txdelta_window_t *window, void *baton) { struct apply_baton *ab = (struct apply_baton *) baton; apr_size_t len; - svn_error_t *err; if (window == NULL) { + svn_error_t *err = SVN_NO_ERROR; + /* We're done; just clean up. */ if (ab->result_digest) - apr_md5_final(ab->result_digest, &(ab->md5_context)); + { + svn_checksum_t *md5_checksum; - err = svn_stream_close(ab->target); + err = svn_checksum_final(&md5_checksum, ab->md5_context, ab->pool); + if (!err) + memcpy(ab->result_digest, md5_checksum->digest, + svn_checksum_size(md5_checksum)); + } + + err = svn_error_compose_create(err, svn_stream_close(ab->target)); svn_pool_destroy(ab->pool); return err; @@ -773,12 +780,10 @@ apply_window(svn_txdelta_window_t *window, void *baton) if (ab->sbuf_len < window->sview_len) { len = window->sview_len - ab->sbuf_len; - err = svn_stream_read_full(ab->source, ab->sbuf + ab->sbuf_len, &len); - if (err == SVN_NO_ERROR && len != window->sview_len - ab->sbuf_len) - err = svn_error_create(SVN_ERR_INCOMPLETE_DATA, NULL, - "Delta source ended unexpectedly"); - if (err != SVN_NO_ERROR) - return err; + SVN_ERR(svn_stream_read_full(ab->source, ab->sbuf + ab->sbuf_len, &len)); + if (len != window->sview_len - ab->sbuf_len) + return svn_error_create(SVN_ERR_INCOMPLETE_DATA, NULL, + "Delta source ended unexpectedly"); ab->sbuf_len = window->sview_len; } @@ -792,7 +797,7 @@ apply_window(svn_txdelta_window_t *window, void *baton) /* Just update the context here. */ if (ab->result_digest) - apr_md5_update(&(ab->md5_context), ab->tbuf, len); + SVN_ERR(svn_checksum_update(ab->md5_context, ab->tbuf, len)); return svn_stream_write(ab->target, ab->tbuf, &len); } @@ -823,7 +828,7 @@ svn_txdelta_apply(svn_stream_t *source, ab->result_digest = result_digest; if (result_digest) - apr_md5_init(&(ab->md5_context)); + ab->md5_context = svn_checksum_ctx_create(svn_checksum_md5, subpool); if (error_info) ab->error_info = apr_pstrdup(subpool, error_info); diff --git a/subversion/libsvn_delta/xdelta.c b/subversion/libsvn_delta/xdelta.c index 2e5bb266acfb..ff95f77f095f 100644 --- a/subversion/libsvn_delta/xdelta.c +++ b/subversion/libsvn_delta/xdelta.c @@ -111,7 +111,7 @@ struct block apr_uint32_t adlersum; /* Even in 64 bit systems, store only 32 bit offsets in our hash table - (our delta window size much much smaller then 4GB). + (our delta window size much much smaller than 4GB). That reduces the hash table size by 50% from 32to 16KB and makes it easier to fit into the CPU's L1 cache. */ apr_uint32_t pos; /* NO_POSITION -> block is not used */ diff --git a/subversion/libsvn_diff/binary_diff.c b/subversion/libsvn_diff/binary_diff.c index 035794dbed57..5ca37052e3a0 100644 --- a/subversion/libsvn_diff/binary_diff.c +++ b/subversion/libsvn_diff/binary_diff.c @@ -28,6 +28,10 @@ #include "svn_diff.h" #include "svn_types.h" +#include "diff.h" + +#include "svn_private_config.h" + /* Copies the data from ORIGINAL_STREAM to a temporary file, returning both the original and compressed size. */ static svn_error_t * @@ -42,7 +46,6 @@ create_compressed(apr_file_t **result, { svn_stream_t *compressed; svn_filesize_t bytes_read = 0; - apr_finfo_t finfo; apr_size_t rd; SVN_ERR(svn_io_open_uniquely_named(result, NULL, NULL, "diffgz", @@ -56,7 +59,7 @@ create_compressed(apr_file_t **result, if (original_stream) do { - char buffer[SVN_STREAM_CHUNK_SIZE]; + char buffer[SVN__STREAM_CHUNK_SIZE]; rd = sizeof(buffer); if (cancel_func) @@ -67,7 +70,7 @@ create_compressed(apr_file_t **result, bytes_read += rd; SVN_ERR(svn_stream_write(compressed, buffer, &rd)); } - while(rd == SVN_STREAM_CHUNK_SIZE); + while(rd == SVN__STREAM_CHUNK_SIZE); else { apr_size_t zero = 0; @@ -77,8 +80,7 @@ create_compressed(apr_file_t **result, SVN_ERR(svn_stream_close(compressed)); /* Flush compression */ *full_size = bytes_read; - SVN_ERR(svn_io_file_info_get(&finfo, APR_FINFO_SIZE, *result, scratch_pool)); - *compressed_size = finfo.size; + SVN_ERR(svn_io_file_size_get(compressed_size, *result, scratch_pool)); return SVN_NO_ERROR; } @@ -92,6 +94,66 @@ static const char b85str[] = "abcdefghijklmnopqrstuvwxyz" "!#$%&()*+-;<=>?@^_`{|}~"; +/* Helper function for svn_diff__base85_decode_line */ +static svn_error_t * +base85_value(int *value, char c) +{ + const char *p = strchr(b85str, c); + if (!p) + return svn_error_create(SVN_ERR_DIFF_UNEXPECTED_DATA, NULL, + _("Invalid base85 value")); + + /* It's safe to cast the ptrdiff_t value of the pointer difference + to int because the value will always be in the range [0..84]. */ + *value = (int)(p - b85str); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_diff__base85_decode_line(char *output_data, + apr_ssize_t output_len, + const char *base85_data, + apr_ssize_t base85_len, + apr_pool_t *scratch_pool) +{ + { + apr_ssize_t expected_data = (output_len + 3) / 4 * 5; + + if (base85_len != expected_data) + return svn_error_create(SVN_ERR_DIFF_UNEXPECTED_DATA, NULL, + _("Unexpected base85 line length")); + } + + while (base85_len) + { + unsigned info = 0; + apr_ssize_t i, n; + + for (i = 0; i < 5; i++) + { + int value; + + SVN_ERR(base85_value(&value, base85_data[i])); + info *= 85; + info += value; + } + + for (i = 0, n=24; i < 4; i++, n-=8) + { + if (i < output_len) + output_data[i] = (info >> n) & 0xFF; + } + + base85_data += 5; + base85_len -= 5; + output_data += 4; + output_len -= 4; + } + + return SVN_NO_ERROR; +} + + /* Git length encoding table for write_literal */ static const char b85lenstr[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -215,7 +277,5 @@ svn_diff_output_binary(svn_stream_t *output_stream, scratch_pool)); svn_pool_destroy(subpool); - SVN_ERR(svn_stream_puts(output_stream, APR_EOL_STR)); - return SVN_NO_ERROR; } diff --git a/subversion/libsvn_diff/diff.h b/subversion/libsvn_diff/diff.h index 51a84c640580..7628e65cc7b5 100644 --- a/subversion/libsvn_diff/diff.h +++ b/subversion/libsvn_diff/diff.h @@ -214,4 +214,14 @@ svn_diff__unified_write_hunk_header(svn_stream_t *output_stream, apr_pool_t *scratch_pool); +/* Decodes a single line of base85 data in BASE85_DATA of length BASE85_LEN, + to OUTPUT_DATA of length OUTPUT_LEN. + */ +svn_error_t * +svn_diff__base85_decode_line(char *output_data, + apr_ssize_t output_len, + const char *base85_data, + apr_ssize_t base85_len, + apr_pool_t *scratch_pool); + #endif /* DIFF_H */ diff --git a/subversion/libsvn_diff/diff3.c b/subversion/libsvn_diff/diff3.c index 8b7c9b332817..aa247468e5ff 100644 --- a/subversion/libsvn_diff/diff3.c +++ b/subversion/libsvn_diff/diff3.c @@ -29,6 +29,7 @@ #include "svn_pools.h" #include "svn_error.h" #include "svn_diff.h" +#include "svn_sorts.h" #include "svn_types.h" #include "diff.h" @@ -474,21 +475,23 @@ svn_diff_diff3_2(svn_diff_t **diff, - (original_sync - lcs_om->position[0]->offset); latest_length = lcs_ol->length - (original_sync - lcs_ol->position[0]->offset); - common_length = modified_length < latest_length - ? modified_length : latest_length; + common_length = MIN(modified_length, latest_length); - (*diff_ref) = apr_palloc(pool, sizeof(**diff_ref)); + if (common_length > 0) + { + (*diff_ref) = apr_palloc(pool, sizeof(**diff_ref)); - (*diff_ref)->type = svn_diff__type_common; - (*diff_ref)->original_start = original_sync - 1; - (*diff_ref)->original_length = common_length; - (*diff_ref)->modified_start = modified_sync - 1; - (*diff_ref)->modified_length = common_length; - (*diff_ref)->latest_start = latest_sync - 1; - (*diff_ref)->latest_length = common_length; - (*diff_ref)->resolved_diff = NULL; + (*diff_ref)->type = svn_diff__type_common; + (*diff_ref)->original_start = original_sync - 1; + (*diff_ref)->original_length = common_length; + (*diff_ref)->modified_start = modified_sync - 1; + (*diff_ref)->modified_length = common_length; + (*diff_ref)->latest_start = latest_sync - 1; + (*diff_ref)->latest_length = common_length; + (*diff_ref)->resolved_diff = NULL; - diff_ref = &(*diff_ref)->next; + diff_ref = &(*diff_ref)->next; + } /* Set the new offsets */ original_start = original_sync + common_length; diff --git a/subversion/libsvn_diff/diff_file.c b/subversion/libsvn_diff/diff_file.c index f54522e7c9c6..d0182c8b3555 100644 --- a/subversion/libsvn_diff/diff_file.c +++ b/subversion/libsvn_diff/diff_file.c @@ -777,7 +777,6 @@ datasources_open(void *baton, { svn_diff__file_baton_t *file_baton = baton; struct file_info files[4]; - apr_finfo_t finfo[4]; apr_off_t length[4]; #ifndef SVN_DISABLE_PREFIX_SUFFIX_SCANNING svn_boolean_t reached_one_eof; @@ -792,14 +791,14 @@ datasources_open(void *baton, /* Open datasources and read first chunk */ for (i = 0; i < datasources_len; i++) { + svn_filesize_t filesize; struct file_info *file = &file_baton->files[datasource_to_index(datasources[i])]; SVN_ERR(svn_io_file_open(&file->file, file->path, APR_READ, APR_OS_DEFAULT, file_baton->pool)); - SVN_ERR(svn_io_file_info_get(&finfo[i], APR_FINFO_SIZE, - file->file, file_baton->pool)); - file->size = finfo[i].size; - length[i] = finfo[i].size > CHUNK_SIZE ? CHUNK_SIZE : finfo[i].size; + SVN_ERR(svn_io_file_size_get(&filesize, file->file, file_baton->pool)); + file->size = filesize; + length[i] = filesize > CHUNK_SIZE ? CHUNK_SIZE : filesize; file->buffer = apr_palloc(file_baton->pool, (apr_size_t) length[i]); SVN_ERR(read_chunk(file->file, file->buffer, length[i], 0, file_baton->pool)); @@ -1243,17 +1242,20 @@ svn_diff_file_options_parse(svn_diff_file_options_t *options, { apr_getopt_t *os; struct opt_parsing_error_baton_t opt_parsing_error_baton; - /* Make room for each option (starting at index 1) plus trailing NULL. */ - const char **argv = apr_palloc(pool, sizeof(char*) * (args->nelts + 2)); + apr_array_header_t *argv; opt_parsing_error_baton.err = NULL; opt_parsing_error_baton.pool = pool; - argv[0] = ""; - memcpy(argv + 1, args->elts, sizeof(char*) * args->nelts); - argv[args->nelts + 1] = NULL; + /* Make room for each option (starting at index 1) plus trailing NULL. */ + argv = apr_array_make(pool, args->nelts + 2, sizeof(char*)); + APR_ARRAY_PUSH(argv, const char *) = ""; + apr_array_cat(argv, args); + APR_ARRAY_PUSH(argv, const char *) = NULL; - apr_getopt_init(&os, pool, args->nelts + 1, argv); + apr_getopt_init(&os, pool, + argv->nelts - 1 /* Exclude trailing NULL */, + (const char *const *) argv->elts); /* Capture any error message from apr_getopt_long(). This will typically * say which option is wrong, which we would not otherwise know. */ @@ -1417,6 +1419,10 @@ typedef struct svn_diff__file_output_baton_t int context_size; + /* Cancel handler */ + svn_cancel_func_t cancel_func; + void *cancel_baton; + apr_pool_t *pool; } svn_diff__file_output_baton_t; @@ -1598,10 +1604,15 @@ static APR_INLINE svn_error_t * output_unified_diff_range(svn_diff__file_output_baton_t *output_baton, int source, svn_diff__file_output_unified_type_e type, - apr_off_t until) + apr_off_t until, + svn_cancel_func_t cancel_func, + void *cancel_baton) { while (output_baton->current_line[source] < until) { + if (cancel_func) + SVN_ERR(cancel_func(cancel_baton)); + SVN_ERR(output_unified_line(output_baton, type, source)); } return SVN_NO_ERROR; @@ -1627,7 +1638,8 @@ output_unified_flush_hunk(svn_diff__file_output_baton_t *baton) /* Add trailing context to the hunk */ SVN_ERR(output_unified_diff_range(baton, 0 /* original */, svn_diff__file_output_unified_context, - target_line)); + target_line, + baton->cancel_func, baton->cancel_baton)); old_start = baton->hunk_start[0]; new_start = baton->hunk_start[1]; @@ -1715,7 +1727,9 @@ output_unified_diff_modified(void *baton, /* Original: Output the context preceding the changed range */ SVN_ERR(output_unified_diff_range(output_baton, 0 /* original */, svn_diff__file_output_unified_context, - original_start)); + original_start, + output_baton->cancel_func, + output_baton->cancel_baton)); } } @@ -1723,7 +1737,9 @@ output_unified_diff_modified(void *baton, to display */ SVN_ERR(output_unified_diff_range(output_baton, 0 /* original */, svn_diff__file_output_unified_skip, - original_start - context_prefix_length)); + original_start - context_prefix_length, + output_baton->cancel_func, + output_baton->cancel_baton)); /* Note that the above skip stores data for the show_c_function support below */ @@ -1769,20 +1785,28 @@ output_unified_diff_modified(void *baton, /* Modified: Skip lines until we are at the start of the changed range */ SVN_ERR(output_unified_diff_range(output_baton, 1 /* modified */, svn_diff__file_output_unified_skip, - modified_start)); + modified_start, + output_baton->cancel_func, + output_baton->cancel_baton)); /* Original: Output the context preceding the changed range */ SVN_ERR(output_unified_diff_range(output_baton, 0 /* original */, svn_diff__file_output_unified_context, - original_start)); + original_start, + output_baton->cancel_func, + output_baton->cancel_baton)); /* Both: Output the changed range */ SVN_ERR(output_unified_diff_range(output_baton, 0 /* original */, svn_diff__file_output_unified_delete, - original_start + original_length)); + original_start + original_length, + output_baton->cancel_func, + output_baton->cancel_baton)); SVN_ERR(output_unified_diff_range(output_baton, 1 /* modified */, svn_diff__file_output_unified_insert, - modified_start + modified_length)); + modified_start + modified_length, + output_baton->cancel_func, + output_baton->cancel_baton)); return SVN_NO_ERROR; } @@ -1843,6 +1867,8 @@ svn_diff_file_output_unified4(svn_stream_t *output_stream, memset(&baton, 0, sizeof(baton)); baton.output_stream = output_stream; + baton.cancel_func = cancel_func; + baton.cancel_baton = cancel_baton; baton.pool = pool; baton.header_encoding = header_encoding; baton.path[0] = original_path; @@ -1956,7 +1982,7 @@ typedef struct context_saver_t { const char **data; /* const char *data[context_size] */ apr_size_t *len; /* apr_size_t len[context_size] */ apr_size_t next_slot; - apr_size_t total_written; + apr_ssize_t total_writes; } context_saver_t; @@ -1972,7 +1998,7 @@ context_saver_stream_write(void *baton, cs->data[cs->next_slot] = data; cs->len[cs->next_slot] = *len; cs->next_slot = (cs->next_slot + 1) % cs->context_size; - cs->total_written++; + cs->total_writes++; } return SVN_NO_ERROR; } @@ -2252,7 +2278,7 @@ output_conflict_with_context(svn_diff3__file_output_baton_t *btn, trailing context)? If so, flush it. */ if (btn->output_stream == btn->context_saver->stream) { - if (btn->context_saver->total_written > btn->context_size) + if (btn->context_saver->total_writes > btn->context_size) SVN_ERR(svn_stream_puts(btn->real_output_stream, "@@\n")); SVN_ERR(flush_context_saver(btn->context_saver, btn->real_output_stream)); } diff --git a/subversion/libsvn_diff/diff_memory.c b/subversion/libsvn_diff/diff_memory.c index d9d800d7162c..3a35e9d7e1e9 100644 --- a/subversion/libsvn_diff/diff_memory.c +++ b/subversion/libsvn_diff/diff_memory.c @@ -688,7 +688,7 @@ typedef struct context_saver_t { const char **data; /* const char *data[context_size] */ apr_size_t *len; /* apr_size_t len[context_size] */ apr_size_t next_slot; - apr_size_t total_written; + apr_ssize_t total_writes; } context_saver_t; @@ -701,7 +701,7 @@ context_saver_stream_write(void *baton, cs->data[cs->next_slot] = data; cs->len[cs->next_slot] = *len; cs->next_slot = (cs->next_slot + 1) % cs->context_size; - cs->total_written++; + cs->total_writes++; return SVN_NO_ERROR; } @@ -822,13 +822,11 @@ make_trailing_context_printer(merge_output_baton_t *btn) static svn_error_t * -output_merge_token_range(apr_size_t *lines_printed_p, - merge_output_baton_t *btn, +output_merge_token_range(merge_output_baton_t *btn, int idx, apr_off_t first, apr_off_t length) { apr_array_header_t *tokens = btn->sources[idx].tokens; - apr_size_t lines_printed = 0; for (; length > 0 && first < tokens->nelts; length--, first++) { @@ -838,12 +836,8 @@ output_merge_token_range(apr_size_t *lines_printed_p, /* Note that the trailing context printer assumes that svn_stream_write is called exactly once per line. */ SVN_ERR(svn_stream_write(btn->output_stream, token->data, &len)); - lines_printed++; } - if (lines_printed_p) - *lines_printed_p = lines_printed; - return SVN_NO_ERROR; } @@ -866,7 +860,7 @@ output_common_modified(void *baton, apr_off_t modified_start, apr_off_t modified_length, apr_off_t latest_start, apr_off_t latest_length) { - return output_merge_token_range(NULL, baton, 1/*modified*/, + return output_merge_token_range(baton, 1/*modified*/, modified_start, modified_length); } @@ -876,7 +870,7 @@ output_latest(void *baton, apr_off_t modified_start, apr_off_t modified_length, apr_off_t latest_start, apr_off_t latest_length) { - return output_merge_token_range(NULL, baton, 2/*latest*/, + return output_merge_token_range(baton, 2/*latest*/, latest_start, latest_length); } @@ -920,26 +914,26 @@ output_conflict(void *baton, style == svn_diff_conflict_display_modified_original_latest) { SVN_ERR(output_merge_marker(btn, 1/*modified*/)); - SVN_ERR(output_merge_token_range(NULL, btn, 1/*modified*/, + SVN_ERR(output_merge_token_range(btn, 1/*modified*/, modified_start, modified_length)); if (style == svn_diff_conflict_display_modified_original_latest) { SVN_ERR(output_merge_marker(btn, 0/*original*/)); - SVN_ERR(output_merge_token_range(NULL, btn, 0/*original*/, + SVN_ERR(output_merge_token_range(btn, 0/*original*/, original_start, original_length)); } SVN_ERR(output_merge_marker(btn, 2/*separator*/)); - SVN_ERR(output_merge_token_range(NULL, btn, 2/*latest*/, + SVN_ERR(output_merge_token_range(btn, 2/*latest*/, latest_start, latest_length)); SVN_ERR(output_merge_marker(btn, 3/*latest (end)*/)); } else if (style == svn_diff_conflict_display_modified) - SVN_ERR(output_merge_token_range(NULL, btn, 1/*modified*/, + SVN_ERR(output_merge_token_range(btn, 1/*modified*/, modified_start, modified_length)); else if (style == svn_diff_conflict_display_latest) - SVN_ERR(output_merge_token_range(NULL, btn, 2/*latest*/, + SVN_ERR(output_merge_token_range(btn, 2/*latest*/, latest_start, latest_length)); else /* unknown style */ SVN_ERR_MALFUNCTION(); @@ -983,7 +977,7 @@ output_conflict_with_context(void *baton, trailing context)? If so, flush it. */ if (btn->output_stream == btn->context_saver->stream) { - if (btn->context_saver->total_written > btn->context_size) + if (btn->context_saver->total_writes > btn->context_size) SVN_ERR(svn_stream_puts(btn->real_output_stream, "@@\n")); SVN_ERR(flush_context_saver(btn->context_saver, btn->real_output_stream)); } @@ -995,17 +989,17 @@ output_conflict_with_context(void *baton, SVN_ERR(output_conflict_with_context_marker(btn, btn->markers[1], modified_start, modified_length)); - SVN_ERR(output_merge_token_range(NULL, btn, 1/*modified*/, + SVN_ERR(output_merge_token_range(btn, 1/*modified*/, modified_start, modified_length)); SVN_ERR(output_conflict_with_context_marker(btn, btn->markers[0], original_start, original_length)); - SVN_ERR(output_merge_token_range(NULL, btn, 0/*original*/, + SVN_ERR(output_merge_token_range(btn, 0/*original*/, original_start, original_length)); SVN_ERR(output_merge_marker(btn, 2/*separator*/)); - SVN_ERR(output_merge_token_range(NULL, btn, 2/*latest*/, + SVN_ERR(output_merge_token_range(btn, 2/*latest*/, latest_start, latest_length)); SVN_ERR(output_conflict_with_context_marker(btn, btn->markers[3], latest_start, diff --git a/subversion/libsvn_diff/parse-diff.c b/subversion/libsvn_diff/parse-diff.c index 3f794b8b1fa7..f2159694c4f6 100644 --- a/subversion/libsvn_diff/parse-diff.c +++ b/subversion/libsvn_diff/parse-diff.c @@ -40,8 +40,13 @@ #include "private/svn_eol_private.h" #include "private/svn_dep_compat.h" +#include "private/svn_diff_private.h" #include "private/svn_sorts_private.h" +#include "diff.h" + +#include "svn_private_config.h" + /* Helper macro for readability */ #define starts_with(str, start) \ (strncmp((str), (start), strlen(start)) == 0) @@ -59,7 +64,7 @@ struct svn_diff__hunk_range { struct svn_diff_hunk_t { /* The patch this hunk belongs to. */ - svn_patch_t *patch; + const svn_patch_t *patch; /* APR file handle to the patch file this hunk came from. */ apr_file_t *apr_file; @@ -80,8 +85,150 @@ struct svn_diff_hunk_t { /* Number of lines of leading and trailing hunk context. */ svn_linenum_t leading_context; svn_linenum_t trailing_context; + + /* Did we see a 'file does not end with eol' marker in this hunk? */ + svn_boolean_t original_no_final_eol; + svn_boolean_t modified_no_final_eol; + + /* Fuzz penalty, triggered by bad patch targets */ + svn_linenum_t original_fuzz; + svn_linenum_t modified_fuzz; }; +struct svn_diff_binary_patch_t { + /* The patch this hunk belongs to. */ + const svn_patch_t *patch; + + /* APR file handle to the patch file this hunk came from. */ + apr_file_t *apr_file; + + /* Offsets inside APR_FILE representing the location of the patch */ + apr_off_t src_start; + apr_off_t src_end; + svn_filesize_t src_filesize; /* Expanded/final size */ + + /* Offsets inside APR_FILE representing the location of the patch */ + apr_off_t dst_start; + apr_off_t dst_end; + svn_filesize_t dst_filesize; /* Expanded/final size */ +}; + +/* Common guts of svn_diff_hunk__create_adds_single_line() and + * svn_diff_hunk__create_deletes_single_line(). + * + * ADD is TRUE if adding and FALSE if deleting. + */ +static svn_error_t * +add_or_delete_single_line(svn_diff_hunk_t **hunk_out, + const char *line, + const svn_patch_t *patch, + svn_boolean_t add, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_diff_hunk_t *hunk = apr_pcalloc(result_pool, sizeof(*hunk)); + static const char *hunk_header[] = { "@@ -1 +0,0 @@\n", "@@ -0,0 +1 @@\n" }; + const apr_size_t header_len = strlen(hunk_header[add]); + const apr_size_t len = strlen(line); + const apr_size_t end = header_len + (1 + len); /* The +1 is for the \n. */ + svn_stringbuf_t *buf = svn_stringbuf_create_ensure(end + 1, scratch_pool); + + hunk->patch = patch; + + /* hunk->apr_file is created below. */ + + hunk->diff_text_range.start = header_len; + hunk->diff_text_range.current = header_len; + + if (add) + { + hunk->original_text_range.start = 0; /* There's no "original" text. */ + hunk->original_text_range.current = 0; + hunk->original_text_range.end = 0; + hunk->original_no_final_eol = FALSE; + + hunk->modified_text_range.start = header_len; + hunk->modified_text_range.current = header_len; + hunk->modified_text_range.end = end; + hunk->modified_no_final_eol = TRUE; + + hunk->original_start = 0; + hunk->original_length = 0; + + hunk->modified_start = 1; + hunk->modified_length = 1; + } + else /* delete */ + { + hunk->original_text_range.start = header_len; + hunk->original_text_range.current = header_len; + hunk->original_text_range.end = end; + hunk->original_no_final_eol = TRUE; + + hunk->modified_text_range.start = 0; /* There's no "original" text. */ + hunk->modified_text_range.current = 0; + hunk->modified_text_range.end = 0; + hunk->modified_no_final_eol = FALSE; + + hunk->original_start = 1; + hunk->original_length = 1; + + hunk->modified_start = 0; + hunk->modified_length = 0; /* setting to '1' works too */ + } + + hunk->leading_context = 0; + hunk->trailing_context = 0; + + /* Create APR_FILE and put just a hunk in it (without a diff header). + * Save the offset of the last byte of the diff line. */ + svn_stringbuf_appendbytes(buf, hunk_header[add], header_len); + svn_stringbuf_appendbyte(buf, add ? '+' : '-'); + svn_stringbuf_appendbytes(buf, line, len); + svn_stringbuf_appendbyte(buf, '\n'); + svn_stringbuf_appendcstr(buf, "\\ No newline at end of hunk\n"); + + hunk->diff_text_range.end = buf->len; + + SVN_ERR(svn_io_open_unique_file3(&hunk->apr_file, NULL /* filename */, + NULL /* system tempdir */, + svn_io_file_del_on_pool_cleanup, + result_pool, scratch_pool)); + SVN_ERR(svn_io_file_write_full(hunk->apr_file, + buf->data, buf->len, + NULL, scratch_pool)); + /* No need to seek. */ + + *hunk_out = hunk; + return SVN_NO_ERROR; +} + +svn_error_t * +svn_diff_hunk__create_adds_single_line(svn_diff_hunk_t **hunk_out, + const char *line, + const svn_patch_t *patch, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + SVN_ERR(add_or_delete_single_line(hunk_out, line, patch, + (!patch->reverse), + result_pool, scratch_pool)); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_diff_hunk__create_deletes_single_line(svn_diff_hunk_t **hunk_out, + const char *line, + const svn_patch_t *patch, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + SVN_ERR(add_or_delete_single_line(hunk_out, line, patch, + patch->reverse, + result_pool, scratch_pool)); + return SVN_NO_ERROR; +} + void svn_diff_hunk_reset_diff_text(svn_diff_hunk_t *hunk) { @@ -142,6 +289,222 @@ svn_diff_hunk_get_trailing_context(const svn_diff_hunk_t *hunk) return hunk->trailing_context; } +svn_linenum_t +svn_diff_hunk__get_fuzz_penalty(const svn_diff_hunk_t *hunk) +{ + return hunk->patch->reverse ? hunk->original_fuzz : hunk->modified_fuzz; +} + +/* Baton for the base85 stream implementation */ +struct base85_baton_t +{ + apr_file_t *file; + apr_pool_t *iterpool; + char buffer[52]; /* Bytes on current line */ + apr_off_t next_pos; /* Start position of next line */ + apr_off_t end_pos; /* Position after last line */ + apr_size_t buf_size; /* Bytes available (52 unless at eof) */ + apr_size_t buf_pos; /* Bytes in linebuffer */ + svn_boolean_t done; /* At eof? */ +}; + +/* Implements svn_read_fn_t for the base85 read stream */ +static svn_error_t * +read_handler_base85(void *baton, char *buffer, apr_size_t *len) +{ + struct base85_baton_t *b85b = baton; + apr_pool_t *iterpool = b85b->iterpool; + apr_size_t remaining = *len; + char *dest = buffer; + + svn_pool_clear(iterpool); + + if (b85b->done) + { + *len = 0; + return SVN_NO_ERROR; + } + + while (remaining && (b85b->buf_size > b85b->buf_pos + || b85b->next_pos < b85b->end_pos)) + { + svn_stringbuf_t *line; + svn_boolean_t at_eof; + + apr_size_t available = b85b->buf_size - b85b->buf_pos; + if (available) + { + apr_size_t n = (remaining < available) ? remaining : available; + + memcpy(dest, b85b->buffer + b85b->buf_pos, n); + dest += n; + remaining -= n; + b85b->buf_pos += n; + + if (!remaining) + return SVN_NO_ERROR; /* *len = OK */ + } + + if (b85b->next_pos >= b85b->end_pos) + break; /* At EOF */ + SVN_ERR(svn_io_file_seek(b85b->file, APR_SET, &b85b->next_pos, + iterpool)); + SVN_ERR(svn_io_file_readline(b85b->file, &line, NULL, &at_eof, + APR_SIZE_MAX, iterpool, iterpool)); + if (at_eof) + b85b->next_pos = b85b->end_pos; + else + { + SVN_ERR(svn_io_file_get_offset(&b85b->next_pos, b85b->file, + iterpool)); + } + + if (line->len && line->data[0] >= 'A' && line->data[0] <= 'Z') + b85b->buf_size = line->data[0] - 'A' + 1; + else if (line->len && line->data[0] >= 'a' && line->data[0] <= 'z') + b85b->buf_size = line->data[0] - 'a' + 26 + 1; + else + return svn_error_create(SVN_ERR_DIFF_UNEXPECTED_DATA, NULL, + _("Unexpected data in base85 section")); + + if (b85b->buf_size < 52) + b85b->next_pos = b85b->end_pos; /* Handle as EOF */ + + SVN_ERR(svn_diff__base85_decode_line(b85b->buffer, b85b->buf_size, + line->data + 1, line->len - 1, + iterpool)); + b85b->buf_pos = 0; + } + + *len -= remaining; + b85b->done = TRUE; + + return SVN_NO_ERROR; +} + +/* Implements svn_close_fn_t for the base85 read stream */ +static svn_error_t * +close_handler_base85(void *baton) +{ + struct base85_baton_t *b85b = baton; + + svn_pool_destroy(b85b->iterpool); + + return SVN_NO_ERROR; +} + +/* Gets a stream that reads decoded base85 data from a segment of a file. + The current implementation might assume that both start_pos and end_pos + are located at line boundaries. */ +static svn_stream_t * +get_base85_data_stream(apr_file_t *file, + apr_off_t start_pos, + apr_off_t end_pos, + apr_pool_t *result_pool) +{ + struct base85_baton_t *b85b = apr_pcalloc(result_pool, sizeof(*b85b)); + svn_stream_t *base85s = svn_stream_create(b85b, result_pool); + + b85b->file = file; + b85b->iterpool = svn_pool_create(result_pool); + b85b->next_pos = start_pos; + b85b->end_pos = end_pos; + + svn_stream_set_read2(base85s, NULL /* only full read support */, + read_handler_base85); + svn_stream_set_close(base85s, close_handler_base85); + return base85s; +} + +/* Baton for the length verification stream functions */ +struct length_verify_baton_t +{ + svn_stream_t *inner; + svn_filesize_t remaining; +}; + +/* Implements svn_read_fn_t for the length verification stream */ +static svn_error_t * +read_handler_length_verify(void *baton, char *buffer, apr_size_t *len) +{ + struct length_verify_baton_t *lvb = baton; + apr_size_t requested_len = *len; + + SVN_ERR(svn_stream_read_full(lvb->inner, buffer, len)); + + if (*len > lvb->remaining) + return svn_error_create(SVN_ERR_DIFF_UNEXPECTED_DATA, NULL, + _("Base85 data expands to longer than declared " + "filesize")); + else if (requested_len > *len && *len != lvb->remaining) + return svn_error_create(SVN_ERR_DIFF_UNEXPECTED_DATA, NULL, + _("Base85 data expands to smaller than declared " + "filesize")); + + lvb->remaining -= *len; + + return SVN_NO_ERROR; +} + +/* Implements svn_close_fn_t for the length verification stream */ +static svn_error_t * +close_handler_length_verify(void *baton) +{ + struct length_verify_baton_t *lvb = baton; + + return svn_error_trace(svn_stream_close(lvb->inner)); +} + +/* Gets a stream that verifies on reads that the inner stream is exactly + of the specified length */ +static svn_stream_t * +get_verify_length_stream(svn_stream_t *inner, + svn_filesize_t expected_size, + apr_pool_t *result_pool) +{ + struct length_verify_baton_t *lvb = apr_palloc(result_pool, sizeof(*lvb)); + svn_stream_t *len_stream = svn_stream_create(lvb, result_pool); + + lvb->inner = inner; + lvb->remaining = expected_size; + + svn_stream_set_read2(len_stream, NULL /* only full read support */, + read_handler_length_verify); + svn_stream_set_close(len_stream, close_handler_length_verify); + + return len_stream; +} + +svn_stream_t * +svn_diff_get_binary_diff_original_stream(const svn_diff_binary_patch_t *bpatch, + apr_pool_t *result_pool) +{ + svn_stream_t *s = get_base85_data_stream(bpatch->apr_file, bpatch->src_start, + bpatch->src_end, result_pool); + + s = svn_stream_compressed(s, result_pool); + + /* ### If we (ever) want to support the DELTA format, then we should hook the + undelta handling here */ + + return get_verify_length_stream(s, bpatch->src_filesize, result_pool); +} + +svn_stream_t * +svn_diff_get_binary_diff_result_stream(const svn_diff_binary_patch_t *bpatch, + apr_pool_t *result_pool) +{ + svn_stream_t *s = get_base85_data_stream(bpatch->apr_file, bpatch->dst_start, + bpatch->dst_end, result_pool); + + s = svn_stream_compressed(s, result_pool); + + /* ### If we (ever) want to support the DELTA format, then we should hook the + undelta handling here */ + + return get_verify_length_stream(s, bpatch->dst_filesize, result_pool); +} + /* Try to parse a positive number from a decimal number encoded * in the string NUMBER. Return parsed number in OFFSET, and return * TRUE if parsing was successful. */ @@ -279,7 +642,8 @@ parse_hunk_header(const char *header, svn_diff_hunk_t *hunk, * Leading unidiff symbols ('+', '-', and ' ') are removed from the line, * Any lines commencing with the VERBOTEN character are discarded. * VERBOTEN should be '+' or '-', depending on which form of hunk text - * is being read. + * is being read. NO_FINAL_EOL declares if the hunk contains a no final + * EOL marker. * * All other parameters are as in svn_diff_hunk_readline_original_text() * and svn_diff_hunk_readline_modified_text(). @@ -291,6 +655,7 @@ hunk_readline_original_or_modified(apr_file_t *file, const char **eol, svn_boolean_t *eof, char verboten, + svn_boolean_t no_final_eol, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { @@ -298,27 +663,35 @@ hunk_readline_original_or_modified(apr_file_t *file, svn_boolean_t filtered; apr_off_t pos; svn_stringbuf_t *str; + const char *eol_p; + apr_pool_t *last_pool; + + if (!eol) + eol = &eol_p; if (range->current >= range->end) { /* We're past the range. Indicate that no bytes can be read. */ *eof = TRUE; - if (eol) - *eol = NULL; + *eol = NULL; *stringbuf = svn_stringbuf_create_empty(result_pool); return SVN_NO_ERROR; } - pos = 0; - SVN_ERR(svn_io_file_seek(file, APR_CUR, &pos, scratch_pool)); + SVN_ERR(svn_io_file_get_offset(&pos, file, scratch_pool)); SVN_ERR(svn_io_file_seek(file, APR_SET, &range->current, scratch_pool)); + + /* It's not ITERPOOL because we use data allocated in LAST_POOL out + of the loop. */ + last_pool = svn_pool_create(scratch_pool); do { + svn_pool_clear(last_pool); + max_len = range->end - range->current; SVN_ERR(svn_io_file_readline(file, &str, eol, eof, max_len, - result_pool, scratch_pool)); - range->current = 0; - SVN_ERR(svn_io_file_seek(file, APR_CUR, &range->current, scratch_pool)); + last_pool, last_pool)); + SVN_ERR(svn_io_file_get_offset(&range->current, file, last_pool)); filtered = (str->data[0] == verboten || str->data[0] == '\\'); } while (filtered && ! *eof); @@ -327,6 +700,7 @@ hunk_readline_original_or_modified(apr_file_t *file, { /* EOF, return an empty string. */ *stringbuf = svn_stringbuf_create_ensure(0, result_pool); + *eol = NULL; } else if (str->data[0] == '+' || str->data[0] == '-' || str->data[0] == ' ') { @@ -335,12 +709,37 @@ hunk_readline_original_or_modified(apr_file_t *file, } else { - /* Return the line as-is. */ + /* Return the line as-is. Handle as a chopped leading spaces */ *stringbuf = svn_stringbuf_dup(str, result_pool); } + if (!filtered && *eof && !*eol && *str->data) + { + /* Ok, we miss a final EOL in the patch file, but didn't see a + no eol marker line. + + We should report that we had an EOL or the patch code will + misbehave (and it knows nothing about no eol markers) */ + + if (!no_final_eol && eol != &eol_p) + { + apr_off_t start = 0; + + SVN_ERR(svn_io_file_seek(file, APR_SET, &start, scratch_pool)); + + SVN_ERR(svn_io_file_readline(file, &str, eol, NULL, APR_SIZE_MAX, + scratch_pool, scratch_pool)); + + /* Every patch file that has hunks has at least one EOL*/ + SVN_ERR_ASSERT(*eol != NULL); + } + + *eof = FALSE; + /* Fall through to seek back to the right location */ + } SVN_ERR(svn_io_file_seek(file, APR_SET, &pos, scratch_pool)); + svn_pool_destroy(last_pool); return SVN_NO_ERROR; } @@ -359,6 +758,9 @@ svn_diff_hunk_readline_original_text(svn_diff_hunk_t *hunk, &hunk->original_text_range, stringbuf, eol, eof, hunk->patch->reverse ? '-' : '+', + hunk->patch->reverse + ? hunk->modified_no_final_eol + : hunk->original_no_final_eol, result_pool, scratch_pool)); } @@ -377,6 +779,9 @@ svn_diff_hunk_readline_modified_text(svn_diff_hunk_t *hunk, &hunk->modified_text_range, stringbuf, eol, eof, hunk->patch->reverse ? '+' : '-', + hunk->patch->reverse + ? hunk->original_no_final_eol + : hunk->modified_no_final_eol, result_pool, scratch_pool)); } @@ -391,28 +796,60 @@ svn_diff_hunk_readline_diff_text(svn_diff_hunk_t *hunk, svn_stringbuf_t *line; apr_size_t max_len; apr_off_t pos; + const char *eol_p; + + if (!eol) + eol = &eol_p; if (hunk->diff_text_range.current >= hunk->diff_text_range.end) { /* We're past the range. Indicate that no bytes can be read. */ *eof = TRUE; - if (eol) - *eol = NULL; + *eol = NULL; *stringbuf = svn_stringbuf_create_empty(result_pool); return SVN_NO_ERROR; } - pos = 0; - SVN_ERR(svn_io_file_seek(hunk->apr_file, APR_CUR, &pos, scratch_pool)); + SVN_ERR(svn_io_file_get_offset(&pos, hunk->apr_file, scratch_pool)); SVN_ERR(svn_io_file_seek(hunk->apr_file, APR_SET, &hunk->diff_text_range.current, scratch_pool)); max_len = hunk->diff_text_range.end - hunk->diff_text_range.current; SVN_ERR(svn_io_file_readline(hunk->apr_file, &line, eol, eof, max_len, result_pool, scratch_pool)); - hunk->diff_text_range.current = 0; - SVN_ERR(svn_io_file_seek(hunk->apr_file, APR_CUR, - &hunk->diff_text_range.current, scratch_pool)); + SVN_ERR(svn_io_file_get_offset(&hunk->diff_text_range.current, + hunk->apr_file, scratch_pool)); + + if (*eof && !*eol && *line->data) + { + /* Ok, we miss a final EOL in the patch file, but didn't see a + no eol marker line. + + We should report that we had an EOL or the patch code will + misbehave (and it knows nothing about no eol markers) */ + + if (eol != &eol_p) + { + /* Lets pick the first eol we find in our patch file */ + apr_off_t start = 0; + svn_stringbuf_t *str; + + SVN_ERR(svn_io_file_seek(hunk->apr_file, APR_SET, &start, + scratch_pool)); + + SVN_ERR(svn_io_file_readline(hunk->apr_file, &str, eol, NULL, + APR_SIZE_MAX, + scratch_pool, scratch_pool)); + + /* Every patch file that has hunks has at least one EOL*/ + SVN_ERR_ASSERT(*eol != NULL); + } + + *eof = FALSE; + + /* Fall through to seek back to the right location */ + } + SVN_ERR(svn_io_file_seek(hunk->apr_file, APR_SET, &pos, scratch_pool)); if (hunk->patch->reverse) @@ -619,6 +1056,8 @@ parse_next_hunk(svn_diff_hunk_t **hunk, apr_off_t start, end; apr_off_t original_end; apr_off_t modified_end; + svn_boolean_t original_no_final_eol = FALSE; + svn_boolean_t modified_no_final_eol = FALSE; svn_linenum_t original_lines; svn_linenum_t modified_lines; svn_linenum_t leading_context; @@ -654,9 +1093,8 @@ parse_next_hunk(svn_diff_hunk_t **hunk, modified_end = 0; *hunk = apr_pcalloc(result_pool, sizeof(**hunk)); - /* Get current seek position -- APR has no ftell() :( */ - pos = 0; - SVN_ERR(svn_io_file_seek(apr_file, APR_CUR, &pos, scratch_pool)); + /* Get current seek position. */ + SVN_ERR(svn_io_file_get_offset(&pos, apr_file, scratch_pool)); /* Start out assuming noise. */ last_line_type = noise_line; @@ -673,8 +1111,7 @@ parse_next_hunk(svn_diff_hunk_t **hunk, iterpool, iterpool)); /* Update line offset for next iteration. */ - pos = 0; - SVN_ERR(svn_io_file_seek(apr_file, APR_CUR, &pos, iterpool)); + SVN_ERR(svn_io_file_get_offset(&pos, apr_file, iterpool)); /* Lines starting with a backslash indicate a missing EOL: * "\ No newline at end of file" or "end of property". */ @@ -715,6 +1152,11 @@ parse_next_hunk(svn_diff_hunk_t **hunk, } SVN_ERR(svn_io_file_seek(apr_file, APR_SET, &pos, iterpool)); + /* Set for the type and context by using != the other type */ + if (last_line_type != modified_line) + original_no_final_eol = TRUE; + if (last_line_type != original_line) + modified_no_final_eol = TRUE; } continue; @@ -728,7 +1170,13 @@ parse_next_hunk(svn_diff_hunk_t **hunk, SVN_ERR(parse_mergeinfo(&found_mergeinfo, line, *hunk, patch, result_pool, iterpool)); if (found_mergeinfo) - continue; /* Proceed to the next line in the patch. */ + continue; /* Proceed to the next line in the svn:mergeinfo hunk. */ + else + { + /* Perhaps we can also use original_lines/modified_lines here */ + + in_hunk = FALSE; /* On to next property */ + } } if (in_hunk) @@ -745,24 +1193,38 @@ parse_next_hunk(svn_diff_hunk_t **hunk, } c = line->data[0]; - if (original_lines > 0 && modified_lines > 0 && - ((c == ' ') + if (c == ' ' + || ((original_lines > 0 && modified_lines > 0) + && ( /* Tolerate chopped leading spaces on empty lines. */ - || (! eof && line->len == 0) + (! eof && line->len == 0) /* Maybe tolerate chopped leading spaces on non-empty lines. */ - || (ignore_whitespace && c != del && c != add))) + || (ignore_whitespace && c != del && c != add)))) { /* It's a "context" line in the hunk. */ hunk_seen = TRUE; - original_lines--; - modified_lines--; + if (original_lines > 0) + original_lines--; + else + { + (*hunk)->original_length++; + (*hunk)->original_fuzz++; + } + if (modified_lines > 0) + modified_lines--; + else + { + (*hunk)->modified_length++; + (*hunk)->modified_fuzz++; + } if (changed_line_seen) trailing_context++; else leading_context++; last_line_type = context_line; } - else if (original_lines > 0 && c == del) + else if (c == del + && (original_lines > 0 || line->data[1] != del)) { /* It's a "deleted" line in the hunk. */ hunk_seen = TRUE; @@ -773,10 +1235,17 @@ parse_next_hunk(svn_diff_hunk_t **hunk, if (trailing_context > 0) trailing_context = 0; - original_lines--; + if (original_lines > 0) + original_lines--; + else + { + (*hunk)->original_length++; + (*hunk)->original_fuzz++; + } last_line_type = original_line; } - else if (modified_lines > 0 && c == add) + else if (c == add + && (modified_lines > 0 || line->data[1] != add)) { /* It's an "added" line in the hunk. */ hunk_seen = TRUE; @@ -787,7 +1256,13 @@ parse_next_hunk(svn_diff_hunk_t **hunk, if (trailing_context > 0) trailing_context = 0; - modified_lines--; + if (modified_lines > 0) + modified_lines--; + else + { + (*hunk)->modified_length++; + (*hunk)->modified_fuzz++; + } last_line_type = modified_line; } else @@ -803,7 +1278,6 @@ parse_next_hunk(svn_diff_hunk_t **hunk, * after the hunk text. */ end = last_line; } - if (original_end == 0) original_end = end; if (modified_end == 0) @@ -843,14 +1317,16 @@ parse_next_hunk(svn_diff_hunk_t **hunk, SVN_ERR(parse_prop_name(prop_name, line->data, "Added: ", result_pool)); if (*prop_name) - *prop_operation = svn_diff_op_added; + *prop_operation = (patch->reverse ? svn_diff_op_deleted + : svn_diff_op_added); } else if (starts_with(line->data, "Deleted: ")) { SVN_ERR(parse_prop_name(prop_name, line->data, "Deleted: ", result_pool)); if (*prop_name) - *prop_operation = svn_diff_op_deleted; + *prop_operation = (patch->reverse ? svn_diff_op_added + : svn_diff_op_deleted); } else if (starts_with(line->data, "Modified: ")) { @@ -878,6 +1354,21 @@ parse_next_hunk(svn_diff_hunk_t **hunk, if (hunk_seen && start < end) { + /* Did we get the number of context lines announced in the header? + + If not... let's limit the number from the header to what we + actually have, and apply a fuzz penalty */ + if (original_lines) + { + (*hunk)->original_length -= original_lines; + (*hunk)->original_fuzz += original_lines; + } + if (modified_lines) + { + (*hunk)->modified_length -= modified_lines; + (*hunk)->modified_fuzz += modified_lines; + } + (*hunk)->patch = patch; (*hunk)->apr_file = apr_file; (*hunk)->leading_context = leading_context; @@ -891,6 +1382,8 @@ parse_next_hunk(svn_diff_hunk_t **hunk, (*hunk)->modified_text_range.start = start; (*hunk)->modified_text_range.current = start; (*hunk)->modified_text_range.end = modified_end; + (*hunk)->original_no_final_eol = original_no_final_eol; + (*hunk)->modified_no_final_eol = modified_no_final_eol; } else /* Something went wrong, just discard the result. */ @@ -917,16 +1410,19 @@ compare_hunks(const void *a, const void *b) /* Possible states of the diff header parser. */ enum parse_state { - state_start, /* initial */ - state_git_diff_seen, /* diff --git */ - state_git_tree_seen, /* a tree operation, rather then content change */ - state_git_minus_seen, /* --- /dev/null; or --- a/ */ - state_git_plus_seen, /* +++ /dev/null; or +++ a/ */ - state_move_from_seen, /* rename from foo.c */ - state_copy_from_seen, /* copy from foo.c */ - state_minus_seen, /* --- foo.c */ - state_unidiff_found, /* valid start of a regular unidiff header */ - state_git_header_found /* valid start of a --git diff header */ + state_start, /* initial */ + state_git_diff_seen, /* diff --git */ + state_git_tree_seen, /* a tree operation, rather than content change */ + state_git_minus_seen, /* --- /dev/null; or --- a/ */ + state_git_plus_seen, /* +++ /dev/null; or +++ a/ */ + state_old_mode_seen, /* old mode 100644 */ + state_git_mode_seen, /* new mode 100644 */ + state_move_from_seen, /* rename from foo.c */ + state_copy_from_seen, /* copy from foo.c */ + state_minus_seen, /* --- foo.c */ + state_unidiff_found, /* valid start of a regular unidiff header */ + state_git_header_found, /* valid start of a --git diff header */ + state_binary_patch_found /* valid start of binary patch */ }; /* Data type describing a valid state transition of the parser. */ @@ -1153,6 +1649,139 @@ git_plus(enum parse_state *new_state, char *line, svn_patch_t *patch, return SVN_NO_ERROR; } +/* Helper for git_old_mode() and git_new_mode(). Translate the git + * file mode MODE_STR into a binary "executable?" and "symlink?" state. */ +static svn_error_t * +parse_git_mode_bits(svn_tristate_t *executable_p, + svn_tristate_t *symlink_p, + const char *mode_str) +{ + apr_uint64_t mode; + SVN_ERR(svn_cstring_strtoui64(&mode, mode_str, + 0 /* min */, + 0777777 /* max: six octal digits */, + 010 /* radix (octal) */)); + + /* Note: 0644 and 0755 are the only modes that can occur for plain files. + * We deliberately choose to parse only those values: we are strict in what + * we accept _and_ in what we produce. + * + * (Having said that, though, we could consider relaxing the parser to also + * map + * (mode & 0111) == 0000 -> svn_tristate_false + * (mode & 0111) == 0111 -> svn_tristate_true + * [anything else] -> svn_tristate_unknown + * .) + */ + + switch (mode & 0777) + { + case 0644: + *executable_p = svn_tristate_false; + break; + + case 0755: + *executable_p = svn_tristate_true; + break; + + default: + /* Ignore unknown values. */ + *executable_p = svn_tristate_unknown; + break; + } + + switch (mode & 0170000 /* S_IFMT */) + { + case 0120000: /* S_IFLNK */ + *symlink_p = svn_tristate_true; + break; + + case 0100000: /* S_IFREG */ + case 0040000: /* S_IFDIR */ + *symlink_p = svn_tristate_false; + break; + + default: + /* Ignore unknown values. + (Including those generated by Subversion <= 1.9) */ + *symlink_p = svn_tristate_unknown; + break; + } + + return SVN_NO_ERROR; +} + +/* Parse the 'old mode ' line of a git extended unidiff. */ +static svn_error_t * +git_old_mode(enum parse_state *new_state, char *line, svn_patch_t *patch, + apr_pool_t *result_pool, apr_pool_t *scratch_pool) +{ + SVN_ERR(parse_git_mode_bits(&patch->old_executable_bit, + &patch->old_symlink_bit, + line + STRLEN_LITERAL("old mode "))); + +#ifdef SVN_DEBUG + /* If this assert trips, the "old mode" is neither ...644 nor ...755 . */ + SVN_ERR_ASSERT(patch->old_executable_bit != svn_tristate_unknown); +#endif + + *new_state = state_old_mode_seen; + return SVN_NO_ERROR; +} + +/* Parse the 'new mode ' line of a git extended unidiff. */ +static svn_error_t * +git_new_mode(enum parse_state *new_state, char *line, svn_patch_t *patch, + apr_pool_t *result_pool, apr_pool_t *scratch_pool) +{ + SVN_ERR(parse_git_mode_bits(&patch->new_executable_bit, + &patch->new_symlink_bit, + line + STRLEN_LITERAL("new mode "))); + +#ifdef SVN_DEBUG + /* If this assert trips, the "old mode" is neither ...644 nor ...755 . */ + SVN_ERR_ASSERT(patch->new_executable_bit != svn_tristate_unknown); +#endif + + /* Don't touch patch->operation. */ + + *new_state = state_git_mode_seen; + return SVN_NO_ERROR; +} + +static svn_error_t * +git_index(enum parse_state *new_state, char *line, svn_patch_t *patch, + apr_pool_t *result_pool, apr_pool_t *scratch_pool) +{ + /* We either have something like "index 33e5b38..0000000" (which we just + ignore as we are not interested in git specific shas) or something like + "index 33e5b38..0000000 120000" which tells us the mode, that isn't + changed by applying this patch. + + If the mode would have changed then we would see 'old mode' and 'new mode' + lines. + */ + line = strchr(line + STRLEN_LITERAL("index "), ' '); + + if (line && patch->new_executable_bit == svn_tristate_unknown + && patch->new_symlink_bit == svn_tristate_unknown + && patch->operation != svn_diff_op_added + && patch->operation != svn_diff_op_deleted) + { + SVN_ERR(parse_git_mode_bits(&patch->new_executable_bit, + &patch->new_symlink_bit, + line + 1)); + + /* There is no change.. so set the old values to the new values */ + patch->old_executable_bit = patch->new_executable_bit; + patch->old_symlink_bit = patch->new_symlink_bit; + } + + /* This function doesn't change the state! */ + /* *new_state = *new_state */ + return SVN_NO_ERROR; +} + /* Parse the 'rename from ' line of a git extended unidiff. */ static svn_error_t * git_move_from(enum parse_state *new_state, char *line, svn_patch_t *patch, @@ -1213,6 +1842,10 @@ static svn_error_t * git_new_file(enum parse_state *new_state, char *line, svn_patch_t *patch, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { + SVN_ERR(parse_git_mode_bits(&patch->new_executable_bit, + &patch->new_symlink_bit, + line + STRLEN_LITERAL("new file mode "))); + patch->operation = svn_diff_op_added; /* Filename already retrieved from diff --git header. */ @@ -1226,6 +1859,10 @@ static svn_error_t * git_deleted_file(enum parse_state *new_state, char *line, svn_patch_t *patch, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { + SVN_ERR(parse_git_mode_bits(&patch->old_executable_bit, + &patch->old_symlink_bit, + line + STRLEN_LITERAL("deleted file mode "))); + patch->operation = svn_diff_op_deleted; /* Filename already retrieved from diff --git header. */ @@ -1234,6 +1871,16 @@ git_deleted_file(enum parse_state *new_state, char *line, svn_patch_t *patch, return SVN_NO_ERROR; } +/* Parse the 'GIT binary patch' header */ +static svn_error_t * +binary_patch_start(enum parse_state *new_state, char *line, svn_patch_t *patch, + apr_pool_t *result_pool, apr_pool_t *scratch_pool) +{ + *new_state = state_binary_patch_found; + return SVN_NO_ERROR; +} + + /* Add a HUNK associated with the property PROP_NAME to PATCH. */ static svn_error_t * add_property_hunk(svn_patch_t *patch, const char *prop_name, @@ -1346,24 +1993,163 @@ parse_hunks(svn_patch_t *patch, apr_file_t *apr_file, return SVN_NO_ERROR; } +static svn_error_t * +parse_binary_patch(svn_patch_t *patch, apr_file_t *apr_file, + svn_boolean_t reverse, + apr_pool_t *result_pool, apr_pool_t *scratch_pool) +{ + apr_pool_t *iterpool = svn_pool_create(scratch_pool); + apr_off_t pos, last_line; + svn_stringbuf_t *line; + svn_boolean_t eof = FALSE; + svn_diff_binary_patch_t *bpatch = apr_pcalloc(result_pool, sizeof(*bpatch)); + svn_boolean_t in_blob = FALSE; + svn_boolean_t in_src = FALSE; + + bpatch->apr_file = apr_file; + + patch->prop_patches = apr_hash_make(result_pool); + + SVN_ERR(svn_io_file_get_offset(&pos, apr_file, scratch_pool)); + + while (!eof) + { + last_line = pos; + SVN_ERR(svn_io_file_readline(apr_file, &line, NULL, &eof, APR_SIZE_MAX, + iterpool, iterpool)); + + /* Update line offset for next iteration. */ + SVN_ERR(svn_io_file_get_offset(&pos, apr_file, iterpool)); + + if (in_blob) + { + char c = line->data[0]; + + /* 66 = len byte + (52/4*5) chars */ + if (((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) + && line->len <= 66 + && !strchr(line->data, ':') + && !strchr(line->data, ' ')) + { + /* One more blop line */ + if (in_src) + bpatch->src_end = pos; + else + bpatch->dst_end = pos; + } + else if (svn_stringbuf_first_non_whitespace(line) < line->len + && !(in_src && bpatch->src_start < last_line)) + { + break; /* Bad patch */ + } + else if (in_src) + { + patch->binary_patch = bpatch; /* SUCCESS! */ + break; + } + else + { + in_blob = FALSE; + in_src = TRUE; + } + } + else if (starts_with(line->data, "literal ")) + { + apr_uint64_t expanded_size; + svn_error_t *err = svn_cstring_strtoui64(&expanded_size, + &line->data[8], + 0, APR_UINT64_MAX, 10); + + if (err) + { + svn_error_clear(err); + break; + } + + if (in_src) + { + bpatch->src_start = pos; + bpatch->src_filesize = expanded_size; + } + else + { + bpatch->dst_start = pos; + bpatch->dst_filesize = expanded_size; + } + in_blob = TRUE; + } + else + break; /* We don't support GIT deltas (yet) */ + } + svn_pool_destroy(iterpool); + + if (!eof) + /* Rewind to the start of the line just read, so subsequent calls + * don't end up skipping the line. It may contain a patch or hunk header.*/ + SVN_ERR(svn_io_file_seek(apr_file, APR_SET, &last_line, scratch_pool)); + else if (in_src + && ((bpatch->src_end > bpatch->src_start) || !bpatch->src_filesize)) + { + patch->binary_patch = bpatch; /* SUCCESS */ + } + + /* Reverse patch if requested */ + if (reverse && patch->binary_patch) + { + apr_off_t tmp_start = bpatch->src_start; + apr_off_t tmp_end = bpatch->src_end; + svn_filesize_t tmp_filesize = bpatch->src_filesize; + + bpatch->src_start = bpatch->dst_start; + bpatch->src_end = bpatch->dst_end; + bpatch->src_filesize = bpatch->dst_filesize; + + bpatch->dst_start = tmp_start; + bpatch->dst_end = tmp_end; + bpatch->dst_filesize = tmp_filesize; + } + + return SVN_NO_ERROR; +} + /* State machine for the diff header parser. * Expected Input Required state Function to call */ static struct transition transitions[] = { - {"--- ", state_start, diff_minus}, - {"+++ ", state_minus_seen, diff_plus}, - {"diff --git", state_start, git_start}, - {"--- a/", state_git_diff_seen, git_minus}, - {"--- a/", state_git_tree_seen, git_minus}, - {"--- /dev/null", state_git_tree_seen, git_minus}, - {"+++ b/", state_git_minus_seen, git_plus}, - {"+++ /dev/null", state_git_minus_seen, git_plus}, - {"rename from ", state_git_diff_seen, git_move_from}, - {"rename to ", state_move_from_seen, git_move_to}, - {"copy from ", state_git_diff_seen, git_copy_from}, - {"copy to ", state_copy_from_seen, git_copy_to}, - {"new file ", state_git_diff_seen, git_new_file}, - {"deleted file ", state_git_diff_seen, git_deleted_file}, + {"--- ", state_start, diff_minus}, + {"+++ ", state_minus_seen, diff_plus}, + + {"diff --git", state_start, git_start}, + {"--- a/", state_git_diff_seen, git_minus}, + {"--- a/", state_git_mode_seen, git_minus}, + {"--- a/", state_git_tree_seen, git_minus}, + {"--- /dev/null", state_git_mode_seen, git_minus}, + {"--- /dev/null", state_git_tree_seen, git_minus}, + {"+++ b/", state_git_minus_seen, git_plus}, + {"+++ /dev/null", state_git_minus_seen, git_plus}, + + {"old mode ", state_git_diff_seen, git_old_mode}, + {"new mode ", state_old_mode_seen, git_new_mode}, + + {"rename from ", state_git_diff_seen, git_move_from}, + {"rename from ", state_git_mode_seen, git_move_from}, + {"rename to ", state_move_from_seen, git_move_to}, + + {"copy from ", state_git_diff_seen, git_copy_from}, + {"copy from ", state_git_mode_seen, git_copy_from}, + {"copy to ", state_copy_from_seen, git_copy_to}, + + {"new file ", state_git_diff_seen, git_new_file}, + + {"deleted file ", state_git_diff_seen, git_deleted_file}, + + {"index ", state_git_diff_seen, git_index}, + {"index ", state_git_tree_seen, git_index}, + {"index ", state_git_mode_seen, git_index}, + + {"GIT binary patch", state_git_diff_seen, binary_patch_start}, + {"GIT binary patch", state_git_tree_seen, binary_patch_start}, + {"GIT binary patch", state_git_mode_seen, binary_patch_start}, }; svn_error_t * @@ -1389,6 +2175,10 @@ svn_diff_parse_next_patch(svn_patch_t **patch_p, } patch = apr_pcalloc(result_pool, sizeof(*patch)); + patch->old_executable_bit = svn_tristate_unknown; + patch->new_executable_bit = svn_tristate_unknown; + patch->old_symlink_bit = svn_tristate_unknown; + patch->new_symlink_bit = svn_tristate_unknown; pos = patch_file->next_patch_offset; SVN_ERR(svn_io_file_seek(patch_file->apr_file, APR_SET, &pos, scratch_pool)); @@ -1410,9 +2200,8 @@ svn_diff_parse_next_patch(svn_patch_t **patch_p, if (! eof) { /* Update line offset for next iteration. */ - pos = 0; - SVN_ERR(svn_io_file_seek(patch_file->apr_file, APR_CUR, &pos, - iterpool)); + SVN_ERR(svn_io_file_get_offset(&pos, patch_file->apr_file, + iterpool)); } /* Run the state machine. */ @@ -1428,32 +2217,32 @@ svn_diff_parse_next_patch(svn_patch_t **patch_p, } } - if (state == state_unidiff_found || state == state_git_header_found) + if (state == state_unidiff_found + || state == state_git_header_found + || state == state_binary_patch_found) { /* We have a valid diff header, yay! */ break; } - else if (state == state_git_tree_seen && line_after_tree_header_read) + else if ((state == state_git_tree_seen || state == state_git_mode_seen) + && line_after_tree_header_read + && !valid_header_line) { - /* git patches can contain an index line after the file mode line */ - if (!starts_with(line->data, "index ")) - { - /* We have a valid diff header for a patch with only tree changes. - * Rewind to the start of the line just read, so subsequent calls - * to this function don't end up skipping the line -- it may - * contain a patch. */ - SVN_ERR(svn_io_file_seek(patch_file->apr_file, APR_SET, &last_line, - scratch_pool)); - break; - } + /* We have a valid diff header for a patch with only tree changes. + * Rewind to the start of the line just read, so subsequent calls + * to this function don't end up skipping the line -- it may + * contain a patch. */ + SVN_ERR(svn_io_file_seek(patch_file->apr_file, APR_SET, &last_line, + scratch_pool)); + break; } - else if (state == state_git_tree_seen) + else if (state == state_git_tree_seen + || state == state_git_mode_seen) { line_after_tree_header_read = TRUE; } else if (! valid_header_line && state != state_start - && state != state_git_diff_seen - && !starts_with(line->data, "index ")) + && state != state_git_diff_seen) { /* We've encountered an invalid diff header. * @@ -1471,9 +2260,38 @@ svn_diff_parse_next_patch(svn_patch_t **patch_p, if (reverse) { const char *temp; + svn_tristate_t ts_tmp; + temp = patch->old_filename; patch->old_filename = patch->new_filename; patch->new_filename = temp; + + switch (patch->operation) + { + case svn_diff_op_added: + patch->operation = svn_diff_op_deleted; + break; + case svn_diff_op_deleted: + patch->operation = svn_diff_op_added; + break; + + case svn_diff_op_modified: + break; /* Stays modified. */ + + case svn_diff_op_copied: + case svn_diff_op_moved: + break; /* Stays copied or moved, just in the other direction. */ + case svn_diff_op_unchanged: + break; /* Stays unchanged, of course. */ + } + + ts_tmp = patch->old_executable_bit; + patch->old_executable_bit = patch->new_executable_bit; + patch->new_executable_bit = ts_tmp; + + ts_tmp = patch->old_symlink_bit; + patch->old_symlink_bit = patch->new_symlink_bit; + patch->new_symlink_bit = ts_tmp; } if (patch->old_filename == NULL || patch->new_filename == NULL) @@ -1482,16 +2300,24 @@ svn_diff_parse_next_patch(svn_patch_t **patch_p, patch = NULL; } else - SVN_ERR(parse_hunks(patch, patch_file->apr_file, ignore_whitespace, - result_pool, iterpool)); + { + if (state == state_binary_patch_found) + { + SVN_ERR(parse_binary_patch(patch, patch_file->apr_file, reverse, + result_pool, iterpool)); + /* And fall through in property parsing */ + } + + SVN_ERR(parse_hunks(patch, patch_file->apr_file, ignore_whitespace, + result_pool, iterpool)); + } svn_pool_destroy(iterpool); - patch_file->next_patch_offset = 0; - SVN_ERR(svn_io_file_seek(patch_file->apr_file, APR_CUR, - &patch_file->next_patch_offset, scratch_pool)); + SVN_ERR(svn_io_file_get_offset(&patch_file->next_patch_offset, + patch_file->apr_file, scratch_pool)); - if (patch) + if (patch && patch->hunks) { /* Usually, hunks appear in the patch sorted by their original line * offset. But just in case they weren't parsed in this order for diff --git a/subversion/libsvn_fs/deprecated.c b/subversion/libsvn_fs/deprecated.c index 03045773f520..0e741c273c58 100644 --- a/subversion/libsvn_fs/deprecated.c +++ b/subversion/libsvn_fs/deprecated.c @@ -26,7 +26,9 @@ deprecated functions in this file. */ #define SVN_DEPRECATED +#include #include "svn_fs.h" +#include "private/svn_subr_private.h" /*** From fs-loader.c ***/ @@ -63,6 +65,28 @@ svn_fs_begin_txn(svn_fs_txn_t **txn_p, svn_fs_t *fs, svn_revnum_t rev, return svn_error_trace(svn_fs_begin_txn2(txn_p, fs, rev, 0, pool)); } +svn_error_t * +svn_fs_revision_prop(svn_string_t **value_p, + svn_fs_t *fs, + svn_revnum_t rev, + const char *propname, + apr_pool_t *pool) +{ + return svn_error_trace( + svn_fs_revision_prop2(value_p, fs, rev, propname, TRUE, pool, + pool)); +} + +svn_error_t * +svn_fs_revision_proplist(apr_hash_t **table_p, + svn_fs_t *fs, + svn_revnum_t rev, + apr_pool_t *pool) +{ + return svn_error_trace( + svn_fs_revision_proplist2(table_p, fs, rev, TRUE, pool, pool)); +} + svn_error_t * svn_fs_change_rev_prop(svn_fs_t *fs, svn_revnum_t rev, const char *name, const svn_string_t *value, apr_pool_t *pool) @@ -81,6 +105,139 @@ svn_fs_get_locks(svn_fs_t *fs, const char *path, pool)); } +svn_error_t * +svn_fs_create(svn_fs_t **fs_p, + const char *path, + apr_hash_t *fs_config, + apr_pool_t *pool) +{ + return svn_fs_create2(fs_p, path, fs_config, pool, pool); +} + +svn_error_t * +svn_fs_open(svn_fs_t **fs_p, + const char *path, + apr_hash_t *fs_config, + apr_pool_t *pool) +{ + return svn_fs_open2(fs_p, path, fs_config, pool, pool); +} + +svn_error_t * +svn_fs_node_history(svn_fs_history_t **history_p, svn_fs_root_t *root, + const char *path, apr_pool_t *pool) +{ + return svn_error_trace(svn_fs_node_history2(history_p, root, path, + pool, pool)); +} + +static svn_error_t * +mergeinfo_receiver(const char *path, + svn_mergeinfo_t mergeinfo, + void *baton, + apr_pool_t *scratch_pool) +{ + svn_mergeinfo_catalog_t catalog = baton; + apr_pool_t *result_pool = apr_hash_pool_get(catalog); + apr_size_t len = strlen(path); + + apr_hash_set(catalog, + apr_pstrmemdup(result_pool, path, len), + len, + svn_mergeinfo_dup(mergeinfo, result_pool)); + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_fs_get_mergeinfo2(svn_mergeinfo_catalog_t *catalog, + svn_fs_root_t *root, + const apr_array_header_t *paths, + svn_mergeinfo_inheritance_t inherit, + svn_boolean_t include_descendants, + svn_boolean_t adjust_inherited_mergeinfo, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_mergeinfo_catalog_t result_catalog = svn_hash__make(result_pool); + SVN_ERR(svn_fs_get_mergeinfo3(root, paths, inherit, + include_descendants, + adjust_inherited_mergeinfo, + mergeinfo_receiver, result_catalog, + scratch_pool)); + *catalog = result_catalog; + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_fs_get_mergeinfo(svn_mergeinfo_catalog_t *catalog, + svn_fs_root_t *root, + const apr_array_header_t *paths, + svn_mergeinfo_inheritance_t inherit, + svn_boolean_t include_descendants, + apr_pool_t *pool) +{ + return svn_error_trace(svn_fs_get_mergeinfo2(catalog, root, paths, + inherit, + include_descendants, + TRUE, pool, pool)); +} + +svn_error_t * +svn_fs_paths_changed(apr_hash_t **changed_paths_p, svn_fs_root_t *root, + apr_pool_t *pool) +{ + apr_hash_t *changed_paths_new_structs; + apr_hash_index_t *hi; + + SVN_ERR(svn_fs_paths_changed2(&changed_paths_new_structs, root, pool)); + *changed_paths_p = apr_hash_make(pool); + for (hi = apr_hash_first(pool, changed_paths_new_structs); + hi; + hi = apr_hash_next(hi)) + { + const void *vkey; + apr_ssize_t klen; + void *vval; + svn_fs_path_change2_t *val; + svn_fs_path_change_t *change; + apr_hash_this(hi, &vkey, &klen, &vval); + val = vval; + change = apr_palloc(pool, sizeof(*change)); + change->node_rev_id = val->node_rev_id; + change->change_kind = val->change_kind; + change->text_mod = val->text_mod; + change->prop_mod = val->prop_mod; + apr_hash_set(*changed_paths_p, vkey, klen, change); + } + return SVN_NO_ERROR; +} + +svn_error_t * +svn_fs_file_md5_checksum(unsigned char digest[], + svn_fs_root_t *root, + const char *path, + apr_pool_t *pool) +{ + svn_checksum_t *md5sum; + + SVN_ERR(svn_fs_file_checksum(&md5sum, svn_checksum_md5, root, path, TRUE, + pool)); + memcpy(digest, md5sum->digest, APR_MD5_DIGESTSIZE); + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_fs_history_prev(svn_fs_history_t **prev_history_p, + svn_fs_history_t *history, svn_boolean_t cross_copies, + apr_pool_t *pool) +{ + return svn_error_trace(svn_fs_history_prev2(prev_history_p, history, + cross_copies, pool, pool)); +} + /*** From access.c ***/ svn_error_t * svn_fs_access_add_lock_token(svn_fs_access_t *access_ctx, diff --git a/subversion/libsvn_fs/editor.c b/subversion/libsvn_fs/editor.c index b4cd3bca3f3e..c24c154e59cf 100644 --- a/subversion/libsvn_fs/editor.c +++ b/subversion/libsvn_fs/editor.c @@ -777,16 +777,24 @@ svn_fs__editor_commit(svn_revnum_t *revision, /* Clean up internal resources (eg. eb->root). This also allows the editor infrastructure to know this editor is "complete". */ err = svn_editor_complete(editor); + if (err) + { + svn_fs_txn_t *txn = eb->txn; + + eb->txn = NULL; + return svn_error_trace(svn_error_compose_create( + err, + svn_fs_abort_txn(txn, scratch_pool))); + } /* Note: docco for svn_fs_commit_txn() states that CONFLICT_PATH will be allocated in the txn's pool. But it lies. Regardless, we want it placed into RESULT_POOL. */ - if (!err) - err = svn_fs_commit_txn(&inner_conflict_path, - revision, - eb->txn, - scratch_pool); + err = svn_fs_commit_txn(&inner_conflict_path, + revision, + eb->txn, + scratch_pool); if (SVN_IS_VALID_REVNUM(*revision)) { if (err) diff --git a/subversion/libsvn_fs/fs-loader.c b/subversion/libsvn_fs/fs-loader.c index ba90554fa263..f898d8a56a6a 100644 --- a/subversion/libsvn_fs/fs-loader.c +++ b/subversion/libsvn_fs/fs-loader.c @@ -26,8 +26,6 @@ #include #include #include -#include -#include #include #include @@ -47,6 +45,7 @@ #include "private/svn_atomic.h" #include "private/svn_fs_private.h" #include "private/svn_fs_util.h" +#include "private/svn_fspath.h" #include "private/svn_utf_private.h" #include "private/svn_mutex.h" #include "private/svn_subr_private.h" @@ -61,6 +60,22 @@ #define FS_TYPE_FILENAME "fs-type" +/* If a FS backend does not implement the PATHS_CHANGED vtable function, + it will get emulated. However, if this macro is defined to non-null + then the API will always be emulated when feasible, i.e. the calls + get "re-directed" to the new API implementation. */ +#ifndef SVN_FS_EMULATE_PATHS_CHANGED +#define SVN_FS_EMULATE_PATHS_CHANGED FALSE +#endif + +/* If a FS backend does not implement the REPORT_CHANGES vtable function, + it will get emulated. However, if this macro is defined to non-null + then the API will always be emulated when feasible, i.e. the calls + get "re-directed" to the old API implementation. */ +#ifndef SVN_FS_EMULATE_REPORT_CHANGES +#define SVN_FS_EMULATE_REPORT_CHANGES FALSE +#endif + /* A pool common to all FS objects. See the documentation on the open/create functions in fs-loader.h and for svn_fs_initialize(). */ static apr_pool_t *common_pool = NULL; @@ -74,7 +89,7 @@ struct fs_type_defn { const char *fs_type; const char *fsap_name; fs_init_func_t initfunc; - fs_library_vtable_t *vtable; + void * volatile vtable; /* fs_library_vtable_t */ struct fs_type_defn *next; }; @@ -140,7 +155,7 @@ load_module(fs_init_func_t *initfunc, const char *name, apr_pool_t *pool) _("Invalid name for FS type '%s'"), name); - libname = apr_psprintf(pool, "libsvn_fs_%s-%d.so.%d", + libname = apr_psprintf(pool, "libsvn_fs_%s-" SVN_DSO_SUFFIX_FMT, name, SVN_VER_MAJOR, SVN_SOVERSION); funcname = apr_psprintf(pool, "svn_fs_%s__init", name); @@ -175,7 +190,7 @@ get_library_vtable_direct(fs_library_vtable_t **vtable, const svn_version_t *fs_version; /* most times, we get lucky */ - *vtable = apr_atomic_casptr((volatile void **)&fst->vtable, NULL, NULL); + *vtable = svn_atomic_casptr(&fst->vtable, NULL, NULL); if (*vtable) return SVN_NO_ERROR; @@ -218,7 +233,7 @@ get_library_vtable_direct(fs_library_vtable_t **vtable, fs_version->patch, fs_version->tag); /* the vtable will not change. Remember it */ - apr_atomic_casptr((volatile void **)&fst->vtable, *vtable, NULL); + svn_atomic_casptr(&fst->vtable, *vtable, NULL); return SVN_NO_ERROR; } @@ -507,24 +522,28 @@ svn_fs_set_warning_func(svn_fs_t *fs, svn_fs_warning_callback_t warning, } svn_error_t * -svn_fs_create(svn_fs_t **fs_p, const char *path, apr_hash_t *fs_config, - apr_pool_t *pool) +svn_fs_create2(svn_fs_t **fs_p, + const char *path, + apr_hash_t *fs_config, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { fs_library_vtable_t *vtable; const char *fs_type = svn_hash__get_cstring(fs_config, SVN_FS_CONFIG_FS_TYPE, DEFAULT_FS_TYPE); - SVN_ERR(get_library_vtable(&vtable, fs_type, pool)); + SVN_ERR(get_library_vtable(&vtable, fs_type, scratch_pool)); /* Create the FS directory and write out the fsap-name file. */ - SVN_ERR(svn_io_dir_make_sgid(path, APR_OS_DEFAULT, pool)); - SVN_ERR(write_fs_type(path, fs_type, pool)); + SVN_ERR(svn_io_dir_make_sgid(path, APR_OS_DEFAULT, scratch_pool)); + SVN_ERR(write_fs_type(path, fs_type, scratch_pool)); /* Perform the actual creation. */ - *fs_p = fs_new(fs_config, pool); + *fs_p = fs_new(fs_config, result_pool); - SVN_ERR(vtable->create(*fs_p, path, common_pool_lock, pool, common_pool)); + SVN_ERR(vtable->create(*fs_p, path, common_pool_lock, scratch_pool, + common_pool)); SVN_ERR(vtable->set_svn_fs_open(*fs_p, svn_fs_open2)); return SVN_NO_ERROR; @@ -546,15 +565,6 @@ svn_fs_open2(svn_fs_t **fs_p, const char *path, apr_hash_t *fs_config, return SVN_NO_ERROR; } -svn_error_t * -svn_fs_open(svn_fs_t **fs_p, - const char *path, - apr_hash_t *fs_config, - apr_pool_t *pool) -{ - return svn_fs_open2(fs_p, path, fs_config, pool, pool); -} - svn_error_t * svn_fs_upgrade2(const char *path, svn_fs_upgrade_notify_t notify_func, @@ -1045,41 +1055,164 @@ svn_fs_revision_root_revision(svn_fs_root_t *root) return root->is_txn_root ? SVN_INVALID_REVNUM : root->rev; } +svn_error_t * +svn_fs_path_change_get(svn_fs_path_change3_t **change, + svn_fs_path_change_iterator_t *iterator) +{ + return iterator->vtable->get(change, iterator); +} + svn_error_t * svn_fs_paths_changed2(apr_hash_t **changed_paths_p, svn_fs_root_t *root, apr_pool_t *pool) { - return root->vtable->paths_changed(changed_paths_p, root, pool); + svn_boolean_t emulate = !root->vtable->paths_changed + || SVN_FS_EMULATE_PATHS_CHANGED; + + if (emulate) + { + apr_pool_t *scratch_pool = svn_pool_create(pool); + apr_hash_t *changes = svn_hash__make(pool); + + svn_fs_path_change_iterator_t *iterator; + svn_fs_path_change3_t *change; + + SVN_ERR(svn_fs_paths_changed3(&iterator, root, scratch_pool, + scratch_pool)); + + SVN_ERR(svn_fs_path_change_get(&change, iterator)); + while (change) + { + svn_fs_path_change2_t *copy; + const svn_fs_id_t *id_copy; + const char *change_path = change->path.data; + svn_fs_root_t *change_root = root; + + /* Copy CHANGE to old API struct. */ + if (change->change_kind == svn_fs_path_change_delete) + SVN_ERR(svn_fs__get_deleted_node(&change_root, &change_path, + change_root, change_path, + scratch_pool, scratch_pool)); + + SVN_ERR(svn_fs_node_id(&id_copy, change_root, change_path, pool)); + + copy = svn_fs_path_change2_create(id_copy, change->change_kind, + pool); + copy->copyfrom_known = change->copyfrom_known; + if ( copy->copyfrom_known + && SVN_IS_VALID_REVNUM(change->copyfrom_rev)) + { + copy->copyfrom_rev = change->copyfrom_rev; + copy->copyfrom_path = apr_pstrdup(pool, change->copyfrom_path); + } + copy->mergeinfo_mod = change->mergeinfo_mod; + copy->node_kind = change->node_kind; + copy->prop_mod = change->prop_mod; + copy->text_mod = change->text_mod; + + svn_hash_sets(changes, apr_pstrmemdup(pool, change->path.data, + change->path.len), copy); + + /* Next change. */ + SVN_ERR(svn_fs_path_change_get(&change, iterator)); + } + svn_pool_destroy(scratch_pool); + + *changed_paths_p = changes; + } + else + { + SVN_ERR(root->vtable->paths_changed(changed_paths_p, root, pool)); + } + + return SVN_NO_ERROR; } -svn_error_t * -svn_fs_paths_changed(apr_hash_t **changed_paths_p, svn_fs_root_t *root, - apr_pool_t *pool) +/* Implement svn_fs_path_change_iterator_t on top of svn_fs_paths_changed2. */ + +/* The iterator builds upon a hash iterator, which in turn operates on the + full prefetched changes list. */ +typedef struct fsap_iterator_data_t { - apr_hash_t *changed_paths_new_structs; apr_hash_index_t *hi; - SVN_ERR(svn_fs_paths_changed2(&changed_paths_new_structs, root, pool)); - *changed_paths_p = apr_hash_make(pool); - for (hi = apr_hash_first(pool, changed_paths_new_structs); - hi; - hi = apr_hash_next(hi)) + /* For efficicency such that we don't need to dynamically allocate + yet another copy of that data. */ + svn_fs_path_change3_t change; +} fsap_iterator_data_t; + +static svn_error_t * +changes_iterator_get(svn_fs_path_change3_t **change, + svn_fs_path_change_iterator_t *iterator) +{ + fsap_iterator_data_t *data = iterator->fsap_data; + + if (data->hi) { - const void *vkey; - apr_ssize_t klen; - void *vval; - svn_fs_path_change2_t *val; - svn_fs_path_change_t *change; - apr_hash_this(hi, &vkey, &klen, &vval); - val = vval; - change = apr_palloc(pool, sizeof(*change)); - change->node_rev_id = val->node_rev_id; - change->change_kind = val->change_kind; - change->text_mod = val->text_mod; - change->prop_mod = val->prop_mod; - apr_hash_set(*changed_paths_p, vkey, klen, change); + const char *path = apr_hash_this_key(data->hi); + svn_fs_path_change2_t *entry = apr_hash_this_val(data->hi); + + data->change.path.data = path; + data->change.path.len = apr_hash_this_key_len(data->hi); + data->change.change_kind = entry->change_kind; + data->change.node_kind = entry->node_kind; + data->change.text_mod = entry->text_mod; + data->change.prop_mod = entry->prop_mod; + data->change.mergeinfo_mod = entry->mergeinfo_mod; + data->change.copyfrom_known = entry->copyfrom_known; + data->change.copyfrom_rev = entry->copyfrom_rev; + data->change.copyfrom_path = entry->copyfrom_path; + + *change = &data->change; + data->hi = apr_hash_next(data->hi); } + else + { + *change = NULL; + } + + return SVN_NO_ERROR; +} + +static changes_iterator_vtable_t iterator_vtable = +{ + changes_iterator_get +}; + +svn_error_t * +svn_fs_paths_changed3(svn_fs_path_change_iterator_t **iterator, + svn_fs_root_t *root, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_boolean_t emulate = !root->vtable->report_changes + || ( SVN_FS_EMULATE_REPORT_CHANGES + && root->vtable->paths_changed); + + if (emulate) + { + svn_fs_path_change_iterator_t *result; + fsap_iterator_data_t *data; + + apr_hash_t *changes; + SVN_ERR(root->vtable->paths_changed(&changes, root, result_pool)); + + data = apr_pcalloc(result_pool, sizeof(*data)); + data->hi = apr_hash_first(result_pool, changes); + + result = apr_pcalloc(result_pool, sizeof(*result)); + result->fsap_data = data; + result->vtable = &iterator_vtable; + + *iterator = result; + } + else + { + SVN_ERR(root->vtable->report_changes(iterator, root, result_pool, + scratch_pool)); + } + return SVN_NO_ERROR; } @@ -1100,14 +1233,6 @@ svn_fs_node_history2(svn_fs_history_t **history_p, svn_fs_root_t *root, scratch_pool)); } -svn_error_t * -svn_fs_node_history(svn_fs_history_t **history_p, svn_fs_root_t *root, - const char *path, apr_pool_t *pool) -{ - return svn_error_trace(root->vtable->node_history(history_p, root, path, - pool, pool)); -} - svn_error_t * svn_fs_is_dir(svn_boolean_t *is_dir, svn_fs_root_t *root, const char *path, apr_pool_t *pool) @@ -1254,32 +1379,38 @@ svn_fs_closest_copy(svn_fs_root_t **root_p, const char **path_p, } svn_error_t * -svn_fs_get_mergeinfo2(svn_mergeinfo_catalog_t *catalog, - svn_fs_root_t *root, +svn_fs_get_mergeinfo3(svn_fs_root_t *root, const apr_array_header_t *paths, svn_mergeinfo_inheritance_t inherit, svn_boolean_t include_descendants, svn_boolean_t adjust_inherited_mergeinfo, - apr_pool_t *result_pool, + svn_fs_mergeinfo_receiver_t receiver, + void *baton, apr_pool_t *scratch_pool) { return svn_error_trace(root->vtable->get_mergeinfo( - catalog, root, paths, inherit, include_descendants, - adjust_inherited_mergeinfo, result_pool, scratch_pool)); + root, paths, inherit, include_descendants, adjust_inherited_mergeinfo, + receiver, baton, scratch_pool)); } -svn_error_t * -svn_fs_get_mergeinfo(svn_mergeinfo_catalog_t *catalog, - svn_fs_root_t *root, - const apr_array_header_t *paths, - svn_mergeinfo_inheritance_t inherit, - svn_boolean_t include_descendants, - apr_pool_t *pool) +/* Baton type to be used with mergeinfo_receiver(). It provides some of + * the parameters passed to svn_fs__get_mergeinfo_for_path. */ +typedef struct mergeinfo_receiver_baton_t { - return svn_error_trace(root->vtable->get_mergeinfo(catalog, root, paths, - inherit, - include_descendants, - TRUE, pool, pool)); + svn_mergeinfo_t *mergeinfo; + apr_pool_t *result_pool; +} mergeinfo_receiver_baton_t; + +static svn_error_t * +mergeinfo_receiver(const char *path, + svn_mergeinfo_t mergeinfo, + void *baton, + apr_pool_t *scratch_pool) +{ + mergeinfo_receiver_baton_t *b = baton; + *b->mergeinfo = svn_mergeinfo_dup(mergeinfo, b->result_pool); + + return SVN_NO_ERROR; } svn_error_t * @@ -1293,15 +1424,19 @@ svn_fs__get_mergeinfo_for_path(svn_mergeinfo_t *mergeinfo, { apr_array_header_t *paths = apr_array_make(scratch_pool, 1, sizeof(const char *)); - svn_mergeinfo_catalog_t catalog; + + mergeinfo_receiver_baton_t baton; + baton.mergeinfo = mergeinfo; + baton.result_pool = result_pool; APR_ARRAY_PUSH(paths, const char *) = path; - SVN_ERR(svn_fs_get_mergeinfo2(&catalog, root, paths, + *mergeinfo = NULL; + SVN_ERR(svn_fs_get_mergeinfo3(root, paths, inherit, FALSE /*include_descendants*/, adjust_inherited_mergeinfo, - result_pool, scratch_pool)); - *mergeinfo = svn_hash_gets(catalog, path); + mergeinfo_receiver, &baton, + scratch_pool)); return SVN_NO_ERROR; } @@ -1390,35 +1525,16 @@ svn_fs_file_checksum(svn_checksum_t **checksum, if (force && (*checksum == NULL || (*checksum)->kind != kind)) { - svn_stream_t *contents, *checksum_contents; + svn_stream_t *contents; SVN_ERR(svn_fs_file_contents(&contents, root, path, pool)); - checksum_contents = svn_stream_checksummed2(contents, checksum, NULL, - kind, TRUE, pool); - - /* This will force a read of any remaining data (which is all of it in - this case) and dump the checksum into checksum->digest. */ - SVN_ERR(svn_stream_close(checksum_contents)); + SVN_ERR(svn_stream_contents_checksum(checksum, contents, kind, + pool, pool)); } return SVN_NO_ERROR; } -svn_error_t * -svn_fs_file_md5_checksum(unsigned char digest[], - svn_fs_root_t *root, - const char *path, - apr_pool_t *pool) -{ - svn_checksum_t *md5sum; - - SVN_ERR(svn_fs_file_checksum(&md5sum, svn_checksum_md5, root, path, TRUE, - pool)); - memcpy(digest, md5sum->digest, APR_MD5_DIGESTSIZE); - - return SVN_NO_ERROR; -} - svn_error_t * svn_fs_file_contents(svn_stream_t **contents, svn_fs_root_t *root, const char *path, apr_pool_t *pool) @@ -1554,19 +1670,39 @@ svn_fs_deltify_revision(svn_fs_t *fs, svn_revnum_t revision, apr_pool_t *pool) } svn_error_t * -svn_fs_revision_prop(svn_string_t **value_p, svn_fs_t *fs, svn_revnum_t rev, - const char *propname, apr_pool_t *pool) +svn_fs_refresh_revision_props(svn_fs_t *fs, + apr_pool_t *scratch_pool) { - return svn_error_trace(fs->vtable->revision_prop(value_p, fs, rev, - propname, pool)); + return svn_error_trace(fs->vtable->refresh_revprops(fs, scratch_pool)); } svn_error_t * -svn_fs_revision_proplist(apr_hash_t **table_p, svn_fs_t *fs, svn_revnum_t rev, - apr_pool_t *pool) +svn_fs_revision_prop2(svn_string_t **value_p, + svn_fs_t *fs, + svn_revnum_t rev, + const char *propname, + svn_boolean_t refresh, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + return svn_error_trace(fs->vtable->revision_prop(value_p, fs, rev, + propname, refresh, + result_pool, + scratch_pool)); +} + +svn_error_t * +svn_fs_revision_proplist2(apr_hash_t **table_p, + svn_fs_t *fs, + svn_revnum_t rev, + svn_boolean_t refresh, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { return svn_error_trace(fs->vtable->revision_proplist(table_p, fs, rev, - pool)); + refresh, + result_pool, + scratch_pool)); } svn_error_t * @@ -1592,6 +1728,64 @@ svn_fs_get_file_delta_stream(svn_txdelta_stream_t **stream_p, target_root, target_path, pool)); } +svn_error_t * +svn_fs__get_deleted_node(svn_fs_root_t **node_root, + const char **node_path, + svn_fs_root_t *root, + const char *path, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + const char *parent_path, *name; + svn_fs_root_t *copy_root; + const char *copy_path; + + /* History traversal does not work with transaction roots. + * Therefore, do it "by hand". */ + + /* If the parent got copied in ROOT, PATH got copied with it. + * Otherwise, we will find the node at PATH in the revision prior to ROOT. + */ + svn_fspath__split(&parent_path, &name, path, scratch_pool); + SVN_ERR(svn_fs_closest_copy(©_root, ©_path, root, parent_path, + scratch_pool)); + + /* Copied in ROOT? */ + if ( copy_root + && ( svn_fs_revision_root_revision(copy_root) + == svn_fs_revision_root_revision(root))) + { + svn_revnum_t copyfrom_rev; + const char *copyfrom_path; + const char *rel_path; + SVN_ERR(svn_fs_copied_from(©from_rev, ©from_path, + copy_root, copy_path, scratch_pool)); + + SVN_ERR(svn_fs_revision_root(node_root, svn_fs_root_fs(root), + copyfrom_rev, result_pool)); + rel_path = svn_fspath__skip_ancestor(copy_path, path); + *node_path = svn_fspath__join(copyfrom_path, rel_path, result_pool); + } + else + { + svn_revnum_t revision; + svn_revnum_t previous_rev; + + /* Determine the latest revision before ROOT. */ + revision = svn_fs_revision_root_revision(root); + if (SVN_IS_VALID_REVNUM(revision)) + previous_rev = revision - 1; + else + previous_rev = svn_fs_txn_root_base_revision(root); + + SVN_ERR(svn_fs_revision_root(node_root, svn_fs_root_fs(root), + previous_rev, result_pool)); + *node_path = apr_pstrdup(result_pool, path); + } + + return SVN_NO_ERROR; +} + svn_error_t * svn_fs_get_uuid(svn_fs_t *fs, const char **uuid, apr_pool_t *pool) { @@ -1662,20 +1856,24 @@ svn_fs_lock_many(svn_fs_t *fs, target->token, "opaquelocktoken"); if (!err) - for (c = target->token; *c && !err; c++) - if (! svn_ctype_isascii(*c) || svn_ctype_iscntrl(*c)) - err = svn_error_createf( - SVN_ERR_FS_BAD_LOCK_TOKEN, NULL, - _("Lock token '%s' is not ASCII or is a " - "control character at byte %u"), - target->token, - (unsigned)(c - target->token)); + { + for (c = target->token; *c && !err; c++) + if (! svn_ctype_isascii(*c) || svn_ctype_iscntrl(*c)) + err = svn_error_createf( + SVN_ERR_FS_BAD_LOCK_TOKEN, NULL, + _("Lock token '%s' is not ASCII or is a " + "control character at byte %u"), + target->token, + (unsigned)(c - target->token)); - /* strlen(token) == c - token. */ - if (!err && !svn_xml_is_xml_safe(target->token, c - target->token)) - err = svn_error_createf(SVN_ERR_FS_BAD_LOCK_TOKEN, NULL, - _("Lock token URI '%s' is not XML-safe"), - target->token); + /* strlen(token) == c - token. */ + if (!err && !svn_xml_is_xml_safe(target->token, + c - target->token)) + err = svn_error_createf( + SVN_ERR_FS_BAD_LOCK_TOKEN, NULL, + _("Lock token URI '%s' is not XML-safe"), + target->token); + } } if (err) @@ -1770,8 +1968,7 @@ svn_fs_lock_target_create(const char *token, svn_revnum_t current_rev, apr_pool_t *result_pool) { - svn_fs_lock_target_t *target = apr_palloc(result_pool, - sizeof(svn_fs_lock_target_t)); + svn_fs_lock_target_t *target = apr_palloc(result_pool, sizeof(*target)); target->token = token; target->current_rev = current_rev; @@ -1857,15 +2054,6 @@ svn_fs_history_prev2(svn_fs_history_t **prev_history_p, scratch_pool)); } -svn_error_t * -svn_fs_history_prev(svn_fs_history_t **prev_history_p, - svn_fs_history_t *history, svn_boolean_t cross_copies, - apr_pool_t *pool) -{ - return svn_error_trace(history->vtable->prev(prev_history_p, history, - cross_copies, pool, pool)); -} - svn_error_t * svn_fs_history_location(const char **path, svn_revnum_t *revision, svn_fs_history_t *history, apr_pool_t *pool) @@ -1965,6 +2153,28 @@ svn_fs_path_change2_create(const svn_fs_id_t *node_rev_id, return svn_fs__path_change_create_internal(node_rev_id, change_kind, pool); } +svn_fs_path_change3_t * +svn_fs_path_change3_create(svn_fs_path_change_kind_t change_kind, + apr_pool_t *result_pool) +{ + return svn_fs__path_change_create_internal2(change_kind, result_pool); +} + +svn_fs_path_change3_t * +svn_fs_path_change3_dup(svn_fs_path_change3_t *change, + apr_pool_t *result_pool) +{ + svn_fs_path_change3_t *copy = apr_pmemdup(result_pool, change, + sizeof(*copy)); + + copy->path.data = apr_pstrmemdup(result_pool, copy->path.data, + copy->path.len); + if (copy->copyfrom_path) + copy->copyfrom_path = apr_pstrdup(result_pool, change->copyfrom_path); + + return copy; +} + /* Return the library version number. */ const svn_version_t * svn_fs_version(void) diff --git a/subversion/libsvn_fs/fs-loader.h b/subversion/libsvn_fs/fs-loader.h index db8374425749..0712c23307d9 100644 --- a/subversion/libsvn_fs/fs-loader.h +++ b/subversion/libsvn_fs/fs-loader.h @@ -22,8 +22,8 @@ */ -#ifndef LIBSVN_FS_FS_H -#define LIBSVN_FS_FS_H +#ifndef LIBSVN_FS_LOADER_H +#define LIBSVN_FS_LOADER_H #include "svn_types.h" #include "svn_fs.h" @@ -79,11 +79,11 @@ typedef struct fs_library_vtable_t parameter for allocating fs-global objects such as an env cache. */ svn_error_t *(*create)(svn_fs_t *fs, const char *path, svn_mutex__t *common_pool_lock, - apr_pool_t *pool, + apr_pool_t *scratch_pool, apr_pool_t *common_pool); svn_error_t *(*open_fs)(svn_fs_t *fs, const char *path, svn_mutex__t *common_pool_lock, - apr_pool_t *pool, + apr_pool_t *scratch_pool, apr_pool_t *common_pool); /* open_for_recovery() is like open(), but used to fill in an fs pointer that will be passed to recover(). We assume that the open() method @@ -184,15 +184,9 @@ typedef svn_error_t *(*fs_init_func_t)(const svn_version_t *loader_version, to the create and open functions and these init functions (as well as the open and create functions) are globally serialized so that they have exclusive access to the common_pool. */ -svn_error_t *svn_fs_base__init(const svn_version_t *loader_version, - fs_library_vtable_t **vtable, - apr_pool_t* common_pool); -svn_error_t *svn_fs_fs__init(const svn_version_t *loader_version, - fs_library_vtable_t **vtable, - apr_pool_t* common_pool); -svn_error_t *svn_fs_x__init(const svn_version_t *loader_version, - fs_library_vtable_t **vtable, - apr_pool_t* common_pool); +#include "../libsvn_fs_base/fs_init.h" +#include "../libsvn_fs_fs/fs_init.h" +#include "../libsvn_fs_x/fs_init.h" @@ -202,11 +196,17 @@ typedef struct fs_vtable_t { svn_error_t *(*youngest_rev)(svn_revnum_t *youngest_p, svn_fs_t *fs, apr_pool_t *pool); + svn_error_t *(*refresh_revprops)(svn_fs_t *fs, apr_pool_t *scratch_pool); svn_error_t *(*revision_prop)(svn_string_t **value_p, svn_fs_t *fs, svn_revnum_t rev, const char *propname, - apr_pool_t *pool); + svn_boolean_t refresh, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); svn_error_t *(*revision_proplist)(apr_hash_t **table_p, svn_fs_t *fs, - svn_revnum_t rev, apr_pool_t *pool); + svn_revnum_t rev, + svn_boolean_t refresh, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); svn_error_t *(*change_rev_prop)(svn_fs_t *fs, svn_revnum_t rev, const char *name, const svn_string_t *const *old_value_p, @@ -301,6 +301,10 @@ typedef struct root_vtable_t svn_error_t *(*paths_changed)(apr_hash_t **changed_paths_p, svn_fs_root_t *root, apr_pool_t *pool); + svn_error_t *(*report_changes)(svn_fs_path_change_iterator_t **iterator, + svn_fs_root_t *root, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); /* Generic node operations */ svn_error_t *(*check_path)(svn_node_kind_t *kind_p, svn_fs_root_t *root, @@ -415,17 +419,24 @@ typedef struct root_vtable_t const char *ancestor_path, apr_pool_t *pool); /* Mergeinfo. */ - svn_error_t *(*get_mergeinfo)(svn_mergeinfo_catalog_t *catalog, - svn_fs_root_t *root, + svn_error_t *(*get_mergeinfo)(svn_fs_root_t *root, const apr_array_header_t *paths, svn_mergeinfo_inheritance_t inherit, svn_boolean_t include_descendants, svn_boolean_t adjust_inherited_mergeinfo, - apr_pool_t *result_pool, + svn_fs_mergeinfo_receiver_t receiver, + void *baton, apr_pool_t *scratch_pool); } root_vtable_t; +typedef struct changes_iterator_vtable_t +{ + svn_error_t *(*get)(svn_fs_path_change3_t **change, + svn_fs_path_change_iterator_t *iterator); +} changes_iterator_vtable_t; + + typedef struct history_vtable_t { svn_error_t *(*prev)(svn_fs_history_t **prev_history_p, @@ -449,7 +460,7 @@ typedef struct id_vtable_t /*** Definitions of the abstract FS object types ***/ /* These are transaction properties that correspond to the bitfields - in the 'flags' argument to svn_fs_lock(). */ + in the 'flags' argument to svn_fs_begin_txn2(). */ #define SVN_FS__PROP_TXN_CHECK_LOCKS SVN_PROP_PREFIX "check-locks" #define SVN_FS__PROP_TXN_CHECK_OOD SVN_PROP_PREFIX "check-ood" /* Set to "0" at the start of the txn, to "1" when svn:date changes. */ @@ -474,7 +485,7 @@ struct svn_fs_t svn_fs_access_t *access_ctx; /* FSAP-specific vtable and private data */ - fs_vtable_t *vtable; + const fs_vtable_t *vtable; void *fsap_data; /* UUID, stored by open(), create(), and set_uuid(). */ @@ -496,7 +507,7 @@ struct svn_fs_txn_t const char *id; /* FSAP-specific vtable and private data */ - txn_vtable_t *vtable; + const txn_vtable_t *vtable; void *fsap_data; }; @@ -524,15 +535,21 @@ struct svn_fs_root_t svn_revnum_t rev; /* FSAP-specific vtable and private data */ - root_vtable_t *vtable; + const root_vtable_t *vtable; void *fsap_data; }; +struct svn_fs_path_change_iterator_t +{ + /* FSAP-specific vtable and private data */ + const changes_iterator_vtable_t *vtable; + void *fsap_data; +}; struct svn_fs_history_t { /* FSAP-specific vtable and private data */ - history_vtable_t *vtable; + const history_vtable_t *vtable; void *fsap_data; }; @@ -540,7 +557,7 @@ struct svn_fs_history_t struct svn_fs_id_t { /* FSAP-specific vtable and private data */ - id_vtable_t *vtable; + const id_vtable_t *vtable; void *fsap_data; }; @@ -569,4 +586,4 @@ struct svn_fs_lock_target_t } #endif /* __cplusplus */ -#endif +#endif /* LIBSVN_FS_LOADER_H */ diff --git a/subversion/libsvn_fs_base/bdb/rev-table.c b/subversion/libsvn_fs_base/bdb/rev-table.c index b752249bfa78..c39d2c962761 100644 --- a/subversion/libsvn_fs_base/bdb/rev-table.c +++ b/subversion/libsvn_fs_base/bdb/rev-table.c @@ -79,6 +79,9 @@ svn_fs_bdb__get_rev(revision_t **revision_p, numbers begin with one. */ db_recno_t recno = (db_recno_t) rev + 1; + if (!SVN_IS_VALID_REVNUM(rev)) + return svn_fs_base__err_dangling_rev(fs, rev); + svn_fs_base__trail_debug(trail, "revisions", "get"); db_err = bfd->revisions->get(bfd->revisions, trail->db_txn, svn_fs_base__set_dbt(&key, &recno, diff --git a/subversion/libsvn_fs_base/fs.c b/subversion/libsvn_fs_base/fs.c index 06dfbaf2f419..903225725f06 100644 --- a/subversion/libsvn_fs_base/fs.c +++ b/subversion/libsvn_fs_base/fs.c @@ -470,6 +470,13 @@ bdb_write_config(svn_fs_t *fs) return svn_io_file_close(dbconfig_file, fs->pool); } +static svn_error_t * +base_bdb_refresh_revision(svn_fs_t *fs, + apr_pool_t *scratch_pool) +{ + return SVN_NO_ERROR; +} + static svn_error_t * base_bdb_info_format(int *fs_format, svn_version_t **supports_version, @@ -545,6 +552,7 @@ base_bdb_freeze(svn_fs_t *fs, static fs_vtable_t fs_vtable = { svn_fs_base__youngest_rev, + base_bdb_refresh_revision, svn_fs_base__revision_prop, svn_fs_base__revision_proplist, svn_fs_base__change_rev_prop, @@ -572,13 +580,12 @@ static fs_vtable_t fs_vtable = { #define FORMAT_FILE "format" /* Depending on CREATE, create or open the environment and databases - for filesystem FS in PATH. Use POOL for temporary allocations. */ + for filesystem FS in PATH. */ static svn_error_t * open_databases(svn_fs_t *fs, svn_boolean_t create, int format, - const char *path, - apr_pool_t *pool) + const char *path) { base_fs_data_t *bfd; @@ -732,7 +739,7 @@ static svn_error_t * base_create(svn_fs_t *fs, const char *path, svn_mutex__t *common_pool_lock, - apr_pool_t *pool, + apr_pool_t *scratch_pool, apr_pool_t *common_pool) { int format = SVN_FS_BASE__FORMAT_NUMBER; @@ -743,7 +750,7 @@ base_create(svn_fs_t *fs, { svn_version_t *compatible_version; SVN_ERR(svn_fs__compatible_version(&compatible_version, fs->config, - pool)); + scratch_pool)); /* select format number */ switch(compatible_version->minor) @@ -765,7 +772,7 @@ base_create(svn_fs_t *fs, } /* Create the environment and databases. */ - svn_err = open_databases(fs, TRUE, format, path, pool); + svn_err = open_databases(fs, TRUE, format, path); if (svn_err) goto error; /* Initialize the DAG subsystem. */ @@ -773,14 +780,15 @@ base_create(svn_fs_t *fs, if (svn_err) goto error; /* This filesystem is ready. Stamp it with a format number. */ - svn_err = svn_io_write_version_file( - svn_dirent_join(fs->path, FORMAT_FILE, pool), format, pool); + svn_err = svn_io_write_version_file(svn_dirent_join(fs->path, FORMAT_FILE, + scratch_pool), + format, scratch_pool); if (svn_err) goto error; ((base_fs_data_t *) fs->fsap_data)->format = format; - SVN_ERR(populate_opened_fs(fs, pool)); - return SVN_NO_ERROR;; + SVN_ERR(populate_opened_fs(fs, scratch_pool)); + return SVN_NO_ERROR; error: return svn_error_compose_create(svn_err, @@ -826,7 +834,7 @@ static svn_error_t * base_open(svn_fs_t *fs, const char *path, svn_mutex__t *common_pool_lock, - apr_pool_t *pool, + apr_pool_t *scratch_pool, apr_pool_t *common_pool) { int format; @@ -835,8 +843,9 @@ base_open(svn_fs_t *fs, /* Read the FS format number. */ svn_err = svn_io_read_version_file(&format, - svn_dirent_join(path, FORMAT_FILE, pool), - pool); + svn_dirent_join(path, FORMAT_FILE, + scratch_pool), + scratch_pool); if (svn_err && APR_STATUS_IS_ENOENT(svn_err->apr_err)) { /* Pre-1.2 filesystems did not have a format file (you could say @@ -852,7 +861,7 @@ base_open(svn_fs_t *fs, goto error; /* Create the environment and databases. */ - svn_err = open_databases(fs, FALSE, format, path, pool); + svn_err = open_databases(fs, FALSE, format, path); if (svn_err) goto error; ((base_fs_data_t *) fs->fsap_data)->format = format; @@ -862,12 +871,12 @@ base_open(svn_fs_t *fs, if (write_format_file) { svn_err = svn_io_write_version_file(svn_dirent_join(path, FORMAT_FILE, - pool), - format, pool); + scratch_pool), + format, scratch_pool); if (svn_err) goto error; } - SVN_ERR(populate_opened_fs(fs, pool)); + SVN_ERR(populate_opened_fs(fs, scratch_pool)); return SVN_NO_ERROR; error: @@ -948,6 +957,7 @@ base_upgrade(svn_fs_t *fs, err = SVN_NO_ERROR; } SVN_ERR(err); + SVN_ERR(check_format(old_format_number)); /* Bump the format file's stored version number. */ SVN_ERR(svn_io_write_version_file(version_file_path, diff --git a/subversion/libsvn_fs_base/fs_init.h b/subversion/libsvn_fs_base/fs_init.h new file mode 100644 index 000000000000..012a40593e09 --- /dev/null +++ b/subversion/libsvn_fs_base/fs_init.h @@ -0,0 +1,33 @@ +/* + * libsvn_fs_base/fs_init.h: Exported function of libsvn_fs_base + * + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#ifndef LIBSVN_FS_LOADER_H +#error Please include libsvn_fs/fs_loader.h instead of this file +#else + +svn_error_t *svn_fs_base__init(const svn_version_t *loader_version, + fs_library_vtable_t **vtable, + apr_pool_t* common_pool); + +#endif diff --git a/subversion/libsvn_fs_base/lock.c b/subversion/libsvn_fs_base/lock.c index 1145207ea38c..7593e9321f37 100644 --- a/subversion/libsvn_fs_base/lock.c +++ b/subversion/libsvn_fs_base/lock.c @@ -108,7 +108,7 @@ txn_body_lock(void *baton, trail_t *trail) SVN_ERR(svn_fs_base__get_path_kind(&kind, args->path, trail, trail->pool)); /* Until we implement directory locks someday, we only allow locks - on files or non-existent paths. */ + on files. */ if (kind == svn_node_dir) return SVN_FS__ERR_NOT_FILE(trail->fs, args->path); diff --git a/subversion/libsvn_fs_base/revs-txns.c b/subversion/libsvn_fs_base/revs-txns.c index f1029f4e0d0f..2ee65455d7d5 100644 --- a/subversion/libsvn_fs_base/revs-txns.c +++ b/subversion/libsvn_fs_base/revs-txns.c @@ -194,7 +194,9 @@ svn_error_t * svn_fs_base__revision_proplist(apr_hash_t **table_p, svn_fs_t *fs, svn_revnum_t rev, - apr_pool_t *pool) + svn_boolean_t refresh, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { struct revision_proplist_args args; apr_hash_t *table; @@ -204,9 +206,9 @@ svn_fs_base__revision_proplist(apr_hash_t **table_p, args.table_p = &table; args.rev = rev; SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_revision_proplist, &args, - FALSE, pool)); + FALSE, result_pool)); - *table_p = table ? table : apr_hash_make(pool); + *table_p = table ? table : apr_hash_make(result_pool); return SVN_NO_ERROR; } @@ -216,7 +218,9 @@ svn_fs_base__revision_prop(svn_string_t **value_p, svn_fs_t *fs, svn_revnum_t rev, const char *propname, - apr_pool_t *pool) + svn_boolean_t refresh, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { struct revision_proplist_args args; apr_hash_t *table; @@ -227,7 +231,7 @@ svn_fs_base__revision_prop(svn_string_t **value_p, args.table_p = &table; args.rev = rev; SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_revision_proplist, &args, - FALSE, pool)); + FALSE, result_pool)); /* And then the prop from that list (if there was a list). */ *value_p = svn_hash_gets(table, propname); @@ -247,8 +251,10 @@ svn_fs_base__set_rev_prop(svn_fs_t *fs, { transaction_t *txn; const char *txn_id; + const svn_string_t *present_value; SVN_ERR(get_rev_txn(&txn, &txn_id, fs, rev, trail, pool)); + present_value = svn_hash_gets(txn->proplist, name); /* If there's no proplist, but we're just deleting a property, exit now. */ if ((! txn->proplist) && (! value)) @@ -262,7 +268,6 @@ svn_fs_base__set_rev_prop(svn_fs_t *fs, if (old_value_p) { const svn_string_t *wanted_value = *old_value_p; - const svn_string_t *present_value = svn_hash_gets(txn->proplist, name); if ((!wanted_value != !present_value) || (wanted_value && present_value && !svn_string_compare(wanted_value, present_value))) @@ -275,6 +280,13 @@ svn_fs_base__set_rev_prop(svn_fs_t *fs, } /* Fall through. */ } + + /* If the prop-set is a no-op, skip the actual write. */ + if ((!present_value && !value) + || (present_value && value + && svn_string_compare(present_value, value))) + return SVN_NO_ERROR; + svn_hash_sets(txn->proplist, name, value); /* Overwrite the revision. */ diff --git a/subversion/libsvn_fs_base/revs-txns.h b/subversion/libsvn_fs_base/revs-txns.h index 558a90c89266..4a2082773f6f 100644 --- a/subversion/libsvn_fs_base/revs-txns.h +++ b/subversion/libsvn_fs_base/revs-txns.h @@ -172,12 +172,16 @@ svn_error_t *svn_fs_base__youngest_rev(svn_revnum_t *youngest_p, svn_fs_t *fs, svn_error_t *svn_fs_base__revision_prop(svn_string_t **value_p, svn_fs_t *fs, svn_revnum_t rev, const char *propname, - apr_pool_t *pool); + svn_boolean_t refresh, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); svn_error_t *svn_fs_base__revision_proplist(apr_hash_t **table_p, svn_fs_t *fs, svn_revnum_t rev, - apr_pool_t *pool); + svn_boolean_t refresh, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); svn_error_t *svn_fs_base__change_rev_prop(svn_fs_t *fs, svn_revnum_t rev, const char *name, diff --git a/subversion/libsvn_fs_base/tree.c b/subversion/libsvn_fs_base/tree.c index 924e7c94a2a0..ba5debbd970b 100644 --- a/subversion/libsvn_fs_base/tree.c +++ b/subversion/libsvn_fs_base/tree.c @@ -68,6 +68,7 @@ #include "private/svn_fspath.h" #include "private/svn_fs_util.h" #include "private/svn_mergeinfo_private.h" +#include "private/svn_sorts_private.h" /* ### I believe this constant will become internal to reps-strings.c. @@ -2580,8 +2581,7 @@ verify_locks(const char *txn_name, apr_hash_this(hi, &key, NULL, NULL); APR_ARRAY_PUSH(changed_paths, const char *) = key; } - qsort(changed_paths->elts, changed_paths->nelts, - changed_paths->elt_size, svn_sort_compare_paths); + svn_sort__array(changed_paths, svn_sort_compare_paths); /* Now, traverse the array of changed paths, verify locks. Note that if we need to do a recursive verification a path, we'll skip @@ -2661,7 +2661,7 @@ txn_body_commit(void *baton, trail_t *trail) svn_revnum_t youngest_rev; const svn_fs_id_t *y_rev_root_id; - dag_node_t *txn_base_root_node; + dag_node_t *txn_base_root_node, *txn_root_node; /* Getting the youngest revision locks the revisions table until this trail is done. */ @@ -2694,6 +2694,19 @@ txn_body_commit(void *baton, trail_t *trail) discovered locks. */ SVN_ERR(verify_locks(txn_name, trail, trail->pool)); + /* Ensure every txn has a mutable root as then the new revision will + have a distinct root node-revision-id. This is necessary as + future transactions use the root node-revision-id as a proxy for + the transaction base revision. */ + SVN_ERR(svn_fs_base__dag_txn_root(&txn_root_node, fs, txn_name, + trail, trail->pool)); + if (!svn_fs_base__dag_check_mutable(txn_root_node, txn->id)) + { + dag_node_t *clone; + SVN_ERR(svn_fs_base__dag_clone_root(&clone, fs, txn->id, + trail, trail->pool)); + } + /* Else, commit the txn. */ return svn_fs_base__dag_commit_txn(&(args->new_rev), txn, trail, trail->pool); @@ -5061,8 +5074,8 @@ base_node_origin_rev(svn_revnum_t *revision, /* Examine directory NODE's immediately children for mergeinfo. - For those which have explicit mergeinfo, add their mergeinfo to - RESULT_CATALOG (allocated in RESULT_CATALOG's pool). + For those which have explicit mergeinfo, invoke RECEIVER with + RECEIVER_BATON. For those which don't, but sit atop trees which contain mergeinfo somewhere deeper, add them to *CHILDREN_ATOP_MERGEINFO_TREES, a @@ -5076,10 +5089,11 @@ base_node_origin_rev(svn_revnum_t *revision, struct get_mergeinfo_data_and_entries_baton { - svn_mergeinfo_catalog_t result_catalog; apr_hash_t *children_atop_mergeinfo_trees; dag_node_t *node; const char *node_path; + svn_fs_mergeinfo_receiver_t receiver; + void *receiver_baton; }; static svn_error_t * @@ -5090,7 +5104,6 @@ txn_body_get_mergeinfo_data_and_entries(void *baton, trail_t *trail) apr_hash_t *entries; apr_hash_index_t *hi; apr_pool_t *iterpool = svn_pool_create(trail->pool); - apr_pool_t *result_pool = apr_hash_pool_get(args->result_catalog); apr_pool_t *children_pool = apr_hash_pool_get(args->children_atop_mergeinfo_trees); @@ -5144,7 +5157,7 @@ txn_body_get_mergeinfo_data_and_entries(void *baton, trail_t *trail) CHILD_NODE then treat it as if no mergeinfo is present rather than raising a parse error. */ err = svn_mergeinfo_parse(&child_mergeinfo, pval->data, - result_pool); + iterpool); if (err) { if (err->apr_err == SVN_ERR_MERGEINFO_PARSE_ERROR) @@ -5154,10 +5167,12 @@ txn_body_get_mergeinfo_data_and_entries(void *baton, trail_t *trail) } else { - svn_hash_sets(args->result_catalog, - svn_fspath__join(args->node_path, dirent->name, - result_pool), - child_mergeinfo); + SVN_ERR(args->receiver(svn_fspath__join(args->node_path, + dirent->name, + iterpool), + child_mergeinfo, + args->receiver_baton, + iterpool)); } } @@ -5191,7 +5206,8 @@ static svn_error_t * crawl_directory_for_mergeinfo(svn_fs_t *fs, dag_node_t *node, const char *node_path, - svn_mergeinfo_catalog_t result_catalog, + svn_fs_mergeinfo_receiver_t receiver, + void *baton, apr_pool_t *pool) { struct get_mergeinfo_data_and_entries_baton gmdae_args; @@ -5201,10 +5217,11 @@ crawl_directory_for_mergeinfo(svn_fs_t *fs, /* Add mergeinfo for immediate children that have it, and fetch immediate children that *don't* have it but sit atop trees that do. */ - gmdae_args.result_catalog = result_catalog; gmdae_args.children_atop_mergeinfo_trees = children_atop_mergeinfo_trees; gmdae_args.node = node; gmdae_args.node_path = node_path; + gmdae_args.receiver = receiver; + gmdae_args.receiver_baton = baton; SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_get_mergeinfo_data_and_entries, &gmdae_args, FALSE, pool)); @@ -5226,7 +5243,7 @@ crawl_directory_for_mergeinfo(svn_fs_t *fs, SVN_ERR(crawl_directory_for_mergeinfo(fs, val, svn_fspath__join(node_path, key, iterpool), - result_catalog, iterpool)); + receiver, baton, iterpool)); } svn_pool_destroy(iterpool); return SVN_NO_ERROR; @@ -5384,20 +5401,21 @@ txn_body_get_node_mergeinfo_stats(void *baton, trail_t *trail) } -/* Get the mergeinfo for a set of paths, returned in - *MERGEINFO_CATALOG. Returned values are allocated in POOL, while - temporary values are allocated in a sub-pool. */ +/* Find all the mergeinfo for a set of PATHS under ROOT and report it + through RECEIVER with BATON. INHERITED, INCLUDE_DESCENDANTS and + ADJUST_INHERITED_MERGEINFO are the same as in the FS API. + + Allocate temporary values are allocated in SCRATCH_POOL. */ static svn_error_t * get_mergeinfos_for_paths(svn_fs_root_t *root, - svn_mergeinfo_catalog_t *mergeinfo_catalog, const apr_array_header_t *paths, svn_mergeinfo_inheritance_t inherit, svn_boolean_t include_descendants, svn_boolean_t adjust_inherited_mergeinfo, - apr_pool_t *result_pool, + svn_fs_mergeinfo_receiver_t receiver, + void *baton, apr_pool_t *scratch_pool) { - svn_mergeinfo_catalog_t result_catalog = apr_hash_make(result_pool); apr_pool_t *iterpool = svn_pool_create(scratch_pool); int i; @@ -5416,14 +5434,13 @@ get_mergeinfos_for_paths(svn_fs_root_t *root, gmfp_args.root = root; gmfp_args.path = path; gmfp_args.inherit = inherit; - gmfp_args.pool = result_pool; + gmfp_args.pool = iterpool; gmfp_args.adjust_inherited_mergeinfo = adjust_inherited_mergeinfo; SVN_ERR(svn_fs_base__retry_txn(root->fs, txn_body_get_mergeinfo_for_path, &gmfp_args, FALSE, iterpool)); if (path_mergeinfo) - svn_hash_sets(result_catalog, apr_pstrdup(result_pool, path), - path_mergeinfo); + SVN_ERR(receiver(path, path_mergeinfo, baton, iterpool)); /* If we're including descendants, do so. */ if (include_descendants) @@ -5449,26 +5466,25 @@ get_mergeinfos_for_paths(svn_fs_root_t *root, /* If it's worth crawling, crawl. */ if (do_crawl) SVN_ERR(crawl_directory_for_mergeinfo(root->fs, gnms_args.node, - path, result_catalog, + path, receiver, baton, iterpool)); } } svn_pool_destroy(iterpool); - *mergeinfo_catalog = result_catalog; return SVN_NO_ERROR; } /* Implements svn_fs_get_mergeinfo. */ static svn_error_t * -base_get_mergeinfo(svn_mergeinfo_catalog_t *catalog, - svn_fs_root_t *root, +base_get_mergeinfo(svn_fs_root_t *root, const apr_array_header_t *paths, svn_mergeinfo_inheritance_t inherit, svn_boolean_t include_descendants, svn_boolean_t adjust_inherited_mergeinfo, - apr_pool_t *result_pool, + svn_fs_mergeinfo_receiver_t receiver, + void *baton, apr_pool_t *scratch_pool) { /* Verify that our filesystem version supports mergeinfo stuff. */ @@ -5480,10 +5496,11 @@ base_get_mergeinfo(svn_mergeinfo_catalog_t *catalog, return svn_error_create(SVN_ERR_FS_NOT_REVISION_ROOT, NULL, NULL); /* Retrieve a path -> mergeinfo mapping. */ - return get_mergeinfos_for_paths(root, catalog, paths, + return get_mergeinfos_for_paths(root, paths, inherit, include_descendants, adjust_inherited_mergeinfo, - result_pool, scratch_pool); + receiver, baton, + scratch_pool); } @@ -5493,6 +5510,7 @@ base_get_mergeinfo(svn_mergeinfo_catalog_t *catalog, static root_vtable_t root_vtable = { base_paths_changed, + NULL, base_check_path, base_node_history, base_node_id, diff --git a/subversion/libsvn_fs_fs/cached_data.c b/subversion/libsvn_fs_fs/cached_data.c index 6581a6c8831c..f8fa2d05bfd6 100644 --- a/subversion/libsvn_fs_fs/cached_data.c +++ b/subversion/libsvn_fs_fs/cached_data.c @@ -57,7 +57,7 @@ block_read(void **result, apr_pool_t *scratch_pool); -/* Defined this to enable access logging via dgb__log_access +/* Define this to enable access logging via dbg_log_access #define SVN_FS_FS__LOG_ACCESS */ @@ -91,7 +91,7 @@ dbg_log_access(svn_fs_t *fs, svn_fs_fs__revision_file_t *rev_file; SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&rev_file, fs, revision, - scratch_pool)); + scratch_pool, scratch_pool)); /* determine rev / pack file offset */ SVN_ERR(svn_fs_fs__item_offset(&offset, fs, rev_file, revision, NULL, @@ -158,7 +158,8 @@ dbg_log_access(svn_fs_t *fs, { /* reverse index lookup: get item description in ENTRY */ SVN_ERR(svn_fs_fs__p2l_entry_lookup(&entry, fs, rev_file, revision, - offset, scratch_pool)); + offset, scratch_pool, + scratch_pool)); if (entry) { /* more details */ @@ -183,6 +184,10 @@ dbg_log_access(svn_fs_t *fs, description); } + /* We don't know when SCRATCH_POOL will be cleared, so close the rev file + explicitly. */ + SVN_ERR(svn_fs_fs__close_revision_file(rev_file)); + #endif return SVN_NO_ERROR; @@ -286,6 +291,114 @@ use_block_read(svn_fs_t *fs) return svn_fs_fs__use_log_addressing(fs) && ffd->use_block_read; } +svn_error_t * +svn_fs_fs__fixup_expanded_size(svn_fs_t *fs, + representation_t *rep, + apr_pool_t *scratch_pool) +{ + svn_checksum_t checksum; + svn_checksum_t *empty_md5; + svn_fs_fs__revision_file_t *revision_file; + svn_fs_fs__rep_header_t *rep_header; + + /* Anything to do at all? + * + * Note that a 0 SIZE is only possible for PLAIN reps due to the SVN\1 + * magic prefix in any DELTA rep. */ + if (!rep || rep->expanded_size != 0 || rep->size == 0) + return SVN_NO_ERROR; + + /* This function may only be called for committed data. */ + assert(!svn_fs_fs__id_txn_used(&rep->txn_id)); + + /* EXPANDED_SIZE is 0. If the MD5 does not match the one for empty + * contents, we know that EXPANDED_SIZE == 0 is wrong and needs to + * be set to the actual value given by SIZE. + * + * Using svn_checksum_match() will also accept all-zero values for + * the MD5 digest and only report a mismatch if the MD5 has actually + * been given. */ + empty_md5 = svn_checksum_empty_checksum(svn_checksum_md5, scratch_pool); + + checksum.digest = rep->md5_digest; + checksum.kind = svn_checksum_md5; + if (!svn_checksum_match(empty_md5, &checksum)) + { + rep->expanded_size = rep->size; + return SVN_NO_ERROR; + } + + /* Data in the rep-cache.db does not have MD5 checksums (all zero) on it. + * Compare SHA1 instead. */ + if (rep->has_sha1) + { + svn_checksum_t *empty_sha1 + = svn_checksum_empty_checksum(svn_checksum_sha1, scratch_pool); + + checksum.digest = rep->sha1_digest; + checksum.kind = svn_checksum_sha1; + if (!svn_checksum_match(empty_sha1, &checksum)) + { + rep->expanded_size = rep->size; + return SVN_NO_ERROR; + } + } + + /* Only two cases are left here. + * (1) A non-empty PLAIN rep with a MD5 collision on EMPTY_MD5. + * (2) A DELTA rep with zero-length output. */ + + /* SVN always stores a DELTA rep with zero-length output as an empty + * sequence of txdelta windows, i.e. as "SVN\1". In that case, SIZE is + * 4 bytes. There is no other possible DELTA rep of that size and any + * PLAIN rep of 4 bytes would produce a different MD5. Hence, if SIZE is + * actually 4 here, we know that this is an empty DELTA rep. + * + * Note that it is technically legal to have DELTA reps with a 0 length + * output window. Their on-disk size would be longer. We handle that + * case later together with the equally unlikely MD5 collision. */ + if (rep->size == 4) + { + /* EXPANDED_SIZE is already 0. */ + return SVN_NO_ERROR; + } + + /* We still have the two options, PLAIN or DELTA rep. At this point, we + * are in an extremely unlikely case and can spend some time to figure it + * out. So, let's just look at the representation header. */ + SVN_ERR(open_and_seek_revision(&revision_file, fs, rep->revision, + rep->item_index, scratch_pool)); + SVN_ERR(svn_fs_fs__read_rep_header(&rep_header, revision_file->stream, + scratch_pool, scratch_pool)); + SVN_ERR(svn_fs_fs__close_revision_file(revision_file)); + + /* Only for PLAIN reps do we have to correct EXPANDED_SIZE. */ + if (rep_header->type == svn_fs_fs__rep_plain) + rep->expanded_size = rep->size; + + return SVN_NO_ERROR; +} + +/* Correct known issues with committed NODEREV in FS. + * Uses SCRATCH_POOL for temporaries. + */ +static svn_error_t * +fixup_node_revision(svn_fs_t *fs, + node_revision_t *noderev, + apr_pool_t *scratch_pool) +{ + /* Workaround issue #4031: is-fresh-txn-root in revision files. */ + noderev->is_fresh_txn_root = FALSE; + + /* Make sure EXPANDED_SIZE has the correct value for every rep. */ + SVN_ERR(svn_fs_fs__fixup_expanded_size(fs, noderev->data_rep, + scratch_pool)); + SVN_ERR(svn_fs_fs__fixup_expanded_size(fs, noderev->prop_rep, + scratch_pool)); + + return SVN_NO_ERROR; +} + /* Get the node-revision for the node ID in FS. Set *NODEREV_P to the new node-revision structure, allocated in POOL. See svn_fs_fs__get_node_revision, which wraps this and adds another @@ -312,14 +425,13 @@ get_node_revision_body(node_revision_t **noderev_p, scratch_pool), APR_READ | APR_BUFFERED, APR_OS_DEFAULT, scratch_pool); - if (err) + if (err && APR_STATUS_IS_ENOENT(err->apr_err)) + { + svn_error_clear(err); + return svn_error_trace(err_dangling_id(fs, id)); + } + else if (err) { - if (APR_STATUS_IS_ENOENT(err->apr_err)) - { - svn_error_clear(err); - return svn_error_trace(err_dangling_id(fs, id)); - } - return svn_error_trace(err); } @@ -376,9 +488,7 @@ get_node_revision_body(node_revision_t **noderev_p, revision_file->stream, result_pool, scratch_pool)); - - /* Workaround issue #4031: is-fresh-txn-root in revision files. */ - (*noderev_p)->is_fresh_txn_root = FALSE; + SVN_ERR(fixup_node_revision(fs, *noderev_p, scratch_pool)); /* The noderev is not in cache, yet. Add it, if caching has been enabled. */ if (ffd->node_revision_cache) @@ -636,15 +746,15 @@ typedef struct rep_state_t int chunk_index; /* number of the window to read */ } rep_state_t; -/* Simple wrapper around svn_fs_fs__get_file_offset to simplify callers. */ +/* Simple wrapper around svn_io_file_get_offset to simplify callers. */ static svn_error_t * get_file_offset(apr_off_t *offset, rep_state_t *rs, apr_pool_t *pool) { - return svn_error_trace(svn_fs_fs__get_file_offset(offset, - rs->sfile->rfile->file, - pool)); + return svn_error_trace(svn_io_file_get_offset(offset, + rs->sfile->rfile->file, + pool)); } /* Simple wrapper around svn_io_file_aligned_seek to simplify callers. */ @@ -756,7 +866,7 @@ create_rep_state_body(rep_state_t **rep_state, rs->size = rep->size; rs->revision = rep->revision; rs->item_index = rep->item_index; - rs->raw_window_cache = ffd->raw_window_cache; + rs->raw_window_cache = use_block_read(fs) ? ffd->raw_window_cache : NULL; rs->ver = -1; rs->start = -1; @@ -765,9 +875,7 @@ create_rep_state_body(rep_state_t **rep_state, Since we don't know the depth of the delta chain, let's assume, the whole contents get rewritten 3 times. */ - estimated_window_storage - = 4 * ( (rep->expanded_size ? rep->expanded_size : rep->size) - + SVN_DELTA_WINDOW_SIZE); + estimated_window_storage = 4 * (rep->expanded_size + SVN_DELTA_WINDOW_SIZE); estimated_window_storage = MIN(estimated_window_storage, APR_SIZE_MAX); rs->window_cache = ffd->txdelta_window_cache @@ -1160,7 +1268,7 @@ parse_raw_window(void **out, stream = svn_stream_from_string(&raw_window, result_pool); /* parse it */ - SVN_ERR(svn_txdelta_read_svndiff_window(&result->window, stream, 1, + SVN_ERR(svn_txdelta_read_svndiff_window(&result->window, stream, window->ver, result_pool)); /* complete the window and return it */ @@ -1322,15 +1430,11 @@ set_cached_combined_window(svn_stringbuf_t *window, ID, and representation REP. Also, set *WINDOW_P to the base window content for *LIST, if it could be found in cache. Otherwise, *LIST will contain the base - representation for the whole delta chain. - Finally, return the expanded size of the representation in - *EXPANDED_SIZE. It will take care of cases where only the on-disk - size is known. */ + representation for the whole delta chain. */ static svn_error_t * build_rep_list(apr_array_header_t **list, svn_stringbuf_t **window_p, rep_state_t **src_state, - svn_filesize_t *expanded_size, svn_fs_t *fs, representation_t *first_rep, apr_pool_t *pool) @@ -1345,24 +1449,9 @@ build_rep_list(apr_array_header_t **list, *list = apr_array_make(pool, 1, sizeof(rep_state_t *)); rep = *first_rep; - /* The value as stored in the data struct. - 0 is either for unknown length or actually zero length. */ - *expanded_size = first_rep->expanded_size; - /* for the top-level rep, we need the rep_args */ SVN_ERR(create_rep_state(&rs, &rep_header, &shared_file, &rep, fs, pool, iterpool)); - - /* Unknown size or empty representation? - That implies the this being the first iteration. - Usually size equals on-disk size, except for empty, - compressed representations (delta, size = 4). - Please note that for all non-empty deltas have - a 4-byte header _plus_ some data. */ - if (*expanded_size == 0) - if (rep_header->type == svn_fs_fs__rep_plain || first_rep->size != 4) - *expanded_size = first_rep->size; - while (1) { svn_pool_clear(iterpool); @@ -1373,7 +1462,8 @@ build_rep_list(apr_array_header_t **list, &rep, fs, pool, iterpool)); /* for txn reps, there won't be a cached combined window */ - if (!svn_fs_fs__id_txn_used(&rep.txn_id)) + if ( !svn_fs_fs__id_txn_used(&rep.txn_id) + && rep.expanded_size < SVN_DELTA_WINDOW_SIZE) SVN_ERR(get_cached_combined_window(window_p, rs, &is_cached, pool)); if (is_cached) @@ -1686,7 +1776,7 @@ get_combined_window(svn_stringbuf_t **result, } /* Returns whether or not the expanded fulltext of the file is cachable - * based on its size SIZE. The decision depends on the cache used by RB. + * based on its size SIZE. The decision depends on the cache used by FFD. */ static svn_boolean_t fulltext_size_is_cachable(fs_fs_data_t *ffd, svn_filesize_t size) @@ -1732,10 +1822,10 @@ get_contents_from_windows(struct rep_read_baton *rb, This is where we need the pseudo rep_state created by build_rep_list(). */ apr_size_t offset = (apr_size_t)rs->current; - if (copy_len + offset > rb->base_window->len) - copy_len = offset < rb->base_window->len - ? rb->base_window->len - offset - : 0ul; + if (offset >= rb->base_window->len) + copy_len = 0ul; + else if (copy_len > rb->base_window->len - offset) + copy_len = rb->base_window->len - offset; memcpy (cur, rb->base_window->data + offset, copy_len); } @@ -1969,11 +2059,21 @@ skip_contents(struct rep_read_baton *baton, len -= to_read; buffer += to_read; } + + /* Make the MD5 calculation catch up with the data delivered + * (we did not run MD5 on the data that we took from the cache). */ + if (!err) + { + SVN_ERR(svn_checksum_update(baton->md5_checksum_ctx, + baton->current_fulltext->data, + baton->current_fulltext->len)); + baton->off += baton->current_fulltext->len; + } } else if (len > 0) { /* Simply drain LEN bytes from the window stream. */ - apr_pool_t *subpool = subpool = svn_pool_create(baton->pool); + apr_pool_t *subpool = svn_pool_create(baton->pool); char *buffer = apr_palloc(subpool, SVN__STREAM_CHUNK_SIZE); while (len > 0 && !err) @@ -1984,6 +2084,15 @@ skip_contents(struct rep_read_baton *baton, err = get_contents_from_windows(baton, buffer, &to_read); len -= to_read; + + /* Make the MD5 calculation catch up with the data delivered + * (we did not run MD5 on the data that we took from the cache). */ + if (!err) + { + SVN_ERR(svn_checksum_update(baton->md5_checksum_ctx, + buffer, to_read)); + baton->off += to_read; + } } svn_pool_destroy(subpool); @@ -2019,8 +2128,9 @@ rep_read_contents(void *baton, if (!rb->rs_list) { /* Window stream not initialized, yet. Do it now. */ + rb->len = rb->rep.expanded_size; SVN_ERR(build_rep_list(&rb->rs_list, &rb->base_window, - &rb->src_state, &rb->len, rb->fs, &rb->rep, + &rb->src_state, rb->fs, &rb->rep, rb->filehandle_pool)); /* In case we did read from the fulltext cache before, make the @@ -2092,7 +2202,6 @@ svn_fs_fs__get_contents(svn_stream_t **contents_p, else { fs_fs_data_t *ffd = fs->fsap_data; - svn_filesize_t len = rep->expanded_size ? rep->expanded_size : rep->size; struct rep_read_baton *rb; pair_cache_key_t fulltext_cache_key = { 0 }; @@ -2108,7 +2217,7 @@ svn_fs_fs__get_contents(svn_stream_t **contents_p, * cache it. */ if (ffd->fulltext_cache && cache_fulltext && SVN_IS_VALID_REVNUM(rep->revision) - && fulltext_size_is_cachable(ffd, len)) + && fulltext_size_is_cachable(ffd, rep->expanded_size)) { rb->fulltext_cache = ffd->fulltext_cache; } @@ -2202,7 +2311,7 @@ svn_fs_fs__get_contents_from_file(svn_stream_t **contents_p, svn_fs_fs__id_txn_reset(&next_rep.txn_id); SVN_ERR(build_rep_list(&rb->rs_list, &rb->base_window, - &rb->src_state, &rb->len, rb->fs, &next_rep, + &rb->src_state, rb->fs, &next_rep, rb->filehandle_pool)); /* Insert the access to REP as the first element of the delta chain. */ @@ -2447,12 +2556,12 @@ compare_dirent_name(const void *a, const void *b) return strcmp(lhs->name, rhs); } -/* Into ENTRIES, read all directories entries from the key-value text in +/* Into *ENTRIES_P, read all directories entries from the key-value text in * STREAM. If INCREMENTAL is TRUE, read until the end of the STREAM and * update the data. ID is provided for nicer error messages. */ static svn_error_t * -read_dir_entries(apr_array_header_t *entries, +read_dir_entries(apr_array_header_t **entries_p, svn_stream_t *stream, svn_boolean_t incremental, const svn_fs_id_t *id, @@ -2460,8 +2569,14 @@ read_dir_entries(apr_array_header_t *entries, apr_pool_t *scratch_pool) { apr_pool_t *iterpool = svn_pool_create(scratch_pool); - apr_hash_t *hash = incremental ? svn_hash__make(scratch_pool) : NULL; + apr_hash_t *hash = NULL; const char *terminator = SVN_HASH_TERMINATOR; + apr_array_header_t *entries = NULL; + + if (incremental) + hash = svn_hash__make(scratch_pool); + else + entries = apr_array_make(result_pool, 16, sizeof(svn_fs_dirent_t *)); /* Read until the terminator (non-incremental) or the end of STREAM (incremental mode). In the latter mode, we use a temporary HASH @@ -2473,8 +2588,11 @@ read_dir_entries(apr_array_header_t *entries, char *str; svn_pool_clear(iterpool); - SVN_ERR(svn_hash__read_entry(&entry, stream, terminator, - incremental, iterpool)); + SVN_ERR_W(svn_hash__read_entry(&entry, stream, terminator, + incremental, iterpool), + apr_psprintf(iterpool, + _("Directory representation corrupt in '%s'"), + svn_fs_fs__id_unparse(id, scratch_pool)->data)); /* End of directory? */ if (entry.key == NULL) @@ -2542,6 +2660,9 @@ read_dir_entries(apr_array_header_t *entries, if (incremental) { apr_hash_index_t *hi; + + entries = apr_array_make(result_pool, apr_hash_count(hash), + sizeof(svn_fs_dirent_t *)); for (hi = apr_hash_first(iterpool, hash); hi; hi = apr_hash_next(hi)) APR_ARRAY_PUSH(entries, svn_fs_dirent_t *) = apr_hash_this_val(hi); } @@ -2551,14 +2672,45 @@ read_dir_entries(apr_array_header_t *entries, svn_pool_destroy(iterpool); + *entries_p = entries; return SVN_NO_ERROR; } -/* Fetch the contents of a directory into ENTRIES. Values are stored +/* For directory NODEREV in FS, return the *FILESIZE of its in-txn + * representation. If the directory representation is comitted data, + * set *FILESIZE to SVN_INVALID_FILESIZE. Use SCRATCH_POOL for temporaries. + */ +static svn_error_t * +get_txn_dir_info(svn_filesize_t *filesize, + svn_fs_t *fs, + node_revision_t *noderev, + apr_pool_t *scratch_pool) +{ + if (noderev->data_rep && svn_fs_fs__id_txn_used(&noderev->data_rep->txn_id)) + { + const svn_io_dirent2_t *dirent; + const char *filename; + + filename = svn_fs_fs__path_txn_node_children(fs, noderev->id, + scratch_pool); + + SVN_ERR(svn_io_stat_dirent2(&dirent, filename, FALSE, FALSE, + scratch_pool, scratch_pool)); + *filesize = dirent->filesize; + } + else + { + *filesize = SVN_INVALID_FILESIZE; + } + + return SVN_NO_ERROR; +} + +/* Fetch the contents of a directory into DIR. Values are stored as filename to string mappings; further conversion is necessary to convert them into svn_fs_dirent_t values. */ static svn_error_t * -get_dir_contents(apr_array_header_t **entries, +get_dir_contents(svn_fs_fs__dir_data_t *dir, svn_fs_t *fs, node_revision_t *noderev, apr_pool_t *result_pool, @@ -2566,18 +2718,30 @@ get_dir_contents(apr_array_header_t **entries, { svn_stream_t *contents; - *entries = apr_array_make(result_pool, 16, sizeof(svn_fs_dirent_t *)); + /* Initialize the result. */ + dir->txn_filesize = SVN_INVALID_FILESIZE; + + /* Read dir contents - unless there is none in which case we are done. */ if (noderev->data_rep && svn_fs_fs__id_txn_used(&noderev->data_rep->txn_id)) { - const char *filename - = svn_fs_fs__path_txn_node_children(fs, noderev->id, scratch_pool); + /* Get location & current size of the directory representation. */ + const char *filename; + apr_file_t *file; + + filename = svn_fs_fs__path_txn_node_children(fs, noderev->id, + scratch_pool); /* The representation is mutable. Read the old directory contents from the mutable children file, followed by the changes we've made in this transaction. */ - SVN_ERR(svn_stream_open_readonly(&contents, filename, scratch_pool, - scratch_pool)); - SVN_ERR(read_dir_entries(*entries, contents, TRUE, noderev->id, + SVN_ERR(svn_io_file_open(&file, filename, APR_READ | APR_BUFFERED, + APR_OS_DEFAULT, scratch_pool)); + + /* Obtain txn children file size. */ + SVN_ERR(svn_io_file_size_get(&dir->txn_filesize, file, scratch_pool)); + + contents = svn_stream_from_aprfile2(file, FALSE, scratch_pool); + SVN_ERR(read_dir_entries(&dir->entries, contents, TRUE, noderev->id, result_pool, scratch_pool)); SVN_ERR(svn_stream_close(contents)); } @@ -2586,9 +2750,7 @@ get_dir_contents(apr_array_header_t **entries, /* Undeltify content before parsing it. Otherwise, we could only * parse it byte-by-byte. */ - apr_size_t len = noderev->data_rep->expanded_size - ? (apr_size_t)noderev->data_rep->expanded_size - : (apr_size_t)noderev->data_rep->size; + apr_size_t len = noderev->data_rep->expanded_size; svn_stringbuf_t *text; /* The representation is immutable. Read it normally. */ @@ -2599,9 +2761,13 @@ get_dir_contents(apr_array_header_t **entries, /* de-serialize hash */ contents = svn_stream_from_stringbuf(text, scratch_pool); - SVN_ERR(read_dir_entries(*entries, contents, FALSE, noderev->id, + SVN_ERR(read_dir_entries(&dir->entries, contents, FALSE, noderev->id, result_pool, scratch_pool)); } + else + { + dir->entries = apr_array_make(result_pool, 0, sizeof(svn_fs_dirent_t *)); + } return SVN_NO_ERROR; } @@ -2620,27 +2786,27 @@ locate_dir_cache(svn_fs_t *fs, apr_pool_t *pool) { fs_fs_data_t *ffd = fs->fsap_data; - if (svn_fs_fs__id_is_txn(noderev->id)) + if (!noderev->data_rep) + { + /* no data rep -> empty directory. + A NULL key causes a cache miss. */ + *key = NULL; + return ffd->dir_cache; + } + + if (svn_fs_fs__id_txn_used(&noderev->data_rep->txn_id)) { /* data in txns requires the expensive fs_id-based addressing mode */ *key = svn_fs_fs__id_unparse(noderev->id, pool)->data; + return ffd->txn_dir_cache; } else { /* committed data can use simple rev,item pairs */ - if (noderev->data_rep) - { - pair_key->revision = noderev->data_rep->revision; - pair_key->second = noderev->data_rep->item_index; - *key = pair_key; - } - else - { - /* no data rep -> empty directory. - A NULL key causes a cache miss. */ - *key = NULL; - } + pair_key->revision = noderev->data_rep->revision; + pair_key->second = noderev->data_rep->item_index; + *key = pair_key; return ffd->dir_cache; } @@ -2655,6 +2821,7 @@ svn_fs_fs__rep_contents_dir(apr_array_header_t **entries_p, { pair_cache_key_t pair_key = { 0 }; const void *key; + svn_fs_fs__dir_data_t *dir; /* find the cache we may use */ svn_cache__t *cache = locate_dir_cache(fs, &key, &pair_key, noderev, @@ -2663,23 +2830,36 @@ svn_fs_fs__rep_contents_dir(apr_array_header_t **entries_p, { svn_boolean_t found; - SVN_ERR(svn_cache__get((void **)entries_p, &found, cache, key, + SVN_ERR(svn_cache__get((void **)&dir, &found, cache, key, result_pool)); if (found) - return SVN_NO_ERROR; + { + /* Verify that the cached dir info is not stale + * (no-op for committed data). */ + svn_filesize_t filesize; + SVN_ERR(get_txn_dir_info(&filesize, fs, noderev, scratch_pool)); + + if (filesize == dir->txn_filesize) + { + /* Still valid. Done. */ + *entries_p = dir->entries; + return SVN_NO_ERROR; + } + } } /* Read in the directory contents. */ - SVN_ERR(get_dir_contents(entries_p, fs, noderev, result_pool, - scratch_pool)); + dir = apr_pcalloc(scratch_pool, sizeof(*dir)); + SVN_ERR(get_dir_contents(dir, fs, noderev, result_pool, scratch_pool)); + *entries_p = dir->entries; /* Update the cache, if we are to use one. * * Don't even attempt to serialize very large directories; it would cause * an unnecessary memory allocation peak. 150 bytes/entry is about right. */ - if (cache && svn_cache__is_cachable(cache, 150 * (*entries_p)->nelts)) - SVN_ERR(svn_cache__set(cache, key, *entries_p, scratch_pool)); + if (cache && svn_cache__is_cachable(cache, 150 * dir->entries->nelts)) + SVN_ERR(svn_cache__set(cache, key, dir, scratch_pool)); return SVN_NO_ERROR; } @@ -2702,6 +2882,7 @@ svn_fs_fs__rep_contents_dir_entry(svn_fs_dirent_t **dirent, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { + extract_dir_entry_baton_t baton; svn_boolean_t found = FALSE; /* find the cache we may use */ @@ -2711,30 +2892,42 @@ svn_fs_fs__rep_contents_dir_entry(svn_fs_dirent_t **dirent, scratch_pool); if (cache) { + svn_filesize_t filesize; + SVN_ERR(get_txn_dir_info(&filesize, fs, noderev, scratch_pool)); + /* Cache lookup. */ + baton.txn_filesize = filesize; + baton.name = name; SVN_ERR(svn_cache__get_partial((void **)dirent, &found, cache, key, svn_fs_fs__extract_dir_entry, - (void*)name, + &baton, result_pool)); } /* fetch data from disk if we did not find it in the cache */ - if (! found) + if (! found || baton.out_of_date) { - apr_array_header_t *entries; svn_fs_dirent_t *entry; svn_fs_dirent_t *entry_copy = NULL; + svn_fs_fs__dir_data_t dir; - /* read the dir from the file system. It will probably be put it - into the cache for faster lookup in future calls. */ - SVN_ERR(svn_fs_fs__rep_contents_dir(&entries, fs, noderev, - scratch_pool, scratch_pool)); + /* Read in the directory contents. */ + SVN_ERR(get_dir_contents(&dir, fs, noderev, scratch_pool, + scratch_pool)); + + /* Update the cache, if we are to use one. + * + * Don't even attempt to serialize very large directories; it would + * cause an unnecessary memory allocation peak. 150 bytes / entry is + * about right. */ + if (cache && svn_cache__is_cachable(cache, 150 * dir.entries->nelts)) + SVN_ERR(svn_cache__set(cache, key, &dir, scratch_pool)); /* find desired entry and return a copy in POOL, if found */ - entry = svn_fs_fs__find_dir_entry(entries, name, NULL); + entry = svn_fs_fs__find_dir_entry(dir.entries, name, NULL); if (entry) { entry_copy = apr_palloc(result_pool, sizeof(*entry_copy)); @@ -2771,7 +2964,7 @@ svn_fs_fs__get_proplist(apr_hash_t **proplist_p, { svn_string_t *id_str = svn_fs_fs__id_unparse(noderev->id, pool); - svn_error_clear(svn_stream_close(stream)); + err = svn_error_compose_create(err, svn_stream_close(stream)); return svn_error_quick_wrapf(err, _("malformed property list for node-revision '%s' in '%s'"), id_str->data, filename); @@ -2803,8 +2996,8 @@ svn_fs_fs__get_proplist(apr_hash_t **proplist_p, if (err) { svn_string_t *id_str = svn_fs_fs__id_unparse(noderev->id, pool); - - svn_error_clear(svn_stream_close(stream)); + + err = svn_error_compose_create(err, svn_stream_close(stream)); return svn_error_quick_wrapf(err, _("malformed property list for node-revision '%s'"), id_str->data); @@ -2826,23 +3019,42 @@ svn_fs_fs__get_proplist(apr_hash_t **proplist_p, } svn_error_t * -svn_fs_fs__get_changes(apr_array_header_t **changes, - svn_fs_t *fs, - svn_revnum_t rev, - apr_pool_t *result_pool) +svn_fs_fs__create_changes_context(svn_fs_fs__changes_context_t **context, + svn_fs_t *fs, + svn_revnum_t rev, + apr_pool_t *result_pool) { - apr_off_t changes_offset = SVN_FS_FS__ITEM_INDEX_CHANGES; - svn_fs_fs__revision_file_t *revision_file; + svn_fs_fs__changes_context_t *result = apr_pcalloc(result_pool, + sizeof(*result)); + result->fs = fs; + result->revision = rev; + result->rev_file_pool = result_pool; + + *context = result; + return SVN_NO_ERROR; +} + +svn_error_t * +svn_fs_fs__get_changes(apr_array_header_t **changes, + svn_fs_fs__changes_context_t *context, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + apr_off_t item_index = SVN_FS_FS__ITEM_INDEX_CHANGES; svn_boolean_t found; - fs_fs_data_t *ffd = fs->fsap_data; - apr_pool_t *scratch_pool = svn_pool_create(result_pool); + fs_fs_data_t *ffd = context->fs->fsap_data; + svn_fs_fs__changes_list_t *changes_list; + + pair_cache_key_t key; + key.revision = context->revision; + key.second = context->next; /* try cache lookup first */ if (ffd->changes_cache) { - SVN_ERR(svn_cache__get((void **) changes, &found, ffd->changes_cache, - &rev, result_pool)); + SVN_ERR(svn_cache__get((void **)&changes_list, &found, + ffd->changes_cache, &key, result_pool)); } else { @@ -2853,61 +3065,113 @@ svn_fs_fs__get_changes(apr_array_header_t **changes, { /* read changes from revision file */ - SVN_ERR(svn_fs_fs__ensure_revision_exists(rev, fs, scratch_pool)); - SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&revision_file, fs, rev, - scratch_pool, scratch_pool)); - - if (use_block_read(fs)) + if (!context->revision_file) { - /* 'block-read' will also provide us with the desired data */ - SVN_ERR(block_read((void **)changes, fs, - rev, SVN_FS_FS__ITEM_INDEX_CHANGES, - revision_file, result_pool, scratch_pool)); + SVN_ERR(svn_fs_fs__ensure_revision_exists(context->revision, + context->fs, + scratch_pool)); + SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&context->revision_file, + context->fs, + context->revision, + context->rev_file_pool, + scratch_pool)); } - else + + if (use_block_read(context->fs)) { + /* 'block-read' will probably populate the cache with the data + * that we want. However, we won't want to force it to process + * very large change lists as part of this prefetching mechanism. + * Those would be better handled by the iterative code below. */ + SVN_ERR(block_read(NULL, context->fs, + context->revision, SVN_FS_FS__ITEM_INDEX_CHANGES, + context->revision_file, scratch_pool, + scratch_pool)); + + /* This may succeed now ... */ + SVN_ERR(svn_cache__get((void **)&changes_list, &found, + ffd->changes_cache, &key, result_pool)); + } + + /* If we still have no data, read it here. */ + if (!found) + { + apr_off_t changes_offset; + /* Addressing is very different for old formats * (needs to read the revision trailer). */ - if (svn_fs_fs__use_log_addressing(fs)) - SVN_ERR(svn_fs_fs__item_offset(&changes_offset, fs, - revision_file, rev, NULL, - SVN_FS_FS__ITEM_INDEX_CHANGES, - scratch_pool)); + if (svn_fs_fs__use_log_addressing(context->fs)) + { + SVN_ERR(svn_fs_fs__item_offset(&changes_offset, context->fs, + context->revision_file, + context->revision, NULL, + SVN_FS_FS__ITEM_INDEX_CHANGES, + scratch_pool)); + } else - SVN_ERR(get_root_changes_offset(NULL, &changes_offset, - revision_file, fs, rev, - scratch_pool)); + { + SVN_ERR(get_root_changes_offset(NULL, &changes_offset, + context->revision_file, + context->fs, context->revision, + scratch_pool)); + + /* This variable will be used for debug logging only. */ + item_index = changes_offset; + } /* Actual reading and parsing are the same, though. */ - SVN_ERR(aligned_seek(fs, revision_file->file, NULL, changes_offset, + SVN_ERR(aligned_seek(context->fs, context->revision_file->file, + NULL, changes_offset + context->next_offset, scratch_pool)); - SVN_ERR(svn_fs_fs__read_changes(changes, revision_file->stream, + + SVN_ERR(svn_fs_fs__read_changes(changes, + context->revision_file->stream, + SVN_FS_FS__CHANGES_BLOCK_SIZE, result_pool, scratch_pool)); + /* Construct the info object for the entries block we just read. */ + changes_list = apr_pcalloc(scratch_pool, sizeof(*changes_list)); + SVN_ERR(svn_io_file_get_offset(&changes_list->end_offset, + context->revision_file->file, + scratch_pool)); + changes_list->end_offset -= changes_offset; + changes_list->start_offset = context->next_offset; + changes_list->count = (*changes)->nelts; + changes_list->changes = (change_t **)(*changes)->elts; + changes_list->eol = changes_list->count < SVN_FS_FS__CHANGES_BLOCK_SIZE; + /* cache for future reference */ if (ffd->changes_cache) - { - /* Guesstimate for the size of the in-cache representation. */ - apr_size_t estimated_size = (apr_size_t)250 * (*changes)->nelts; - - /* Don't even serialize data that probably won't fit into the - * cache. This often implies that either CHANGES is very - * large, memory is scarce or both. Having a huge temporary - * copy would not be a good thing in either case. */ - if (svn_cache__is_cachable(ffd->changes_cache, estimated_size)) - SVN_ERR(svn_cache__set(ffd->changes_cache, &rev, *changes, - scratch_pool)); - } + SVN_ERR(svn_cache__set(ffd->changes_cache, &key, changes_list, + scratch_pool)); } - - SVN_ERR(svn_fs_fs__close_revision_file(revision_file)); } - SVN_ERR(dbg_log_access(fs, rev, changes_offset, *changes, + if (found) + { + /* Return the block as a "proper" APR array. */ + (*changes) = apr_array_make(result_pool, 0, sizeof(void *)); + (*changes)->elts = (char *)changes_list->changes; + (*changes)->nelts = changes_list->count; + (*changes)->nalloc = changes_list->count; + } + + /* Where to look next - if there is more data. */ + context->next += (*changes)->nelts; + context->next_offset = changes_list->end_offset; + context->eol = changes_list->eol; + + /* Close the revision file after we read all data. */ + if (context->eol && context->revision_file) + { + SVN_ERR(svn_fs_fs__close_revision_file(context->revision_file)); + context->revision_file = NULL; + } + + SVN_ERR(dbg_log_access(context->fs, context->revision, item_index, *changes, SVN_FS_FS__ITEM_TYPE_CHANGES, scratch_pool)); - svn_pool_destroy(scratch_pool); return SVN_NO_ERROR; } @@ -2942,7 +3206,7 @@ init_rep_state(rep_state_t *rs, rs->start = entry->offset + rs->header_size; rs->current = rep_header->type == svn_fs_fs__rep_plain ? 0 : 4; rs->size = entry->size - rep_header->header_size - 7; - rs->ver = 1; + rs->ver = -1; rs->chunk_index = 0; rs->raw_window_cache = ffd->raw_window_cache; rs->window_cache = ffd->txdelta_window_cache; @@ -3000,6 +3264,9 @@ cache_windows(svn_fs_t *fs, apr_pool_t *pool) { apr_pool_t *iterpool = svn_pool_create(pool); + + SVN_ERR(auto_read_diff_version(rs, iterpool)); + while (rs->current < rs->size) { apr_off_t end_offset; @@ -3060,6 +3327,7 @@ cache_windows(svn_fs_t *fs, window.end_offset = rs->current; window.window.len = window_len; window.window.data = buf; + window.ver = rs->ver; /* cache the window now */ SVN_ERR(svn_cache__set(rs->raw_window_cache, &key, &window, @@ -3181,9 +3449,8 @@ read_rep_header(svn_fs_fs__rep_header_t **rep_header, /* Fetch the representation data (header, txdelta / plain windows) * addressed by ENTRY->ITEM in FS and cache it if caches are enabled. - * Read the data from the already open FILE and the wrapping - * STREAM object. If MAX_OFFSET is not -1, don't read windows that start - * at or beyond that offset. + * Read the data from REV_FILE. If MAX_OFFSET is not -1, don't read + * windows that start at or beyond that offset. * Use SCRATCH_POOL for temporary allocations. */ static svn_error_t * @@ -3191,7 +3458,6 @@ block_read_contents(svn_fs_t *fs, svn_fs_fs__revision_file_t *rev_file, svn_fs_fs__p2l_entry_t* entry, apr_off_t max_offset, - apr_pool_t *result_pool, apr_pool_t *scratch_pool) { pair_cache_key_t header_key = { 0 }; @@ -3201,9 +3467,9 @@ block_read_contents(svn_fs_t *fs, header_key.second = entry->item.number; SVN_ERR(read_rep_header(&rep_header, fs, rev_file->stream, &header_key, - result_pool, scratch_pool)); + scratch_pool, scratch_pool)); SVN_ERR(block_read_windows(rep_header, fs, rev_file, entry, max_offset, - result_pool, scratch_pool)); + scratch_pool, scratch_pool)); return SVN_NO_ERROR; } @@ -3252,37 +3518,39 @@ read_item(svn_stream_t **stream, _("Low-level checksum mismatch while reading\n" "%s bytes of meta data at offset %s " "for item %s in revision %ld"), - apr_psprintf(pool, "%" APR_OFF_T_FMT, entry->size), - apr_psprintf(pool, "%" APR_OFF_T_FMT, entry->offset), + apr_off_t_toa(pool, entry->size), + apr_off_t_toa(pool, entry->offset), apr_psprintf(pool, "%" APR_UINT64_T_FMT, entry->item.number), entry->item.revision); } -/* If not already cached or if MUST_READ is set, read the changed paths - * list addressed by ENTRY in FS and retúrn it in *CHANGES. Cache the - * result if caching is enabled. Read the data from the already open - * FILE and wrapping FILE_STREAM. Use POOL for allocations. +/* If not already cached, read the changed paths list addressed by ENTRY in + * FS and cache it if it has no more than SVN_FS_FS__CHANGES_BLOCK_SIZE + * entries and caching is enabled. Read the data from REV_FILE. + * Allocate temporaries in SCRATCH_POOL. */ static svn_error_t * -block_read_changes(apr_array_header_t **changes, - svn_fs_t *fs, +block_read_changes(svn_fs_t *fs, svn_fs_fs__revision_file_t *rev_file, svn_fs_fs__p2l_entry_t *entry, - svn_boolean_t must_read, - apr_pool_t *result_pool, apr_pool_t *scratch_pool) { fs_fs_data_t *ffd = fs->fsap_data; svn_stream_t *stream; - if (!must_read && !ffd->changes_cache) + apr_array_header_t *changes; + + pair_cache_key_t key; + key.revision = entry->item.revision; + key.second = 0; + + if (!ffd->changes_cache) return SVN_NO_ERROR; /* already in cache? */ - if (!must_read && ffd->changes_cache) + if (ffd->changes_cache) { svn_boolean_t is_cached; - SVN_ERR(svn_cache__has_key(&is_cached, ffd->changes_cache, - &entry->item.revision, + SVN_ERR(svn_cache__has_key(&is_cached, ffd->changes_cache, &key, scratch_pool)); if (is_cached) return SVN_NO_ERROR; @@ -3290,22 +3558,40 @@ block_read_changes(apr_array_header_t **changes, SVN_ERR(read_item(&stream, fs, rev_file, entry, scratch_pool)); - /* read changes from revision file */ - SVN_ERR(svn_fs_fs__read_changes(changes, stream, result_pool, - scratch_pool)); + /* Read changes from revision file. But read just past the first block to + enable us to determine whether the first block already hit the EOL. - /* cache for future reference */ - if (ffd->changes_cache) - SVN_ERR(svn_cache__set(ffd->changes_cache, &entry->item.revision, - *changes, scratch_pool)); + Note: A 100 entries block is already > 10kB on disk. With a 4kB default + disk block size, this function won't even be called for larger + changed paths lists. */ + SVN_ERR(svn_fs_fs__read_changes(&changes, stream, + SVN_FS_FS__CHANGES_BLOCK_SIZE + 1, + scratch_pool, scratch_pool)); + + /* We can only cache small lists that don't need to be split up. + For longer lists, we miss the file offset info for the respective */ + if (changes->nelts <= SVN_FS_FS__CHANGES_BLOCK_SIZE) + { + svn_fs_fs__changes_list_t changes_list; + + /* Construct the info object for the entries block we just read. */ + changes_list.end_offset = entry->size; + changes_list.start_offset = 0; + changes_list.count = changes->nelts; + changes_list.changes = (change_t **)changes->elts; + changes_list.eol = TRUE; + + SVN_ERR(svn_cache__set(ffd->changes_cache, &key, &changes_list, + scratch_pool)); + } return SVN_NO_ERROR; } -/* If not already cached or if MUST_READ is set, read the nod revision +/* If not already cached or if MUST_READ is set, read the node revision * addressed by ENTRY in FS and retúrn it in *NODEREV_P. Cache the - * result if caching is enabled. Read the data from the already open - * FILE and wrapping FILE_STREAM. Use SCRATCH_POOL for temporary allocations. + * result if caching is enabled. Read the data from REV_FILE. Allocate + * *NODEREV_P in RESUSLT_POOL and allocate temporaries in SCRATCH_POOL. */ static svn_error_t * block_read_noderev(node_revision_t **noderev_p, @@ -3341,9 +3627,7 @@ block_read_noderev(node_revision_t **noderev_p, /* read node rev from revision file */ SVN_ERR(svn_fs_fs__read_noderev(noderev_p, stream, result_pool, scratch_pool)); - - /* Workaround issue #4031: is-fresh-txn-root in revision files. */ - (*noderev_p)->is_fresh_txn_root = FALSE; + SVN_ERR(fixup_node_revision(fs, *noderev_p, scratch_pool)); if (ffd->node_revision_cache) SVN_ERR(svn_cache__set(ffd->node_revision_cache, &key, *noderev_p, @@ -3457,7 +3741,7 @@ block_read(void **result, is_wanted ? -1 : block_start + ffd->block_size, - pool, iterpool)); + iterpool)); break; case SVN_FS_FS__ITEM_TYPE_NODEREV: @@ -3469,10 +3753,8 @@ block_read(void **result, break; case SVN_FS_FS__ITEM_TYPE_CHANGES: - SVN_ERR(block_read_changes((apr_array_header_t **)&item, - fs, revision_file, - entry, is_result, - pool, iterpool)); + SVN_ERR(block_read_changes(fs, revision_file, + entry, iterpool)); break; default: @@ -3485,7 +3767,7 @@ block_read(void **result, /* if we crossed a block boundary, read the remainder of * the last block as well */ offset = entry->offset + entry->size; - if (offset > block_start + ffd->block_size) + if (offset - block_start > ffd->block_size) ++run_count; } } diff --git a/subversion/libsvn_fs_fs/cached_data.h b/subversion/libsvn_fs_fs/cached_data.h index 07fa956765e0..7b25fcf43cda 100644 --- a/subversion/libsvn_fs_fs/cached_data.h +++ b/subversion/libsvn_fs_fs/cached_data.h @@ -30,6 +30,18 @@ +/* Resolve a FSFS quirk: if REP in FS is a "PLAIN" representation, its + * EXPANDED_SIZE element may be 0, in which case its value has to be taken + * from SIZE. + * + * This function ensures that EXPANDED_SIZE in REP always contains the + * actual value. No-op if REP is NULL. Uses SCRATCH_POOL for temporaries. + */ +svn_error_t * +svn_fs_fs__fixup_expanded_size(svn_fs_t *fs, + representation_t *rep, + apr_pool_t *scratch_pool); + /* Set *NODEREV_P to the node-revision for the node ID in FS. Do any allocations in POOL. */ svn_error_t * @@ -69,7 +81,7 @@ svn_fs_fs__rep_chain_length(int *chain_length, svn_fs_t *fs, apr_pool_t *scratch_pool); -/* Set *CONTENTS to be a readable svn_stream_t that receives the text +/* Set *CONTENTS_P to be a readable svn_stream_t that receives the text representation REP as seen in filesystem FS. If CACHE_FULLTEXT is not set, bypass fulltext cache lookup for this rep and don't put the reconstructed fulltext into cache. @@ -158,21 +170,22 @@ svn_fs_fs__get_proplist(apr_hash_t **proplist, node_revision_t *noderev, apr_pool_t *pool); -/* Set *HAS_PROPS to TRUE if NODEREV has properties in FS, otherwise - to FALSE. Use SCRATCH_POOL for temporary allocations. */ +/* Create a changes retrieval context object in *RESULT_POOL and return it + * in *CONTEXT. It will allow svn_fs_x__get_changes to fetch consecutive + * blocks (one per invocation) from REV's changed paths list in FS. */ svn_error_t * -svn_fs_fs__has_props(svn_boolean_t *has_props, - svn_fs_t *fs, - node_revision_t *noderev, - apr_pool_t *scratch_pool); +svn_fs_fs__create_changes_context(svn_fs_fs__changes_context_t **context, + svn_fs_t *fs, + svn_revnum_t rev, + apr_pool_t *result_pool); -/* Fetch the list of change in revision REV in FS and return it in *CHANGES. - * Allocate the result in POOL. +/* Fetch the block of changes from the CONTEXT and return it in *CHANGES. + * Allocate the result in RESULT_POOL and use SCRATCH_POOL for temporaries. */ svn_error_t * svn_fs_fs__get_changes(apr_array_header_t **changes, - svn_fs_t *fs, - svn_revnum_t rev, - apr_pool_t *pool); + svn_fs_fs__changes_context_t *context, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); #endif diff --git a/subversion/libsvn_fs_fs/caching.c b/subversion/libsvn_fs_fs/caching.c index b54d69b3039a..39b2e757e5c8 100644 --- a/subversion/libsvn_fs_fs/caching.c +++ b/subversion/libsvn_fs_fs/caching.c @@ -66,8 +66,9 @@ normalize_key_part(const char *original, return normalized->data; } -/* *CACHE_TXDELTAS, *CACHE_FULLTEXTS flags will be set according to - FS->CONFIG. *CACHE_NAMESPACE receives the cache prefix to use. +/* *CACHE_TXDELTAS, *CACHE_FULLTEXTS, *CACHE_NODEPROPS flags will be set + according to FS->CONFIG. *CACHE_NAMESPACE receives the cache prefix to + use. Use FS->pool for allocating the memcache and CACHE_NAMESPACE, and POOL for temporary allocations. */ @@ -75,6 +76,7 @@ static svn_error_t * read_config(const char **cache_namespace, svn_boolean_t *cache_txdeltas, svn_boolean_t *cache_fulltexts, + svn_boolean_t *cache_nodeprops, svn_fs_t *fs, apr_pool_t *pool) { @@ -94,11 +96,8 @@ read_config(const char **cache_namespace, ""), pool); - /* don't cache text deltas by default. - * Once we reconstructed the fulltexts from the deltas, - * these deltas are rarely re-used. Therefore, only tools - * like svnadmin will activate this to speed up operations - * dump and verify. + /* Cache text deltas by default. + * They tend to be smaller and have finer granularity than fulltexts. */ *cache_txdeltas = svn_hash__get_bool(fs->config, @@ -117,6 +116,14 @@ read_config(const char **cache_namespace, SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS, TRUE); + /* by default, cache nodeprops. + * Pre-1.10, this was controlled by the SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS + * configuration option which defaulted to TRUE. + */ + *cache_nodeprops + = svn_hash__get_bool(fs->config, + SVN_FS_CONFIG_FSFS_CACHE_NODEPROPS, + TRUE); return SVN_NO_ERROR; } @@ -274,7 +281,8 @@ init_callbacks(svn_cache__t *cache, * MEMBUFFER is not NULL. Fallbacks to inprocess cache if MEMCACHE and * MEMBUFFER are NULL and pages is non-zero. Sets *CACHE_P to NULL * otherwise. Use the given PRIORITY class for the new cache. If it - * is 0, then use the default priority class. + * is 0, then use the default priority class. HAS_NAMESPACE indicates + * whether we prefixed this cache instance with a namespace. * * Unless NO_HANDLER is true, register an error handler that reports errors * as warnings to the FS warning callback. @@ -292,6 +300,7 @@ create_cache(svn_cache__t **cache_p, apr_ssize_t klen, const char *prefix, apr_uint32_t priority, + svn_boolean_t has_namespace, svn_fs_t *fs, svn_boolean_t no_handler, apr_pool_t *result_pool, @@ -314,9 +323,12 @@ create_cache(svn_cache__t **cache_p, } else if (membuffer) { + /* We assume caches with namespaces to be relatively short-lived, + * i.e. their data will not be needed after a while. */ SVN_ERR(svn_cache__create_membuffer_cache( cache_p, membuffer, serializer, deserializer, - klen, prefix, priority, FALSE, result_pool, scratch_pool)); + klen, prefix, priority, FALSE, has_namespace, + result_pool, scratch_pool)); } else if (pages) { @@ -348,26 +360,30 @@ svn_fs_fs__initialize_caches(svn_fs_t *fs, svn_boolean_t no_handler = ffd->fail_stop; svn_boolean_t cache_txdeltas; svn_boolean_t cache_fulltexts; + svn_boolean_t cache_nodeprops; const char *cache_namespace; + svn_boolean_t has_namespace; /* Evaluating the cache configuration. */ SVN_ERR(read_config(&cache_namespace, &cache_txdeltas, &cache_fulltexts, + &cache_nodeprops, fs, pool)); prefix = apr_pstrcat(pool, "ns:", cache_namespace, ":", prefix, SVN_VA_NULL); + has_namespace = strlen(cache_namespace) > 0; membuffer = svn_cache__get_global_membuffer_cache(); /* General rules for assigning cache priorities: * * - Data that can be reconstructed from other elements has low prio - * (e.g. fulltexts, directories etc.) + * (e.g. fulltexts etc.) * - Index data required to find any of the other data has high prio * (e.g. noderevs, L2P and P2L index pages) - * - everthing else should use default prio + * - everything else should use default prio */ #ifdef SVN_DEBUG_CACHE_DUMP_STATS @@ -386,34 +402,35 @@ svn_fs_fs__initialize_caches(svn_fs_t *fs, * commands, this is only going to contain a few entries (svnadmin * dump/verify is an exception here), so to reduce overhead let's * try to keep it to just one page. I estimate each entry has about - * 72 bytes of overhead (svn_revnum_t key, svn_fs_id_t + - * id_private_t + 3 strings for value, and the cache_entry); the - * default pool size is 8192, so about a hundred should fit - * comfortably. */ + * 130 bytes of overhead (svn_revnum_t key, ID struct, and the cache_entry); + * the default pool size is 8192, so about a fifty should fit comfortably. + */ SVN_ERR(create_cache(&(ffd->rev_root_id_cache), NULL, membuffer, - 1, 100, + 1, 50, svn_fs_fs__serialize_id, svn_fs_fs__deserialize_id, sizeof(svn_revnum_t), apr_pstrcat(pool, prefix, "RRI", SVN_VA_NULL), 0, + has_namespace, fs, no_handler, fs->pool, pool)); - /* Rough estimate: revision DAG nodes have size around 320 bytes, so - * let's put 16 on a page. */ + /* Rough estimate: revision DAG nodes have size around 1kBytes, so + * let's put 8 on a page. */ SVN_ERR(create_cache(&(ffd->rev_node_cache), NULL, membuffer, - 1024, 16, + 1, 8, svn_fs_fs__dag_serialize, svn_fs_fs__dag_deserialize, APR_HASH_KEY_STRING, apr_pstrcat(pool, prefix, "DAG", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_LOW_PRIORITY, + has_namespace, fs, no_handler, fs->pool, pool)); @@ -425,28 +442,30 @@ svn_fs_fs__initialize_caches(svn_fs_t *fs, SVN_ERR(create_cache(&(ffd->dir_cache), NULL, membuffer, - 1024, 8, + 1, 8, svn_fs_fs__serialize_dir_entries, svn_fs_fs__deserialize_dir_entries, sizeof(pair_cache_key_t), apr_pstrcat(pool, prefix, "DIR", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, + has_namespace, fs, no_handler, fs->pool, pool)); - /* Only 16 bytes per entry (a revision number + the corresponding offset). - Since we want ~8k pages, that means 512 entries per page. */ + /* 8 kBytes per entry (1000 revs / shared, one file offset per rev). + Covering about 8 pack files gives us an "o.k." hit rate. */ SVN_ERR(create_cache(&(ffd->packed_offset_cache), NULL, membuffer, - 32, 1, + 8, 1, svn_fs_fs__serialize_manifest, svn_fs_fs__deserialize_manifest, sizeof(svn_revnum_t), apr_pstrcat(pool, prefix, "PACK-MANIFEST", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, + has_namespace, fs, no_handler, fs->pool, pool)); @@ -455,12 +474,13 @@ svn_fs_fs__initialize_caches(svn_fs_t *fs, SVN_ERR(create_cache(&(ffd->node_revision_cache), NULL, membuffer, - 32, 32, /* ~200 byte / entry; 1k entries total */ + 2, 16, /* ~500 byte / entry; 32 entries total */ svn_fs_fs__serialize_node_revision, svn_fs_fs__deserialize_node_revision, sizeof(pair_cache_key_t), apr_pstrcat(pool, prefix, "NODEREVS", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, + has_namespace, fs, no_handler, fs->pool, pool)); @@ -469,12 +489,13 @@ svn_fs_fs__initialize_caches(svn_fs_t *fs, SVN_ERR(create_cache(&(ffd->rep_header_cache), NULL, membuffer, - 1, 1000, /* ~8 bytes / entry; 1k entries total */ + 1, 200, /* ~40 bytes / entry; 200 entries total */ svn_fs_fs__serialize_rep_header, svn_fs_fs__deserialize_rep_header, sizeof(pair_cache_key_t), apr_pstrcat(pool, prefix, "REPHEADER", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY, + has_namespace, fs, no_handler, fs->pool, pool)); @@ -486,9 +507,25 @@ svn_fs_fs__initialize_caches(svn_fs_t *fs, 1, 8, /* 1k / entry; 8 entries total, rarely used */ svn_fs_fs__serialize_changes, svn_fs_fs__deserialize_changes, - sizeof(svn_revnum_t), + sizeof(pair_cache_key_t), apr_pstrcat(pool, prefix, "CHANGES", SVN_VA_NULL), 0, + has_namespace, + fs, + no_handler, + fs->pool, pool)); + + /* if enabled, cache revprops */ + SVN_ERR(create_cache(&(ffd->revprop_cache), + NULL, + membuffer, + 8, 20, /* ~400 bytes / entry, capa for ~2 packs */ + svn_fs_fs__serialize_revprops, + svn_fs_fs__deserialize_revprops, + sizeof(pair_cache_key_t), + apr_pstrcat(pool, prefix, "REVPROP", SVN_VA_NULL), + SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY, + TRUE, /* contents is short-lived */ fs, no_handler, fs->pool, pool)); @@ -499,26 +536,13 @@ svn_fs_fs__initialize_caches(svn_fs_t *fs, SVN_ERR(create_cache(&(ffd->fulltext_cache), ffd->memcache, membuffer, - 0, 0, /* Do not use inprocess cache */ + 0, 0, /* Do not use the inprocess cache */ /* Values are svn_stringbuf_t */ NULL, NULL, sizeof(pair_cache_key_t), apr_pstrcat(pool, prefix, "TEXT", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY, - fs, - no_handler, - fs->pool, pool)); - - SVN_ERR(create_cache(&(ffd->properties_cache), - NULL, - membuffer, - 0, 0, /* Do not use inprocess cache */ - svn_fs_fs__serialize_properties, - svn_fs_fs__deserialize_properties, - sizeof(pair_cache_key_t), - apr_pstrcat(pool, prefix, "PROP", - SVN_VA_NULL), - SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY, + has_namespace, fs, no_handler, fs->pool, pool)); @@ -526,13 +550,14 @@ svn_fs_fs__initialize_caches(svn_fs_t *fs, SVN_ERR(create_cache(&(ffd->mergeinfo_cache), NULL, membuffer, - 0, 0, /* Do not use inprocess cache */ + 0, 0, /* Do not use the inprocess cache */ svn_fs_fs__serialize_mergeinfo, svn_fs_fs__deserialize_mergeinfo, APR_HASH_KEY_STRING, apr_pstrcat(pool, prefix, "MERGEINFO", SVN_VA_NULL), 0, + has_namespace, fs, no_handler, fs->pool, pool)); @@ -540,13 +565,14 @@ svn_fs_fs__initialize_caches(svn_fs_t *fs, SVN_ERR(create_cache(&(ffd->mergeinfo_existence_cache), NULL, membuffer, - 0, 0, /* Do not use inprocess cache */ + 0, 0, /* Do not use the inprocess cache */ /* Values are svn_stringbuf_t */ NULL, NULL, APR_HASH_KEY_STRING, apr_pstrcat(pool, prefix, "HAS_MERGEINFO", SVN_VA_NULL), 0, + has_namespace, fs, no_handler, fs->pool, pool)); @@ -554,24 +580,47 @@ svn_fs_fs__initialize_caches(svn_fs_t *fs, else { ffd->fulltext_cache = NULL; - ffd->properties_cache = NULL; ffd->mergeinfo_cache = NULL; ffd->mergeinfo_existence_cache = NULL; } + /* if enabled, cache node properties */ + if (cache_nodeprops) + { + SVN_ERR(create_cache(&(ffd->properties_cache), + NULL, + membuffer, + 0, 0, /* Do not use the inprocess cache */ + svn_fs_fs__serialize_properties, + svn_fs_fs__deserialize_properties, + sizeof(pair_cache_key_t), + apr_pstrcat(pool, prefix, "PROP", + SVN_VA_NULL), + SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY, + has_namespace, + fs, + no_handler, + fs->pool, pool)); + } + else + { + ffd->properties_cache = NULL; + } + /* if enabled, cache text deltas and their combinations */ if (cache_txdeltas) { SVN_ERR(create_cache(&(ffd->raw_window_cache), NULL, membuffer, - 0, 0, /* Do not use inprocess cache */ + 0, 0, /* Do not use the inprocess cache */ svn_fs_fs__serialize_raw_window, svn_fs_fs__deserialize_raw_window, sizeof(window_cache_key_t), apr_pstrcat(pool, prefix, "RAW_WINDOW", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_LOW_PRIORITY, + has_namespace, fs, no_handler, fs->pool, pool)); @@ -579,13 +628,14 @@ svn_fs_fs__initialize_caches(svn_fs_t *fs, SVN_ERR(create_cache(&(ffd->txdelta_window_cache), NULL, membuffer, - 0, 0, /* Do not use inprocess cache */ + 0, 0, /* Do not use the inprocess cache */ svn_fs_fs__serialize_txdelta_window, svn_fs_fs__deserialize_txdelta_window, sizeof(window_cache_key_t), apr_pstrcat(pool, prefix, "TXDELTA_WINDOW", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_LOW_PRIORITY, + has_namespace, fs, no_handler, fs->pool, pool)); @@ -593,13 +643,14 @@ svn_fs_fs__initialize_caches(svn_fs_t *fs, SVN_ERR(create_cache(&(ffd->combined_window_cache), NULL, membuffer, - 0, 0, /* Do not use inprocess cache */ + 0, 0, /* Do not use the inprocess cache */ /* Values are svn_stringbuf_t */ NULL, NULL, sizeof(window_cache_key_t), apr_pstrcat(pool, prefix, "COMBINED_WINDOW", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_LOW_PRIORITY, + has_namespace, fs, no_handler, fs->pool, pool)); @@ -613,28 +664,34 @@ svn_fs_fs__initialize_caches(svn_fs_t *fs, SVN_ERR(create_cache(&(ffd->l2p_header_cache), NULL, membuffer, - 64, 16, /* entry size varies but we must cover - a reasonable number of revisions (1k) */ + 8, 16, /* entry size varies but we must cover a + reasonable number of rev / pack files + to allow for delta chains to be walked + efficiently etc. */ svn_fs_fs__serialize_l2p_header, svn_fs_fs__deserialize_l2p_header, sizeof(pair_cache_key_t), apr_pstrcat(pool, prefix, "L2P_HEADER", (char *)NULL), SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, + has_namespace, fs, no_handler, fs->pool, pool)); SVN_ERR(create_cache(&(ffd->l2p_page_cache), NULL, membuffer, - 64, 16, /* entry size varies but we must cover - a reasonable number of revisions (1k) */ + 8, 16, /* entry size varies but we must cover a + reasonable number of rev / pack files + to allow for delta chains to be walked + efficiently etc. */ svn_fs_fs__serialize_l2p_page, svn_fs_fs__deserialize_l2p_page, sizeof(svn_fs_fs__page_cache_key_t), apr_pstrcat(pool, prefix, "L2P_PAGE", (char *)NULL), SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, + has_namespace, fs, no_handler, fs->pool, pool)); @@ -648,19 +705,21 @@ svn_fs_fs__initialize_caches(svn_fs_t *fs, apr_pstrcat(pool, prefix, "P2L_HEADER", (char *)NULL), SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, + has_namespace, fs, no_handler, fs->pool, pool)); SVN_ERR(create_cache(&(ffd->p2l_page_cache), NULL, membuffer, - 4, 16, /* Variably sized entries. Rarely used. */ + 4, 1, /* Variably sized entries. Rarely used. */ svn_fs_fs__serialize_p2l_page, svn_fs_fs__deserialize_p2l_page, sizeof(svn_fs_fs__page_cache_key_t), apr_pstrcat(pool, prefix, "P2L_PAGE", (char *)NULL), SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, + has_namespace, fs, no_handler, fs->pool, pool)); @@ -773,18 +832,7 @@ svn_fs_fs__initialize_txn_caches(svn_fs_t *fs, apr_pool_t *pool) { fs_fs_data_t *ffd = fs->fsap_data; - - /* Transaction content needs to be carefully prefixed to virtually - eliminate any chance for conflicts. The (repo, txn_id) pair - should be unique but if a transaction fails, it might be possible - to start a new transaction later that receives the same id. - Therefore, throw in a uuid as well - just to be sure. */ - const char *prefix = apr_pstrcat(pool, - "fsfs:", fs->uuid, - "/", fs->path, - ":", txn_id, - ":", svn_uuid_generate(pool), ":", - SVN_VA_NULL); + const char *prefix; /* We don't support caching for concurrent transactions in the SAME * FSFS session. Maybe, you forgot to clean POOL. */ @@ -796,17 +844,40 @@ svn_fs_fs__initialize_txn_caches(svn_fs_t *fs, return SVN_NO_ERROR; } + /* Transaction content needs to be carefully prefixed to virtually + eliminate any chance for conflicts. The (repo, txn_id) pair + should be unique but if the filesystem format doesn't store the + global transaction ID via the txn-current file, and a transaction + fails, it might be possible to start a new transaction later that + receives the same id. For such older formats, throw in an uuid as + well -- just to be sure. */ + if (ffd->format >= SVN_FS_FS__MIN_TXN_CURRENT_FORMAT) + prefix = apr_pstrcat(pool, + "fsfs:", fs->uuid, + "/", fs->path, + ":", txn_id, + ":", "TXNDIR", + SVN_VA_NULL); + else + prefix = apr_pstrcat(pool, + "fsfs:", fs->uuid, + "/", fs->path, + ":", txn_id, + ":", svn_uuid_generate(pool), + ":", "TXNDIR", + SVN_VA_NULL); + /* create a txn-local directory cache */ SVN_ERR(create_cache(&ffd->txn_dir_cache, NULL, svn_cache__get_global_membuffer_cache(), 1024, 8, - svn_fs_fs__serialize_dir_entries, + svn_fs_fs__serialize_txndir_entries, svn_fs_fs__deserialize_dir_entries, APR_HASH_KEY_STRING, - apr_pstrcat(pool, prefix, "TXNDIR", - SVN_VA_NULL), + prefix, SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, + TRUE, /* The TXN-ID is our namespace. */ fs, TRUE, pool, pool)); diff --git a/subversion/libsvn_fs_fs/dag.c b/subversion/libsvn_fs_fs/dag.c index d21c17c4b9aa..714235dd0ee0 100644 --- a/subversion/libsvn_fs_fs/dag.c +++ b/subversion/libsvn_fs_fs/dag.c @@ -527,9 +527,7 @@ svn_fs_fs__dag_has_props(svn_boolean_t *has_props, { /* Properties are stored as a standard hash stream, always ending with "END\n" (4 bytes) */ - *has_props = (noderev->prop_rep->expanded_size > 4 - || (noderev->prop_rep->expanded_size == 0 - && noderev->prop_rep->size > 4)); + *has_props = noderev->prop_rep->expanded_size > 4; } return SVN_NO_ERROR; @@ -755,8 +753,7 @@ svn_fs_fs__dag_clone_child(dag_node_t **child_p, noderev->copyfrom_rev = SVN_INVALID_REVNUM; noderev->predecessor_id = svn_fs_fs__id_copy(cur_entry->id, pool); - if (noderev->predecessor_count != -1) - noderev->predecessor_count++; + noderev->predecessor_count++; noderev->created_path = svn_fspath__join(parent_path, name, pool); SVN_ERR(svn_fs_fs__create_successor(&new_node_id, fs, cur_entry->id, @@ -1269,8 +1266,7 @@ svn_fs_fs__dag_copy(dag_node_t *to_node, /* Create a successor with its predecessor pointing at the copy source. */ to_noderev->predecessor_id = svn_fs_fs__id_copy(src_id, pool); - if (to_noderev->predecessor_count != -1) - to_noderev->predecessor_count++; + to_noderev->predecessor_count++; to_noderev->created_path = svn_fspath__join(svn_fs_fs__dag_get_created_path(to_node), entry, pool); @@ -1425,8 +1421,7 @@ svn_fs_fs__dag_update_ancestry(dag_node_t *target, target_noderev->predecessor_id = source->id; target_noderev->predecessor_count = source_noderev->predecessor_count; - if (target_noderev->predecessor_count != -1) - target_noderev->predecessor_count++; + target_noderev->predecessor_count++; return svn_fs_fs__put_node_revision(target->fs, target->id, target_noderev, FALSE, pool); diff --git a/subversion/libsvn_fs_fs/fs.c b/subversion/libsvn_fs_fs/fs.c index 1978798917b9..508ecdbaba33 100644 --- a/subversion/libsvn_fs_fs/fs.c +++ b/subversion/libsvn_fs_fs/fs.c @@ -27,7 +27,6 @@ #include #include #include -#include #include "svn_fs.h" #include "svn_delta.h" @@ -135,8 +134,29 @@ fs_serialized_init(svn_fs_t *fs, apr_pool_t *common_pool, apr_pool_t *pool) return SVN_NO_ERROR; } +svn_error_t * +svn_fs_fs__initialize_shared_data(svn_fs_t *fs, + svn_mutex__t *common_pool_lock, + apr_pool_t *pool, + apr_pool_t *common_pool) +{ + SVN_MUTEX__WITH_LOCK(common_pool_lock, + fs_serialized_init(fs, common_pool, pool)); + + return SVN_NO_ERROR; +} + +static svn_error_t * +fs_refresh_revprops(svn_fs_t *fs, + apr_pool_t *scratch_pool) +{ + svn_fs_fs__reset_revprop_cache(fs); + + return SVN_NO_ERROR; +} + /* This function is provided for Subversion 1.0.x compatibility. It has no effect for fsfs backed Subversion filesystems. It conforms to the fs_library_vtable_t.bdb_set_errcall() API. */ @@ -238,6 +258,7 @@ fs_set_uuid(svn_fs_t *fs, /* The vtable associated with a specific open filesystem. */ static fs_vtable_t fs_vtable = { svn_fs_fs__youngest_rev, + fs_refresh_revprops, svn_fs_fs__revision_prop, svn_fs_fs__get_revision_proplist, svn_fs_fs__change_rev_prop, @@ -270,6 +291,8 @@ initialize_fs_struct(svn_fs_t *fs) { fs_fs_data_t *ffd = apr_pcalloc(fs->pool, sizeof(*ffd)); ffd->use_log_addressing = FALSE; + ffd->revprop_prefix = 0; + ffd->flush_to_disk = TRUE; fs->vtable = &fs_vtable; fs->fsap_data = ffd; @@ -293,18 +316,18 @@ static svn_error_t * fs_create(svn_fs_t *fs, const char *path, svn_mutex__t *common_pool_lock, - apr_pool_t *pool, + apr_pool_t *scratch_pool, apr_pool_t *common_pool) { SVN_ERR(svn_fs__check_fs(fs, FALSE)); SVN_ERR(initialize_fs_struct(fs)); - SVN_ERR(svn_fs_fs__create(fs, path, pool)); + SVN_ERR(svn_fs_fs__create(fs, path, scratch_pool)); - SVN_ERR(svn_fs_fs__initialize_caches(fs, pool)); + SVN_ERR(svn_fs_fs__initialize_caches(fs, scratch_pool)); SVN_MUTEX__WITH_LOCK(common_pool_lock, - fs_serialized_init(fs, common_pool, pool)); + fs_serialized_init(fs, common_pool, scratch_pool)); return SVN_NO_ERROR; } @@ -322,10 +345,10 @@ static svn_error_t * fs_open(svn_fs_t *fs, const char *path, svn_mutex__t *common_pool_lock, - apr_pool_t *pool, + apr_pool_t *scratch_pool, apr_pool_t *common_pool) { - apr_pool_t *subpool = svn_pool_create(pool); + apr_pool_t *subpool = svn_pool_create(scratch_pool); SVN_ERR(svn_fs__check_fs(fs, FALSE)); @@ -481,28 +504,19 @@ fs_hotcopy(svn_fs_t *src_fs, apr_pool_t *pool, apr_pool_t *common_pool) { - /* Open the source repo as usual. */ SVN_ERR(fs_open(src_fs, src_path, common_pool_lock, pool, common_pool)); - if (cancel_func) - SVN_ERR(cancel_func(cancel_baton)); - /* Test target repo when in INCREMENTAL mode, initialize it when not. - * For this, we need our FS internal data structures to be temporarily - * available. */ + SVN_ERR(svn_fs__check_fs(dst_fs, FALSE)); SVN_ERR(initialize_fs_struct(dst_fs)); - SVN_ERR(svn_fs_fs__hotcopy_prepare_target(src_fs, dst_fs, dst_path, - incremental, pool)); - uninitialize_fs_struct(dst_fs); - /* Now, the destination repo should open just fine. */ - SVN_ERR(fs_open(dst_fs, dst_path, common_pool_lock, pool, common_pool)); - if (cancel_func) - SVN_ERR(cancel_func(cancel_baton)); - - /* Now, we may copy data as needed ... */ - return svn_fs_fs__hotcopy(src_fs, dst_fs, incremental, - notify_func, notify_baton, - cancel_func, cancel_baton, pool); + /* In INCREMENTAL mode, svn_fs_fs__hotcopy() will open DST_FS. + Otherwise, it's not an FS yet --- possibly just an empty dir --- so + can't be opened. + */ + return svn_fs_fs__hotcopy(src_fs, dst_fs, src_path, dst_path, + incremental, notify_func, notify_baton, + cancel_func, cancel_baton, common_pool_lock, + pool, common_pool); } diff --git a/subversion/libsvn_fs_fs/fs.h b/subversion/libsvn_fs_fs/fs.h index c75eafbd5c09..d11d923d9b05 100644 --- a/subversion/libsvn_fs_fs/fs.h +++ b/subversion/libsvn_fs_fs/fs.h @@ -37,7 +37,7 @@ #include "private/svn_sqlite.h" #include "private/svn_mutex.h" -#include "id.h" +#include "rev_file.h" #ifdef __cplusplus extern "C" { @@ -82,8 +82,6 @@ extern "C" { /* Names of special files and file extensions for transactions */ #define PATH_CHANGES "changes" /* Records changes made so far */ #define PATH_TXN_PROPS "props" /* Transaction properties */ -#define PATH_TXN_PROPS_FINAL "props-final" /* Final transaction properties - before moving to revprops */ #define PATH_NEXT_IDS "next-ids" /* Next temporary ID assignments */ #define PATH_PREFIX_NODE "node." /* Prefix for node filename */ #define PATH_EXT_TXN ".txn" /* Extension of txn dir */ @@ -119,6 +117,8 @@ extern "C" { #define CONFIG_OPTION_P2L_PAGE_SIZE "p2l-page-size" #define CONFIG_SECTION_DEBUG "debug" #define CONFIG_OPTION_PACK_AFTER_COMMIT "pack-after-commit" +#define CONFIG_OPTION_VERIFY_BEFORE_COMMIT "verify-before-commit" +#define CONFIG_OPTION_COMPRESSION "compression" /* The format number of this filesystem. This is independent of the repository format number, and @@ -127,7 +127,7 @@ extern "C" { Note: If you bump this, please update the switch statement in svn_fs_fs__create() as well. */ -#define SVN_FS_FS__FORMAT_NUMBER 7 +#define SVN_FS_FS__FORMAT_NUMBER 8 /* The minimum format number that supports svndiff version 1. */ #define SVN_FS_FS__MIN_SVNDIFF1_FORMAT 2 @@ -163,6 +163,9 @@ extern "C" { * issues with very old servers, restrict those options to the 1.6+ format*/ #define SVN_FS_FS__MIN_DELTIFICATION_FORMAT 4 +/* The minimum format number that supports a configuration file (fsfs.conf) */ +#define SVN_FS_FS__MIN_CONFIG_FILE 4 + /* The 1.7-dev format, never released, that packed revprops into SQLite revprops.db . */ #define SVN_FS_FS__PACKED_REVPROP_SQLITE_DEV_FORMAT 5 @@ -182,8 +185,20 @@ extern "C" { /* Minimum format number that supports per-instance filesystem IDs. */ #define SVN_FS_FS__MIN_INSTANCE_ID_FORMAT 7 -/* The minimum format number that supports a configuration file (fsfs.conf) */ -#define SVN_FS_FS__MIN_CONFIG_FILE 4 +/* The minimum format number that supports svndiff version 2. */ +#define SVN_FS_FS__MIN_SVNDIFF2_FORMAT 8 + +/* The minimum format number that supports the special notation ("-") + for optional values that are not present in the representation strings, + such as SHA1 or the uniquifier. For example: + + 15 0 563 7809 28ef320a82e7bd11eebdf3502d69e608 - 14-g/_5 + */ +#define SVN_FS_FS__MIN_REP_STRING_OPTIONAL_VALUES_FORMAT 8 + + /* The minimum format number that supports V2 schema of the rep-cache.db + database. */ +#define SVN_FS_FS__MIN_REP_CACHE_SCHEMA_V2_FORMAT 8 /* On most operating systems apr implements file locks per process, not per file. On Windows apr implements the locking as per file handle @@ -195,6 +210,11 @@ extern "C" { #define SVN_FS_FS__USE_LOCK_MUTEX 0 #endif +/* Maximum number of changes we deliver per request when listing the + changed paths for a given revision. Anything > 0 will do. + At 100..300 bytes per entry, this limits the allocation to ~30kB. */ +#define SVN_FS_FS__CHANGES_BLOCK_SIZE 100 + /* Private FSFS-specific data shared between all svn_txn_t objects that relate to a particular transaction in a filesystem (as identified by transaction id and filesystem UUID). Objects of this type are @@ -291,6 +311,13 @@ typedef struct window_cache_key_t apr_uint64_t item_index; } window_cache_key_t; +typedef enum compression_type_t +{ + compression_type_none, + compression_type_zlib, + compression_type_lz4 +} compression_type_t; + /* Private (non-shared) FSFS-specific data for each svn_fs_t object. Any caches in here may be NULL. */ typedef struct fs_fs_data_t @@ -353,6 +380,15 @@ typedef struct fs_fs_data_t rep key (revision/offset) to svn_stringbuf_t. */ svn_cache__t *fulltext_cache; + /* The current prefix to be used for revprop cache entries. + If this is 0, a new unique prefix must be chosen. */ + apr_uint64_t revprop_prefix; + + /* Revision property cache. Maps from (rev,prefix) to apr_hash_t. + Unparsed svn_string_t representations of the serialized hash + will be written to the cache but the getter returns apr_hash_t. */ + svn_cache__t *revprop_cache; + /* Node properties cache. Maps from rep key to apr_hash_t. */ svn_cache__t *properties_cache; @@ -376,8 +412,8 @@ typedef struct fs_fs_data_t /* Cache for node_revision_t objects; the key is (revision, item_index) */ svn_cache__t *node_revision_cache; - /* Cache for change lists as APR arrays of change_t * objects; the key - is the revision */ + /* Cache for change lists n blocks as svn_fs_fs__changes_list_t * objects; + the key is the (revision, first-element-in-block) pair. */ svn_cache__t *changes_cache; /* Cache for svn_fs_fs__rep_header_t objects; the key is a @@ -457,18 +493,27 @@ typedef struct fs_fs_data_t * deltification history after which skip deltas will be used. */ apr_int64_t max_linear_deltification; - /* Compression level to use with txdelta storage format in new revs. */ + /* Compression type to use with txdelta storage format in new revs. */ + compression_type_t delta_compression_type; + + /* Compression level (currently, only used with compression_type_zlib). */ int delta_compression_level; /* Pack after every commit. */ svn_boolean_t pack_after_commit; + /* Verify each new revision before commit. */ + svn_boolean_t verify_before_commit; + /* Per-instance filesystem ID, which provides an additional level of uniqueness for filesystems that share the same UUID, but should still be distinguishable (e.g. backups produced by svn_fs_hotcopy() or dump / load cycles). */ const char *instance_id; + /* Ensure that all filesystem changes are written to disk. */ + svn_boolean_t flush_to_disk; + /* Pointer to svn_fs_open. */ svn_error_t *(*svn_fs_open_)(svn_fs_t **, const char *, apr_hash_t *, apr_pool_t *, apr_pool_t *); @@ -515,7 +560,7 @@ typedef struct representation_t /* Revision where this representation is located. */ svn_revnum_t revision; - /* Item index with the the revision. */ + /* Item index with the revision. */ apr_uint64_t item_index; /* The size of the representation in bytes as seen in the revision @@ -523,7 +568,14 @@ typedef struct representation_t svn_filesize_t size; /* The size of the fulltext of the representation. If this is 0, - * the fulltext size is equal to representation size in the rev file, */ + * for a plain rep, the real fulltext size is equal to the SIZE field. + * For a delta rep, this field is always the real fulltext size. + * + * Note that svn_fs_fs__fixup_expanded_size() checks for these special + * cases and ensures that this field contains the actual value. We call + * it early after reading a representation struct, so most code does not + * have to worry about it. + */ svn_filesize_t expanded_size; /* Is this a representation (still) within a transaction? */ @@ -568,8 +620,8 @@ typedef struct node_revision_t svn_revnum_t copyroot_rev; const char *copyroot_path; - /* number of predecessors this node revision has (recursively), or - -1 if not known (for backward compatibility). */ + /* Number of predecessors this node revision has (recursively). + A difference from the BDB backend is that it cannot be -1. */ int predecessor_count; /* representation key for this node's properties. may be NULL if @@ -606,6 +658,45 @@ typedef struct change_t svn_fs_path_change2_t info; } change_t; + +/*** Context for reading changed paths lists iteratively. */ +typedef struct svn_fs_fs__changes_context_t +{ + /* Repository to fetch from. */ + svn_fs_t *fs; + + /* Revision that we read from. */ + svn_revnum_t revision; + + /* Revision file object to use when needed. NULL until the first access. */ + svn_fs_fs__revision_file_t *revision_file; + + /* Pool to create REVISION_FILE in. */ + apr_pool_t *rev_file_pool; + + /* Index of the next change to fetch. */ + apr_size_t next; + + /* Offset, within the changed paths list on disk, of the next change to + fetch. */ + apr_off_t next_offset; + + /* Has the end of the list been reached? */ + svn_boolean_t eol; + +} svn_fs_fs__changes_context_t; + +/*** Directory (only used at the cache interface) ***/ +typedef struct svn_fs_fs__dir_data_t +{ + /* Contents, i.e. all directory entries, sorted by name. */ + apr_array_header_t *entries; + + /* SVN_INVALID_FILESIZE for committed data, otherwise the length of the + * in-txn on-disk representation of that directory. */ + svn_filesize_t txn_filesize; +} svn_fs_fs__dir_data_t; + #ifdef __cplusplus } diff --git a/subversion/libsvn_fs_fs/fs_fs.c b/subversion/libsvn_fs_fs/fs_fs.c index 103458d8ef0a..5cb1362d8451 100644 --- a/subversion/libsvn_fs_fs/fs_fs.c +++ b/subversion/libsvn_fs_fs/fs_fs.c @@ -623,8 +623,9 @@ svn_fs_fs__write_format(svn_fs_t *fs, } else { - SVN_ERR(svn_io_write_atomic(path, sb->data, sb->len, - NULL /* copy_perms_path */, pool)); + SVN_ERR(svn_io_write_atomic2(path, sb->data, sb->len, + NULL /* copy_perms_path */, + ffd->flush_to_disk, pool)); } /* And set the perms to make it read only */ @@ -682,6 +683,60 @@ verify_block_size(apr_int64_t block_size, return SVN_NO_ERROR; } +static svn_error_t * +parse_compression_option(compression_type_t *compression_type_p, + int *compression_level_p, + const char *value) +{ + compression_type_t type; + int level; + svn_boolean_t is_valid = TRUE; + + /* compression = none | lz4 | zlib | zlib-1 ... zlib-9 */ + if (strcmp(value, "none") == 0) + { + type = compression_type_none; + level = SVN_DELTA_COMPRESSION_LEVEL_NONE; + } + else if (strcmp(value, "lz4") == 0) + { + type = compression_type_lz4; + level = SVN_DELTA_COMPRESSION_LEVEL_DEFAULT; + } + else if (strncmp(value, "zlib", 4) == 0) + { + const char *p = value + 4; + + type = compression_type_zlib; + if (*p == 0) + { + level = SVN_DELTA_COMPRESSION_LEVEL_DEFAULT; + } + else if (*p == '-') + { + p++; + SVN_ERR(svn_cstring_atoi(&level, p)); + if (level < 1 || level > 9) + is_valid = FALSE; + } + else + is_valid = FALSE; + } + else + { + is_valid = FALSE; + } + + if (!is_valid) + return svn_error_createf(SVN_ERR_BAD_CONFIG_VALUE, NULL, + _("Invalid 'compression' value '%s' in the config"), + value); + + *compression_type_p = type; + *compression_level_p = level; + return SVN_NO_ERROR; +} + /* Read the configuration information of the file system at FS_PATH * and set the respective values in FFD. Use pools as usual. */ @@ -708,8 +763,6 @@ read_config(fs_fs_data_t *ffd, /* Initialize deltification settings in ffd. */ if (ffd->format >= SVN_FS_FS__MIN_DELTIFICATION_FORMAT) { - apr_int64_t compression_level; - SVN_ERR(svn_config_get_bool(config, &ffd->deltify_directories, CONFIG_SECTION_DELTIFICATION, CONFIG_OPTION_ENABLE_DIR_DELTIFICATION, @@ -726,14 +779,6 @@ read_config(fs_fs_data_t *ffd, CONFIG_SECTION_DELTIFICATION, CONFIG_OPTION_MAX_LINEAR_DELTIFICATION, SVN_FS_FS_MAX_LINEAR_DELTIFICATION)); - - SVN_ERR(svn_config_get_int64(config, &compression_level, - CONFIG_SECTION_DELTIFICATION, - CONFIG_OPTION_COMPRESSION_LEVEL, - SVN_DELTA_COMPRESSION_LEVEL_DEFAULT)); - ffd->delta_compression_level - = (int)MIN(MAX(SVN_DELTA_COMPRESSION_LEVEL_NONE, compression_level), - SVN_DELTA_COMPRESSION_LEVEL_MAX); } else { @@ -741,7 +786,6 @@ read_config(fs_fs_data_t *ffd, ffd->deltify_properties = FALSE; ffd->max_deltification_walk = SVN_FS_FS_MAX_DELTIFICATION_WALK; ffd->max_linear_deltification = SVN_FS_FS_MAX_LINEAR_DELTIFICATION; - ffd->delta_compression_level = SVN_DELTA_COMPRESSION_LEVEL_DEFAULT; } /* Initialize revprop packing settings in ffd. */ @@ -755,8 +799,8 @@ read_config(fs_fs_data_t *ffd, CONFIG_SECTION_PACKED_REVPROPS, CONFIG_OPTION_REVPROP_PACK_SIZE, ffd->compress_packed_revprops - ? 0x10 - : 0x4)); + ? 0x40 + : 0x10)); ffd->revprop_pack_size *= 1024; } @@ -816,6 +860,83 @@ read_config(fs_fs_data_t *ffd, ffd->pack_after_commit = FALSE; } + /* Initialize compression settings in ffd. */ + if (ffd->format >= SVN_FS_FS__MIN_DELTIFICATION_FORMAT) + { + const char *compression_val; + const char *compression_level_val; + + svn_config_get(config, &compression_val, + CONFIG_SECTION_DELTIFICATION, + CONFIG_OPTION_COMPRESSION, NULL); + svn_config_get(config, &compression_level_val, + CONFIG_SECTION_DELTIFICATION, + CONFIG_OPTION_COMPRESSION_LEVEL, NULL); + if (compression_val && compression_level_val) + { + return svn_error_create(SVN_ERR_BAD_CONFIG_VALUE, NULL, + _("The 'compression' and 'compression-level' " + "config options are mutually exclusive")); + } + else if (compression_val) + { + SVN_ERR(parse_compression_option(&ffd->delta_compression_type, + &ffd->delta_compression_level, + compression_val)); + if (ffd->delta_compression_type == compression_type_lz4 && + ffd->format < SVN_FS_FS__MIN_SVNDIFF2_FORMAT) + { + return svn_error_create(SVN_ERR_BAD_CONFIG_VALUE, NULL, + _("Compression type 'lz4' requires " + "filesystem format 8 or higher")); + } + } + else if (compression_level_val) + { + /* Handle the deprecated 'compression-level' option. */ + ffd->delta_compression_type = compression_type_zlib; + SVN_ERR(svn_cstring_atoi(&ffd->delta_compression_level, + compression_level_val)); + ffd->delta_compression_level = + MIN(MAX(SVN_DELTA_COMPRESSION_LEVEL_NONE, + ffd->delta_compression_level), + SVN_DELTA_COMPRESSION_LEVEL_MAX); + } + else + { + /* Nothing specified explicitly, use the default settings: + * LZ4 compression for formats supporting it and zlib otherwise. */ + if (ffd->format >= SVN_FS_FS__MIN_SVNDIFF2_FORMAT) + ffd->delta_compression_type = compression_type_lz4; + else + ffd->delta_compression_type = compression_type_zlib; + + ffd->delta_compression_level = SVN_DELTA_COMPRESSION_LEVEL_DEFAULT; + } + } + else if (ffd->format >= SVN_FS_FS__MIN_SVNDIFF1_FORMAT) + { + ffd->delta_compression_type = compression_type_zlib; + ffd->delta_compression_level = SVN_DELTA_COMPRESSION_LEVEL_DEFAULT; + } + else + { + ffd->delta_compression_type = compression_type_none; + ffd->delta_compression_level = SVN_DELTA_COMPRESSION_LEVEL_NONE; + } + +#ifdef SVN_DEBUG + SVN_ERR(svn_config_get_bool(config, &ffd->verify_before_commit, + CONFIG_SECTION_DEBUG, + CONFIG_OPTION_VERIFY_BEFORE_COMMIT, + TRUE)); +#else + SVN_ERR(svn_config_get_bool(config, &ffd->verify_before_commit, + CONFIG_SECTION_DEBUG, + CONFIG_OPTION_VERIFY_BEFORE_COMMIT, + FALSE)); +#endif + /* memcached configuration */ SVN_ERR(svn_cache__make_memcache_from_config(&ffd->memcache, config, result_pool, scratch_pool)); @@ -934,23 +1055,30 @@ write_config(svn_fs_t *fs, "### For 1.8, the default value is 16; earlier versions use 1." NL "# " CONFIG_OPTION_MAX_LINEAR_DELTIFICATION " = 16" NL "###" NL -"### After deltification, we compress the data through zlib to minimize on-" NL -"### disk size. That can be an expensive and ineffective process. This" NL -"### setting controls the usage of zlib in future revisions." NL -"### Revisions with highly compressible data in them may shrink in size" NL -"### if the setting is increased but may take much longer to commit. The" NL -"### time taken to uncompress that data again is widely independent of the" NL -"### compression level." NL -"### Compression will be ineffective if the incoming content is already" NL -"### highly compressed. In that case, disabling the compression entirely" NL -"### will speed up commits as well as reading the data. Repositories with" NL -"### many small compressible files (source code) but also a high percentage" NL -"### of large incompressible ones (artwork) may benefit from compression" NL -"### levels lowered to e.g. 1." NL -"### Valid values are 0 to 9 with 9 providing the highest compression ratio" NL -"### and 0 disabling it altogether." NL -"### The default value is 5." NL -"# " CONFIG_OPTION_COMPRESSION_LEVEL " = 5" NL +"### After deltification, we compress the data to minimize on-disk size." NL +"### This setting controls the compression algorithm, which will be used in" NL +"### future revisions. It can be used to either disable compression or to" NL +"### select between available algorithms (zlib, lz4). zlib is a general-" NL +"### purpose compression algorithm. lz4 is a fast compression algorithm" NL +"### which should be preferred for repositories with large and, possibly," NL +"### incompressible files. Note that the compression ratio of lz4 is" NL +"### usually lower than the one provided by zlib, but using it can" NL +"### significantly speed up commits as well as reading the data." NL +"### lz4 compression algorithm is supported, starting from format 8" NL +"### repositories, available in Subversion 1.10 and higher." NL +"### The syntax of this option is:" NL +"### " CONFIG_OPTION_COMPRESSION " = none | lz4 | zlib | zlib-1 ... zlib-9" NL +"### Versions prior to Subversion 1.10 will ignore this option." NL +"### The default value is 'lz4' if supported by the repository format and" NL +"### 'zlib' otherwise. 'zlib' is currently equivalent to 'zlib-5'." NL +"# " CONFIG_OPTION_COMPRESSION " = lz4" NL +"###" NL +"### DEPRECATED: The new '" CONFIG_OPTION_COMPRESSION "' option deprecates previously used" NL +"### '" CONFIG_OPTION_COMPRESSION_LEVEL "' option, which was used to configure zlib compression." NL +"### For compatibility with previous versions of Subversion, this option can"NL +"### still be used (and it will result in zlib compression with the" NL +"### corresponding compression level)." NL +"### " CONFIG_OPTION_COMPRESSION_LEVEL " = 0 ... 9 (default is 5)" NL "" NL "[" CONFIG_SECTION_PACKED_REVPROPS "]" NL "### This parameter controls the size (in kBytes) of packed revprop files." NL @@ -963,9 +1091,9 @@ write_config(svn_fs_t *fs, "### latency and CPU usage reading and changing individual revprops." NL "### Values smaller than 4 kByte will not improve latency any further and " NL "### quickly render revprop packing ineffective." NL -"### revprop-pack-size is 4 kBytes by default for non-compressed revprop" NL -"### pack files and 16 kBytes when compression has been enabled." NL -"# " CONFIG_OPTION_REVPROP_PACK_SIZE " = 4" NL +"### revprop-pack-size is 16 kBytes by default for non-compressed revprop" NL +"### pack files and 64 kBytes when compression has been enabled." NL +"# " CONFIG_OPTION_REVPROP_PACK_SIZE " = 16" NL "###" NL "### To save disk space, packed revprop files may be compressed. Standard" NL "### revprops tend to allow for very effective compression. Reading and" NL @@ -1019,6 +1147,13 @@ write_config(svn_fs_t *fs, "### Must be a power of 2." NL "### p2l-page-size is given in kBytes and with a default of 1024 kBytes." NL "# " CONFIG_OPTION_P2L_PAGE_SIZE " = 1024" NL +"" NL +"[" CONFIG_SECTION_DEBUG "]" NL +"###" NL +"### Whether to verify each new revision immediately before finalizing" NL +"### the commit. This is disabled by default except in maintainer-mode" NL +"### builds." NL +"# " CONFIG_OPTION_VERIFY_BEFORE_COMMIT " = false" NL ; #undef NL return svn_io_file_create(svn_dirent_join(fs->path, PATH_CONFIG, pool), @@ -1032,13 +1167,12 @@ read_global_config(svn_fs_t *fs) { fs_fs_data_t *ffd = fs->fsap_data; - /* Providing a config hash is optional. */ - if (fs->config) - ffd->use_block_read = svn_hash__get_bool(fs->config, - SVN_FS_CONFIG_FSFS_BLOCK_READ, - FALSE); - else - ffd->use_block_read = FALSE; + ffd->use_block_read = svn_hash__get_bool(fs->config, + SVN_FS_CONFIG_FSFS_BLOCK_READ, + FALSE); + ffd->flush_to_disk = !svn_hash__get_bool(fs->config, + SVN_FS_CONFIG_NO_FLUSH_TO_DISK, + FALSE); /* Ignore the user-specified larger block size if we don't use block-read. Defaulting to 4k gives us the same access granularity in format 7 as in @@ -1127,7 +1261,9 @@ svn_fs_fs__open(svn_fs_t *fs, const char *path, apr_pool_t *pool) /* Global configuration options. */ SVN_ERR(read_global_config(fs)); - return get_youngest(&(ffd->youngest_rev_cache), fs, pool); + ffd->youngest_rev_cache = 0; + + return SVN_NO_ERROR; } /* Wrapper around svn_io_file_create which ignores EEXIST. */ @@ -1334,7 +1470,10 @@ svn_fs_fs__min_unpacked_rev(svn_revnum_t *min_unpacked, { fs_fs_data_t *ffd = fs->fsap_data; - SVN_ERR(svn_fs_fs__update_min_unpacked_rev(fs, pool)); + /* Calling this for pre-v4 repos is illegal. */ + if (ffd->format >= SVN_FS_FS__MIN_PACKED_FORMAT) + SVN_ERR(svn_fs_fs__update_min_unpacked_rev(fs, pool)); + *min_unpacked = ffd->min_unpacked_rev; return SVN_NO_ERROR; @@ -1378,38 +1517,9 @@ svn_fs_fs__file_length(svn_filesize_t *length, /* Treat "no representation" as "empty file". */ *length = 0; } - else if (data_rep->expanded_size) - { - /* Standard case: a non-empty file. */ - *length = data_rep->expanded_size; - } else { - /* Work around a FSFS format quirk (see issue #4554). - - A plain representation may specify its EXPANDED LENGTH as "0" - in which case, the SIZE value is what we want. - - Because EXPANDED_LENGTH will also be 0 for empty files, while - SIZE is non-null, we need to check wether the content is - actually empty. We simply compare with the MD5 checksum of - empty content (sha-1 is not always available). - */ - svn_checksum_t *empty_md5 - = svn_checksum_empty_checksum(svn_checksum_md5, pool); - - if (memcmp(empty_md5->digest, data_rep->md5_digest, - sizeof(data_rep->md5_digest))) - { - /* Contents is not empty, i.e. EXPANDED_LENGTH cannot be the - actual file length. */ - *length = data_rep->size; - } - else - { - /* Contents is empty. */ - *length = 0; - } + *length = data_rep->expanded_size; } return SVN_NO_ERROR; @@ -1444,8 +1554,8 @@ svn_fs_fs__file_text_rep_equal(svn_boolean_t *equal, svn_stream_t *contents_a, *contents_b; representation_t *rep_a = a->data_rep; representation_t *rep_b = b->data_rep; - svn_boolean_t a_empty = !rep_a; - svn_boolean_t b_empty = !rep_b; + svn_boolean_t a_empty = !rep_a || rep_a->expanded_size == 0; + svn_boolean_t b_empty = !rep_b || rep_b->expanded_size == 0; /* This makes sure that neither rep will be NULL later on */ if (a_empty && b_empty) @@ -1454,6 +1564,28 @@ svn_fs_fs__file_text_rep_equal(svn_boolean_t *equal, return SVN_NO_ERROR; } + if (a_empty != b_empty) + { + *equal = FALSE; + return SVN_NO_ERROR; + } + + /* File text representations always know their checksums - even in a txn. */ + if (memcmp(rep_a->md5_digest, rep_b->md5_digest, sizeof(rep_a->md5_digest))) + { + *equal = FALSE; + return SVN_NO_ERROR; + } + + /* Paranoia. Compare SHA1 checksums because that's the level of + confidence we require for e.g. the working copy. */ + if (rep_a->has_sha1 && rep_b->has_sha1) + { + *equal = memcmp(rep_a->sha1_digest, rep_b->sha1_digest, + sizeof(rep_a->sha1_digest)) == 0; + return SVN_NO_ERROR; + } + /* Same path in same rev or txn? */ if (svn_fs_fs__id_eq(a->id, b->id)) { @@ -1461,30 +1593,6 @@ svn_fs_fs__file_text_rep_equal(svn_boolean_t *equal, return SVN_NO_ERROR; } - /* Beware of the combination NULL rep and possibly empty rep. - * Due to EXPANDED_SIZE not being reliable, we can't easily detect empty - * reps. So, we can only take further shortcuts if both reps are given. */ - if (!a_empty && !b_empty) - { - /* File text representations always know their checksums - - * even in a txn. */ - if (memcmp(rep_a->md5_digest, rep_b->md5_digest, - sizeof(rep_a->md5_digest))) - { - *equal = FALSE; - return SVN_NO_ERROR; - } - - /* Paranoia. Compare SHA1 checksums because that's the level of - confidence we require for e.g. the working copy. */ - if (rep_a->has_sha1 && rep_b->has_sha1) - { - *equal = memcmp(rep_a->sha1_digest, rep_b->sha1_digest, - sizeof(rep_a->sha1_digest)) == 0; - return SVN_NO_ERROR; - } - } - SVN_ERR(svn_fs_fs__get_contents(&contents_a, fs, rep_a, TRUE, scratch_pool)); SVN_ERR(svn_fs_fs__get_contents(&contents_b, fs, rep_b, TRUE, @@ -1519,14 +1627,27 @@ svn_fs_fs__prop_rep_equal(svn_boolean_t *equal, && !svn_fs_fs__id_txn_used(&rep_a->txn_id) && !svn_fs_fs__id_txn_used(&rep_b->txn_id)) { - /* MD5 must be given. Having the same checksum is good enough for - accepting the prop lists as equal. */ - *equal = memcmp(rep_a->md5_digest, rep_b->md5_digest, - sizeof(rep_a->md5_digest)) == 0; - return SVN_NO_ERROR; + /* Same representation? */ + if ( (rep_a->revision == rep_b->revision) + && (rep_a->item_index == rep_b->item_index)) + { + *equal = TRUE; + return SVN_NO_ERROR; + } + + /* Known different content? MD5 must be given. */ + if (memcmp(rep_a->md5_digest, rep_b->md5_digest, + sizeof(rep_a->md5_digest))) + { + *equal = FALSE; + return SVN_NO_ERROR; + } } - /* Same path in same txn? */ + /* Same path in same txn? + * + * For committed reps, IDs cannot be the same here b/c we already know + * that they point to different representations. */ if (svn_fs_fs__id_eq(a->id, b->id)) { *equal = TRUE; @@ -1827,6 +1948,8 @@ svn_fs_fs__create(svn_fs_t *fs, case 8: format = 6; break; + case 9: format = 7; + break; default:format = SVN_FS_FS__FORMAT_NUMBER; } @@ -1883,9 +2006,9 @@ svn_fs_fs__set_uuid(svn_fs_t *fs, /* We use the permissions of the 'current' file, because the 'uuid' file does not exist during repository creation. */ - SVN_ERR(svn_io_write_atomic(uuid_path, contents->data, contents->len, - svn_fs_fs__path_current(fs, pool) /* perms */, - pool)); + SVN_ERR(svn_io_write_atomic2(uuid_path, contents->data, contents->len, + svn_fs_fs__path_current(fs, pool) /* perms */, + ffd->flush_to_disk, pool)); fs->uuid = apr_pstrdup(fs->pool, uuid); @@ -2036,7 +2159,7 @@ set_node_origins_for_file(svn_fs_t *fs, SVN_ERR(svn_stream_close(stream)); /* Rename the temp file as the real destination */ - return svn_io_file_rename(path_tmp, node_origins_path, pool); + return svn_io_file_rename2(path_tmp, node_origins_path, FALSE, pool); } @@ -2071,14 +2194,17 @@ svn_fs_fs__revision_prop(svn_string_t **value_p, svn_fs_t *fs, svn_revnum_t rev, const char *propname, - apr_pool_t *pool) + svn_boolean_t refresh, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { apr_hash_t *table; SVN_ERR(svn_fs__check_fs(fs, TRUE)); - SVN_ERR(svn_fs_fs__get_revision_proplist(&table, fs, rev, pool)); + SVN_ERR(svn_fs_fs__get_revision_proplist(&table, fs, rev, refresh, + scratch_pool, scratch_pool)); - *value_p = svn_hash_gets(table, propname); + *value_p = svn_string_dup(svn_hash_gets(table, propname), result_pool); return SVN_NO_ERROR; } @@ -2101,13 +2227,17 @@ change_rev_prop_body(void *baton, apr_pool_t *pool) { struct change_rev_prop_baton *cb = baton; apr_hash_t *table; + const svn_string_t *present_value; - SVN_ERR(svn_fs_fs__get_revision_proplist(&table, cb->fs, cb->rev, pool)); + /* We always need to read the current revprops from disk. + * Hence, always "refresh" here. */ + SVN_ERR(svn_fs_fs__get_revision_proplist(&table, cb->fs, cb->rev, TRUE, + pool, pool)); + present_value = svn_hash_gets(table, cb->name); if (cb->old_value_p) { const svn_string_t *wanted_value = *cb->old_value_p; - const svn_string_t *present_value = svn_hash_gets(table, cb->name); if ((!wanted_value != !present_value) || (wanted_value && present_value && !svn_string_compare(wanted_value, present_value))) @@ -2120,6 +2250,13 @@ change_rev_prop_body(void *baton, apr_pool_t *pool) } /* Fall through. */ } + + /* If the prop-set is a no-op, skip the actual write. */ + if ((!present_value && !cb->value) + || (present_value && cb->value + && svn_string_compare(present_value, cb->value))) + return SVN_NO_ERROR; + svn_hash_sets(table, cb->name, cb->value); return svn_fs_fs__set_revision_proplist(cb->fs, cb->rev, table, pool); @@ -2182,8 +2319,11 @@ svn_fs_fs__info_format(int *fs_format, case 7: (*supports_version)->minor = 9; break; + case 8: + (*supports_version)->minor = 10; + break; #ifdef SVN_DEBUG -# if SVN_FS_FS__FORMAT_NUMBER != 7 +# if SVN_FS_FS__FORMAT_NUMBER != 8 # error "Need to add a 'case' statement here" # endif #endif diff --git a/subversion/libsvn_fs_fs/fs_fs.h b/subversion/libsvn_fs_fs/fs_fs.h index b6c94c7e7ff3..cef95fe3209e 100644 --- a/subversion/libsvn_fs_fs/fs_fs.h +++ b/subversion/libsvn_fs_fs/fs_fs.h @@ -39,6 +39,15 @@ svn_error_t *svn_fs_fs__open(svn_fs_t *fs, const char *path, apr_pool_t *pool); +/* Initialize parts of the FS data that are being shared across multiple + filesystem objects. Use COMMON_POOL for process-wide and POOL for + temporary allocations. Use COMMON_POOL_LOCK to ensure that the + initialization is serialized. */ +svn_error_t *svn_fs_fs__initialize_shared_data(svn_fs_t *fs, + svn_mutex__t *common_pool_lock, + apr_pool_t *pool, + apr_pool_t *common_pool); + /* Upgrade the fsfs filesystem FS. Indicate progress via the optional * NOTIFY_FUNC callback using NOTIFY_BATON. The optional CANCEL_FUNC * will periodically be called with CANCEL_BATON to allow for preemption. @@ -216,13 +225,16 @@ svn_fs_fs__with_all_locks(svn_fs_t *fs, void *baton, apr_pool_t *pool); -/* Find the value of the property named PROPNAME in transaction TXN. +/* Find the value of the property named PROPNAME in revision REV. Return the contents in *VALUE_P. The contents will be allocated - from POOL. */ + from RESULT_POOL and SCRATCH_POOL is used for temporaries. + Invalidate any revprop cache is REFRESH is set. */ svn_error_t *svn_fs_fs__revision_prop(svn_string_t **value_p, svn_fs_t *fs, svn_revnum_t rev, const char *propname, - apr_pool_t *pool); + svn_boolean_t refresh, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); /* Change, add, or delete a property on a revision REV in filesystem FS. NAME gives the name of the property, and value, if non-NULL, diff --git a/subversion/libsvn_fs_fs/fs_init.h b/subversion/libsvn_fs_fs/fs_init.h new file mode 100644 index 000000000000..c9f8474469dd --- /dev/null +++ b/subversion/libsvn_fs_fs/fs_init.h @@ -0,0 +1,32 @@ +/* + * libsvn_fs_fs/fs_init.h: Exported function of libsvn_fs_fs + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#ifndef LIBSVN_FS_LOADER_H +#error Please include libsvn_fs/fs_loader.h instead of this file +#else + +svn_error_t *svn_fs_fs__init(const svn_version_t *loader_version, + fs_library_vtable_t **vtable, + apr_pool_t* common_pool); + +#endif diff --git a/subversion/libsvn_fs_fs/hotcopy.c b/subversion/libsvn_fs_fs/hotcopy.c index 43f513e350f0..44a4ea442eb9 100644 --- a/subversion/libsvn_fs_fs/hotcopy.c +++ b/subversion/libsvn_fs_fs/hotcopy.c @@ -795,7 +795,7 @@ struct hotcopy_body_baton { * An incremental hotcopy copies only changed or new files to the destination, * and removes files from the destination no longer present in the source. * While the incremental hotcopy is running, readers should still be able - * to access the destintation repository without error and should not see + * to access the destination repository without error and should not see * revisions currently in progress of being copied. Readers are able to see * new fully copied revisions even if the entire incremental hotcopy procedure * has not yet completed. @@ -995,50 +995,33 @@ hotcopy_body(void *baton, apr_pool_t *pool) SVN_ERR(svn_io_dir_file_copy(src_fs->path, dst_fs->path, PATH_TXN_CURRENT, pool)); - return SVN_NO_ERROR; -} - -/* Create an empty filesystem at DST_FS at DST_PATH with the same - * configuration as SRC_FS (uuid, format, and other parameters). - * After creation DST_FS has no revisions, not even revision zero. */ -static svn_error_t * -hotcopy_create_empty_dest(svn_fs_t *src_fs, - svn_fs_t *dst_fs, - const char *dst_path, - apr_pool_t *pool) -{ - fs_fs_data_t *src_ffd = src_fs->fsap_data; - - /* Create the DST_FS repository with the same layout as SRC_FS. */ - SVN_ERR(svn_fs_fs__create_file_tree(dst_fs, dst_path, src_ffd->format, - src_ffd->max_files_per_dir, - src_ffd->use_log_addressing, - pool)); - - /* Copy the UUID. Hotcopy destination receives a new instance ID, but - * has the same filesystem UUID as the source. */ - SVN_ERR(svn_fs_fs__set_uuid(dst_fs, src_fs->uuid, NULL, pool)); - - /* Remove revision 0 contents. Otherwise, it may not get overwritten - * due to having a newer timestamp. */ - SVN_ERR(hotcopy_remove_file(svn_fs_fs__path_rev(dst_fs, 0, pool), pool)); - SVN_ERR(hotcopy_remove_file(svn_fs_fs__path_revprops(dst_fs, 0, pool), - pool)); - - /* This filesystem is ready. Stamp it with a format number. Fail if - * the 'format' file should already exist. */ - SVN_ERR(svn_fs_fs__write_format(dst_fs, FALSE, pool)); + /* Hotcopied FS is complete. Stamp it with a format file. */ + SVN_ERR(svn_fs_fs__write_format(dst_fs, TRUE, pool)); return SVN_NO_ERROR; } svn_error_t * -svn_fs_fs__hotcopy_prepare_target(svn_fs_t *src_fs, - svn_fs_t *dst_fs, - const char *dst_path, - svn_boolean_t incremental, - apr_pool_t *pool) +svn_fs_fs__hotcopy(svn_fs_t *src_fs, + svn_fs_t *dst_fs, + const char *src_path, + const char *dst_path, + svn_boolean_t incremental, + svn_fs_hotcopy_notify_t notify_func, + void *notify_baton, + svn_cancel_func_t cancel_func, + void *cancel_baton, + svn_mutex__t *common_pool_lock, + apr_pool_t *pool, + apr_pool_t *common_pool) { + struct hotcopy_body_baton hbb; + + if (cancel_func) + SVN_ERR(cancel_func(cancel_baton)); + + SVN_ERR(svn_fs_fs__open(src_fs, src_path, pool)); + if (incremental) { const char *dst_format_abspath; @@ -1050,39 +1033,51 @@ svn_fs_fs__hotcopy_prepare_target(svn_fs_t *src_fs, SVN_ERR(svn_io_check_path(dst_format_abspath, &dst_format_kind, pool)); if (dst_format_kind == svn_node_none) { - /* Destination doesn't exist yet. Perform a normal hotcopy to a - * empty destination using the same configuration as the source. */ - SVN_ERR(hotcopy_create_empty_dest(src_fs, dst_fs, dst_path, pool)); - } - else - { - /* Check the existing repository. */ - SVN_ERR(svn_fs_fs__open(dst_fs, dst_path, pool)); - SVN_ERR(hotcopy_incremental_check_preconditions(src_fs, dst_fs, - pool)); + /* No destination? Fallback to a non-incremental hotcopy. */ + incremental = FALSE; } } + + if (incremental) + { + /* Check the existing repository. */ + SVN_ERR(svn_fs_fs__open(dst_fs, dst_path, pool)); + SVN_ERR(hotcopy_incremental_check_preconditions(src_fs, dst_fs, pool)); + + SVN_ERR(svn_fs_fs__initialize_shared_data(dst_fs, common_pool_lock, + pool, common_pool)); + SVN_ERR(svn_fs_fs__initialize_caches(dst_fs, pool)); + } else { /* Start out with an empty destination using the same configuration * as the source. */ - SVN_ERR(hotcopy_create_empty_dest(src_fs, dst_fs, dst_path, pool)); + fs_fs_data_t *src_ffd = src_fs->fsap_data; + + /* Create the DST_FS repository with the same layout as SRC_FS. */ + SVN_ERR(svn_fs_fs__create_file_tree(dst_fs, dst_path, src_ffd->format, + src_ffd->max_files_per_dir, + src_ffd->use_log_addressing, + pool)); + + /* Copy the UUID. Hotcopy destination receives a new instance ID, but + * has the same filesystem UUID as the source. */ + SVN_ERR(svn_fs_fs__set_uuid(dst_fs, src_fs->uuid, NULL, pool)); + + /* Remove revision 0 contents. Otherwise, it may not get overwritten + * due to having a newer timestamp. */ + SVN_ERR(hotcopy_remove_file(svn_fs_fs__path_rev(dst_fs, 0, pool), + pool)); + SVN_ERR(hotcopy_remove_file(svn_fs_fs__path_revprops(dst_fs, 0, pool), + pool)); + + SVN_ERR(svn_fs_fs__initialize_shared_data(dst_fs, common_pool_lock, + pool, common_pool)); + SVN_ERR(svn_fs_fs__initialize_caches(dst_fs, pool)); } - return SVN_NO_ERROR; -} - -svn_error_t * -svn_fs_fs__hotcopy(svn_fs_t *src_fs, - svn_fs_t *dst_fs, - svn_boolean_t incremental, - svn_fs_hotcopy_notify_t notify_func, - void *notify_baton, - svn_cancel_func_t cancel_func, - void *cancel_baton, - apr_pool_t *pool) -{ - struct hotcopy_body_baton hbb; + if (cancel_func) + SVN_ERR(cancel_func(cancel_baton)); hbb.src_fs = src_fs; hbb.dst_fs = dst_fs; @@ -1091,7 +1086,15 @@ svn_fs_fs__hotcopy(svn_fs_t *src_fs, hbb.notify_baton = notify_baton; hbb.cancel_func = cancel_func; hbb.cancel_baton = cancel_baton; - SVN_ERR(svn_fs_fs__with_all_locks(dst_fs, hotcopy_body, &hbb, pool)); + + /* Lock the destination in the incremental mode. For a non-incremental + * hotcopy, don't take any locks. In that case the destination cannot be + * opened until the hotcopy finishes, and we don't have to worry about + * concurrency. */ + if (incremental) + SVN_ERR(svn_fs_fs__with_all_locks(dst_fs, hotcopy_body, &hbb, pool)); + else + SVN_ERR(hotcopy_body(&hbb, pool)); return SVN_NO_ERROR; } diff --git a/subversion/libsvn_fs_fs/hotcopy.h b/subversion/libsvn_fs_fs/hotcopy.h index ddd62183a927..2f2322c410c2 100644 --- a/subversion/libsvn_fs_fs/hotcopy.h +++ b/subversion/libsvn_fs_fs/hotcopy.h @@ -25,27 +25,23 @@ #include "fs.h" -/* Create an empty copy of the fsfs filesystem SRC_FS into a new DST_FS at - * DST_PATH. If INCREMENTAL is TRUE, perform a few pre-checks only if - * a repo already exists at DST_PATH. Use POOL for temporary allocations. */ -svn_error_t * -svn_fs_fs__hotcopy_prepare_target(svn_fs_t *src_fs, - svn_fs_t *dst_fs, - const char *dst_path, - svn_boolean_t incremental, - apr_pool_t *pool); - -/* Copy the fsfs filesystem SRC_FS into DST_FS. If INCREMENTAL is TRUE, do - * not re-copy data which already exists in DST_FS. Indicate progress via - * the optional NOTIFY_FUNC callback using NOTIFY_BATON. Use POOL for - * temporary allocations. */ +/* Copy the fsfs filesystem SRC_FS at SRC_PATH into a new copy DST_FS at + * DST_PATH. If INCREMENTAL is TRUE, do not re-copy data which already + * exists in DST_FS. Indicate progress via the optional NOTIFY_FUNC + * callback using NOTIFY_BATON. Use COMMON_POOL for process-wide and + * POOL for temporary allocations. Use COMMON_POOL_LOCK to ensure + * that the initialization of the shared data is serialized. */ svn_error_t * svn_fs_fs__hotcopy(svn_fs_t *src_fs, svn_fs_t *dst_fs, + const char *src_path, + const char *dst_path, svn_boolean_t incremental, svn_fs_hotcopy_notify_t notify_func, void *notify_baton, svn_cancel_func_t cancel_func, void *cancel_baton, - apr_pool_t *pool); + svn_mutex__t *common_pool_lock, + apr_pool_t *pool, + apr_pool_t *common_pool); #endif diff --git a/subversion/libsvn_fs_fs/id.c b/subversion/libsvn_fs_fs/id.c index bd505e06cbbc..d22b8f776359 100644 --- a/subversion/libsvn_fs_fs/id.c +++ b/subversion/libsvn_fs_fs/id.c @@ -82,9 +82,11 @@ locale_independent_strtol(long *result_p, next = result * 10 + c; - /* Overflow check. In case of an overflow, NEXT is 0..9. - * In the non-overflow case, RESULT is either >= 10 or RESULT and NEXT - * are both 0. */ + /* Overflow check. In case of an overflow, NEXT is 0..9 and RESULT + * is much larger than 10. We will then return FALSE. + * + * In the non-overflow case, NEXT is >= 10 * RESULT but never smaller. + * We will continue the loop in that case. */ if (next < result) return FALSE; @@ -610,7 +612,9 @@ svn_fs_fs__id_serialize(svn_temp_serializer__context_t *context, if (id == NULL) return; - /* serialize the id data struct itself */ + /* Serialize the id data struct itself. + * Note that the structure behind IN is actually larger than a mere + * svn_fs_id_t . */ svn_temp_serializer__add_leaf(context, (const void * const *)in, sizeof(fs_fs__id_t)); diff --git a/subversion/libsvn_fs_fs/index.c b/subversion/libsvn_fs_fs/index.c index a6695580a0f5..1cb8fba80ad6 100644 --- a/subversion/libsvn_fs_fs/index.c +++ b/subversion/libsvn_fs_fs/index.c @@ -231,7 +231,7 @@ stream_error_create(svn_fs_fs__packed_number_stream_t *stream, apr_off_t offset; SVN_ERR(svn_io_file_name_get(&file_name, stream->file, stream->pool)); - SVN_ERR(svn_fs_fs__get_file_offset(&offset, stream->file, stream->pool)); + SVN_ERR(svn_io_file_get_offset(&offset, stream->file, stream->pool)); return svn_error_createf(err, NULL, message, file_name, apr_psprintf(stream->pool, @@ -251,7 +251,7 @@ static svn_error_t * packed_stream_read(svn_fs_fs__packed_number_stream_t *stream) { unsigned char buffer[MAX_NUMBER_PREFETCH]; - apr_size_t read = 0; + apr_size_t bytes_read = 0; apr_size_t i; value_position_pair_t *target; apr_off_t block_start = 0; @@ -273,33 +273,34 @@ packed_stream_read(svn_fs_fs__packed_number_stream_t *stream) * boundaries. This shall prevent jumping back and forth between two * blocks because the extra data was not actually request _now_. */ - read = sizeof(buffer); + bytes_read = sizeof(buffer); block_left = stream->block_size - (stream->next_offset - block_start); - if (block_left >= 10 && block_left < read) - read = (apr_size_t)block_left; + if (block_left >= 10 && block_left < bytes_read) + bytes_read = (apr_size_t)block_left; /* Don't read beyond the end of the file section that belongs to this * index / stream. */ - read = (apr_size_t)MIN(read, stream->stream_end - stream->next_offset); + bytes_read = (apr_size_t)MIN(bytes_read, + stream->stream_end - stream->next_offset); - err = apr_file_read(stream->file, buffer, &read); + err = apr_file_read(stream->file, buffer, &bytes_read); if (err && !APR_STATUS_IS_EOF(err)) return stream_error_create(stream, err, _("Can't read index file '%s' at offset 0x%s")); /* if the last number is incomplete, trim it from the buffer */ - while (read > 0 && buffer[read-1] >= 0x80) - --read; + while (bytes_read > 0 && buffer[bytes_read-1] >= 0x80) + --bytes_read; /* we call read() only if get() requires more data. So, there must be * at least *one* further number. */ - if SVN__PREDICT_FALSE(read == 0) + if SVN__PREDICT_FALSE(bytes_read == 0) return stream_error_create(stream, err, _("Unexpected end of index file %s at offset 0x%s")); /* parse file buffer and expand into stream buffer */ target = stream->buffer; - for (i = 0; i < read;) + for (i = 0; i < bytes_read;) { if (buffer[i] < 0x80) { @@ -558,13 +559,13 @@ read_uint64_from_proto_index(apr_file_t *proto_index, apr_pool_t *scratch_pool) { apr_byte_t buffer[sizeof(*value_p)]; - apr_size_t read; + apr_size_t bytes_read; /* Read the full 8 bytes or our 64 bit value, unless we hit EOF. * Assert that we never read partial values. */ SVN_ERR(svn_io_file_read_full2(proto_index, buffer, sizeof(buffer), - &read, eof, scratch_pool)); - SVN_ERR_ASSERT((eof && *eof) || read == sizeof(buffer)); + &bytes_read, eof, scratch_pool)); + SVN_ERR_ASSERT((eof && *eof) || bytes_read == sizeof(buffer)); /* If we did not hit EOF, reconstruct the uint64 value and return it. */ if (!eof || !*eof) @@ -1735,7 +1736,7 @@ svn_fs_fs__l2p_get_max_ids(apr_array_header_t **max_ids, apr_uint64_t item_count; apr_size_t first_page_index, last_page_index; - if (revision >= header->first_revision + header->revision_count) + if (revision - header->first_revision >= header->revision_count) { /* need to read the next index. Clear up memory used for the * previous one. Note that intermittent pack runs do not change @@ -2421,6 +2422,13 @@ read_entry(svn_fs_fs__packed_number_stream_t *stream, return svn_error_create(SVN_ERR_FS_INDEX_CORRUPTION, NULL, _("Empty regions must have item number 0 and checksum 0")); + /* Corrupted SIZE values might cause arithmetic overflow. + * The same can happen if you copy a repository from a system with 63 bit + * file lengths to one with 31 bit file lengths. */ + if ((apr_uint64_t)entry.offset + (apr_uint64_t)entry.size > off_t_max) + return svn_error_create(SVN_ERR_FS_INDEX_OVERFLOW , NULL, + _("P2L index entry size overflow.")); + APR_ARRAY_PUSH(result, svn_fs_fs__p2l_entry_t) = entry; *item_offset += entry.size; @@ -3207,18 +3215,11 @@ svn_fs_fs__l2p_index_from_p2l_entries(const char **protoname, apr_pool_t *iterpool = svn_pool_create(scratch_pool); int i; svn_revnum_t last_revision = SVN_INVALID_REVNUM; - svn_revnum_t revision = SVN_INVALID_REVNUM; /* L2P index must be written in revision order. * Sort ENTRIES accordingly. */ svn_sort__array(entries, compare_p2l_entry_revision); - /* Find the first revision in the index - * (must exist since no truly empty revs are allowed). */ - for (i = 0; i < entries->nelts && !SVN_IS_VALID_REVNUM(revision); ++i) - revision = APR_ARRAY_IDX(entries, i, const svn_fs_fs__p2l_entry_t *) - ->item.revision; - /* Create the temporary proto-rev file. */ SVN_ERR(svn_io_open_unique_file3(NULL, protoname, NULL, svn_io_file_del_on_pool_cleanup, diff --git a/subversion/libsvn_fs_fs/load-index.c b/subversion/libsvn_fs_fs/load-index.c index 3142e8e35402..0ba66725d35c 100644 --- a/subversion/libsvn_fs_fs/load-index.c +++ b/subversion/libsvn_fs_fs/load-index.c @@ -29,6 +29,53 @@ #include "util.h" #include "transaction.h" +/* From the ENTRIES array of svn_fs_fs__p2l_entry_t*, sorted by offset, + * return the first offset behind the last item. */ +static apr_off_t +get_max_covered(apr_array_header_t *entries) +{ + const svn_fs_fs__p2l_entry_t *entry; + if (entries->nelts == 0) + return -1; + + entry = APR_ARRAY_IDX(entries, entries->nelts - 1, + const svn_fs_fs__p2l_entry_t *); + return entry->offset + entry->size; +} + +/* Make sure that the svn_fs_fs__p2l_entry_t* in ENTRIES are consecutive + * and non-overlapping. Use SCRATCH_POOL for temporaries. */ +static svn_error_t * +check_all_covered(apr_array_header_t *entries, + apr_pool_t *scratch_pool) +{ + int i; + apr_off_t expected = 0; + for (i = 0; i < entries->nelts; ++i) + { + const svn_fs_fs__p2l_entry_t *entry + = APR_ARRAY_IDX(entries, i, const svn_fs_fs__p2l_entry_t *); + + if (entry->offset < expected) + return svn_error_createf(SVN_ERR_INVALID_INPUT, NULL, + "Overlapping index data for offset %s", + apr_psprintf(scratch_pool, + "%" APR_UINT64_T_HEX_FMT, + (apr_uint64_t)expected)); + + if (entry->offset > expected) + return svn_error_createf(SVN_ERR_INVALID_INPUT, NULL, + "Missing index data for offset %s", + apr_psprintf(scratch_pool, + "%" APR_UINT64_T_HEX_FMT, + (apr_uint64_t)expected)); + + expected = entry->offset + entry->size; + } + + return SVN_NO_ERROR; +} + /* A svn_sort__array compatible comparator function, sorting the * svn_fs_fs__p2l_entry_t** given in LHS, RHS by offset. */ static int @@ -52,7 +99,7 @@ svn_fs_fs__load_index(svn_fs_t *fs, apr_array_header_t *entries, apr_pool_t *scratch_pool) { - apr_pool_t *iterpool = svn_pool_create(scratch_pool); + apr_pool_t *subpool = svn_pool_create(scratch_pool); /* Check the FS format number. */ if (! svn_fs_fs__use_log_addressing(fs)) @@ -68,31 +115,60 @@ svn_fs_fs__load_index(svn_fs_t *fs, const char *l2p_proto_index; const char *p2l_proto_index; svn_fs_fs__revision_file_t *rev_file; + svn_error_t *err; + apr_off_t max_covered = get_max_covered(entries); + + /* Ensure that the index data is complete. */ + SVN_ERR(check_all_covered(entries, scratch_pool)); /* Open rev / pack file & trim indexes + footer off it. */ SVN_ERR(svn_fs_fs__open_pack_or_rev_file_writable(&rev_file, fs, - revision, iterpool, - iterpool)); - SVN_ERR(svn_fs_fs__auto_read_footer(rev_file)); - SVN_ERR(svn_io_file_trunc(rev_file->file, rev_file->l2p_offset, - iterpool)); + revision, subpool, + subpool)); + + /* Remove the existing index info. */ + err = svn_fs_fs__auto_read_footer(rev_file); + if (err) + { + /* Even the index footer cannot be read, even less be trusted. + * Take the range of valid data from the new index data. */ + svn_error_clear(err); + SVN_ERR(svn_io_file_trunc(rev_file->file, max_covered, + subpool)); + } + else + { + /* We assume that the new index data covers all contents. + * Error out if it doesn't. The user can always truncate + * the file themselves. */ + if (max_covered != rev_file->l2p_offset) + return svn_error_createf(SVN_ERR_INVALID_INPUT, NULL, + "New index data ends at %s, old index ended at %s", + apr_psprintf(scratch_pool, "%" APR_UINT64_T_HEX_FMT, + (apr_uint64_t)max_covered), + apr_psprintf(scratch_pool, "%" APR_UINT64_T_HEX_FMT, + (apr_uint64_t) rev_file->l2p_offset)); + + SVN_ERR(svn_io_file_trunc(rev_file->file, rev_file->l2p_offset, + subpool)); + } /* Create proto index files for the new index data * (will be cleaned up automatically with iterpool). */ SVN_ERR(svn_fs_fs__p2l_index_from_p2l_entries(&p2l_proto_index, fs, rev_file, entries, - iterpool, iterpool)); + subpool, subpool)); SVN_ERR(svn_fs_fs__l2p_index_from_p2l_entries(&l2p_proto_index, fs, - entries, iterpool, - iterpool)); + entries, subpool, + subpool)); /* Combine rev data with new index data. */ SVN_ERR(svn_fs_fs__add_index_data(fs, rev_file->file, l2p_proto_index, p2l_proto_index, - rev_file->start_revision, iterpool)); + rev_file->start_revision, subpool)); } - svn_pool_destroy(iterpool); + svn_pool_destroy(subpool); return SVN_NO_ERROR; } diff --git a/subversion/libsvn_fs_fs/lock.c b/subversion/libsvn_fs_fs/lock.c index c852025f2dac..3b8284d3ee46 100644 --- a/subversion/libsvn_fs_fs/lock.c +++ b/subversion/libsvn_fs_fs/lock.c @@ -222,7 +222,7 @@ write_digest_file(apr_hash_t *children, svn_io_file_del_none, pool, pool)); if ((err = svn_hash_write2(hash, stream, SVN_HASH_TERMINATOR, pool))) { - svn_error_clear(svn_stream_close(stream)); + err = svn_error_compose_create(err, svn_stream_close(stream)); return svn_error_createf(err->apr_err, err, _("Cannot write lock/entries hashfile '%s'"), @@ -230,7 +230,7 @@ write_digest_file(apr_hash_t *children, } SVN_ERR(svn_stream_close(stream)); - SVN_ERR(svn_io_file_rename(tmp_path, digest_path, pool)); + SVN_ERR(svn_io_file_rename2(tmp_path, digest_path, FALSE, pool)); SVN_ERR(svn_io_copy_perms(perms_reference, digest_path, pool)); return SVN_NO_ERROR; } @@ -273,7 +273,7 @@ read_digest_file(apr_hash_t **children_p, hash = apr_hash_make(pool); if ((err = svn_hash_read2(hash, stream, SVN_HASH_TERMINATOR, pool))) { - svn_error_clear(svn_stream_close(stream)); + err = svn_error_compose_create(err, svn_stream_close(stream)); return svn_error_createf(err->apr_err, err, _("Can't parse lock/entries hashfile '%s'"), @@ -847,7 +847,7 @@ lock_body(void *baton, apr_pool_t *pool) apr_pool_t *iterpool = svn_pool_create(pool); /* Until we implement directory locks someday, we only allow locks - on files or non-existent paths. */ + on files. */ /* Use fs->vtable->foo instead of svn_fs_foo to avoid circular library dependencies, which are not portable. */ SVN_ERR(lb->fs->vtable->youngest_rev(&youngest, lb->fs, pool)); diff --git a/subversion/libsvn_fs_fs/low_level.c b/subversion/libsvn_fs_fs/low_level.c index d21e312faa2e..2854bc6e2d84 100644 --- a/subversion/libsvn_fs_fs/low_level.c +++ b/subversion/libsvn_fs_fs/low_level.c @@ -189,6 +189,19 @@ svn_fs_fs__unparse_revision_trailer(apr_off_t root_offset, changes_offset); } +/* If ERR is not NULL, wrap it MESSAGE. The latter must have an %ld + * format parameter that will be filled with REV. */ +static svn_error_t * +wrap_footer_error(svn_error_t *err, + const char *message, + svn_revnum_t rev) +{ + if (err) + return svn_error_quick_wrapf(err, message, rev); + + return SVN_NO_ERROR; +} + svn_error_t * svn_fs_fs__parse_footer(apr_off_t *l2p_offset, svn_checksum_t **l2p_checksum, @@ -196,6 +209,7 @@ svn_fs_fs__parse_footer(apr_off_t *l2p_offset, svn_checksum_t **p2l_checksum, svn_stringbuf_t *footer, svn_revnum_t rev, + apr_off_t footer_offset, apr_pool_t *result_pool) { apr_int64_t val; @@ -204,17 +218,20 @@ svn_fs_fs__parse_footer(apr_off_t *l2p_offset, /* Get the L2P offset. */ const char *str = svn_cstring_tokenize(" ", &last_str); if (str == NULL) - return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, - _("Invalid revision footer")); + return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, + "Invalid r%ld footer", rev); - SVN_ERR(svn_cstring_atoi64(&val, str)); + SVN_ERR(wrap_footer_error(svn_cstring_strtoi64(&val, str, 0, + footer_offset - 1, 10), + "Invalid L2P offset in r%ld footer", + rev)); *l2p_offset = (apr_off_t)val; /* Get the L2P checksum. */ str = svn_cstring_tokenize(" ", &last_str); if (str == NULL) - return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, - _("Invalid revision footer")); + return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, + "Invalid r%ld footer", rev); SVN_ERR(svn_checksum_parse_hex(l2p_checksum, svn_checksum_md5, str, result_pool)); @@ -222,17 +239,33 @@ svn_fs_fs__parse_footer(apr_off_t *l2p_offset, /* Get the P2L offset. */ str = svn_cstring_tokenize(" ", &last_str); if (str == NULL) - return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, - _("Invalid revision footer")); + return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, + "Invalid r%ld footer", rev); - SVN_ERR(svn_cstring_atoi64(&val, str)); + SVN_ERR(wrap_footer_error(svn_cstring_strtoi64(&val, str, 0, + footer_offset - 1, 10), + "Invalid P2L offset in r%ld footer", + rev)); *p2l_offset = (apr_off_t)val; + /* The P2L indes follows the L2P index */ + if (*p2l_offset <= *l2p_offset) + return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, + "P2L offset %s must be larger than L2P offset %s" + " in r%ld footer", + apr_psprintf(result_pool, + "%" APR_UINT64_T_HEX_FMT, + (apr_uint64_t)*p2l_offset), + apr_psprintf(result_pool, + "%" APR_UINT64_T_HEX_FMT, + (apr_uint64_t)*l2p_offset), + rev); + /* Get the P2L checksum. */ str = svn_cstring_tokenize(" ", &last_str); if (str == NULL) - return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, - _("Invalid revision footer")); + return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, + "Invalid r%ld footer", rev); SVN_ERR(svn_checksum_parse_hex(p2l_checksum, svn_checksum_md5, str, result_pool)); @@ -449,10 +482,10 @@ read_change(change_t **change_p, svn_error_t * svn_fs_fs__read_changes(apr_array_header_t **changes, svn_stream_t *stream, + int max_count, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - change_t *change; apr_pool_t *iterpool; /* Pre-allocate enough room for most change lists. @@ -465,13 +498,16 @@ svn_fs_fs__read_changes(apr_array_header_t **changes, */ *changes = apr_array_make(result_pool, 63, sizeof(change_t *)); - SVN_ERR(read_change(&change, stream, result_pool, scratch_pool)); iterpool = svn_pool_create(scratch_pool); - while (change) + for (; max_count > 0; --max_count) { - APR_ARRAY_PUSH(*changes, change_t*) = change; - SVN_ERR(read_change(&change, stream, result_pool, iterpool)); + change_t *change; svn_pool_clear(iterpool); + SVN_ERR(read_change(&change, stream, result_pool, iterpool)); + if (!change) + break; + + APR_ARRAY_PUSH(*changes, change_t*) = change; } svn_pool_destroy(iterpool); @@ -705,6 +741,9 @@ read_header_block(apr_hash_t **headers, return SVN_NO_ERROR; } +/* ### Ouch! The implementation of this function currently modifies + ### the input string when tokenizing it (so the input cannot be + ### used after that). */ svn_error_t * svn_fs_fs__parse_representation(representation_t **rep_p, svn_stringbuf_t *text, @@ -775,13 +814,21 @@ svn_fs_fs__parse_representation(representation_t **rep_p, if (str == NULL) return SVN_NO_ERROR; - /* Read the SHA1 hash. */ - if (strlen(str) != (APR_SHA1_DIGESTSIZE * 2)) - return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, - _("Malformed text representation offset line in node-rev")); + /* Is the SHA1 hash present? */ + if (str[0] == '-' && str[1] == 0) + { + checksum = NULL; + } + else + { + /* Read the SHA1 hash. */ + if (strlen(str) != (APR_SHA1_DIGESTSIZE * 2)) + return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, + _("Malformed text representation offset line in node-rev")); - SVN_ERR(svn_checksum_parse_hex(&checksum, svn_checksum_sha1, str, - scratch_pool)); + SVN_ERR(svn_checksum_parse_hex(&checksum, svn_checksum_sha1, str, + scratch_pool)); + } /* We do have a valid SHA1 but it might be all 0. We cannot be sure where that came from (Alas! legacy), so let's not @@ -793,21 +840,36 @@ svn_fs_fs__parse_representation(representation_t **rep_p, if (checksum) memcpy(rep->sha1_digest, checksum->digest, sizeof(rep->sha1_digest)); - /* Read the uniquifier. */ - str = svn_cstring_tokenize("/", &string); + str = svn_cstring_tokenize(" ", &string); if (str == NULL) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Malformed text representation offset line in node-rev")); - SVN_ERR(svn_fs_fs__id_txn_parse(&rep->uniquifier.noderev_txn_id, str)); + /* Is the uniquifier present? */ + if (str[0] == '-' && str[1] == 0) + { + end = string; + } + else + { + char *substring = str; - str = svn_cstring_tokenize(" ", &string); - if (str == NULL || *str != '_') - return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, - _("Malformed text representation offset line in node-rev")); + /* Read the uniquifier. */ + str = svn_cstring_tokenize("/", &substring); + if (str == NULL) + return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, + _("Malformed text representation offset line in node-rev")); - ++str; - rep->uniquifier.number = svn__base36toui64(&end, str); + SVN_ERR(svn_fs_fs__id_txn_parse(&rep->uniquifier.noderev_txn_id, str)); + + str = svn_cstring_tokenize(" ", &substring); + if (str == NULL || *str != '_') + return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, + _("Malformed text representation offset line in node-rev")); + + ++str; + rep->uniquifier.number = svn__base36toui64(&end, str); + } if (*end) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, @@ -998,25 +1060,37 @@ svn_fs_fs__read_noderev(node_revision_t **noderev_p, } /* Return a textual representation of the DIGEST of given KIND. - * If IS_NULL is TRUE, no digest is available. * Allocate the result in RESULT_POOL. */ static const char * format_digest(const unsigned char *digest, svn_checksum_kind_t kind, - svn_boolean_t is_null, apr_pool_t *result_pool) { svn_checksum_t checksum; checksum.digest = digest; checksum.kind = kind; - if (is_null) - return "(null)"; - return svn_checksum_to_cstring_display(&checksum, result_pool); } +/* Return a textual representation of the uniquifier represented + * by NODEREV_TXN_ID and NUMBER. Use POOL for the allocations. + */ +static const char * +format_uniquifier(const svn_fs_fs__id_part_t *noderev_txn_id, + apr_uint64_t number, + apr_pool_t *pool) +{ + char buf[SVN_INT64_BUFFER_SIZE]; + const char *txn_id_str; + + txn_id_str = svn_fs_fs__id_txn_unparse(noderev_txn_id, pool); + svn__ui64tobase36(buf, number); + + return apr_psprintf(pool, "%s/_%s", txn_id_str, buf); +} + svn_stringbuf_t * svn_fs_fs__unparse_representation(representation_t *rep, int format, @@ -1024,32 +1098,80 @@ svn_fs_fs__unparse_representation(representation_t *rep, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - char buffer[SVN_INT64_BUFFER_SIZE]; + svn_stringbuf_t *str; + const char *sha1_str; + const char *uniquifier_str; + if (svn_fs_fs__id_txn_used(&rep->txn_id) && mutable_rep_truncated) return svn_stringbuf_ncreate("-1", 2, result_pool); - if (format < SVN_FS_FS__MIN_REP_SHARING_FORMAT || !rep->has_sha1) - return svn_stringbuf_createf - (result_pool, "%ld %" APR_UINT64_T_FMT " %" SVN_FILESIZE_T_FMT - " %" SVN_FILESIZE_T_FMT " %s", - rep->revision, rep->item_index, rep->size, - rep->expanded_size, - format_digest(rep->md5_digest, svn_checksum_md5, FALSE, - scratch_pool)); + /* Format of the string: + [] [] + */ + str = svn_stringbuf_createf( + result_pool, + "%ld" + " %" APR_UINT64_T_FMT + " %" SVN_FILESIZE_T_FMT + " %" SVN_FILESIZE_T_FMT + " %s", + rep->revision, + rep->item_index, + rep->size, + rep->expanded_size, + format_digest(rep->md5_digest, svn_checksum_md5, scratch_pool)); - svn__ui64tobase36(buffer, rep->uniquifier.number); - return svn_stringbuf_createf - (result_pool, "%ld %" APR_UINT64_T_FMT " %" SVN_FILESIZE_T_FMT - " %" SVN_FILESIZE_T_FMT " %s %s %s/_%s", - rep->revision, rep->item_index, rep->size, - rep->expanded_size, - format_digest(rep->md5_digest, svn_checksum_md5, - FALSE, scratch_pool), - format_digest(rep->sha1_digest, svn_checksum_sha1, - !rep->has_sha1, scratch_pool), - svn_fs_fs__id_txn_unparse(&rep->uniquifier.noderev_txn_id, - scratch_pool), - buffer); + /* Compatibility: these formats don't understand and . */ + if (format < SVN_FS_FS__MIN_REP_SHARING_FORMAT) + return str; + + if (format < SVN_FS_FS__MIN_REP_STRING_OPTIONAL_VALUES_FORMAT) + { + /* Compatibility: these formats can only have and + present simultaneously, or don't have them at all. */ + if (rep->has_sha1) + { + sha1_str = format_digest(rep->sha1_digest, svn_checksum_sha1, + scratch_pool); + uniquifier_str = format_uniquifier(&rep->uniquifier.noderev_txn_id, + rep->uniquifier.number, + scratch_pool); + svn_stringbuf_appendbyte(str, ' '); + svn_stringbuf_appendcstr(str, sha1_str); + svn_stringbuf_appendbyte(str, ' '); + svn_stringbuf_appendcstr(str, uniquifier_str); + } + return str; + } + + /* The most recent formats support optional and values. */ + if (rep->has_sha1) + { + sha1_str = format_digest(rep->sha1_digest, svn_checksum_sha1, + scratch_pool); + } + else + sha1_str = "-"; + + if (rep->uniquifier.number == 0 && + rep->uniquifier.noderev_txn_id.number == 0 && + rep->uniquifier.noderev_txn_id.revision == 0) + { + uniquifier_str = "-"; + } + else + { + uniquifier_str = format_uniquifier(&rep->uniquifier.noderev_txn_id, + rep->uniquifier.number, + scratch_pool); + } + + svn_stringbuf_appendbyte(str, ' '); + svn_stringbuf_appendcstr(str, sha1_str); + svn_stringbuf_appendbyte(str, ' '); + svn_stringbuf_appendcstr(str, uniquifier_str); + + return str; } diff --git a/subversion/libsvn_fs_fs/low_level.h b/subversion/libsvn_fs_fs/low_level.h index 35b9d0da5000..3029e2789052 100644 --- a/subversion/libsvn_fs_fs/low_level.h +++ b/subversion/libsvn_fs_fs/low_level.h @@ -67,6 +67,8 @@ svn_fs_fs__unparse_revision_trailer(apr_off_t root_offset, * *P2L_OFFSET, respectively. Also, return the expected checksums in * in *L2P_CHECKSUM and *P2L_CHECKSUM. * + * FOOTER_OFFSET is used for validation. + * * Note that REV is only used to construct nicer error objects that * mention this revision. Allocate the checksums in RESULT_POOL. */ @@ -77,6 +79,7 @@ svn_fs_fs__parse_footer(apr_off_t *l2p_offset, svn_checksum_t **p2l_checksum, svn_stringbuf_t *footer, svn_revnum_t rev, + apr_off_t footer_offset, apr_pool_t *result_pool); /* Given the offset of the L2P index data in L2P_OFFSET, the content @@ -94,11 +97,13 @@ svn_fs_fs__unparse_footer(apr_off_t l2p_offset, apr_pool_t *result_pool, apr_pool_t *scratch_pool); -/* Read all the changes from STREAM and store them in *CHANGES, - allocated in RESULT_POOL. Do temporary allocations in SCRATCH_POOL. */ +/* Read up to MAX_COUNT of the changes from STREAM and store them in + *CHANGES, allocated in RESULT_POOL. Do temporary allocations in + SCRATCH_POOL. */ svn_error_t * svn_fs_fs__read_changes(apr_array_header_t **changes, svn_stream_t *stream, + int max_count, apr_pool_t *result_pool, apr_pool_t *scratch_pool); diff --git a/subversion/libsvn_fs_fs/pack.c b/subversion/libsvn_fs_fs/pack.c index 8c4ef37fbaa4..1119857998fc 100644 --- a/subversion/libsvn_fs_fs/pack.c +++ b/subversion/libsvn_fs_fs/pack.c @@ -108,8 +108,8 @@ typedef struct path_order_t /* noderev predecessor count */ int predecessor_count; - /* this is a directory node */ - svn_boolean_t is_dir; + /* this is a node is the latest for this PATH in this rev / pack file */ + svn_boolean_t is_head; /* length of the expanded representation content */ apr_int64_t expanded_size; @@ -221,7 +221,7 @@ typedef struct pack_context_t * to NULL that we already processed. */ apr_array_header_t *reps; - /* array of int, marking for each revision, the which offset their items + /* array of int, marking for each revision, at which offset their items * begin in REPS. Will be filled in phase 2 and be cleared after * each revision range. */ apr_array_header_t *rev_offsets; @@ -233,6 +233,9 @@ typedef struct pack_context_t /* pool used for temporary data structures that will be cleaned up when * the next range of revisions is being processed */ apr_pool_t *info_pool; + + /* ensure that all filesystem changes are written to disk. */ + svn_boolean_t flush_to_disk; } pack_context_t; /* Create and initialize a new pack context for packing shard SHARD_REV in @@ -240,7 +243,7 @@ typedef struct pack_context_t * and return the structure in *CONTEXT. * * Limit the number of items being copied per iteration to MAX_ITEMS. - * Set CANCEL_FUNC and CANCEL_BATON as well. + * Set FLUSH_TO_DISK, CANCEL_FUNC and CANCEL_BATON as well. */ static svn_error_t * initialize_pack_context(pack_context_t *context, @@ -249,6 +252,7 @@ initialize_pack_context(pack_context_t *context, const char *shard_dir, svn_revnum_t shard_rev, int max_items, + svn_boolean_t flush_to_disk, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *pool) @@ -273,6 +277,12 @@ initialize_pack_context(pack_context_t *context, context->end_rev = shard_rev; context->shard_end_rev = shard_rev + ffd->max_files_per_dir; + /* the pool used for temp structures */ + context->info_pool = svn_pool_create(pool); + context->paths = svn_prefix_tree__create(context->info_pool); + + context->flush_to_disk = flush_to_disk; + /* Create the new directory and pack file. */ context->shard_dir = shard_dir; context->pack_file_dir = pack_file_dir; @@ -300,15 +310,18 @@ initialize_pack_context(pack_context_t *context, context->changes = apr_array_make(pool, max_items, sizeof(svn_fs_fs__p2l_entry_t *)); SVN_ERR(svn_io_open_unique_file3(&context->changes_file, NULL, temp_dir, - svn_io_file_del_on_close, pool, pool)); + svn_io_file_del_on_close, + context->info_pool, pool)); context->file_props = apr_array_make(pool, max_items, sizeof(svn_fs_fs__p2l_entry_t *)); SVN_ERR(svn_io_open_unique_file3(&context->file_props_file, NULL, temp_dir, - svn_io_file_del_on_close, pool, pool)); + svn_io_file_del_on_close, + context->info_pool, pool)); context->dir_props = apr_array_make(pool, max_items, sizeof(svn_fs_fs__p2l_entry_t *)); SVN_ERR(svn_io_open_unique_file3(&context->dir_props_file, NULL, temp_dir, - svn_io_file_del_on_close, pool, pool)); + svn_io_file_del_on_close, + context->info_pool, pool)); /* noderev and representation item bucket */ context->rev_offsets = apr_array_make(pool, max_revs, sizeof(int)); @@ -321,10 +334,6 @@ initialize_pack_context(pack_context_t *context, SVN_ERR(svn_io_open_unique_file3(&context->reps_file, NULL, temp_dir, svn_io_file_del_on_close, pool, pool)); - /* the pool used for temp structures */ - context->info_pool = svn_pool_create(pool); - context->paths = svn_prefix_tree__create(context->info_pool); - return SVN_NO_ERROR; } @@ -404,7 +413,8 @@ close_pack_context(pack_context_t *context, SVN_ERR(svn_io_remove_file2(proto_p2l_index_path, FALSE, pool)); /* Ensure that packed file is written to disk.*/ - SVN_ERR(svn_io_file_flush_to_disk(context->pack_file, pool)); + if (context->flush_to_disk) + SVN_ERR(svn_io_file_flush_to_disk(context->pack_file, pool)); SVN_ERR(svn_io_file_close(context->pack_file, pool)); return SVN_NO_ERROR; @@ -500,7 +510,7 @@ copy_item_to_temp(pack_context_t *context, svn_fs_fs__p2l_entry_t *new_entry = apr_pmemdup(context->info_pool, entry, sizeof(*entry)); - SVN_ERR(svn_fs_fs__get_file_offset(&new_entry->offset, temp_file, pool)); + SVN_ERR(svn_io_file_get_offset(&new_entry->offset, temp_file, pool)); APR_ARRAY_PUSH(entries, svn_fs_fs__p2l_entry_t *) = new_entry; SVN_ERR(copy_file_data(context, temp_file, rev_file, entry->size, pool)); @@ -587,13 +597,13 @@ copy_rep_to_temp(pack_context_t *context, /* create a copy of ENTRY, make it point to the copy destination and * store it in CONTEXT */ entry = apr_pmemdup(context->info_pool, entry, sizeof(*entry)); - SVN_ERR(svn_fs_fs__get_file_offset(&entry->offset, context->reps_file, pool)); + SVN_ERR(svn_io_file_get_offset(&entry->offset, context->reps_file, pool)); add_item_rep_mapping(context, entry); /* read & parse the representation header */ stream = svn_stream_from_aprfile2(rev_file, TRUE, pool); SVN_ERR(svn_fs_fs__read_rep_header(&rep_header, stream, pool, pool)); - svn_stream_close(stream); + SVN_ERR(svn_stream_close(stream)); /* if the representation is a delta against some other rep, link the two */ if ( rep_header->type == svn_fs_fs__rep_delta @@ -629,9 +639,6 @@ compare_dir_entries_format7(const svn_sort__item_t *a, const svn_fs_dirent_t *lhs = (const svn_fs_dirent_t *) a->value; const svn_fs_dirent_t *rhs = (const svn_fs_dirent_t *) b->value; - if (lhs->kind != rhs->kind) - return lhs->kind == svn_node_dir ? -1 : 1; - return strcmp(lhs->name, rhs->name); } @@ -685,7 +692,7 @@ svn_fs_fs__order_dir_entries(svn_fs_t *fs, return result; } -/* Return a duplicate of the the ORIGINAL path and with special sub-strins +/* Return a duplicate of the ORIGINAL path and with special sub-strings * (e.g. "trunk") modified in such a way that have a lower lexicographic * value than any other "normal" file name. */ @@ -722,7 +729,7 @@ tweak_path_for_ordering(const char *original, */ static svn_error_t * copy_node_to_temp(pack_context_t *context, - apr_file_t *rev_file, + svn_fs_fs__revision_file_t *rev_file, svn_fs_fs__p2l_entry_t *entry, apr_pool_t *pool) { @@ -730,25 +737,22 @@ copy_node_to_temp(pack_context_t *context, sizeof(*path_order)); node_revision_t *noderev; const char *sort_path; - svn_stream_t *stream; apr_off_t source_offset = entry->offset; /* read & parse noderev */ - stream = svn_stream_from_aprfile2(rev_file, TRUE, pool); - SVN_ERR(svn_fs_fs__read_noderev(&noderev, stream, pool, pool)); - svn_stream_close(stream); + SVN_ERR(svn_fs_fs__read_noderev(&noderev, rev_file->stream, pool, pool)); /* create a copy of ENTRY, make it point to the copy destination and * store it in CONTEXT */ entry = apr_pmemdup(context->info_pool, entry, sizeof(*entry)); - SVN_ERR(svn_fs_fs__get_file_offset(&entry->offset, context->reps_file, - pool)); + SVN_ERR(svn_io_file_get_offset(&entry->offset, context->reps_file, + pool)); add_item_rep_mapping(context, entry); /* copy the noderev to our temp file */ - SVN_ERR(svn_io_file_seek(rev_file, APR_SET, &source_offset, pool)); - SVN_ERR(copy_file_data(context, context->reps_file, rev_file, entry->size, - pool)); + SVN_ERR(svn_io_file_seek(rev_file->file, APR_SET, &source_offset, pool)); + SVN_ERR(copy_file_data(context, context->reps_file, rev_file->file, + entry->size, pool)); /* if the node has a data representation, make that the node's "base". * This will (often) cause the noderev to be placed right in front of @@ -758,9 +762,7 @@ copy_node_to_temp(pack_context_t *context, { path_order->rep_id.revision = noderev->data_rep->revision; path_order->rep_id.number = noderev->data_rep->item_index; - path_order->expanded_size = noderev->data_rep->expanded_size - ? noderev->data_rep->expanded_size - : noderev->data_rep->size; + path_order->expanded_size = noderev->data_rep->expanded_size; } /* Sort path is the key used for ordering noderevs and associated reps. @@ -770,7 +772,6 @@ copy_node_to_temp(pack_context_t *context, path_order->node_id = *svn_fs_fs__id_node_id(noderev->id); path_order->revision = svn_fs_fs__id_rev(noderev->id); path_order->predecessor_count = noderev->predecessor_count; - path_order->is_dir = noderev->kind == svn_node_dir; path_order->noderev_id = *svn_fs_fs__id_rev_item(noderev->id); APR_ARRAY_PUSH(context->path_order, path_order_t *) = path_order; @@ -787,13 +788,8 @@ compare_path_order(const path_order_t * const * lhs_p, const path_order_t * lhs = *lhs_p; const path_order_t * rhs = *rhs_p; - /* cluster all directories */ - int diff = rhs->is_dir - lhs->is_dir; - if (diff) - return diff; - /* lexicographic order on path and node (i.e. latest first) */ - diff = svn_prefix_string__compare(lhs->path, rhs->path); + int diff = svn_prefix_string__compare(lhs->path, rhs->path); if (diff) return diff; @@ -831,22 +827,48 @@ compare_ref_to_item(const reference_t * const * lhs_p, return svn_fs_fs__id_part_compare(&(*lhs_p)->from, rhs_p); } -/* implements compare_fn_t. Finds the DIR / FILE boundary. - */ -static int -compare_is_dir(const path_order_t * const * lhs_p, - const void *unused) -{ - return (*lhs_p)->is_dir ? -1 : 0; -} - /* Look for the least significant bit set in VALUE and return the smallest * number with the same property, i.e. the largest power of 2 that is a - * factor in VALUE. */ + * factor in VALUE. Edge case: roundness(0) := 0 . */ static int roundness(int value) { - return value ? value - (value & (value - 1)) : INT_MAX; + return value - (value & (value - 1)); +} + +/* For all paths in first COUNT entries in PATH_ORDER, mark their latest + * node as "HEAD". PATH_ORDER must be ordered by path, revision. + */ +static void +classify_nodes(path_order_t **path_order, + int count) +{ + const svn_prefix_string__t *path; + int i; + + /* The logic below would fail for empty ranges. */ + if (count == 0) + return; + + /* All entries are sorted by path, followed by revision. + * So, the first index is also HEAD for the first path. + */ + path = path_order[0]->path; + path_order[0]->is_head = TRUE; + + /* Since the sorting implicitly groups all entries by path and then sorts + * by descending revision within the group, whenever we encounter a new + * path, the first entry is "HEAD" for that path. + */ + for (i = 1; i < count; ++i) + { + /* New path? */ + if (svn_prefix_string__compare(path, path_order[i]->path)) + { + path = path_order[i]->path; + path_order[i]->is_head = TRUE; + } + } } /* Order a range of data collected in CONTEXT such that we can place them @@ -855,13 +877,13 @@ roundness(int value) */ static void sort_reps_range(pack_context_t *context, - const path_order_t **path_order, - const path_order_t **temp, + path_order_t **path_order, + path_order_t **temp, int first, int last) { const svn_prefix_string__t *path; - int i, dest, best; + int i, dest; svn_fs_fs__id_part_t rep_id; fs_fs_data_t *ffd = context->fs->fsap_data; @@ -878,49 +900,52 @@ sort_reps_range(pack_context_t *context, * We simply pick & chose from the existing path, rev order. */ dest = first; - path = path_order[first]->path; - best = first; - /* (1) For each path, pick the "roundest" representation and put it in - * front of all other nodes in the pack file. The "roundest" rep is - * the one most likely to be referenced from future pack files, i.e. we - * concentrate those potential "foreign link targets" in one section of - * the pack file. + /* (1) There are two classes of representations that are likely to be + * referenced from future shards. These form a "hot zone" of mostly + * relevant data, i.e. we try to include as many reps as possible that + * are needed for future checkouts while trying to exclude as many as + * possible that are likely not needed in future checkouts. * - * And we only apply this to reps outside the linear deltification - * sections because references *into* linear deltification ranges are - * much less likely. + * First, "very round" representations from frequently changing nodes. + * That excludes many in-between representations not accessed from HEAD. + * + * The second class are infrequently changing nodes. Because they are + * unlikely to change often in the future, they will remain relevant for + * HEAD even over long spans of revisions. They are most likely the only + * thing we need from very old pack files. */ for (i = first; i < last; ++i) { - /* Investigated all nodes for the current path? */ - if (svn_prefix_string__compare(path, path_order[i]->path)) + int round = roundness(path_order[i]->predecessor_count); + + /* Class 1: + * Pretty round _and_ a significant stop in the node's delta chain. + * This may pick up more than one representation from the same chain + * but that's rare and not a problem. Prefer simple checks here. + * + * The divider of 4 is arbitrary but seems to work well in practice. + * Larger values increase the number of items in the "hot zone". + * Smaller values make delta chains at HEAD more likely to contain + * "cold zone" representations. */ + svn_boolean_t likely_target + = (round >= ffd->max_linear_deltification) + && (round >= path_order[i]->predecessor_count / 4); + + /* Class 2: + * Anything from short node chains. The default of 16 is generous + * but we'd rather include too many than too few nodes here to keep + * seeks between different regions of this pack file at a minimum. */ + svn_boolean_t likely_head + = path_order[i]->predecessor_count + < ffd->max_linear_deltification; + + /* Pick any node that from either class. */ + if (likely_target || likely_head) { - /* next path */ - path = path_order[i]->path; - - /* Pick roundest non-linear deltified node. */ - if (roundness(path_order[best]->predecessor_count) - >= ffd->max_linear_deltification) - { - temp[dest++] = path_order[best]; - path_order[best] = NULL; - best = i; - } + temp[dest++] = path_order[i]; + path_order[i] = NULL; } - - /* next entry */ - if ( roundness(path_order[best]->predecessor_count) - < roundness(path_order[i]->predecessor_count)) - best = i; - } - - /* Treat the last path the same as all others. */ - if (roundness(path_order[best]->predecessor_count) - >= ffd->max_linear_deltification) - { - temp[dest++] = path_order[best]; - path_order[best] = NULL; } /* (2) For each (remaining) path, pick the nodes along the delta chain @@ -986,8 +1011,8 @@ static void sort_reps(pack_context_t *context) { apr_pool_t *temp_pool; - const path_order_t **temp, **path_order; - int i, count, dir_count; + path_order_t **temp, **path_order; + int i, count; /* We will later assume that there is at least one node / path. */ @@ -1012,13 +1037,11 @@ sort_reps(pack_context_t *context) temp = apr_pcalloc(temp_pool, count * sizeof(*temp)); path_order = (void *)context->path_order->elts; - /* Find the boundary between DIR and FILE section. */ - dir_count = svn_sort__bsearch_lower_bound(context->path_order, NULL, - (int (*)(const void *, const void *))compare_is_dir); + /* Mark nodes depending on what other nodes exist for the same path etc. */ + classify_nodes(path_order, count); - /* Sort those sub-sections separately. */ - sort_reps_range(context, path_order, temp, 0, dir_count); - sort_reps_range(context, path_order, temp, dir_count, count); + /* Rearrange those sub-sections separately. */ + sort_reps_range(context, path_order, temp, 0, count); /* We now know the final ordering. */ for (i = 0; i < count; ++i) @@ -1054,7 +1077,7 @@ sort_items(apr_array_header_t *entries) /* Return the remaining unused bytes in the current block in CONTEXT's * pack file. */ -static apr_ssize_t +static apr_off_t get_block_left(pack_context_t *context) { fs_fs_data_t *ffd = context->fs->fsap_data; @@ -1185,7 +1208,7 @@ copy_reps_from_temp(pack_context_t *context, apr_array_header_t *path_order = context->path_order; int i; - /* copy items in path order. */ + /* copy items in path order. Exclude the non-HEAD noderevs. */ for (i = 0; i < path_order->nelts; ++i) { path_order_t *current_path; @@ -1195,15 +1218,32 @@ copy_reps_from_temp(pack_context_t *context, svn_pool_clear(iterpool); current_path = APR_ARRAY_IDX(path_order, i, path_order_t *); - node_part = get_item(context, ¤t_path->noderev_id, TRUE); - rep_part = get_item(context, ¤t_path->rep_id, TRUE); + if (current_path->is_head) + { + node_part = get_item(context, ¤t_path->noderev_id, TRUE); + if (node_part) + SVN_ERR(store_item(context, temp_file, node_part, iterpool)); + } - if (node_part) - SVN_ERR(store_item(context, temp_file, node_part, iterpool)); + rep_part = get_item(context, ¤t_path->rep_id, TRUE); if (rep_part) SVN_ERR(store_item(context, temp_file, rep_part, iterpool)); } + /* copy the remaining non-head noderevs. */ + for (i = 0; i < path_order->nelts; ++i) + { + path_order_t *current_path; + svn_fs_fs__p2l_entry_t *node_part; + + svn_pool_clear(iterpool); + + current_path = APR_ARRAY_IDX(path_order, i, path_order_t *); + node_part = get_item(context, ¤t_path->noderev_id, TRUE); + if (node_part) + SVN_ERR(store_item(context, temp_file, node_part, iterpool)); + } + svn_pool_destroy(iterpool); return SVN_NO_ERROR; @@ -1370,7 +1410,7 @@ pack_range(pack_context_t *context, SVN_ERR(copy_rep_to_temp(context, rev_file->file, entry, iterpool2)); else if (entry->type == SVN_FS_FS__ITEM_TYPE_NODEREV) - SVN_ERR(copy_node_to_temp(context, rev_file->file, entry, + SVN_ERR(copy_node_to_temp(context, rev_file, entry, iterpool2)); else SVN_ERR_ASSERT(entry->type == SVN_FS_FS__ITEM_TYPE_UNUSED); @@ -1435,7 +1475,6 @@ append_revision(pack_context_t *context, SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&rev_file, context->fs, context->start_rev, pool, iterpool)); - SVN_ERR(svn_fs_fs__auto_read_footer(rev_file)); revdata_size = rev_file->l2p_offset; @@ -1499,8 +1538,9 @@ append_revision(pack_context_t *context, * * Pack the revision shard starting at SHARD_REV in filesystem FS from * SHARD_DIR into the PACK_FILE_DIR, using POOL for allocations. Limit - * the extra memory consumption to MAX_MEM bytes. CANCEL_FUNC and - * CANCEL_BATON are what you think they are. + * the extra memory consumption to MAX_MEM bytes. If FLUSH_TO_DISK is + * non-zero, do not return until the data has actually been written on + * the disk. CANCEL_FUNC and CANCEL_BATON are what you think they are. */ static svn_error_t * pack_log_addressed(svn_fs_t *fs, @@ -1508,6 +1548,7 @@ pack_log_addressed(svn_fs_t *fs, const char *shard_dir, svn_revnum_t shard_rev, apr_size_t max_mem, + svn_boolean_t flush_to_disk, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *pool) @@ -1540,8 +1581,8 @@ pack_log_addressed(svn_fs_t *fs, /* set up a pack context */ SVN_ERR(initialize_pack_context(&context, fs, pack_file_dir, shard_dir, - shard_rev, max_items, cancel_func, - cancel_baton, pool)); + shard_rev, max_items, flush_to_disk, + cancel_func, cancel_baton, pool)); /* phase 1: determine the size of the revisions to pack */ SVN_ERR(svn_fs_fs__l2p_get_max_ids(&max_ids, fs, shard_rev, @@ -1550,7 +1591,8 @@ pack_log_addressed(svn_fs_t *fs, /* pack revisions in ranges that don't exceed MAX_MEM */ for (i = 0; i < max_ids->nelts; ++i) - if (APR_ARRAY_IDX(max_ids, i, apr_uint64_t) + item_count <= max_items) + if ( APR_ARRAY_IDX(max_ids, i, apr_uint64_t) + <= (apr_uint64_t)max_items - item_count) { item_count += APR_ARRAY_IDX(max_ids, i, apr_uint64_t); context.end_rev++; @@ -1664,14 +1706,16 @@ svn_fs_fs__get_packed_offset(apr_off_t *rev_offset, * * Pack the revision shard starting at SHARD_REV containing exactly * MAX_FILES_PER_DIR revisions from SHARD_PATH into the PACK_FILE_DIR, - * using POOL for allocations. CANCEL_FUNC and CANCEL_BATON are what you - * think they are. + * using POOL for allocations. If FLUSH_TO_DISK is non-zero, do not + * return until the data has actually been written on the disk. + * CANCEL_FUNC and CANCEL_BATON are what you think they are. */ static svn_error_t * pack_phys_addressed(const char *pack_file_dir, const char *shard_path, svn_revnum_t start_rev, int max_files_per_dir, + svn_boolean_t flush_to_disk, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *pool) @@ -1681,7 +1725,6 @@ pack_phys_addressed(const char *pack_file_dir, apr_file_t *manifest_file; svn_stream_t *manifest_stream; svn_revnum_t end_rev, rev; - apr_off_t next_offset; apr_pool_t *iterpool; /* Some useful paths. */ @@ -1702,32 +1745,37 @@ pack_phys_addressed(const char *pack_file_dir, manifest_stream = svn_stream_from_aprfile2(manifest_file, TRUE, pool); end_rev = start_rev + max_files_per_dir - 1; - next_offset = 0; iterpool = svn_pool_create(pool); /* Iterate over the revisions in this shard, squashing them together. */ for (rev = start_rev; rev <= end_rev; rev++) { svn_stream_t *rev_stream; - apr_finfo_t finfo; const char *path; + apr_off_t offset; + apr_file_t *rev_file; svn_pool_clear(iterpool); - /* Get the size of the file. */ path = svn_dirent_join(shard_path, apr_psprintf(iterpool, "%ld", rev), iterpool); - SVN_ERR(svn_io_stat(&finfo, path, APR_FINFO_SIZE, iterpool)); + + /* Obtain current offset in pack file. */ + SVN_ERR(svn_io_file_get_offset(&offset, pack_file, iterpool)); /* build manifest */ SVN_ERR(svn_stream_printf(manifest_stream, iterpool, - "%" APR_OFF_T_FMT "\n", next_offset)); - next_offset += finfo.size; + "%" APR_OFF_T_FMT "\n", offset)); - /* Copy all the bits from the rev file to the end of the pack file. */ - SVN_ERR(svn_stream_open_readonly(&rev_stream, path, iterpool, iterpool)); + /* Copy all the bits from the rev file to the end of the pack file. + * Use unbuffered apr_file_t since we're going to write using 16kb + * chunks. */ + SVN_ERR(svn_io_file_open(&rev_file, path, APR_READ, APR_OS_DEFAULT, + iterpool)); + rev_stream = svn_stream_from_aprfile2(rev_file, FALSE, iterpool); SVN_ERR(svn_stream_copy3(rev_stream, - svn_stream_from_aprfile2(pack_file, TRUE, pool), + svn_stream_from_aprfile2(pack_file, TRUE, + iterpool), cancel_func, cancel_baton, iterpool)); } @@ -1735,14 +1783,16 @@ pack_phys_addressed(const char *pack_file_dir, SVN_ERR(svn_stream_close(manifest_stream)); /* Ensure that pack file is written to disk. */ - SVN_ERR(svn_io_file_flush_to_disk(manifest_file, pool)); + if (flush_to_disk) + SVN_ERR(svn_io_file_flush_to_disk(manifest_file, pool)); SVN_ERR(svn_io_file_close(manifest_file, pool)); /* disallow write access to the manifest file */ SVN_ERR(svn_io_set_file_read_only(manifest_file_path, FALSE, iterpool)); /* Ensure that pack file is written to disk. */ - SVN_ERR(svn_io_file_flush_to_disk(pack_file, pool)); + if (flush_to_disk) + SVN_ERR(svn_io_file_flush_to_disk(pack_file, pool)); SVN_ERR(svn_io_file_close(pack_file, pool)); svn_pool_destroy(iterpool); @@ -1753,8 +1803,9 @@ pack_phys_addressed(const char *pack_file_dir, /* In filesystem FS, pack the revision SHARD containing exactly * MAX_FILES_PER_DIR revisions from SHARD_PATH into the PACK_FILE_DIR, * using POOL for allocations. Try to limit the amount of temporary - * memory needed to MAX_MEM bytes. CANCEL_FUNC and CANCEL_BATON are what - * you think they are. + * memory needed to MAX_MEM bytes. If FLUSH_TO_DISK is non-zero, do + * not return until the data has actually been written on the disk. + * CANCEL_FUNC and CANCEL_BATON are what you think they are. * * If for some reason we detect a partial packing already performed, we * remove the pack file and start again. @@ -1768,6 +1819,7 @@ pack_rev_shard(svn_fs_t *fs, apr_int64_t shard, int max_files_per_dir, apr_size_t max_mem, + svn_boolean_t flush_to_disk, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *pool) @@ -1787,12 +1839,13 @@ pack_rev_shard(svn_fs_t *fs, /* Index information files */ if (svn_fs_fs__use_log_addressing(fs)) - SVN_ERR(pack_log_addressed(fs, pack_file_dir, shard_path, shard_rev, - max_mem, cancel_func, cancel_baton, pool)); + SVN_ERR(pack_log_addressed(fs, pack_file_dir, shard_path, + shard_rev, max_mem, flush_to_disk, + cancel_func, cancel_baton, pool)); else SVN_ERR(pack_phys_addressed(pack_file_dir, shard_path, shard_rev, - max_files_per_dir, cancel_func, - cancel_baton, pool)); + max_files_per_dir, flush_to_disk, + cancel_func, cancel_baton, pool)); SVN_ERR(svn_io_copy_perms(shard_path, pack_file_dir, pool)); SVN_ERR(svn_io_set_file_read_only(pack_file_path, FALSE, pool)); @@ -1840,6 +1893,8 @@ synced_pack_shard(void *baton, /* if enabled, pack the revprops in an equivalent way */ if (pb->revsprops_dir) { + apr_int64_t pack_size_limit = 0.9 * ffd->revprop_pack_size; + revprops_pack_file_dir = svn_dirent_join(pb->revsprops_dir, apr_psprintf(pool, "%" APR_INT64_T_FMT PATH_EXT_PACKED_SHARD, @@ -1853,10 +1908,11 @@ synced_pack_shard(void *baton, revprops_shard_path, pb->shard, ffd->max_files_per_dir, - (int)(0.9*ffd->revprop_pack_size), + pack_size_limit, ffd->compress_packed_revprops ? SVN__COMPRESSION_ZLIB_DEFAULT : SVN__COMPRESSION_NONE, + ffd->flush_to_disk, pb->cancel_func, pb->cancel_baton, pool)); @@ -1933,8 +1989,8 @@ pack_shard(struct pack_baton *baton, /* pack the revision content */ SVN_ERR(pack_rev_shard(baton->fs, rev_pack_file_dir, baton->rev_shard_path, baton->shard, ffd->max_files_per_dir, - baton->max_mem, baton->cancel_func, - baton->cancel_baton, pool)); + baton->max_mem, ffd->flush_to_disk, + baton->cancel_func, baton->cancel_baton, pool)); /* For newer repo formats, we only acquired the pack lock so far. Before modifying the repo state by switching over to the packed @@ -1953,6 +2009,34 @@ pack_shard(struct pack_baton *baton, return SVN_NO_ERROR; } +/* Read the youngest rev and the first non-packed rev info for FS from disk. + Set *FULLY_PACKED when there is no completed unpacked shard. + Use SCRATCH_POOL for temporary allocations. + */ +static svn_error_t * +get_pack_status(svn_boolean_t *fully_packed, + svn_fs_t *fs, + apr_pool_t *scratch_pool) +{ + fs_fs_data_t *ffd = fs->fsap_data; + apr_int64_t completed_shards; + svn_revnum_t youngest; + + SVN_ERR(svn_fs_fs__read_min_unpacked_rev(&ffd->min_unpacked_rev, fs, + scratch_pool)); + + SVN_ERR(svn_fs_fs__youngest_rev(&youngest, fs, scratch_pool)); + completed_shards = (youngest + 1) / ffd->max_files_per_dir; + + /* See if we've already completed all possible shards thus far. */ + if (ffd->min_unpacked_rev == (completed_shards * ffd->max_files_per_dir)) + *fully_packed = TRUE; + else + *fully_packed = FALSE; + + return SVN_NO_ERROR; +} + /* The work-horse for svn_fs_fs__pack, called with the FS write lock. This implements the svn_fs_fs__with_write_lock() 'body' callback type. BATON is a 'struct pack_baton *'. @@ -1974,30 +2058,23 @@ pack_body(void *baton, struct pack_baton *pb = baton; fs_fs_data_t *ffd = pb->fs->fsap_data; apr_int64_t completed_shards; - svn_revnum_t youngest; apr_pool_t *iterpool; + svn_boolean_t fully_packed; - /* If the repository isn't a new enough format, we don't support packing. - Return a friendly error to that effect. */ - if (ffd->format < SVN_FS_FS__MIN_PACKED_FORMAT) - return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL, - _("FSFS format (%d) too old to pack; please upgrade the filesystem."), - ffd->format); + /* Since another process might have already packed the repo, + we need to re-read the pack status. */ + SVN_ERR(get_pack_status(&fully_packed, pb->fs, pool)); + if (fully_packed) + { + if (pb->notify_func) + (*pb->notify_func)(pb->notify_baton, + ffd->min_unpacked_rev / ffd->max_files_per_dir, + svn_fs_pack_notify_noop, pool); - /* If we aren't using sharding, we can't do any packing, so quit. */ - if (!ffd->max_files_per_dir) - return SVN_NO_ERROR; - - SVN_ERR(svn_fs_fs__read_min_unpacked_rev(&ffd->min_unpacked_rev, pb->fs, - pool)); - - SVN_ERR(svn_fs_fs__youngest_rev(&youngest, pb->fs, pool)); - completed_shards = (youngest + 1) / ffd->max_files_per_dir; - - /* See if we've already completed all possible shards thus far. */ - if (ffd->min_unpacked_rev == (completed_shards * ffd->max_files_per_dir)) - return SVN_NO_ERROR; + return SVN_NO_ERROR; + } + completed_shards = (ffd->youngest_rev_cache + 1) / ffd->max_files_per_dir; pb->revs_dir = svn_dirent_join(pb->fs->path, PATH_REVS_DIR, pool); if (ffd->format >= SVN_FS_FS__MIN_PACKED_REVPROP_FORMAT) pb->revsprops_dir = svn_dirent_join(pb->fs->path, PATH_REVPROPS_DIR, @@ -2032,7 +2109,37 @@ svn_fs_fs__pack(svn_fs_t *fs, struct pack_baton pb = { 0 }; fs_fs_data_t *ffd = fs->fsap_data; svn_error_t *err; + svn_boolean_t fully_packed; + /* If the repository isn't a new enough format, we don't support packing. + Return a friendly error to that effect. */ + if (ffd->format < SVN_FS_FS__MIN_PACKED_FORMAT) + return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL, + _("FSFS format (%d) too old to pack; please upgrade the filesystem."), + ffd->format); + + /* If we aren't using sharding, we can't do any packing, so quit. */ + if (!ffd->max_files_per_dir) + { + if (notify_func) + (*notify_func)(notify_baton, -1, svn_fs_pack_notify_noop, pool); + + return SVN_NO_ERROR; + } + + /* Is there we even anything to do?. */ + SVN_ERR(get_pack_status(&fully_packed, fs, pool)); + if (fully_packed) + { + if (notify_func) + (*notify_func)(notify_baton, + ffd->min_unpacked_rev / ffd->max_files_per_dir, + svn_fs_pack_notify_noop, pool); + + return SVN_NO_ERROR; + } + + /* Lock the repo and start the pack process. */ pb.fs = fs; pb.notify_func = notify_func; pb.notify_baton = notify_baton; diff --git a/subversion/libsvn_fs_fs/recovery.c b/subversion/libsvn_fs_fs/recovery.c index 125d47a1f370..eef06f65942a 100644 --- a/subversion/libsvn_fs_fs/recovery.c +++ b/subversion/libsvn_fs_fs/recovery.c @@ -197,9 +197,7 @@ recover_find_max_ids(svn_fs_t *fs, stored in the representation. Note that this is a directory, i.e. represented using the hash format on disk and can never have 0 length. */ baton.pool = pool; - baton.remaining = noderev->data_rep->expanded_size - ? noderev->data_rep->expanded_size - : noderev->data_rep->size; + baton.remaining = noderev->data_rep->expanded_size; stream = svn_stream_create(&baton, pool); svn_stream_set_read2(stream, NULL /* only full read support */, read_handler_recover); @@ -211,7 +209,7 @@ recover_find_max_ids(svn_fs_t *fs, { svn_string_t *id_str = svn_fs_fs__id_unparse(noderev->id, pool); - svn_error_clear(svn_stream_close(stream)); + err = svn_error_compose_create(err, svn_stream_close(stream)); return svn_error_quick_wrapf(err, _("malformed representation for node-revision '%s'"), id_str->data); diff --git a/subversion/libsvn_fs_fs/rep-cache-db.h b/subversion/libsvn_fs_fs/rep-cache-db.h index 0f2cc89aa7ff..e66253810c9d 100644 --- a/subversion/libsvn_fs_fs/rep-cache-db.h +++ b/subversion/libsvn_fs_fs/rep-cache-db.h @@ -1,8 +1,8 @@ -/* This file is automatically generated from rep-cache-db.sql and .dist_sandbox/subversion-1.9.7/subversion/libsvn_fs_fs/token-map.h. +/* This file is automatically generated from rep-cache-db.sql and subversion/libsvn_fs_fs/token-map.h. * Do not edit this file -- edit the source and rerun gen-make.py */ -#define STMT_CREATE_SCHEMA 0 -#define STMT_0_INFO {"STMT_CREATE_SCHEMA", NULL} +#define STMT_CREATE_SCHEMA_V1 0 +#define STMT_0_INFO {"STMT_CREATE_SCHEMA_V1", NULL} #define STMT_0 \ "CREATE TABLE rep_cache ( " \ " hash TEXT NOT NULL PRIMARY KEY, " \ @@ -14,53 +14,66 @@ "PRAGMA USER_VERSION = 1; " \ "" -#define STMT_GET_REP 1 -#define STMT_1_INFO {"STMT_GET_REP", NULL} +#define STMT_CREATE_SCHEMA_V2 1 +#define STMT_1_INFO {"STMT_CREATE_SCHEMA_V2", NULL} #define STMT_1 \ + "CREATE TABLE rep_cache ( " \ + " hash TEXT NOT NULL PRIMARY KEY, " \ + " revision INTEGER NOT NULL, " \ + " offset INTEGER NOT NULL, " \ + " size INTEGER NOT NULL, " \ + " expanded_size INTEGER NOT NULL " \ + " ) WITHOUT ROWID; " \ + "PRAGMA USER_VERSION = 2; " \ + "" + +#define STMT_GET_REP 2 +#define STMT_2_INFO {"STMT_GET_REP", NULL} +#define STMT_2 \ "SELECT revision, offset, size, expanded_size " \ "FROM rep_cache " \ "WHERE hash = ?1 " \ "" -#define STMT_SET_REP 2 -#define STMT_2_INFO {"STMT_SET_REP", NULL} -#define STMT_2 \ +#define STMT_SET_REP 3 +#define STMT_3_INFO {"STMT_SET_REP", NULL} +#define STMT_3 \ "INSERT OR FAIL INTO rep_cache (hash, revision, offset, size, expanded_size) " \ "VALUES (?1, ?2, ?3, ?4, ?5) " \ "" -#define STMT_GET_REPS_FOR_RANGE 3 -#define STMT_3_INFO {"STMT_GET_REPS_FOR_RANGE", NULL} -#define STMT_3 \ +#define STMT_GET_REPS_FOR_RANGE 4 +#define STMT_4_INFO {"STMT_GET_REPS_FOR_RANGE", NULL} +#define STMT_4 \ "SELECT hash, revision, offset, size, expanded_size " \ "FROM rep_cache " \ "WHERE revision >= ?1 AND revision <= ?2 " \ "" -#define STMT_GET_MAX_REV 4 -#define STMT_4_INFO {"STMT_GET_MAX_REV", NULL} -#define STMT_4 \ +#define STMT_GET_MAX_REV 5 +#define STMT_5_INFO {"STMT_GET_MAX_REV", NULL} +#define STMT_5 \ "SELECT MAX(revision) " \ "FROM rep_cache " \ "" -#define STMT_DEL_REPS_YOUNGER_THAN_REV 5 -#define STMT_5_INFO {"STMT_DEL_REPS_YOUNGER_THAN_REV", NULL} -#define STMT_5 \ +#define STMT_DEL_REPS_YOUNGER_THAN_REV 6 +#define STMT_6_INFO {"STMT_DEL_REPS_YOUNGER_THAN_REV", NULL} +#define STMT_6 \ "DELETE FROM rep_cache " \ "WHERE revision > ?1 " \ "" -#define STMT_LOCK_REP 6 -#define STMT_6_INFO {"STMT_LOCK_REP", NULL} -#define STMT_6 \ +#define STMT_LOCK_REP 7 +#define STMT_7_INFO {"STMT_LOCK_REP", NULL} +#define STMT_7 \ "BEGIN TRANSACTION; " \ "INSERT INTO rep_cache VALUES ('dummy', 0, 0, 0, 0) " \ "" -#define STMT_UNLOCK_REP 7 -#define STMT_7_INFO {"STMT_UNLOCK_REP", NULL} -#define STMT_7 \ +#define STMT_UNLOCK_REP 8 +#define STMT_8_INFO {"STMT_UNLOCK_REP", NULL} +#define STMT_8 \ "ROLLBACK TRANSACTION; " \ "" @@ -74,6 +87,7 @@ STMT_5, \ STMT_6, \ STMT_7, \ + STMT_8, \ NULL \ } @@ -87,5 +101,6 @@ STMT_5_INFO, \ STMT_6_INFO, \ STMT_7_INFO, \ + STMT_8_INFO, \ {NULL, NULL} \ } diff --git a/subversion/libsvn_fs_fs/rep-cache-db.sql b/subversion/libsvn_fs_fs/rep-cache-db.sql index caaac334c68b..cd89f35c63ee 100644 --- a/subversion/libsvn_fs_fs/rep-cache-db.sql +++ b/subversion/libsvn_fs_fs/rep-cache-db.sql @@ -21,7 +21,7 @@ * ==================================================================== */ --- STMT_CREATE_SCHEMA +-- STMT_CREATE_SCHEMA_V1 /* A table mapping representation hashes to locations in a rev file. */ CREATE TABLE rep_cache ( hash TEXT NOT NULL PRIMARY KEY, @@ -33,36 +33,63 @@ CREATE TABLE rep_cache ( PRAGMA USER_VERSION = 1; +-- STMT_CREATE_SCHEMA_V2 +/* A table mapping representation hashes to locations in a rev file. + Same as in V1 schema, except that it uses the `WITHOUT ROWID` optimization: + https://sqlite.org/withoutrowid.html + + Note that this optimization is only supported starting from SQLite version + 3.8.2 (2013-12-06). To keep compatibility with existing binaries, it is + only used for newer filesystem formats that were released together with + bumping the minimum required SQLite version. + */ +CREATE TABLE rep_cache ( + hash TEXT NOT NULL PRIMARY KEY, + revision INTEGER NOT NULL, + offset INTEGER NOT NULL, + size INTEGER NOT NULL, + expanded_size INTEGER NOT NULL + ) WITHOUT ROWID; + +PRAGMA USER_VERSION = 2; -- STMT_GET_REP +/* Works for both V1 and V2 schemas. */ SELECT revision, offset, size, expanded_size FROM rep_cache WHERE hash = ?1 -- STMT_SET_REP +/* Works for both V1 and V2 schemas. */ INSERT OR FAIL INTO rep_cache (hash, revision, offset, size, expanded_size) VALUES (?1, ?2, ?3, ?4, ?5) -- STMT_GET_REPS_FOR_RANGE +/* Works for both V1 and V2 schemas. */ SELECT hash, revision, offset, size, expanded_size FROM rep_cache WHERE revision >= ?1 AND revision <= ?2 -- STMT_GET_MAX_REV +/* Works for both V1 and V2 schemas. */ SELECT MAX(revision) FROM rep_cache -- STMT_DEL_REPS_YOUNGER_THAN_REV +/* Works for both V1 and V2 schemas. */ DELETE FROM rep_cache WHERE revision > ?1 /* An INSERT takes an SQLite reserved lock that prevents other writes but doesn't block reads. The incomplete transaction means that no permanent change is made to the database and the transaction is - removed when the database is closed. */ + removed when the database is closed. + + Works for both V1 and V2 schemas. */ -- STMT_LOCK_REP BEGIN TRANSACTION; INSERT INTO rep_cache VALUES ('dummy', 0, 0, 0, 0) -- STMT_UNLOCK_REP +/* Works for both V1 and V2 schemas. */ ROLLBACK TRANSACTION; diff --git a/subversion/libsvn_fs_fs/rep-cache.c b/subversion/libsvn_fs_fs/rep-cache.c index 437d60381ddb..b0b81fad9ac3 100644 --- a/subversion/libsvn_fs_fs/rep-cache.c +++ b/subversion/libsvn_fs_fs/rep-cache.c @@ -24,6 +24,7 @@ #include "svn_private_config.h" +#include "cached_data.h" #include "fs_fs.h" #include "fs.h" #include "rep-cache.h" @@ -35,9 +36,6 @@ #include "rep-cache-db.h" -/* A few magic values */ -#define REP_CACHE_SCHEMA_FORMAT 1 - REP_CACHE_DB_SQL_DECLARE_STATEMENTS(statements); @@ -50,13 +48,6 @@ path_rep_cache_db(const char *fs_path, return svn_dirent_join(fs_path, REP_CACHE_DB_NAME, result_pool); } -#define SVN_ERR_CLOSE(x, db) do \ -{ \ - svn_error_t *svn__err = (x); \ - if (svn__err) \ - return svn_error_compose_create(svn__err, svn_sqlite__close(db)); \ -} while (0) - /** Library-private API's. **/ @@ -106,12 +97,19 @@ open_rep_cache(void *baton, 0, NULL, 0, fs->pool, pool)); - SVN_ERR_CLOSE(svn_sqlite__read_schema_version(&version, sdb, pool), sdb); - if (version < REP_CACHE_SCHEMA_FORMAT) + SVN_SQLITE__ERR_CLOSE(svn_sqlite__read_schema_version(&version, sdb, pool), + sdb); + /* If we have an uninitialized database, go ahead and create the schema. */ + if (version <= 0) { - /* Must be 0 -- an uninitialized (no schema) database. Create - the schema. Results in schema version of 1. */ - SVN_ERR_CLOSE(svn_sqlite__exec_statements(sdb, STMT_CREATE_SCHEMA), sdb); + int stmt; + + if (ffd->format >= SVN_FS_FS__MIN_REP_CACHE_SCHEMA_V2_FORMAT) + stmt = STMT_CREATE_SCHEMA_V2; + else + stmt = STMT_CREATE_SCHEMA_V1; + + SVN_SQLITE__ERR_CLOSE(svn_sqlite__exec_statements(sdb, stmt), sdb); } /* This is used as a flag that the database is available so don't @@ -263,7 +261,7 @@ svn_fs_fs__walk_rep_reference(svn_fs_t *fs, If you extend this function, check the callsite to see if you have to make it not-ignore additional error codes. */ svn_error_t * -svn_fs_fs__get_rep_reference(representation_t **rep, +svn_fs_fs__get_rep_reference(representation_t **rep_p, svn_fs_t *fs, svn_checksum_t *checksum, apr_pool_t *pool) @@ -271,6 +269,7 @@ svn_fs_fs__get_rep_reference(representation_t **rep, fs_fs_data_t *ffd = fs->fsap_data; svn_sqlite__stmt_t *stmt; svn_boolean_t have_row; + representation_t *rep; SVN_ERR_ASSERT(ffd->rep_sharing_allowed); if (! ffd->rep_cache_db) @@ -289,26 +288,28 @@ svn_fs_fs__get_rep_reference(representation_t **rep, SVN_ERR(svn_sqlite__step(&have_row, stmt)); if (have_row) { - *rep = apr_pcalloc(pool, sizeof(**rep)); - svn_fs_fs__id_txn_reset(&(*rep)->txn_id); - memcpy((*rep)->sha1_digest, checksum->digest, - sizeof((*rep)->sha1_digest)); - (*rep)->has_sha1 = TRUE; - (*rep)->revision = svn_sqlite__column_revnum(stmt, 0); - (*rep)->item_index = svn_sqlite__column_int64(stmt, 1); - (*rep)->size = svn_sqlite__column_int64(stmt, 2); - (*rep)->expanded_size = svn_sqlite__column_int64(stmt, 3); + rep = apr_pcalloc(pool, sizeof(*rep)); + svn_fs_fs__id_txn_reset(&(rep->txn_id)); + memcpy(rep->sha1_digest, checksum->digest, sizeof(rep->sha1_digest)); + rep->has_sha1 = TRUE; + rep->revision = svn_sqlite__column_revnum(stmt, 0); + rep->item_index = svn_sqlite__column_int64(stmt, 1); + rep->size = svn_sqlite__column_int64(stmt, 2); + rep->expanded_size = svn_sqlite__column_int64(stmt, 3); } else - *rep = NULL; + rep = NULL; SVN_ERR(svn_sqlite__reset(stmt)); - if (*rep) + if (rep) { + svn_error_t *err; + + SVN_ERR(svn_fs_fs__fixup_expanded_size(fs, rep, pool)); + /* Check that REP refers to a revision that exists in FS. */ - svn_error_t *err = svn_fs_fs__ensure_revision_exists((*rep)->revision, - fs, pool); + err = svn_fs_fs__ensure_revision_exists(rep->revision, fs, pool); if (err) return svn_error_createf(SVN_ERR_FS_CORRUPT, err, "Checksum '%s' in rep-cache is beyond HEAD", @@ -316,6 +317,7 @@ svn_fs_fs__get_rep_reference(representation_t **rep, pool)); } + *rep_p = rep; return SVN_NO_ERROR; } diff --git a/subversion/libsvn_fs_fs/rep-cache.h b/subversion/libsvn_fs_fs/rep-cache.h index 75072a03eb59..30377786c5c1 100644 --- a/subversion/libsvn_fs_fs/rep-cache.h +++ b/subversion/libsvn_fs_fs/rep-cache.h @@ -64,11 +64,11 @@ svn_fs_fs__walk_rep_reference(svn_fs_t *fs, apr_pool_t *pool); /* Return the representation REP in FS which has fulltext CHECKSUM. - REP is allocated in POOL. If the rep cache database has not been - opened, just set *REP to NULL. Returns SVN_ERR_FS_CORRUPT if + *REP_P is allocated in POOL. If the rep cache database has not been + opened, just set *REP_P to NULL. Returns SVN_ERR_FS_CORRUPT if a reference beyond HEAD is detected. */ svn_error_t * -svn_fs_fs__get_rep_reference(representation_t **rep, +svn_fs_fs__get_rep_reference(representation_t **rep_p, svn_fs_t *fs, svn_checksum_t *checksum, apr_pool_t *pool); diff --git a/subversion/libsvn_fs_fs/rev_file.c b/subversion/libsvn_fs_fs/rev_file.c index 7c18ac851002..7ebee63225ab 100644 --- a/subversion/libsvn_fs_fs/rev_file.c +++ b/subversion/libsvn_fs_fs/rev_file.c @@ -259,6 +259,7 @@ svn_fs_fs__auto_read_footer(svn_fs_fs__revision_file_t *file) SVN_ERR(svn_fs_fs__parse_footer(&file->l2p_offset, &file->l2p_checksum, &file->p2l_offset, &file->p2l_checksum, footer, file->start_revision, + filesize - footer_length - 1, file->pool)); file->footer_offset = filesize - footer_length - 1; } diff --git a/subversion/libsvn_fs_fs/revprops.c b/subversion/libsvn_fs_fs/revprops.c index dbb185beca79..6d41fd882d7e 100644 --- a/subversion/libsvn_fs_fs/revprops.c +++ b/subversion/libsvn_fs_fs/revprops.c @@ -25,9 +25,11 @@ #include "svn_pools.h" #include "svn_hash.h" #include "svn_dirent_uri.h" +#include "svn_sorts.h" #include "fs_fs.h" #include "revprops.h" +#include "temp_serializer.h" #include "util.h" #include "private/svn_subr_private.h" @@ -36,11 +38,6 @@ #include "svn_private_config.h" -/* Give writing processes 10 seconds to replace an existing revprop - file with a new one. After that time, we assume that the writing - process got aborted and that we have re-read revprops. */ -#define REVPROP_CHANGE_TIMEOUT (10 * 1000000) - svn_error_t * svn_fs_fs__upgrade_pack_revprops(svn_fs_t *fs, svn_fs_upgrade_notify_t notify_func, @@ -82,6 +79,7 @@ svn_fs_fs__upgrade_pack_revprops(svn_fs_t *fs, shard, ffd->max_files_per_dir, (int)(0.9 * ffd->revprop_pack_size), compression_level, + ffd->flush_to_disk, cancel_func, cancel_baton, iterpool)); if (notify_func) @@ -144,9 +142,6 @@ typedef struct packed_revprops_t /* revision number to read (not necessarily the first in the pack) */ svn_revnum_t revision; - /* current revprop generation. Used when populating the revprop cache */ - apr_int64_t generation; - /* the actual revision properties */ apr_hash_t *properties; @@ -189,35 +184,84 @@ typedef struct packed_revprops_t /* Parse the serialized revprops in CONTENT and return them in *PROPERTIES. * Also, put them into the revprop cache, if activated, for future use. - * Three more parameters are being used to update the revprop cache: FS is - * our file system, the revprops belong to REVISION and the global revprop - * GENERATION is used as well. * - * The returned hash will be allocated in POOL, SCRATCH_POOL is being used - * for temporary allocations. + * The returned hash will be allocated in RESULT_POOL, SCRATCH_POOL is being + * used for temporary allocations. */ static svn_error_t * parse_revprop(apr_hash_t **properties, svn_fs_t *fs, svn_revnum_t revision, - apr_int64_t generation, svn_string_t *content, - apr_pool_t *pool, + apr_pool_t *result_pool, apr_pool_t *scratch_pool) { svn_stream_t *stream = svn_stream_from_string(content, scratch_pool); - *properties = apr_hash_make(pool); + *properties = apr_hash_make(result_pool); - SVN_ERR_W(svn_hash_read2(*properties, stream, SVN_HASH_TERMINATOR, pool), + SVN_ERR_W(svn_hash_read2(*properties, stream, SVN_HASH_TERMINATOR, + result_pool), apr_psprintf(scratch_pool, "Failed to parse revprops for r%ld.", revision)); return SVN_NO_ERROR; } +void +svn_fs_fs__reset_revprop_cache(svn_fs_t *fs) +{ + fs_fs_data_t *ffd = fs->fsap_data; + ffd->revprop_prefix = 0; +} + +/* If FS has not a revprop cache prefix set, generate one. + * Always call this before accessing the revprop cache. + */ +static svn_error_t * +prepare_revprop_cache(svn_fs_t *fs, + apr_pool_t *scratch_pool) +{ + fs_fs_data_t *ffd = fs->fsap_data; + if (!ffd->revprop_prefix) + SVN_ERR(svn_atomic__unique_counter(&ffd->revprop_prefix)); + + return SVN_NO_ERROR; +} + +/* Store the unparsed revprop hash CONTENT for REVISION in FS's revprop + * cache. If CACHED is not NULL, set *CACHED if there already is such + * an entry and skip the cache write in that case. Use SCRATCH_POOL for + * temporary allocations. */ +static svn_error_t * +cache_revprops(svn_boolean_t *is_cached, + svn_fs_t *fs, + svn_revnum_t revision, + svn_string_t *content, + apr_pool_t *scratch_pool) +{ + fs_fs_data_t *ffd = fs->fsap_data; + pair_cache_key_t key; + + /* Make sure prepare_revprop_cache() has been called. */ + SVN_ERR_ASSERT(ffd->revprop_prefix); + key.revision = revision; + key.second = ffd->revprop_prefix; + + if (is_cached) + { + SVN_ERR(svn_cache__has_key(is_cached, ffd->revprop_cache, &key, + scratch_pool)); + if (*is_cached) + return SVN_NO_ERROR; + } + + SVN_ERR(svn_cache__set(ffd->revprop_cache, &key, content, scratch_pool)); + + return SVN_NO_ERROR; +} + /* Read the non-packed revprops for revision REV in FS, put them into the - * revprop cache if activated and return them in *PROPERTIES. GENERATION - * is the current revprop generation. + * revprop cache if PROPULATE_CACHE is set and return them in *PROPERTIES. * * If the data could not be read due to an otherwise recoverable error, * leave *PROPERTIES unchanged. No error will be returned in that case. @@ -228,7 +272,7 @@ static svn_error_t * read_non_packed_revprop(apr_hash_t **properties, svn_fs_t *fs, svn_revnum_t rev, - apr_int64_t generation, + svn_boolean_t populate_cache, apr_pool_t *pool) { svn_stringbuf_t *content = NULL; @@ -249,9 +293,13 @@ read_non_packed_revprop(apr_hash_t **properties, } if (content) - SVN_ERR(parse_revprop(properties, fs, rev, generation, - svn_stringbuf__morph_into_string(content), - pool, iterpool)); + { + svn_string_t *as_string = svn_stringbuf__morph_into_string(content); + SVN_ERR(parse_revprop(properties, fs, rev, as_string, pool, iterpool)); + + if (populate_cache) + SVN_ERR(cache_revprops(NULL, fs, rev, as_string, iterpool)); + } svn_pool_clear(iterpool); @@ -272,12 +320,13 @@ get_min_filename_len(packed_revprops_t *revprops) } /* Given FS and REVPROPS->REVISION, fill the FILENAME, FOLDER and MANIFEST - * members. Use POOL for allocating results and SCRATCH_POOL for temporaries. + * members. Use RESULT_POOL for allocating results and SCRATCH_POOL for + * temporaries. */ static svn_error_t * get_revprop_packname(svn_fs_t *fs, packed_revprops_t *revprops, - apr_pool_t *pool, + apr_pool_t *result_pool, apr_pool_t *scratch_pool) { fs_fs_data_t *ffd = fs->fsap_data; @@ -298,18 +347,20 @@ get_revprop_packname(svn_fs_t *fs, --rev_count; } - revprops->manifest = apr_array_make(pool, rev_count, sizeof(const char*)); + revprops->manifest = apr_array_make(result_pool, rev_count, + sizeof(const char*)); /* No line in the file can be less than this number of chars long. */ min_filename_len = get_min_filename_len(revprops); /* Read the content of the manifest file */ revprops->folder - = svn_fs_fs__path_revprops_pack_shard(fs, revprops->revision, pool); + = svn_fs_fs__path_revprops_pack_shard(fs, revprops->revision, + result_pool); manifest_file_path - = svn_dirent_join(revprops->folder, PATH_MANIFEST, pool); + = svn_dirent_join(revprops->folder, PATH_MANIFEST, result_pool); - SVN_ERR(svn_fs_fs__read_content(&content, manifest_file_path, pool)); + SVN_ERR(svn_fs_fs__read_content(&content, manifest_file_path, result_pool)); /* There CONTENT must have a certain minimal size and there no * unterminated lines at the end of the file. Both guarantees also @@ -392,7 +443,8 @@ same_shard(svn_fs_t *fs, /* Given FS and the full packed file content in REVPROPS->PACKED_REVPROPS, * fill the START_REVISION member, and make PACKED_REVPROPS point to the * first serialized revprop. If READ_ALL is set, initialize the SIZES - * and OFFSETS members as well. + * and OFFSETS members as well. If POPULATE_CACHE is set, cache all + * revprops found in this pack. * * Parse the revprops for REVPROPS->REVISION and set the PROPERTIES as * well as the SERIALIZED_SIZE member. If revprop caching has been @@ -402,20 +454,25 @@ static svn_error_t * parse_packed_revprops(svn_fs_t *fs, packed_revprops_t *revprops, svn_boolean_t read_all, - apr_pool_t *pool, + svn_boolean_t populate_cache, + apr_pool_t *result_pool, apr_pool_t *scratch_pool) { svn_stream_t *stream; apr_int64_t first_rev, count, i; - apr_off_t offset; + apr_size_t offset; const char *header_end; apr_pool_t *iterpool = svn_pool_create(scratch_pool); + /* Initial value for the "Leaking bucket" pattern. */ + int bucket = 4; + /* decompress (even if the data is only "stored", there is still a * length header to remove) */ svn_stringbuf_t *compressed = revprops->packed_revprops; - svn_stringbuf_t *uncompressed = svn_stringbuf_create_empty(pool); - SVN_ERR(svn__decompress(compressed, uncompressed, APR_SIZE_MAX)); + svn_stringbuf_t *uncompressed = svn_stringbuf_create_empty(result_pool); + SVN_ERR(svn__decompress_zlib(compressed->data, compressed->len, + uncompressed, APR_SIZE_MAX)); /* read first revision number and number of revisions in the pack */ stream = svn_stream_from_stringbuf(uncompressed, scratch_pool); @@ -453,18 +510,21 @@ parse_packed_revprops(svn_fs_t *fs, offset = header_end - uncompressed->data + 2; - revprops->packed_revprops = svn_stringbuf_create_empty(pool); + revprops->packed_revprops = svn_stringbuf_create_empty(result_pool); revprops->packed_revprops->data = uncompressed->data + offset; revprops->packed_revprops->len = (apr_size_t)(uncompressed->len - offset); - revprops->packed_revprops->blocksize = (apr_size_t)(uncompressed->blocksize - offset); + revprops->packed_revprops->blocksize = (apr_size_t)(uncompressed->blocksize + - offset); /* STREAM still points to the first entry in the sizes list. */ revprops->start_revision = (svn_revnum_t)first_rev; if (read_all) { /* Init / construct REVPROPS members. */ - revprops->sizes = apr_array_make(pool, (int)count, sizeof(offset)); - revprops->offsets = apr_array_make(pool, (int)count, sizeof(offset)); + revprops->sizes = apr_array_make(result_pool, (int)count, + sizeof(offset)); + revprops->offsets = apr_array_make(result_pool, (int)count, + sizeof(offset)); } /* Now parse, revision by revision, the size and content of each @@ -479,7 +539,7 @@ parse_packed_revprops(svn_fs_t *fs, /* read & check the serialized size */ SVN_ERR(svn_fs_fs__read_number_from_stream(&size, NULL, stream, iterpool)); - if (size + offset > (apr_int64_t)revprops->packed_revprops->len) + if (size > (apr_int64_t)revprops->packed_revprops->len - offset) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, _("Packed revprop size exceeds pack file size")); @@ -489,21 +549,47 @@ parse_packed_revprops(svn_fs_t *fs, if (revision == revprops->revision) { + /* Parse (and possibly cache) the one revprop list we care about. */ SVN_ERR(parse_revprop(&revprops->properties, fs, revision, - revprops->generation, &serialized, - pool, iterpool)); + &serialized, result_pool, iterpool)); revprops->serialized_size = serialized.len; /* If we only wanted the revprops for REVISION then we are done. */ - if (!read_all) + if (!read_all && !populate_cache) break; } + if (populate_cache) + { + /* Adding all those revprops is expensive, in particular in a + * multi-threaded environment. There are situations where hit + * rates are low and revprops get evicted before re-using them. + * + * We try to detect thosse cases here. + * Only keep going while most (at least 2/3) aren't cached, yet. */ + svn_boolean_t already_cached; + SVN_ERR(cache_revprops(&already_cached, fs, revision, &serialized, + iterpool)); + + /* Stop populating the cache once we encountered too many entries + * already present relative to the numbers being added. */ + if (!already_cached) + { + ++bucket; + } + else + { + bucket -= 2; + if (bucket < 0) + populate_cache = FALSE; + } + } + if (read_all) { /* fill REVPROPS data structures */ - APR_ARRAY_PUSH(revprops->sizes, apr_off_t) = serialized.len; - APR_ARRAY_PUSH(revprops->offsets, apr_off_t) = offset; + APR_ARRAY_PUSH(revprops->sizes, apr_size_t) = serialized.len; + APR_ARRAY_PUSH(revprops->offsets, apr_size_t) = offset; } revprops->total_size += serialized.len; @@ -514,7 +600,7 @@ parse_packed_revprops(svn_fs_t *fs, } /* In filesystem FS, read the packed revprops for revision REV into - * *REVPROPS. Use GENERATION to populate the revprop cache, if enabled. + * *REVPROPS. Populate the revprop cache, if POPULATE_CACHE is set. * If you want to modify revprop contents / update REVPROPS, READ_ALL * must be set. Otherwise, only the properties of REV are being provided. * Allocate data in POOL. @@ -523,8 +609,8 @@ static svn_error_t * read_pack_revprop(packed_revprops_t **revprops, svn_fs_t *fs, svn_revnum_t rev, - apr_int64_t generation, svn_boolean_t read_all, + svn_boolean_t populate_cache, apr_pool_t *pool) { apr_pool_t *iterpool = svn_pool_create(pool); @@ -544,7 +630,6 @@ read_pack_revprop(packed_revprops_t **revprops, /* initialize the result data structure */ result = apr_pcalloc(pool, sizeof(*result)); result->revision = rev; - result->generation = generation; /* try to read the packed revprops. This may require retries if we have * concurrent writers. */ @@ -575,7 +660,8 @@ read_pack_revprop(packed_revprops_t **revprops, _("Failed to read revprop pack file for r%ld"), rev); /* parse it. RESULT will be complete afterwards. */ - err = parse_packed_revprops(fs, result, read_all, pool, iterpool); + err = parse_packed_revprops(fs, result, read_all, populate_cache, pool, + iterpool); svn_pool_destroy(iterpool); if (err) return svn_error_createf(SVN_ERR_FS_CORRUPT, err, @@ -594,16 +680,48 @@ svn_error_t * svn_fs_fs__get_revision_proplist(apr_hash_t **proplist_p, svn_fs_t *fs, svn_revnum_t rev, - apr_pool_t *pool) + svn_boolean_t refresh, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { fs_fs_data_t *ffd = fs->fsap_data; - apr_int64_t generation = 0; + + /* Only populate the cache if we did not just cross a sync barrier. + * This is to eliminate overhead from code that always sets REFRESH. + * For callers that want caching, the caching kicks in on read "later". */ + svn_boolean_t populate_cache = !refresh; /* not found, yet */ *proplist_p = NULL; /* should they be available at all? */ - SVN_ERR(svn_fs_fs__ensure_revision_exists(rev, fs, pool)); + SVN_ERR(svn_fs_fs__ensure_revision_exists(rev, fs, scratch_pool)); + + if (refresh) + { + /* Previous cache contents is invalid now. */ + svn_fs_fs__reset_revprop_cache(fs); + } + else + { + /* Try cache lookup first. */ + svn_boolean_t is_cached; + pair_cache_key_t key; + + /* Auto-alloc prefix and construct the key. */ + SVN_ERR(prepare_revprop_cache(fs, scratch_pool)); + key.revision = rev; + key.second = ffd->revprop_prefix; + + /* The only way that this might error out is due to parser error. */ + SVN_ERR_W(svn_cache__get((void **) proplist_p, &is_cached, + ffd->revprop_cache, &key, result_pool), + apr_psprintf(scratch_pool, + "Failed to parse revprops for r%ld.", + rev)); + if (is_cached) + return SVN_NO_ERROR; + } /* if REV had not been packed when we began, try reading it from the * non-packed shard. If that fails, we will fall through to packed @@ -611,7 +729,7 @@ svn_fs_fs__get_revision_proplist(apr_hash_t **proplist_p, if (!svn_fs_fs__is_packed_revprop(fs, rev)) { svn_error_t *err = read_non_packed_revprop(proplist_p, fs, rev, - generation, pool); + populate_cache, result_pool); if (err) { if (!APR_STATUS_IS_ENOENT(err->apr_err) @@ -629,7 +747,8 @@ svn_fs_fs__get_revision_proplist(apr_hash_t **proplist_p, if (ffd->format >= SVN_FS_FS__MIN_PACKED_REVPROP_FORMAT && !*proplist_p) { packed_revprops_t *revprops; - SVN_ERR(read_pack_revprop(&revprops, fs, rev, generation, FALSE, pool)); + SVN_ERR(read_pack_revprop(&revprops, fs, rev, FALSE, populate_cache, + result_pool)); *proplist_p = revprops->properties; } @@ -657,6 +776,7 @@ write_non_packed_revprop(const char **final_path, apr_hash_t *proplist, apr_pool_t *pool) { + fs_fs_data_t *ffd = fs->fsap_data; apr_file_t *file; svn_stream_t *stream; *final_path = svn_fs_fs__path_revprops(fs, rev, pool); @@ -671,7 +791,8 @@ write_non_packed_revprop(const char **final_path, SVN_ERR(svn_stream_close(stream)); /* Flush temporary file to disk and close it. */ - SVN_ERR(svn_io_file_flush_to_disk(file, pool)); + if (ffd->flush_to_disk) + SVN_ERR(svn_io_file_flush_to_disk(file, pool)); SVN_ERR(svn_io_file_close(file, pool)); return SVN_NO_ERROR; @@ -694,8 +815,10 @@ switch_to_new_revprop(svn_fs_t *fs, apr_array_header_t *files_to_delete, apr_pool_t *pool) { + fs_fs_data_t *ffd = fs->fsap_data; + SVN_ERR(svn_fs_fs__move_into_place(tmp_path, final_path, perms_reference, - pool)); + ffd->flush_to_disk, pool)); /* Clean up temporary files, if necessary. */ if (files_to_delete) @@ -744,13 +867,13 @@ serialize_revprops_header(svn_stream_t *stream, * We only allocate a few bytes each iteration -- even with a * million iterations we would still be in good shape memory-wise. */ - apr_off_t size = APR_ARRAY_IDX(sizes, i, apr_off_t); - SVN_ERR(svn_stream_printf(stream, iterpool, "%" APR_OFF_T_FMT "\n", + apr_size_t size = APR_ARRAY_IDX(sizes, i, apr_size_t); + SVN_ERR(svn_stream_printf(stream, iterpool, "%" APR_SIZE_T_FMT "\n", size)); } /* the double newline char indicates the end of the header */ - SVN_ERR(svn_stream_printf(stream, iterpool, "\n")); + SVN_ERR(svn_stream_puts(stream, "\n")); svn_pool_destroy(iterpool); return SVN_NO_ERROR; @@ -773,7 +896,7 @@ repack_revprops(svn_fs_t *fs, int end, int changed_index, svn_stringbuf_t *new_serialized, - apr_off_t new_total_size, + apr_size_t new_total_size, apr_file_t *file, apr_pool_t *pool) { @@ -802,10 +925,8 @@ repack_revprops(svn_fs_t *fs, } else { - apr_size_t size - = (apr_size_t)APR_ARRAY_IDX(revprops->sizes, i, apr_off_t); - apr_size_t offset - = (apr_size_t)APR_ARRAY_IDX(revprops->offsets, i, apr_off_t); + apr_size_t size = APR_ARRAY_IDX(revprops->sizes, i, apr_size_t); + apr_size_t offset = APR_ARRAY_IDX(revprops->offsets, i, apr_size_t); SVN_ERR(svn_stream_write(stream, revprops->packed_revprops->data + offset, @@ -816,16 +937,17 @@ repack_revprops(svn_fs_t *fs, SVN_ERR(svn_stream_close(stream)); /* compress / store the data */ - SVN_ERR(svn__compress(uncompressed, - compressed, - ffd->compress_packed_revprops - ? SVN_DELTA_COMPRESSION_LEVEL_DEFAULT - : SVN_DELTA_COMPRESSION_LEVEL_NONE)); + SVN_ERR(svn__compress_zlib(uncompressed->data, uncompressed->len, + compressed, + ffd->compress_packed_revprops + ? SVN_DELTA_COMPRESSION_LEVEL_DEFAULT + : SVN_DELTA_COMPRESSION_LEVEL_NONE)); /* finally, write the content to the target file, flush and close it */ SVN_ERR(svn_io_file_write_full(file, compressed->data, compressed->len, NULL, pool)); - SVN_ERR(svn_io_file_flush_to_disk(file, pool)); + if (ffd->flush_to_disk) + SVN_ERR(svn_io_file_flush_to_disk(file, pool)); SVN_ERR(svn_io_file_close(file, pool)); return SVN_NO_ERROR; @@ -848,7 +970,7 @@ repack_file_open(apr_file_t **file, { apr_int64_t tag; const char *tag_string; - svn_string_t *new_filename; + const char *new_filename; int i; int manifest_offset = (int)(revprops->start_revision - revprops->manifest_start); @@ -872,18 +994,18 @@ repack_file_open(apr_file_t **file, old_filename); SVN_ERR(svn_cstring_atoi64(&tag, tag_string + 1)); - new_filename = svn_string_createf(pool, "%ld.%" APR_INT64_T_FMT, - revprops->start_revision + start, - ++tag); + new_filename = apr_psprintf(pool, "%ld.%" APR_INT64_T_FMT, + revprops->start_revision + start, + ++tag); /* update the manifest to point to the new file */ for (i = start; i < end; ++i) APR_ARRAY_IDX(revprops->manifest, i + manifest_offset, const char*) - = new_filename->data; + = new_filename; /* open the file */ SVN_ERR(svn_io_file_open(file, svn_dirent_join(revprops->folder, - new_filename->data, + new_filename, pool), APR_WRITE | APR_CREATE, APR_OS_DEFAULT, pool)); @@ -907,15 +1029,14 @@ write_packed_revprop(const char **final_path, { fs_fs_data_t *ffd = fs->fsap_data; packed_revprops_t *revprops; - apr_int64_t generation = 0; svn_stream_t *stream; apr_file_t *file; svn_stringbuf_t *serialized; - apr_off_t new_total_size; + apr_size_t new_total_size; int changed_index; /* read contents of the current pack file */ - SVN_ERR(read_pack_revprop(&revprops, fs, rev, generation, TRUE, pool)); + SVN_ERR(read_pack_revprop(&revprops, fs, rev, TRUE, FALSE, pool)); /* serialize the new revprops */ serialized = svn_stringbuf_create_empty(pool); @@ -929,7 +1050,7 @@ write_packed_revprop(const char **final_path, + serialized->len + (revprops->offsets->nelts + 2) * SVN_INT64_BUFFER_SIZE; - APR_ARRAY_IDX(revprops->sizes, changed_index, apr_off_t) = serialized->len; + APR_ARRAY_IDX(revprops->sizes, changed_index, apr_size_t) = serialized->len; /* can we put the new data into the same pack as the before? */ if ( new_total_size < ffd->revprop_pack_size @@ -953,23 +1074,23 @@ write_packed_revprop(const char **final_path, int left = 0; int right = revprops->sizes->nelts - 1; - apr_off_t left_size = 2 * SVN_INT64_BUFFER_SIZE; - apr_off_t right_size = 2 * SVN_INT64_BUFFER_SIZE; + apr_size_t left_size = 2 * SVN_INT64_BUFFER_SIZE; + apr_size_t right_size = 2 * SVN_INT64_BUFFER_SIZE; /* let left and right side grow such that their size difference * is minimal after each step. */ while (left <= right) - if ( left_size + APR_ARRAY_IDX(revprops->sizes, left, apr_off_t) - < right_size + APR_ARRAY_IDX(revprops->sizes, right, apr_off_t)) + if ( left_size + APR_ARRAY_IDX(revprops->sizes, left, apr_size_t) + < right_size + APR_ARRAY_IDX(revprops->sizes, right, apr_size_t)) { - left_size += APR_ARRAY_IDX(revprops->sizes, left, apr_off_t) + left_size += APR_ARRAY_IDX(revprops->sizes, left, apr_size_t) + SVN_INT64_BUFFER_SIZE; ++left; } else { - right_size += APR_ARRAY_IDX(revprops->sizes, right, apr_off_t) - + SVN_INT64_BUFFER_SIZE; + right_size += APR_ARRAY_IDX(revprops->sizes, right, apr_size_t) + + SVN_INT64_BUFFER_SIZE; --right; } @@ -1025,17 +1146,16 @@ write_packed_revprop(const char **final_path, *final_path = svn_dirent_join(revprops->folder, PATH_MANIFEST, pool); SVN_ERR(svn_io_open_unique_file3(&file, tmp_path, revprops->folder, svn_io_file_del_none, pool, pool)); - + stream = svn_stream_from_aprfile2(file, TRUE, pool); for (i = 0; i < revprops->manifest->nelts; ++i) { const char *filename = APR_ARRAY_IDX(revprops->manifest, i, const char*); - SVN_ERR(svn_io_file_write_full(file, filename, strlen(filename), - NULL, pool)); - SVN_ERR(svn_io_file_putc('\n', file, pool)); + SVN_ERR(svn_stream_printf(stream, pool, "%s\n", filename)); } - - SVN_ERR(svn_io_file_flush_to_disk(file, pool)); + SVN_ERR(svn_stream_close(stream)); + if (ffd->flush_to_disk) + SVN_ERR(svn_io_file_flush_to_disk(file, pool)); SVN_ERR(svn_io_file_close(file, pool)); } @@ -1069,6 +1189,9 @@ svn_fs_fs__set_revision_proplist(svn_fs_t *fs, SVN_ERR(write_non_packed_revprop(&final_path, &tmp_path, fs, rev, proplist, pool)); + /* Previous cache contents is invalid now. */ + svn_fs_fs__reset_revprop_cache(fs); + /* We use the rev file of this revision as the perms reference, * because when setting revprops for the first time, the revprop * file won't exist and therefore can't serve as its own reference. @@ -1167,6 +1290,7 @@ svn_fs_fs__copy_revprops(const char *pack_file_dir, apr_array_header_t *sizes, apr_size_t total_size, int compression_level, + svn_boolean_t flush_to_disk, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *scratch_pool) @@ -1199,6 +1323,7 @@ svn_fs_fs__copy_revprops(const char *pack_file_dir, { const char *path; svn_stream_t *stream; + apr_file_t *file; svn_pool_clear(iterpool); @@ -1207,8 +1332,11 @@ svn_fs_fs__copy_revprops(const char *pack_file_dir, iterpool); /* Copy all the bits from the non-packed revprop file to the end of - * the pack file. */ - SVN_ERR(svn_stream_open_readonly(&stream, path, iterpool, iterpool)); + * the pack file. Use unbuffered apr_file_t since we're going to + * write using 16kb chunks. */ + SVN_ERR(svn_io_file_open(&file, path, APR_READ, APR_OS_DEFAULT, + iterpool)); + stream = svn_stream_from_aprfile2(file, FALSE, iterpool); SVN_ERR(svn_stream_copy3(stream, pack_stream, cancel_func, cancel_baton, iterpool)); } @@ -1217,12 +1345,14 @@ svn_fs_fs__copy_revprops(const char *pack_file_dir, SVN_ERR(svn_stream_close(pack_stream)); /* compress the content (or just store it for COMPRESSION_LEVEL 0) */ - SVN_ERR(svn__compress(uncompressed, compressed, compression_level)); + SVN_ERR(svn__compress_zlib(uncompressed->data, uncompressed->len, + compressed, compression_level)); /* write the pack file content to disk */ SVN_ERR(svn_io_file_write_full(pack_file, compressed->data, compressed->len, NULL, scratch_pool)); - SVN_ERR(svn_io_file_flush_to_disk(pack_file, scratch_pool)); + if (flush_to_disk) + SVN_ERR(svn_io_file_flush_to_disk(pack_file, scratch_pool)); SVN_ERR(svn_io_file_close(pack_file, scratch_pool)); svn_pool_destroy(iterpool); @@ -1235,8 +1365,9 @@ svn_fs_fs__pack_revprops_shard(const char *pack_file_dir, const char *shard_path, apr_int64_t shard, int max_files_per_dir, - apr_off_t max_pack_size, + apr_int64_t max_pack_size, int compression_level, + svn_boolean_t flush_to_disk, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *scratch_pool) @@ -1245,10 +1376,14 @@ svn_fs_fs__pack_revprops_shard(const char *pack_file_dir, apr_file_t *manifest_file; svn_stream_t *manifest_stream; svn_revnum_t start_rev, end_rev, rev; - apr_off_t total_size; + apr_size_t total_size; apr_pool_t *iterpool = svn_pool_create(scratch_pool); apr_array_header_t *sizes; + /* Sanitize config file values. */ + apr_size_t max_size = (apr_size_t)MIN(MAX(max_pack_size, 1), + SVN_MAX_OBJECT_SIZE); + /* Some useful paths. */ manifest_file_path = svn_dirent_join(pack_file_dir, PATH_MANIFEST, scratch_pool); @@ -1276,7 +1411,7 @@ svn_fs_fs__pack_revprops_shard(const char *pack_file_dir, works. */ /* initialize the revprop size info */ - sizes = apr_array_make(scratch_pool, max_files_per_dir, sizeof(apr_off_t)); + sizes = apr_array_make(scratch_pool, max_files_per_dir, sizeof(apr_size_t)); total_size = 2 * SVN_INT64_BUFFER_SIZE; /* Iterate over the revisions in this shard, determine their size and @@ -1293,16 +1428,20 @@ svn_fs_fs__pack_revprops_shard(const char *pack_file_dir, iterpool); SVN_ERR(svn_io_stat(&finfo, path, APR_FINFO_SIZE, iterpool)); - /* if we already have started a pack file and this revprop cannot be - * appended to it, write the previous pack file. */ - if (sizes->nelts != 0 && - total_size + SVN_INT64_BUFFER_SIZE + finfo.size > max_pack_size) + /* If we already have started a pack file and this revprop cannot be + * appended to it, write the previous pack file. Note this overflow + * check works because we enforced MAX_SIZE <= SVN_MAX_OBJECT_SIZE. */ + if (sizes->nelts != 0 + && ( finfo.size > max_size + || total_size > max_size + || SVN_INT64_BUFFER_SIZE + finfo.size > max_size - total_size)) { SVN_ERR(svn_fs_fs__copy_revprops(pack_file_dir, pack_filename, shard_path, start_rev, rev-1, - sizes, (apr_size_t)total_size, - compression_level, cancel_func, - cancel_baton, iterpool)); + sizes, total_size, + compression_level, flush_to_disk, + cancel_func, cancel_baton, + iterpool)); /* next pack file starts empty again */ apr_array_clear(sizes); @@ -1319,7 +1458,7 @@ svn_fs_fs__pack_revprops_shard(const char *pack_file_dir, pack_filename)); /* add to list of files to put into the current pack file */ - APR_ARRAY_PUSH(sizes, apr_off_t) = finfo.size; + APR_ARRAY_PUSH(sizes, apr_size_t) = finfo.size; total_size += SVN_INT64_BUFFER_SIZE + finfo.size; } @@ -1328,12 +1467,13 @@ svn_fs_fs__pack_revprops_shard(const char *pack_file_dir, SVN_ERR(svn_fs_fs__copy_revprops(pack_file_dir, pack_filename, shard_path, start_rev, rev-1, sizes, (apr_size_t)total_size, - compression_level, cancel_func, - cancel_baton, iterpool)); + compression_level, flush_to_disk, + cancel_func, cancel_baton, iterpool)); /* flush the manifest file to disk and update permissions */ SVN_ERR(svn_stream_close(manifest_stream)); - SVN_ERR(svn_io_file_flush_to_disk(manifest_file, iterpool)); + if (flush_to_disk) + SVN_ERR(svn_io_file_flush_to_disk(manifest_file, iterpool)); SVN_ERR(svn_io_file_close(manifest_file, iterpool)); SVN_ERR(svn_io_copy_perms(shard_path, pack_file_dir, iterpool)); @@ -1365,7 +1505,7 @@ svn_fs_fs__delete_revprops_shard(const char *shard_path, apr_psprintf(iterpool, "%d", i), iterpool); if (cancel_func) - SVN_ERR((*cancel_func)(cancel_baton)); + SVN_ERR(cancel_func(cancel_baton)); SVN_ERR(svn_io_remove_file2(path, TRUE, iterpool)); } diff --git a/subversion/libsvn_fs_fs/revprops.h b/subversion/libsvn_fs_fs/revprops.h index 66c137c33bf5..37063f96e9ae 100644 --- a/subversion/libsvn_fs_fs/revprops.h +++ b/subversion/libsvn_fs_fs/revprops.h @@ -58,15 +58,23 @@ svn_fs_fs__upgrade_cleanup_pack_revprops(svn_fs_t *fs, void *cancel_baton, apr_pool_t *scratch_pool); +/* Invalidate the revprop cache in FS. */ +void +svn_fs_fs__reset_revprop_cache(svn_fs_t *fs); + /* Read the revprops for revision REV in FS and return them in *PROPERTIES_P. + * If REFRESH is set, clear the revprop cache before accessing the data. * - * Allocations will be done in POOL. + * The result will be allocated in RESULT_POOL; SCRATCH_POOL is used for + * temporaries. */ svn_error_t * svn_fs_fs__get_revision_proplist(apr_hash_t **proplist_p, svn_fs_t *fs, svn_revnum_t rev, - apr_pool_t *pool); + svn_boolean_t refresh, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); /* Set the revision property list of revision REV in filesystem FS to PROPLIST. Use POOL for temporary allocations. */ @@ -103,8 +111,9 @@ svn_fs_fs__packed_revprop_available(svn_boolean_t *missing, * a hint on which initial buffer size we should use to hold the pack file * content. * - * CANCEL_FUNC and CANCEL_BATON are used as usual. Temporary allocations - * are done in SCRATCH_POOL. + * If FLUSH_TO_DISK is non-zero, do not return until the data has actually + * been written on the disk. CANCEL_FUNC and CANCEL_BATON are used as usual. + * Temporary allocations are done in SCRATCH_POOL. */ svn_error_t * svn_fs_fs__copy_revprops(const char *pack_file_dir, @@ -115,6 +124,7 @@ svn_fs_fs__copy_revprops(const char *pack_file_dir, apr_array_header_t *sizes, apr_size_t total_size, int compression_level, + svn_boolean_t flush_to_disk, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *scratch_pool); @@ -126,16 +136,18 @@ svn_fs_fs__copy_revprops(const char *pack_file_dir, * have no unpacked data anymore. Call upgrade_cleanup_pack_revprops after * the bump. * - * NOTIFY_FUNC and NOTIFY_BATON as well as CANCEL_FUNC and CANCEL_BATON are - * used in the usual way. Temporary allocations are done in SCRATCH_POOL. + * If FLUSH_TO_DISK is non-zero, do not return until the data has actually + * been written on the disk. CANCEL_FUNC and CANCEL_BATON areused in the + * usual way. Temporary allocations are done in SCRATCH_POOL. */ svn_error_t * svn_fs_fs__pack_revprops_shard(const char *pack_file_dir, const char *shard_path, apr_int64_t shard, int max_files_per_dir, - apr_off_t max_pack_size, + apr_int64_t max_pack_size, int compression_level, + svn_boolean_t flush_to_disk, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *scratch_pool); diff --git a/subversion/libsvn_fs_fs/stats.c b/subversion/libsvn_fs_fs/stats.c index 97a2ed7736f3..36992dbaeb66 100644 --- a/subversion/libsvn_fs_fs/stats.c +++ b/subversion/libsvn_fs_fs/stats.c @@ -70,8 +70,9 @@ typedef enum rep_kind_t */ typedef struct rep_stats_t { - /* absolute offset in the file */ - apr_off_t offset; + /* offset in the revision file (phys. addressing) / + * item index within REVISION (log. addressing) */ + apr_uint64_t item_index; /* item length in bytes */ apr_uint64_t size; @@ -92,8 +93,36 @@ typedef struct rep_stats_t /* classification of the representation. values of rep_kind_t */ char kind; + /* length of the delta chain, including this representation, + * saturated to 255 - if need be */ + apr_byte_t chain_length; } rep_stats_t; +/* Represents a link in the rep delta chain. REVISION + ITEM_INDEX points + * to BASE_REVISION + BASE_ITEM_INDEX. We collect this info while scanning + * a f7 repo in a single pass and resolve it afterwards. */ +typedef struct rep_ref_t +{ + /* Revision that contains this representation. */ + svn_revnum_t revision; + + /* Item index of this rep within REVISION. */ + apr_uint64_t item_index; + + /* Revision of the representation we deltified against. + * -1 if this representation is either PLAIN or a self-delta. */ + svn_revnum_t base_revision; + + /* Item index of that rep within BASE_REVISION. */ + apr_uint64_t base_item_index; + + /* Length of the PLAIN / DELTA line in the source file in bytes. + * We use this to update the info in the rep stats after scanning the + * whole file. */ + apr_uint16_t header_size; + +} rep_ref_t; + /* Represents a single revision. * There will be only one instance per revision. */ typedef struct revision_info_t @@ -176,23 +205,6 @@ typedef struct query_t void *cancel_baton; } query_t; -/* Return the length of REV_FILE in *FILE_SIZE. - * Use SCRATCH_POOL for temporary allocations. - */ -static svn_error_t * -get_file_size(apr_off_t *file_size, - svn_fs_fs__revision_file_t *rev_file, - apr_pool_t *scratch_pool) -{ - apr_finfo_t finfo; - - SVN_ERR(svn_io_file_info_get(&finfo, APR_FINFO_SIZE, rev_file->file, - scratch_pool)); - - *file_size = finfo.size; - return SVN_NO_ERROR; -} - /* Initialize the LARGEST_CHANGES member in STATS with a capacity of COUNT * entries. Allocate the result in RESULT_POOL. */ @@ -345,13 +357,13 @@ add_change(svn_fs_fs__stats_t *stats, /* Comparator used for binary search comparing the absolute file offset * of a representation to some other offset. DATA is a *rep_stats_t, - * KEY is a pointer to an apr_off_t. + * KEY is a pointer to an apr_uint64_t. */ static int -compare_representation_offsets(const void *data, const void *key) +compare_representation_item_index(const void *data, const void *key) { - apr_off_t lhs = (*(const rep_stats_t *const *)data)->offset; - apr_off_t rhs = *(const apr_off_t *)key; + apr_uint64_t lhs = (*(const rep_stats_t *const *)data)->item_index; + apr_uint64_t rhs = *(const apr_uint64_t *)key; if (lhs < rhs) return -1; @@ -362,7 +374,7 @@ compare_representation_offsets(const void *data, const void *key) * return it in *REVISION_INFO. For performance reasons, we skip the * lookup if the info is already provided. * - * In that revision, look for the rep_stats_t object for offset OFFSET. + * In that revision, look for the rep_stats_t object for item ITEM_INDEX. * If it already exists, set *IDX to its index in *REVISION_INFO's * representations list and return the representation object. Otherwise, * set the index to where it must be inserted and return NULL. @@ -372,7 +384,7 @@ find_representation(int *idx, query_t *query, revision_info_t **revision_info, svn_revnum_t revision, - apr_off_t offset) + apr_uint64_t item_index) { revision_info_t *info; *idx = -1; @@ -392,14 +404,14 @@ find_representation(int *idx, /* look for the representation */ *idx = svn_sort__bsearch_lower_bound(info->representations, - &offset, - compare_representation_offsets); + &item_index, + compare_representation_item_index); if (*idx < info->representations->nelts) { /* return the representation, if this is the one we were looking for */ rep_stats_t *result = APR_ARRAY_IDX(info->representations, *idx, rep_stats_t *); - if (result->offset == offset) + if (result->item_index == item_index) return result; } @@ -428,7 +440,7 @@ parse_representation(rep_stats_t **representation, /* look it up */ result = find_representation(&idx, query, &revision_info, rep->revision, - (apr_off_t)rep->item_index); + rep->item_index); if (!result) { /* not parsed, yet (probably a rep in the same revision). @@ -436,9 +448,8 @@ parse_representation(rep_stats_t **representation, */ result = apr_pcalloc(result_pool, sizeof(*result)); result->revision = rep->revision; - result->expanded_size = (rep->expanded_size ? rep->expanded_size - : rep->size); - result->offset = (apr_off_t)rep->item_index; + result->expanded_size = rep->expanded_size; + result->item_index = rep->item_index; result->size = rep->size; /* In phys. addressing mode, follow link to the actual representation. @@ -447,7 +458,8 @@ parse_representation(rep_stats_t **representation, if (!svn_fs_fs__use_log_addressing(query->fs)) { svn_fs_fs__rep_header_t *header; - apr_off_t offset = revision_info->offset + result->offset; + apr_off_t offset = revision_info->offset + + (apr_off_t)rep->item_index; SVN_ERR_ASSERT(revision_info->rev_file); SVN_ERR(svn_io_file_seek(revision_info->rev_file->file, APR_SET, @@ -457,6 +469,23 @@ parse_representation(rep_stats_t **representation, scratch_pool, scratch_pool)); result->header_size = header->header_size; + + /* Determine length of the delta chain. */ + if (header->type == svn_fs_fs__rep_delta) + { + int base_idx; + rep_stats_t *base_rep + = find_representation(&base_idx, query, NULL, + header->base_revision, + header->base_item_index); + + result->chain_length = 1 + MIN(base_rep->chain_length, + (apr_byte_t)0xfe); + } + else + { + result->chain_length = 1; + } } svn_sort__array_insert(revision_info->representations, &result, idx); @@ -588,6 +617,10 @@ read_noderev(query_t *query, svn_stream_t *stream = svn_stream_from_stringbuf(noderev_str, scratch_pool); SVN_ERR(svn_fs_fs__read_noderev(&noderev, stream, scratch_pool, scratch_pool)); + SVN_ERR(svn_fs_fs__fixup_expanded_size(query->fs, noderev->data_rep, + scratch_pool)); + SVN_ERR(svn_fs_fs__fixup_expanded_size(query->fs, noderev->prop_rep, + scratch_pool)); if (noderev->data_rep) { @@ -652,19 +685,25 @@ get_phys_change_count(query_t *query, revision_info_t *revision_info, apr_pool_t *scratch_pool) { - /* We are going to use our own sub-pool here because the changes object - * may well be >100MB and SCRATCH_POOL may not get cleared until all other - * info has been read by read_phys_revision(). Therefore, tidy up early. - */ - apr_pool_t *subpool = svn_pool_create(scratch_pool); - apr_array_header_t *changes; + apr_pool_t *iterpool = svn_pool_create(scratch_pool); + svn_fs_fs__changes_context_t *context; - SVN_ERR(svn_fs_fs__get_changes(&changes, query->fs, - revision_info->revision, subpool)); - revision_info->change_count = changes->nelts; + /* Fetch the first block of data. */ + SVN_ERR(svn_fs_fs__create_changes_context(&context, query->fs, + revision_info->revision, + scratch_pool)); - /* Release potentially tons of memory. */ - svn_pool_destroy(subpool); + revision_info->change_count = 0; + while (!context->eol) + { + apr_array_header_t *changes; + + svn_pool_clear(iterpool); + SVN_ERR(svn_fs_fs__get_changes(&changes, context, iterpool, iterpool)); + revision_info->change_count = changes->nelts; + } + + svn_pool_destroy(iterpool); return SVN_NO_ERROR; } @@ -729,12 +768,12 @@ read_phys_pack_file(query_t *query, { apr_pool_t *iterpool = svn_pool_create(scratch_pool); int i; - apr_off_t file_size = 0; + svn_filesize_t file_size = 0; svn_fs_fs__revision_file_t *rev_file; SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&rev_file, query->fs, base, scratch_pool, scratch_pool)); - SVN_ERR(get_file_size(&file_size, rev_file, scratch_pool)); + SVN_ERR(svn_io_file_size_get(&file_size, rev_file->file, scratch_pool)); /* process each revision in the pack file */ for (i = 0; i < query->shard_size; ++i) @@ -798,7 +837,7 @@ read_phys_revision_file(query_t *query, apr_pool_t *scratch_pool) { revision_info_t *info = apr_pcalloc(result_pool, sizeof(*info)); - apr_off_t file_size = 0; + svn_filesize_t file_size = 0; svn_fs_fs__revision_file_t *rev_file; /* cancellation support */ @@ -808,7 +847,7 @@ read_phys_revision_file(query_t *query, /* read the whole pack file into memory */ SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&rev_file, query->fs, revision, scratch_pool, scratch_pool)); - SVN_ERR(get_file_size(&file_size, rev_file, scratch_pool)); + SVN_ERR(svn_io_file_size_get(&file_size, rev_file->file, scratch_pool)); /* create the revision info for the current rev */ info->representations = apr_array_make(result_pool, 4, sizeof(rep_stats_t*)); @@ -885,6 +924,70 @@ read_item(svn_stringbuf_t **contents, return SVN_NO_ERROR; } +/* Predicate comparing the two rep_ref_t** LHS and RHS by the respective + * representation's revision. + */ +static int +compare_representation_refs(const void *lhs, const void *rhs) +{ + svn_revnum_t lhs_rev = (*(const rep_ref_t *const *)lhs)->revision; + svn_revnum_t rhs_rev = (*(const rep_ref_t *const *)rhs)->revision; + + if (lhs_rev < rhs_rev) + return -1; + return (lhs_rev > rhs_rev ? 1 : 0); +} + +/* Given all the presentations found in a single rev / pack file as + * rep_ref_t * in REP_REFS, update the delta chain lengths in QUERY. + * REP_REFS and its contents can then be discarded. + */ +static svn_error_t * +resolve_representation_refs(query_t *query, + apr_array_header_t *rep_refs) +{ + int i; + + /* Because delta chains can only point to previous revs, after sorting + * REP_REFS, all base refs have already been updated. */ + svn_sort__array(rep_refs, compare_representation_refs); + + /* Build up the CHAIN_LENGTH values. */ + for (i = 0; i < rep_refs->nelts; ++i) + { + int idx; + rep_ref_t *ref = APR_ARRAY_IDX(rep_refs, i, rep_ref_t *); + rep_stats_t *rep = find_representation(&idx, query, NULL, + ref->revision, ref->item_index); + + /* No dangling pointers and all base reps have been processed. */ + SVN_ERR_ASSERT(rep); + SVN_ERR_ASSERT(!rep->chain_length); + + /* Set the HEADER_SIZE as we found it during the scan. */ + rep->header_size = ref->header_size; + + /* The delta chain got 1 element longer. */ + if (ref->base_revision == SVN_INVALID_REVNUM) + { + rep->chain_length = 1; + } + else + { + rep_stats_t *base; + + base = find_representation(&idx, query, NULL, ref->base_revision, + ref->base_item_index); + SVN_ERR_ASSERT(base); + SVN_ERR_ASSERT(base->chain_length); + + rep->chain_length = 1 + MIN(base->chain_length, (apr_byte_t)0xfe); + } + } + + return SVN_NO_ERROR; +} + /* Process the logically addressed revision contents of revisions BASE to * BASE + COUNT - 1 in QUERY. * @@ -905,6 +1008,12 @@ read_log_rev_or_packfile(query_t *query, int i; svn_fs_fs__revision_file_t *rev_file; + /* We collect the delta chain links as we scan the file. Afterwards, + * we determine the lengths of those delta chains and throw this + * temporary container away. */ + apr_array_header_t *rep_refs = apr_array_make(scratch_pool, 64, + sizeof(rep_ref_t *)); + /* we will process every revision in the rev / pack file */ for (i = 0; i < count; ++i) { @@ -947,6 +1056,8 @@ read_log_rev_or_packfile(query_t *query, /* process all entries (and later continue with the next block) */ for (i = 0; i < entries->nelts; ++i) { + svn_stringbuf_t *item; + revision_info_t *info; svn_fs_fs__p2l_entry_t *entry = &APR_ARRAY_IDX(entries, i, svn_fs_fs__p2l_entry_t); @@ -959,32 +1070,64 @@ read_log_rev_or_packfile(query_t *query, continue; /* read and process interesting items */ + info = APR_ARRAY_IDX(query->revisions, entry->item.revision, + revision_info_t*); + if (entry->type == SVN_FS_FS__ITEM_TYPE_NODEREV) { - svn_stringbuf_t *item; - revision_info_t *info = APR_ARRAY_IDX(query->revisions, - entry->item.revision, - revision_info_t*); SVN_ERR(read_item(&item, rev_file, entry, iterpool, iterpool)); SVN_ERR(read_noderev(query, item, info, result_pool, iterpool)); } else if (entry->type == SVN_FS_FS__ITEM_TYPE_CHANGES) { - svn_stringbuf_t *item; - revision_info_t *info = APR_ARRAY_IDX(query->revisions, - entry->item.revision, - revision_info_t*); SVN_ERR(read_item(&item, rev_file, entry, iterpool, iterpool)); info->change_count = get_log_change_count(item->data + 0, item->len); info->changes_len += entry->size; } + else if ( (entry->type == SVN_FS_FS__ITEM_TYPE_FILE_REP) + || (entry->type == SVN_FS_FS__ITEM_TYPE_DIR_REP) + || (entry->type == SVN_FS_FS__ITEM_TYPE_FILE_PROPS) + || (entry->type == SVN_FS_FS__ITEM_TYPE_DIR_PROPS)) + { + /* Collect the delta chain link. */ + svn_fs_fs__rep_header_t *header; + rep_ref_t *ref = apr_pcalloc(scratch_pool, sizeof(*ref)); + + SVN_ERR(svn_io_file_aligned_seek(rev_file->file, + rev_file->block_size, + NULL, entry->offset, + iterpool)); + SVN_ERR(svn_fs_fs__read_rep_header(&header, + rev_file->stream, + iterpool, iterpool)); + + ref->header_size = header->header_size; + ref->revision = entry->item.revision; + ref->item_index = entry->item.number; + + if (header->type == svn_fs_fs__rep_delta) + { + ref->base_item_index = header->base_item_index; + ref->base_revision = header->base_revision; + } + else + { + ref->base_item_index = SVN_FS_FS__ITEM_INDEX_UNUSED; + ref->base_revision = SVN_INVALID_REVNUM; + } + + APR_ARRAY_PUSH(rep_refs, rep_ref_t *) = ref; + } /* advance offset */ offset += entry->size; } } + /* Resolve the delta chain links. */ + SVN_ERR(resolve_representation_refs(query, rep_refs)); + /* clean up and close file handles */ svn_pool_destroy(iterpool); @@ -1111,6 +1254,7 @@ add_rep_stats(svn_fs_fs__representation_stats_t *stats, stats->references += rep->ref_count; stats->expanded_size += rep->ref_count * rep->expanded_size; + stats->chain_len += rep->chain_length; } /* Aggregate the info the in revision_info_t * array REVISIONS into the diff --git a/subversion/libsvn_fs_fs/structure b/subversion/libsvn_fs_fs/structure index 7b5129f17cee..f624d616c7b5 100644 --- a/subversion/libsvn_fs_fs/structure +++ b/subversion/libsvn_fs_fs/structure @@ -150,12 +150,14 @@ The formats are: Format 5, understood by Subversion 1.7-dev, never released Format 6, understood by Subversion 1.8 Format 7, understood by Subversion 1.9 + Format 8, understood by Subversion 1.10 The differences between the formats are: Delta representation in revision files - Format 1: svndiff0 only - Formats 2+: svndiff0 or svndiff1 + Format 1: svndiff0 only + Formats 2-7: svndiff0 or svndiff1 + Formats 8: svndiff0, svndiff1 or svndiff2 Format options Formats 1-2: none permitted @@ -198,9 +200,9 @@ Shard packing: (i.e. same min packed revision) Addressing: - Format 1-6: Physical addressing; uses fixed positions within a rev file + Format 1+: Physical addressing; uses fixed positions within a rev file Format 7+: Logical addressing; uses item index that will be translated - on-the-fly to the actual rev / pack file location + on-the-fly to the actual rev / pack file location (default for 7+ created) Repository IDs: Format 1+: The first line of db/uuid contains the repository UUID @@ -525,6 +527,7 @@ A revision file contains a concatenation of various kinds of data: * Text and property representations * Node-revisions * The changed-path data + * Two offsets at the very end (physical addressing only) * Index data (logical addressing only) * Revision / pack file footer (logical addressing only) @@ -565,6 +568,9 @@ defined: ### in formats >=4, also present: gives hex SHA1 digest of expanded rep see representation_t->uniquifier in fs.h + ### Starting from format 8, a special notation "-" + can be used for optional values that are not present + ( and ). cpath FS pathname node was created at copyfrom " " of copyfrom data copyroot " " of the root of this copy @@ -757,6 +763,9 @@ Format 7 introduces logical addressing that requires item indexes to be translated / mapped to physical rev / pack file offsets. These indexes are appended to the respective rev / pack file. +The indexes map (revision number, item-index) pairs to absolute file offsets +and absolute file offsets to (revision number, item-index, item metadata). + Details of the binary format used by these index files can be found in structure-indexes. diff --git a/subversion/libsvn_fs_fs/structure-indexes b/subversion/libsvn_fs_fs/structure-indexes index 25490c7ca8f0..545f2ffcbe8c 100644 --- a/subversion/libsvn_fs_fs/structure-indexes +++ b/subversion/libsvn_fs_fs/structure-indexes @@ -13,10 +13,10 @@ to read and cache any data without traversing DAGs. Rev and pack files are immutable, so the same is true for index data. During a transaction or while packing a file, a proto index file gets -written (actually, one log-to-phys and one phys-to-log). Its format is -a simple concatenation of runtime structs and as such, an implementation -detail subject to change. A proto index basically aggregates all the -information that must later be transformed into the final index. +written (actually, one log-to-phys and one phys-to-log). They use a +simpler, less compact format with fixed record lengths. A proto index +basically aggregates all the information that must later be transformed +into the final index. General design concerns @@ -192,11 +192,11 @@ at the beginning of the file is optional and will be ignored. /* begin of proto index file for revision r and following */ (0, 0) /* mark start of revision r, optional for first rev */ - (off, item)* /* zero to many mappings in random order */ + (off, item)* /* zero or more mappings in random order */ (0, 0) /* mark start of revision r + 1 */ - (off, item)* /* zero to many mappings in random order */ + (off, item)* /* zero or more mappings in random order */ (0, 0) /* mark start of revision r + 2 */ - (off, item)* /* zero to many mappings in random order */ + (off, item)* /* zero or more mappings in random order */ ... /* end of file. */ @@ -343,10 +343,12 @@ For performance reasons we use a modified version: h0 = fnv_1a([b0 b4 b8 ..]), ..., h3 = fnv_1a([b3 b7 b11 ..]) -* combine the big endian representation of these checksums plus the - remnant of the original stream into a 12 to 15 byte long intermediate +* concatenate the big endian representation of these checksums (4 bytes + each) plus the remnant of the original stream into a 16 to 19 byte long + intermediate: - [i0 .. iK], 12 <= K+1 <= 15 + [i0 .. iK] = [big-endian(h0) ... big-endian(h3) remnant ], 16 <= K+1 <= 19 -* FNV checksum = fnv_1a([i0 .. iK]) in big endian representation +* fold the variable-length intermediate into a compact 32 bit checksum: + FNV checksum = fnv_1a([i0 .. iK]) diff --git a/subversion/libsvn_fs_fs/temp_serializer.c b/subversion/libsvn_fs_fs/temp_serializer.c index 4e7ae2d1abb2..f6e9e3a0971c 100644 --- a/subversion/libsvn_fs_fs/temp_serializer.c +++ b/subversion/libsvn_fs_fs/temp_serializer.c @@ -103,9 +103,7 @@ serialize_svn_string(svn_temp_serializer__context_t *context, if (string == NULL) return; - svn_temp_serializer__push(context, - (const void * const *)s, - sizeof(*string)); + svn_temp_serializer__push(context, (const void * const *)s, sizeof(**s)); /* the "string" content may actually be arbitrary binary data. * Thus, we cannot use svn_temp_serializer__add_string. */ @@ -143,7 +141,7 @@ serialize_representation(svn_temp_serializer__context_t *context, /* serialize the representation struct itself */ svn_temp_serializer__add_leaf(context, (const void * const *)representation, - sizeof(*rep)); + sizeof(**representation)); } /* auxiliary structure representing the content of a directory array */ @@ -153,6 +151,10 @@ typedef struct dir_data_t * (it's int because the directory is an APR array) */ int count; + /** Current length of the in-txn in-disk representation of the directory. + * SVN_INVALID_FILESIZE if unknown (i.e. committed data). */ + svn_filesize_t txn_filesize; + /* number of unused dir entry buckets in the index */ apr_size_t over_provision; @@ -187,7 +189,7 @@ serialize_dir_entry(svn_temp_serializer__context_t *context, svn_temp_serializer__push(context, (const void * const *)entry_p, - sizeof(svn_fs_dirent_t)); + sizeof(**entry_p)); svn_fs_fs__id_serialize(context, &entry->id); svn_temp_serializer__add_string(context, &entry->name); @@ -198,24 +200,27 @@ serialize_dir_entry(svn_temp_serializer__context_t *context, svn_temp_serializer__pop(context); } -/* Utility function to serialize the ENTRIES into a new serialization +/* Utility function to serialize the DIR into a new serialization * context to be returned. Allocation will be made form POOL. */ static svn_temp_serializer__context_t * -serialize_dir(apr_array_header_t *entries, apr_pool_t *pool) +serialize_dir(svn_fs_fs__dir_data_t *dir, apr_pool_t *pool) { dir_data_t dir_data; int i = 0; svn_temp_serializer__context_t *context; + apr_array_header_t *entries = dir->entries; /* calculate sizes */ int count = entries->nelts; apr_size_t over_provision = 2 + count / 4; - apr_size_t entries_len = (count + over_provision) * sizeof(svn_fs_dirent_t*); - apr_size_t lengths_len = (count + over_provision) * sizeof(apr_uint32_t); + apr_size_t total_count = count + over_provision; + apr_size_t entries_len = total_count * sizeof(*dir_data.entries); + apr_size_t lengths_len = total_count * sizeof(*dir_data.lengths); /* copy the hash entries to an auxiliary struct of known layout */ dir_data.count = count; + dir_data.txn_filesize = dir->txn_filesize; dir_data.over_provision = over_provision; dir_data.operations = 0; dir_data.entries = apr_palloc(pool, entries_len); @@ -252,24 +257,29 @@ serialize_dir(apr_array_header_t *entries, apr_pool_t *pool) return context; } -/* Utility function to reconstruct a dir entries array from serialized data +/* Utility function to reconstruct a dir entries struct from serialized data * in BUFFER and DIR_DATA. Allocation will be made form POOL. */ -static apr_array_header_t * +static svn_fs_fs__dir_data_t * deserialize_dir(void *buffer, dir_data_t *dir_data, apr_pool_t *pool) { - apr_array_header_t *result - = apr_array_make(pool, dir_data->count, sizeof(svn_fs_dirent_t *)); + svn_fs_fs__dir_data_t *result; apr_size_t i; apr_size_t count; svn_fs_dirent_t *entry; svn_fs_dirent_t **entries; + /* Construct empty directory object. */ + result = apr_pcalloc(pool, sizeof(*result)); + result->entries + = apr_array_make(pool, dir_data->count, sizeof(svn_fs_dirent_t *)); + result->txn_filesize = dir_data->txn_filesize; + /* resolve the reference to the entries array */ svn_temp_deserializer__resolve(buffer, (void **)&dir_data->entries); entries = dir_data->entries; - /* fixup the references within each entry and add it to the hash */ + /* fixup the references within each entry and add it to the RESULT */ for (i = 0, count = dir_data->count; i < count; ++i) { svn_temp_deserializer__resolve(entries, (void **)&entries[i]); @@ -280,7 +290,7 @@ deserialize_dir(void *buffer, dir_data_t *dir_data, apr_pool_t *pool) svn_fs_fs__id_deserialize(entry, (svn_fs_id_t **)&entry->id); /* add the entry to the hash */ - APR_ARRAY_PUSH(result, svn_fs_dirent_t *) = entry; + APR_ARRAY_PUSH(result->entries, svn_fs_dirent_t *) = entry; } /* return the now complete hash */ @@ -405,7 +415,7 @@ serialize_txdelta_ops(svn_temp_serializer__context_t *context, /* the ops form a contiguous chunk of memory with no further references */ svn_temp_serializer__add_leaf(context, (const void * const *)ops, - count * sizeof(svn_txdelta_op_t)); + count * sizeof(**ops)); } /* Utility function to serialize W in the given serialization CONTEXT. @@ -417,9 +427,7 @@ serialize_txdeltawindow(svn_temp_serializer__context_t *context, svn_txdelta_window_t *window = *w; /* serialize the window struct itself */ - svn_temp_serializer__push(context, - (const void * const *)w, - sizeof(svn_txdelta_window_t)); + svn_temp_serializer__push(context, (const void * const *)w, sizeof(**w)); /* serialize its sub-structures */ serialize_txdelta_ops(context, &window->ops, window->num_ops); @@ -496,8 +504,7 @@ svn_fs_fs__serialize_manifest(void **data, apr_array_header_t *manifest = in; *data_len = sizeof(apr_off_t) *manifest->nelts; - *data = apr_palloc(pool, *data_len); - memcpy(*data, manifest->elts, *data_len); + *data = apr_pmemdup(pool, manifest->elts, *data_len); return SVN_NO_ERROR; } @@ -592,7 +599,7 @@ svn_fs_fs__serialize_properties(void **data, /* create our auxiliary data structure */ properties.count = apr_hash_count(hash); properties.keys = apr_palloc(pool, sizeof(const char*) * (properties.count + 1)); - properties.values = apr_palloc(pool, sizeof(const char*) * properties.count); + properties.values = apr_palloc(pool, sizeof(const svn_string_t *) * properties.count); /* populate it with the hash entries */ for (hi = apr_hash_first(pool, hash), i=0; hi; hi = apr_hash_next(hi), ++i) @@ -655,6 +662,44 @@ svn_fs_fs__deserialize_properties(void **out, return SVN_NO_ERROR; } +svn_error_t * +svn_fs_fs__serialize_revprops(void **data, + apr_size_t *data_len, + void *in, + apr_pool_t *pool) +{ + svn_string_t *buffer = in; + + *data = (void *)buffer->data; + *data_len = buffer->len; + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_fs_fs__deserialize_revprops(void **out, + void *data, + apr_size_t data_len, + apr_pool_t *pool) +{ + apr_hash_t *properties; + svn_stream_t *stream; + + svn_string_t buffer; + buffer.data = data; + buffer.len = data_len; + + stream = svn_stream_from_string(&buffer, pool); + properties = svn_hash__make(pool); + + SVN_ERR(svn_hash_read2(properties, stream, SVN_HASH_TERMINATOR, pool)); + + /* done */ + *out = properties; + + return SVN_NO_ERROR; +} + svn_error_t * svn_fs_fs__serialize_id(void **data, apr_size_t *data_len, @@ -743,16 +788,18 @@ svn_fs_fs__deserialize_node_revision(void **item, } /* Utility function that returns the directory serialized inside CONTEXT - * to DATA and DATA_LEN. */ + * to DATA and DATA_LEN. If OVERPROVISION is set, allocate some extra + * room for future in-place changes by svn_fs_fs__replace_dir_entry. */ static svn_error_t * return_serialized_dir_context(svn_temp_serializer__context_t *context, void **data, - apr_size_t *data_len) + apr_size_t *data_len, + svn_boolean_t overprovision) { svn_stringbuf_t *serialized = svn_temp_serializer__get(context); *data = serialized->data; - *data_len = serialized->blocksize; + *data_len = overprovision ? serialized->blocksize : serialized->len; ((dir_data_t *)serialized->data)->len = serialized->len; return SVN_NO_ERROR; @@ -764,13 +811,30 @@ svn_fs_fs__serialize_dir_entries(void **data, void *in, apr_pool_t *pool) { - apr_array_header_t *dir = in; + svn_fs_fs__dir_data_t *dir = in; /* serialize the dir content into a new serialization context * and return the serialized data */ return return_serialized_dir_context(serialize_dir(dir, pool), data, - data_len); + data_len, + FALSE); +} + +svn_error_t * +svn_fs_fs__serialize_txndir_entries(void **data, + apr_size_t *data_len, + void *in, + apr_pool_t *pool) +{ + svn_fs_fs__dir_data_t *dir = in; + + /* serialize the dir content into a new serialization context + * and return the serialized data */ + return return_serialized_dir_context(serialize_dir(dir, pool), + data, + data_len, + TRUE); } svn_error_t * @@ -803,6 +867,20 @@ svn_fs_fs__get_sharded_offset(void **out, return SVN_NO_ERROR; } +svn_error_t * +svn_fs_fs__extract_dir_filesize(void **out, + const void *data, + apr_size_t data_len, + void *baton, + apr_pool_t *pool) +{ + const dir_data_t *dir_data = data; + + *(svn_filesize_t *)out = dir_data->txn_filesize; + + return SVN_NO_ERROR; +} + /* Utility function that returns the lowest index of the first entry in * *ENTRIES that points to a dir entry with a name equal or larger than NAME. * If an exact match has been found, *FOUND will be set to TRUE. COUNT is @@ -857,7 +935,7 @@ svn_fs_fs__extract_dir_entry(void **out, apr_pool_t *pool) { const dir_data_t *dir_data = data; - const char* name = baton; + extract_dir_entry_baton_t *entry_baton = baton; svn_boolean_t found; /* resolve the reference to the entries array */ @@ -870,13 +948,17 @@ svn_fs_fs__extract_dir_entry(void **out, /* binary search for the desired entry by name */ apr_size_t pos = find_entry((svn_fs_dirent_t **)entries, - name, + entry_baton->name, dir_data->count, &found); - /* de-serialize that entry or return NULL, if no match has been found */ + /* de-serialize that entry or return NULL, if no match has been found. + * Be sure to check that the directory contents is still up-to-date. */ + entry_baton->out_of_date + = dir_data->txn_filesize != entry_baton->txn_filesize; + *out = NULL; - if (found) + if (found && !entry_baton->out_of_date) { const svn_fs_dirent_t *source = svn_temp_deserializer__ptr(entries, (const void *const *)&entries[pos]); @@ -889,8 +971,7 @@ svn_fs_fs__extract_dir_entry(void **out, apr_size_t size = lengths[pos]; /* copy & deserialize the entry */ - svn_fs_dirent_t *new_entry = apr_palloc(pool, size); - memcpy(new_entry, source, size); + svn_fs_dirent_t *new_entry = apr_pmemdup(pool, source, size); svn_temp_deserializer__resolve(new_entry, (void **)&new_entry->name); svn_fs_fs__id_deserialize(new_entry, (svn_fs_id_t **)&new_entry->id); @@ -911,31 +992,34 @@ slowly_replace_dir_entry(void **data, { replace_baton_t *replace_baton = (replace_baton_t *)baton; dir_data_t *dir_data = (dir_data_t *)*data; - apr_array_header_t *dir; + svn_fs_fs__dir_data_t *dir; int idx = -1; svn_fs_dirent_t *entry; + apr_array_header_t *entries; SVN_ERR(svn_fs_fs__deserialize_dir_entries((void **)&dir, *data, dir_data->len, pool)); - entry = svn_fs_fs__find_dir_entry(dir, replace_baton->name, &idx); + entries = dir->entries; + entry = svn_fs_fs__find_dir_entry(entries, replace_baton->name, &idx); /* Replacement or removal? */ if (replace_baton->new_entry) { /* Replace ENTRY with / insert the NEW_ENTRY */ if (entry) - APR_ARRAY_IDX(dir, idx, svn_fs_dirent_t *) = replace_baton->new_entry; + APR_ARRAY_IDX(entries, idx, svn_fs_dirent_t *) + = replace_baton->new_entry; else - svn_sort__array_insert(dir, &replace_baton->new_entry, idx); + svn_sort__array_insert(entries, &replace_baton->new_entry, idx); } else { /* Remove the old ENTRY. */ if (entry) - svn_sort__array_delete(dir, idx, 1); + svn_sort__array_delete(entries, idx, 1); } return svn_fs_fs__serialize_dir_entries(data, data_len, dir, pool); @@ -957,6 +1041,12 @@ svn_fs_fs__replace_dir_entry(void **data, svn_temp_serializer__context_t *context; + /* update the cached file length info. + * Because we are writing to the cache, it is fair to assume that the + * caller made sure that the current contents is consistent with the + * previous state of the directory file. */ + dir_data->txn_filesize = replace_baton->txn_filesize; + /* after quite a number of operations, let's re-pack everything. * This is to limit the number of wasted space as we cannot overwrite * existing data but must always append. */ @@ -1029,9 +1119,7 @@ svn_fs_fs__replace_dir_entry(void **data, serialize_dir_entry(context, &entries[pos], &length); /* return the updated serialized data */ - SVN_ERR (return_serialized_dir_context(context, - data, - data_len)); + SVN_ERR(return_serialized_dir_context(context, data, data_len, TRUE)); /* since the previous call may have re-allocated the buffer, the lengths * pointer may no longer point to the entry in that buffer. Therefore, @@ -1046,6 +1134,18 @@ svn_fs_fs__replace_dir_entry(void **data, return SVN_NO_ERROR; } +svn_error_t * +svn_fs_fs__reset_txn_filesize(void **data, + apr_size_t *data_len, + void *baton, + apr_pool_t *pool) +{ + dir_data_t *dir_data = (dir_data_t *)*data; + dir_data->txn_filesize = SVN_INVALID_FILESIZE; + + return SVN_NO_ERROR; +} + svn_error_t * svn_fs_fs__serialize_rep_header(void **data, apr_size_t *data_len, @@ -1055,7 +1155,7 @@ svn_fs_fs__serialize_rep_header(void **data, svn_fs_fs__rep_header_t *copy = apr_palloc(pool, sizeof(*copy)); *copy = *(svn_fs_fs__rep_header_t *)in; - *data_len = sizeof(svn_fs_fs__rep_header_t); + *data_len = sizeof(*copy); *data = copy; return SVN_NO_ERROR; @@ -1124,47 +1224,29 @@ deserialize_change(void *buffer, change_t **change_p) svn_temp_deserializer__resolve(change, (void **)&change->info.copyfrom_path); } -/* Auxiliary structure representing the content of a change_t array. - This structure is much easier to (de-)serialize than an APR array. - */ -typedef struct changes_data_t -{ - /* number of entries in the array */ - int count; - - /* reference to the changes */ - change_t **changes; -} changes_data_t; - svn_error_t * svn_fs_fs__serialize_changes(void **data, apr_size_t *data_len, void *in, apr_pool_t *pool) { - apr_array_header_t *array = in; - changes_data_t changes; + svn_fs_fs__changes_list_t *changes = in; svn_temp_serializer__context_t *context; svn_stringbuf_t *serialized; int i; - /* initialize our auxiliary data structure and link it to the - * array elements */ - changes.count = array->nelts; - changes.changes = (change_t **)array->elts; - /* serialize it and all its elements */ - context = svn_temp_serializer__init(&changes, - sizeof(changes), - changes.count * 250, + context = svn_temp_serializer__init(changes, + sizeof(*changes), + changes->count * 250, pool); svn_temp_serializer__push(context, - (const void * const *)&changes.changes, - changes.count * sizeof(change_t*)); + (const void * const *)&changes->changes, + changes->count * sizeof(*changes->changes)); - for (i = 0; i < changes.count; ++i) - serialize_change(context, &changes.changes[i]); + for (i = 0; i < changes->count; ++i) + serialize_change(context, &changes->changes[i]); svn_temp_serializer__pop(context); @@ -1184,8 +1266,7 @@ svn_fs_fs__deserialize_changes(void **out, apr_pool_t *pool) { int i; - changes_data_t *changes = (changes_data_t *)data; - apr_array_header_t *array = apr_array_make(pool, 0, sizeof(change_t *)); + svn_fs_fs__changes_list_t *changes = (svn_fs_fs__changes_list_t *)data; /* de-serialize our auxiliary data structure */ svn_temp_deserializer__resolve(changes, (void**)&changes->changes); @@ -1195,14 +1276,8 @@ svn_fs_fs__deserialize_changes(void **out, deserialize_change(changes->changes, (change_t **)&changes->changes[i]); - /* Use the changes buffer as the array's data buffer - * (DATA remains valid for at least as long as POOL). */ - array->elts = (char *)changes->changes; - array->nelts = changes->count; - array->nalloc = changes->count; - /* done */ - *out = array; + *out = changes; return SVN_NO_ERROR; } diff --git a/subversion/libsvn_fs_fs/temp_serializer.h b/subversion/libsvn_fs_fs/temp_serializer.h index 4d14b01fe63d..187c8d000206 100644 --- a/subversion/libsvn_fs_fs/temp_serializer.h +++ b/subversion/libsvn_fs_fs/temp_serializer.h @@ -51,7 +51,7 @@ svn_fs_fs__noderev_deserialize(void *buffer, /** - * Adds position information to the the raw window data in WINDOW. + * Adds position information to the raw window data in WINDOW. */ typedef struct { @@ -60,6 +60,9 @@ typedef struct /* the offset within the representation right after reading the window */ apr_off_t end_offset; + + /* svndiff version */ + int ver; } svn_fs_fs__raw_cached_window_t; /** @@ -155,6 +158,26 @@ svn_fs_fs__deserialize_properties(void **out, apr_size_t data_len, apr_pool_t *pool); +/** + * Implements #svn_cache__serialize_func_t for a properties hash + * (@a in is an #apr_hash_t of svn_string_t elements, keyed by const char*). + */ +svn_error_t * +svn_fs_fs__serialize_revprops(void **data, + apr_size_t *data_len, + void *in, + apr_pool_t *pool); + +/** + * Implements #svn_cache__deserialize_func_t for a properties hash + * (@a *out is an #apr_hash_t of svn_string_t elements, keyed by const char*). + */ +svn_error_t * +svn_fs_fs__deserialize_revprops(void **out, + void *data, + apr_size_t data_len, + apr_pool_t *pool); + /** * Implements #svn_cache__serialize_func_t for #svn_fs_id_t */ @@ -192,7 +215,7 @@ svn_fs_fs__deserialize_node_revision(void **item, apr_pool_t *pool); /** - * Implements #svn_cache__serialize_func_t for a directory contents array + * Implements #svn_cache__serialize_func_t for a #svn_fs_fs__dir_data_t */ svn_error_t * svn_fs_fs__serialize_dir_entries(void **data, @@ -201,7 +224,17 @@ svn_fs_fs__serialize_dir_entries(void **data, apr_pool_t *pool); /** - * Implements #svn_cache__deserialize_func_t for a directory contents array + * Same as svn_fs_fs__serialize_dir_entries but allocates extra room for + * in-place modification. + */ +svn_error_t * +svn_fs_fs__serialize_txndir_entries(void **data, + apr_size_t *data_len, + void *in, + apr_pool_t *pool); + +/** + * Implements #svn_cache__deserialize_func_t for a #svn_fs_fs__dir_data_t */ svn_error_t * svn_fs_fs__deserialize_dir_entries(void **out, @@ -220,10 +253,45 @@ svn_fs_fs__get_sharded_offset(void **out, void *baton, apr_pool_t *pool); +/** + * Implements #svn_cache__partial_getter_func_t. + * Set (svn_filesize_t) @a *out to the filesize info stored with the + * serialized directory in @a data of @a data_len. @a baton is unused. + */ +svn_error_t * +svn_fs_fs__extract_dir_filesize(void **out, + const void *data, + apr_size_t data_len, + void *baton, + apr_pool_t *pool); + +/** + * Describes the entry to be found in a directory: Identifies the entry + * by @a name and requires the directory file size to be @a filesize. + */ +typedef struct extract_dir_entry_baton_t +{ + /** name of the directory entry to return */ + const char *name; + + /** Current length of the in-txn in-disk representation of the directory. + * SVN_INVALID_FILESIZE if unknown. */ + svn_filesize_t txn_filesize; + + /** Will be set by the callback. If FALSE, the cached data is out of date. + * We need this indicator because the svn_cache__t interface will always + * report the lookup as a success (FOUND==TRUE) if the generic lookup was + * successful -- regardless of what the entry extraction callback does. */ + svn_boolean_t out_of_date; +} extract_dir_entry_baton_t; + + /** * Implements #svn_cache__partial_getter_func_t for a single * #svn_fs_dirent_t within a serialized directory contents hash, - * identified by its name (const char @a *baton). + * identified by its name (in (extract_dir_entry_baton_t *) @a *baton). + * If the filesize specified in the baton does not match the cached + * value for this directory, @a *out will be NULL as well. */ svn_error_t * svn_fs_fs__extract_dir_entry(void **out, @@ -236,7 +304,10 @@ svn_fs_fs__extract_dir_entry(void **out, * Describes the change to be done to a directory: Set the entry * identify by @a name to the value @a new_entry. If the latter is * @c NULL, the entry shall be removed if it exists. Otherwise it - * will be replaced or automatically added, respectively. + * will be replaced or automatically added, respectively. The + * @a filesize allows readers to identify stale cache data (e.g. + * due to concurrent access to txns); writers use it to update the + * cached file size info. */ typedef struct replace_baton_t { @@ -245,6 +316,10 @@ typedef struct replace_baton_t /** directory entry to insert instead */ svn_fs_dirent_t *new_entry; + + /** Current length of the in-txn in-disk representation of the directory. + * SVN_INVALID_FILESIZE if unknown. */ + svn_filesize_t txn_filesize; } replace_baton_t; /** @@ -258,6 +333,17 @@ svn_fs_fs__replace_dir_entry(void **data, void *baton, apr_pool_t *pool); +/** + * Implements #svn_cache__partial_setter_func_t for a #svn_fs_fs__dir_data_t + * at @a *data, resetting its txn_filesize field to SVN_INVALID_FILESIZE. + * &a baton should be NULL. + */ +svn_error_t * +svn_fs_fs__reset_txn_filesize(void **data, + apr_size_t *data_len, + void *baton, + apr_pool_t *pool); + /** * Implements #svn_cache__serialize_func_t for a #svn_fs_fs__rep_header_t. */ @@ -276,9 +362,34 @@ svn_fs_fs__deserialize_rep_header(void **out, apr_size_t data_len, apr_pool_t *pool); +/*** Block of changes in a changed paths list. */ +typedef struct svn_fs_fs__changes_list_t +{ + /* Offset of the first element in CHANGES within the changed paths list + on disk. */ + apr_off_t start_offset; + + /* Offset of the first element behind CHANGES within the changed paths + list on disk. */ + apr_off_t end_offset; + + /* End of list reached? This may have false negatives in case the number + of elements in the list is a multiple of our block / range size. */ + svn_boolean_t eol; + + /* Array of #svn_fs_x__change_t * representing a consecutive sub-range of + elements in a changed paths list. */ + + /* number of entries in the array */ + int count; + + /* reference to the changes */ + change_t **changes; + +} svn_fs_fs__changes_list_t; + /** - * Implements #svn_cache__serialize_func_t for an #apr_array_header_t of - * #change_t *. + * Implements #svn_cache__serialize_func_t for a #svn_fs_fs__changes_list_t. */ svn_error_t * svn_fs_fs__serialize_changes(void **data, @@ -287,8 +398,7 @@ svn_fs_fs__serialize_changes(void **data, apr_pool_t *pool); /** - * Implements #svn_cache__deserialize_func_t for an #apr_array_header_t of - * #change_t *. + * Implements #svn_cache__deserialize_func_t for a #svn_fs_fs__changes_list_t. */ svn_error_t * svn_fs_fs__deserialize_changes(void **out, diff --git a/subversion/libsvn_fs_fs/transaction.c b/subversion/libsvn_fs_fs/transaction.c index bc93a5c27b82..eb6fefaeae22 100644 --- a/subversion/libsvn_fs_fs/transaction.c +++ b/subversion/libsvn_fs_fs/transaction.c @@ -25,6 +25,7 @@ #include #include +#include "svn_error_codes.h" #include "svn_hash.h" #include "svn_props.h" #include "svn_sorts.h" @@ -87,15 +88,6 @@ path_txn_props(svn_fs_t *fs, PATH_TXN_PROPS, pool); } -static APR_INLINE const char * -path_txn_props_final(svn_fs_t *fs, - const svn_fs_fs__id_part_t *txn_id, - apr_pool_t *pool) -{ - return svn_dirent_join(svn_fs_fs__path_txn_dir(fs, txn_id, pool), - PATH_TXN_PROPS_FINAL, pool); -} - static APR_INLINE const char * path_txn_next_ids(svn_fs_t *fs, const svn_fs_fs__id_part_t *txn_id, @@ -584,16 +576,62 @@ unparse_dir_entry(svn_fs_dirent_t *dirent, svn_stream_t *stream, apr_pool_t *pool) { - const char *val - = apr_psprintf(pool, "%s %s", - (dirent->kind == svn_node_file) ? SVN_FS_FS__KIND_FILE - : SVN_FS_FS__KIND_DIR, - svn_fs_fs__id_unparse(dirent->id, pool)->data); + apr_size_t to_write; + svn_string_t *id_str = svn_fs_fs__id_unparse(dirent->id, pool); + apr_size_t name_len = strlen(dirent->name); - SVN_ERR(svn_stream_printf(stream, pool, "K %" APR_SIZE_T_FMT "\n%s\n" - "V %" APR_SIZE_T_FMT "\n%s\n", - strlen(dirent->name), dirent->name, - strlen(val), val)); + /* Note that sizeof == len + 1, i.e. accounts for the space between + * type and ID. */ + apr_size_t type_len = (dirent->kind == svn_node_file) + ? sizeof(SVN_FS_FS__KIND_FILE) + : sizeof(SVN_FS_FS__KIND_DIR); + apr_size_t value_len = type_len + id_str->len; + + /* A buffer with sufficient space for + * - both string lines + * - 4 newlines + * - 2 lines K/V lines containing a number each + */ + char *buffer = apr_palloc(pool, name_len + value_len + + 4 + + 2 * (2 + SVN_INT64_BUFFER_SIZE)); + + /* Now construct the value. */ + char *p = buffer; + + /* The "K length(name)\n" line. */ + p[0] = 'K'; + p[1] = ' '; + p += 2; + p += svn__i64toa(p, name_len); + *(p++) = '\n'; + + /* The line with the key, i.e. dir entry name. */ + memcpy(p, dirent->name, name_len); + p += name_len; + *(p++) = '\n'; + + /* The "V length(type+id)\n" line. */ + p[0] = 'V'; + p[1] = ' '; + p += 2; + p += svn__i64toa(p, value_len); + *(p++) = '\n'; + + /* The line with the type and ID. */ + memcpy(p, + (dirent->kind == svn_node_file) ? SVN_FS_FS__KIND_FILE + : SVN_FS_FS__KIND_DIR, + type_len - 1); + p += type_len - 1; + *(p++) = ' '; + memcpy(p, id_str->data, id_str->len); + p+=id_str->len; + *(p++) = '\n'; + + /* Add the entry to the output stream. */ + to_write = p - buffer; + SVN_ERR(svn_stream_write(stream, buffer, &to_write)); return SVN_NO_ERROR; } @@ -894,20 +932,36 @@ svn_fs_fs__paths_changed(apr_hash_t **changed_paths_p, svn_revnum_t rev, apr_pool_t *pool) { - apr_hash_t *changed_paths; - apr_array_header_t *changes; - int i; + apr_hash_t *changed_paths = svn_hash__make(pool); + svn_fs_fs__changes_context_t *context; - SVN_ERR(svn_fs_fs__get_changes(&changes, fs, rev, pool)); + apr_pool_t *iterpool = svn_pool_create(pool); - changed_paths = svn_hash__make(pool); - for (i = 0; i < changes->nelts; ++i) + /* Fetch all data block-by-block. */ + SVN_ERR(svn_fs_fs__create_changes_context(&context, fs, rev, pool)); + while (!context->eol) { - change_t *change = APR_ARRAY_IDX(changes, i, change_t *); - apr_hash_set(changed_paths, change->path.data, change->path.len, - &change->info); + apr_array_header_t *changes; + int i; + + svn_pool_clear(iterpool); + + /* Be sure to allocate the changes in the result POOL, even though + we don't need the array itself afterwards. Copying the entries + from a temp pool to the result POOL would be expensive and saves + use less then 10% memory. */ + SVN_ERR(svn_fs_fs__get_changes(&changes, context, pool, iterpool)); + + for (i = 0; i < changes->nelts; ++i) + { + change_t *change = APR_ARRAY_IDX(changes, i, change_t *); + apr_hash_set(changed_paths, change->path.data, change->path.len, + &change->info); + } } + svn_pool_destroy(iterpool); + *changed_paths_p = changed_paths; return SVN_NO_ERROR; @@ -959,6 +1013,7 @@ static svn_error_t * get_and_increment_txn_key_body(void *baton, apr_pool_t *pool) { struct get_and_increment_txn_key_baton *cb = baton; + fs_fs_data_t *ffd = cb->fs->fsap_data; const char *txn_current_filename = svn_fs_fs__path_txn_current(cb->fs, pool); char new_id_str[SVN_INT64_BUFFER_SIZE + 1]; /* add space for a newline */ @@ -976,10 +1031,10 @@ get_and_increment_txn_key_body(void *baton, apr_pool_t *pool) /* Increment the key and add a trailing \n to the string so the txn-current file has a newline in it. */ - SVN_ERR(svn_io_write_atomic(txn_current_filename, new_id_str, - line_length + 1, - txn_current_filename /* copy_perms path */, - pool)); + SVN_ERR(svn_io_write_atomic2(txn_current_filename, new_id_str, + line_length + 1, + txn_current_filename /* copy_perms path */, + ffd->flush_to_disk, pool)); return SVN_NO_ERROR; } @@ -1144,7 +1199,7 @@ get_txn_proplist(apr_hash_t *proplist, err = svn_hash_read2(proplist, stream, SVN_HASH_TERMINATOR, pool); if (err) { - svn_error_clear(svn_stream_close(stream)); + err = svn_error_compose_create(err, svn_stream_close(stream)); return svn_error_quick_wrapf(err, _("malformed property list in transaction '%s'"), path_txn_props(fs, txn_id, pool)); @@ -1159,24 +1214,24 @@ static svn_error_t * set_txn_proplist(svn_fs_t *fs, const svn_fs_fs__id_part_t *txn_id, apr_hash_t *props, - svn_boolean_t final, apr_pool_t *pool) { - svn_stringbuf_t *buf; - svn_stream_t *stream; + svn_stream_t *tmp_stream; + const char *tmp_path; + const char *final_path = path_txn_props(fs, txn_id, pool); - /* Write out the new file contents to BUF. */ - buf = svn_stringbuf_create_ensure(1024, pool); - stream = svn_stream_from_stringbuf(buf, pool); - SVN_ERR(svn_hash_write2(props, stream, SVN_HASH_TERMINATOR, pool)); - SVN_ERR(svn_stream_close(stream)); + /* Write the new contents into a temporary file. */ + SVN_ERR(svn_stream_open_unique(&tmp_stream, &tmp_path, + svn_dirent_dirname(final_path, pool), + svn_io_file_del_none, + pool, pool)); + + /* Replace the old file with the new one. */ + SVN_ERR(svn_hash_write2(props, tmp_stream, SVN_HASH_TERMINATOR, pool)); + SVN_ERR(svn_stream_close(tmp_stream)); + + SVN_ERR(svn_io_file_rename2(tmp_path, final_path, FALSE, pool)); - /* Open the transaction properties file and write new contents to it. */ - SVN_ERR(svn_io_write_atomic((final - ? path_txn_props_final(fs, txn_id, pool) - : path_txn_props(fs, txn_id, pool)), - buf->data, buf->len, - NULL /* copy_perms_path */, pool)); return SVN_NO_ERROR; } @@ -1231,7 +1286,7 @@ svn_fs_fs__change_txn_props(svn_fs_txn_t *txn, /* Create a new version of the file and write out the new props. */ /* Open the transaction properties file. */ - SVN_ERR(set_txn_proplist(txn->fs, &ftd->txn_id, txn_prop, FALSE, pool)); + SVN_ERR(set_txn_proplist(txn->fs, &ftd->txn_id, txn_prop, pool)); return SVN_NO_ERROR; } @@ -1490,6 +1545,7 @@ svn_fs_fs__set_entry(svn_fs_t *fs, = svn_fs_fs__path_txn_node_children(fs, parent_noderev->id, pool); apr_file_t *file; svn_stream_t *out; + svn_filesize_t filesize; fs_fs_data_t *ffd = fs->fsap_data; apr_pool_t *subpool = svn_pool_create(pool); @@ -1507,8 +1563,6 @@ svn_fs_fs__set_entry(svn_fs_t *fs, out = svn_stream_from_aprfile2(file, TRUE, pool); SVN_ERR(unparse_dir_entries(entries, out, subpool)); - svn_pool_clear(subpool); - /* Mark the node-rev's data rep as mutable. */ rep = apr_pcalloc(pool, sizeof(*rep)); rep->revision = SVN_INVALID_REVNUM; @@ -1517,40 +1571,67 @@ svn_fs_fs__set_entry(svn_fs_t *fs, parent_noderev->data_rep = rep; SVN_ERR(svn_fs_fs__put_node_revision(fs, parent_noderev->id, parent_noderev, FALSE, pool)); + + /* Immediately populate the txn dir cache to avoid re-reading + * the file we just wrote. */ + if (ffd->txn_dir_cache) + { + const char *key + = svn_fs_fs__id_unparse(parent_noderev->id, subpool)->data; + svn_fs_fs__dir_data_t dir_data; + + /* Flush APR buffers. */ + SVN_ERR(svn_io_file_flush(file, subpool)); + + /* Obtain final file size to update txn_dir_cache. */ + SVN_ERR(svn_io_file_size_get(&filesize, file, subpool)); + + /* Store in the cache. */ + dir_data.entries = entries; + dir_data.txn_filesize = filesize; + SVN_ERR(svn_cache__set(ffd->txn_dir_cache, key, &dir_data, + subpool)); + } + + svn_pool_clear(subpool); } else { /* The directory rep is already mutable, so just open it for append. */ SVN_ERR(svn_io_file_open(&file, filename, APR_WRITE | APR_APPEND, - APR_OS_DEFAULT, pool)); - out = svn_stream_from_aprfile2(file, TRUE, pool); - } + APR_OS_DEFAULT, subpool)); + out = svn_stream_from_aprfile2(file, TRUE, subpool); - /* if we have a directory cache for this transaction, update it */ - if (ffd->txn_dir_cache) - { - /* build parameters: (name, new entry) pair */ - const char *key = - svn_fs_fs__id_unparse(parent_noderev->id, subpool)->data; - replace_baton_t baton; - - baton.name = name; - baton.new_entry = NULL; - - if (id) + /* If the cache contents is stale, drop it. + * + * Note that the directory file is append-only, i.e. if the size + * did not change, the contents didn't either. */ + if (ffd->txn_dir_cache) { - baton.new_entry = apr_pcalloc(subpool, sizeof(*baton.new_entry)); - baton.new_entry->name = name; - baton.new_entry->kind = kind; - baton.new_entry->id = id; - } + const char *key + = svn_fs_fs__id_unparse(parent_noderev->id, subpool)->data; + svn_boolean_t found; + svn_filesize_t cached_filesize; - /* actually update the cached directory (if cached) */ - SVN_ERR(svn_cache__set_partial(ffd->txn_dir_cache, key, - svn_fs_fs__replace_dir_entry, &baton, - subpool)); + /* Get the file size that corresponds to the cached contents + * (if any). */ + SVN_ERR(svn_cache__get_partial((void **)&cached_filesize, &found, + ffd->txn_dir_cache, key, + svn_fs_fs__extract_dir_filesize, + NULL, subpool)); + + /* File size info still matches? + * If not, we need to drop the cache entry. */ + if (found) + { + SVN_ERR(svn_io_file_size_get(&filesize, file, subpool)); + + if (cached_filesize != filesize) + SVN_ERR(svn_cache__set(ffd->txn_dir_cache, key, NULL, + subpool)); + } + } } - svn_pool_clear(subpool); /* Append an incremental hash entry for the entry change. */ if (id) @@ -1568,7 +1649,42 @@ svn_fs_fs__set_entry(svn_fs_t *fs, strlen(name), name)); } + /* Flush APR buffers. */ + SVN_ERR(svn_io_file_flush(file, subpool)); + + /* Obtain final file size to update txn_dir_cache. */ + SVN_ERR(svn_io_file_size_get(&filesize, file, subpool)); + + /* Close file. */ SVN_ERR(svn_io_file_close(file, subpool)); + svn_pool_clear(subpool); + + /* if we have a directory cache for this transaction, update it */ + if (ffd->txn_dir_cache) + { + /* build parameters: name, new entry, new file size */ + const char *key = + svn_fs_fs__id_unparse(parent_noderev->id, subpool)->data; + replace_baton_t baton; + + baton.name = name; + baton.new_entry = NULL; + baton.txn_filesize = filesize; + + if (id) + { + baton.new_entry = apr_pcalloc(subpool, sizeof(*baton.new_entry)); + baton.new_entry->name = name; + baton.new_entry->kind = kind; + baton.new_entry->id = id; + } + + /* actually update the cached directory (if cached) */ + SVN_ERR(svn_cache__set_partial(ffd->txn_dir_cache, key, + svn_fs_fs__replace_dir_entry, &baton, + subpool)); + } + svn_pool_destroy(subpool); return SVN_NO_ERROR; } @@ -1615,9 +1731,11 @@ svn_fs_fs__add_change(svn_fs_t *fs, return svn_io_file_close(file, pool); } -/* If the transaction TXN_ID in FS uses logical addressing, store the - * (ITEM_INDEX, OFFSET) pair in the txn's log-to-phys proto index file. +/* Store the (ITEM_INDEX, OFFSET) pair in the txn's log-to-phys proto + * index file. * Use POOL for allocations. + * This function assumes that transaction TXN_ID in FS uses logical + * addressing. */ static svn_error_t * store_l2p_index_entry(svn_fs_t *fs, @@ -1626,37 +1744,40 @@ store_l2p_index_entry(svn_fs_t *fs, apr_uint64_t item_index, apr_pool_t *pool) { - if (svn_fs_fs__use_log_addressing(fs)) - { - const char *path = svn_fs_fs__path_l2p_proto_index(fs, txn_id, pool); - apr_file_t *file; - SVN_ERR(svn_fs_fs__l2p_proto_index_open(&file, path, pool)); - SVN_ERR(svn_fs_fs__l2p_proto_index_add_entry(file, offset, - item_index, pool)); - SVN_ERR(svn_io_file_close(file, pool)); - } + const char *path; + apr_file_t *file; + + SVN_ERR_ASSERT(svn_fs_fs__use_log_addressing(fs)); + + path = svn_fs_fs__path_l2p_proto_index(fs, txn_id, pool); + SVN_ERR(svn_fs_fs__l2p_proto_index_open(&file, path, pool)); + SVN_ERR(svn_fs_fs__l2p_proto_index_add_entry(file, offset, + item_index, pool)); + SVN_ERR(svn_io_file_close(file, pool)); return SVN_NO_ERROR; } -/* If the transaction TXN_ID in FS uses logical addressing, store ENTRY - * in the phys-to-log proto index file of transaction TXN_ID. +/* Store ENTRY in the phys-to-log proto index file of transaction TXN_ID. * Use POOL for allocations. + * This function assumes that transaction TXN_ID in FS uses logical + * addressing. */ static svn_error_t * store_p2l_index_entry(svn_fs_t *fs, const svn_fs_fs__id_part_t *txn_id, - svn_fs_fs__p2l_entry_t *entry, + const svn_fs_fs__p2l_entry_t *entry, apr_pool_t *pool) { - if (svn_fs_fs__use_log_addressing(fs)) - { - const char *path = svn_fs_fs__path_p2l_proto_index(fs, txn_id, pool); - apr_file_t *file; - SVN_ERR(svn_fs_fs__p2l_proto_index_open(&file, path, pool)); - SVN_ERR(svn_fs_fs__p2l_proto_index_add_entry(file, entry, pool)); - SVN_ERR(svn_io_file_close(file, pool)); - } + const char *path; + apr_file_t *file; + + SVN_ERR_ASSERT(svn_fs_fs__use_log_addressing(fs)); + + path = svn_fs_fs__path_p2l_proto_index(fs, txn_id, pool); + SVN_ERR(svn_fs_fs__p2l_proto_index_open(&file, path, pool)); + SVN_ERR(svn_fs_fs__p2l_proto_index_add_entry(file, entry, pool)); + SVN_ERR(svn_io_file_close(file, pool)); return SVN_NO_ERROR; } @@ -1680,17 +1801,23 @@ allocate_item_index(apr_uint64_t *item_index, char buffer[SVN_INT64_BUFFER_SIZE] = { 0 }; svn_boolean_t eof = FALSE; apr_size_t to_write; - apr_size_t read; + apr_size_t bytes_read; apr_off_t offset = 0; /* read number, increment it and write it back to disk */ SVN_ERR(svn_io_file_open(&file, svn_fs_fs__path_txn_item_index(fs, txn_id, pool), - APR_READ | APR_WRITE | APR_CREATE | APR_BUFFERED, + APR_READ | APR_WRITE | APR_CREATE, APR_OS_DEFAULT, pool)); SVN_ERR(svn_io_file_read_full2(file, buffer, sizeof(buffer)-1, - &read, &eof, pool)); - if (read) + &bytes_read, &eof, pool)); + + /* Item index file should be shorter than SVN_INT64_BUFFER_SIZE, + otherwise we truncate data. */ + if (!eof) + return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, + _("Unexpected itemidx file length")); + else if (bytes_read) SVN_ERR(svn_cstring_atoui64(item_index, buffer)); else *item_index = SVN_FS_FS__ITEM_INDEX_FIRST_USER; @@ -1968,9 +2095,7 @@ choose_delta_base(representation_t **rep, /* Very short rep bases are simply not worth it as we are unlikely * to re-coup the deltification space overhead of 20+ bytes. */ - svn_filesize_t rep_size = (*rep)->expanded_size - ? (*rep)->expanded_size - : (*rep)->size; + svn_filesize_t rep_size = (*rep)->expanded_size; if (rep_size < 64) { *rep = NULL; @@ -2034,6 +2159,35 @@ rep_write_cleanup(void *data) return APR_SUCCESS; } +static void +txdelta_to_svndiff(svn_txdelta_window_handler_t *handler, + void **handler_baton, + svn_stream_t *output, + svn_fs_t *fs, + apr_pool_t *pool) +{ + fs_fs_data_t *ffd = fs->fsap_data; + int svndiff_version; + + if (ffd->delta_compression_type == compression_type_lz4) + { + SVN_ERR_ASSERT_NO_RETURN(ffd->format >= SVN_FS_FS__MIN_SVNDIFF2_FORMAT); + svndiff_version = 2; + } + else if (ffd->delta_compression_type == compression_type_zlib) + { + SVN_ERR_ASSERT_NO_RETURN(ffd->format >= SVN_FS_FS__MIN_SVNDIFF1_FORMAT); + svndiff_version = 1; + } + else + { + svndiff_version = 0; + } + + svn_txdelta_to_svndiff3(handler, handler_baton, output, svndiff_version, + ffd->delta_compression_level, pool); +} + /* Get a rep_write_baton and store it in *WB_P for the representation indicated by NODEREV in filesystem FS. Perform allocations in POOL. Only appropriate for file contents, not for props or @@ -2050,8 +2204,6 @@ rep_write_get_baton(struct rep_write_baton **wb_p, svn_stream_t *source; svn_txdelta_window_handler_t wh; void *whb; - fs_fs_data_t *ffd = fs->fsap_data; - int diff_version = ffd->format >= SVN_FS_FS__MIN_SVNDIFF1_FORMAT ? 1 : 0; svn_fs_fs__rep_header_t header = { 0 }; b = apr_pcalloc(pool, sizeof(*b)); @@ -2071,12 +2223,12 @@ rep_write_get_baton(struct rep_write_baton **wb_p, b->scratch_pool)); b->file = file; - b->rep_stream = fnv1a_wrap_stream(&b->fnv1a_checksum_ctx, - svn_stream_from_aprfile2(file, TRUE, - b->scratch_pool), - b->scratch_pool); + b->rep_stream = svn_stream_from_aprfile2(file, TRUE, b->scratch_pool); + if (svn_fs_fs__use_log_addressing(fs)) + b->rep_stream = fnv1a_wrap_stream(&b->fnv1a_checksum_ctx, b->rep_stream, + b->scratch_pool); - SVN_ERR(svn_fs_fs__get_file_offset(&b->rep_offset, file, b->scratch_pool)); + SVN_ERR(svn_io_file_get_offset(&b->rep_offset, file, b->scratch_pool)); /* Get the base for this delta. */ SVN_ERR(choose_delta_base(&base_rep, fs, noderev, FALSE, b->scratch_pool)); @@ -2099,20 +2251,15 @@ rep_write_get_baton(struct rep_write_baton **wb_p, b->scratch_pool)); /* Now determine the offset of the actual svndiff data. */ - SVN_ERR(svn_fs_fs__get_file_offset(&b->delta_start, file, - b->scratch_pool)); + SVN_ERR(svn_io_file_get_offset(&b->delta_start, file, + b->scratch_pool)); /* Cleanup in case something goes wrong. */ apr_pool_cleanup_register(b->scratch_pool, b, rep_write_cleanup, apr_pool_cleanup_null); /* Prepare to write the svndiff data. */ - svn_txdelta_to_svndiff3(&wh, - &whb, - b->rep_stream, - diff_version, - ffd->delta_compression_level, - pool); + txdelta_to_svndiff(&wh, &whb, b->rep_stream, fs, pool); b->delta_stream = svn_txdelta_target_push(wh, whb, source, b->scratch_pool); @@ -2123,7 +2270,7 @@ rep_write_get_baton(struct rep_write_baton **wb_p, } /* For REP->SHA1_CHECKSUM, try to find an already existing representation - in FS and return it in *OUT_REP. If no such representation exists or + in FS and return it in *OLD_REP. If no such representation exists or if rep sharing has been disabled for FS, NULL will be returned. Since there may be new duplicate representations within the same uncommitted revision, those can be passed in REPS_HASH (maps a sha1 digest onto @@ -2158,9 +2305,13 @@ get_shared_rep(representation_t **old_rep, if (!ffd->rep_sharing_allowed) return SVN_NO_ERROR; + /* Can't look up if we don't know the key (happens for directories). */ + if (!rep->has_sha1) + return SVN_NO_ERROR; + /* Check and see if we already have a representation somewhere that's identical to the one we just wrote out. Start with the hash lookup - because it is cheepest. */ + because it is cheapest. */ if (reps_hash) *old_rep = apr_hash_get(reps_hash, rep->sha1_digest, @@ -2226,13 +2377,33 @@ get_shared_rep(representation_t **old_rep, if (!*old_rep) return SVN_NO_ERROR; - /* We don't want 0-length PLAIN representations to replace non-0-length - ones (see issue #4554). Take into account that EXPANDED_SIZE may be - 0 in which case we have to check the on-disk SIZE. Also, this doubles - as a simple guard against general rep-cache induced corruption. */ - if ( ((*old_rep)->expanded_size != rep->expanded_size) - || ((rep->expanded_size == 0) && ((*old_rep)->size != rep->size))) + /* A simple guard against general rep-cache induced corruption. */ + if ((*old_rep)->expanded_size != rep->expanded_size) { + /* Make the problem show up in the server log. + + Because not sharing reps is always a safe option, + terminating the request would be inappropriate. + */ + err = svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, + "Rep size %s mismatches rep-cache.db value %s " + "for SHA1 %s.\n" + "You should delete the rep-cache.db and " + "verify the repository. The cached rep will " + "not be shared.", + apr_psprintf(scratch_pool, + "%" SVN_FILESIZE_T_FMT, + rep->expanded_size), + apr_psprintf(scratch_pool, + "%" SVN_FILESIZE_T_FMT, + (*old_rep)->expanded_size), + svn_checksum_to_cstring_display(&checksum, + scratch_pool)); + + (fs->warning)(fs->warning_baton, err); + svn_error_clear(err); + + /* Ignore the shared rep. */ *old_rep = NULL; } else @@ -2268,7 +2439,7 @@ get_shared_rep(representation_t **old_rep, old_rep_norm.txn_id = rep->txn_id; /* Make sure we can later restore FILE's current position. */ - SVN_ERR(svn_fs_fs__get_file_offset(&old_position, file, scratch_pool)); + SVN_ERR(svn_io_file_get_offset(&old_position, file, scratch_pool)); /* Compare the two representations. * Note that the stream comparison might also produce MD5 checksum @@ -2298,7 +2469,7 @@ get_shared_rep(representation_t **old_rep, const char *checksum__str = svn_checksum_to_cstring_display(&checksum, scratch_pool); - return svn_error_createf(SVN_ERR_FS_GENERAL, + return svn_error_createf(SVN_ERR_FS_AMBIGUOUS_CHECKSUM_REP, err, "SHA1 of reps '%s' and '%s' " "matches (%s) but contents differ", old_rep_str->data, rep_str->data, @@ -2313,6 +2484,7 @@ get_shared_rep(representation_t **old_rep, } /* Copy the hash sum calculation results from MD5_CTX, SHA1_CTX into REP. + * SHA1 results are only be set if SHA1_CTX is not NULL. * Use POOL for allocations. */ static svn_error_t * @@ -2325,10 +2497,12 @@ digests_final(representation_t *rep, SVN_ERR(svn_checksum_final(&checksum, md5_ctx, pool)); memcpy(rep->md5_digest, checksum->digest, svn_checksum_size(checksum)); - SVN_ERR(svn_checksum_final(&checksum, sha1_ctx, pool)); - rep->has_sha1 = checksum != NULL; + rep->has_sha1 = sha1_ctx != NULL; if (rep->has_sha1) - memcpy(rep->sha1_digest, checksum->digest, svn_checksum_size(checksum)); + { + SVN_ERR(svn_checksum_final(&checksum, sha1_ctx, pool)); + memcpy(rep->sha1_digest, checksum->digest, svn_checksum_size(checksum)); + } return SVN_NO_ERROR; } @@ -2352,7 +2526,7 @@ rep_write_contents_close(void *baton) SVN_ERR(svn_stream_close(b->delta_stream)); /* Determine the length of the svndiff data. */ - SVN_ERR(svn_fs_fs__get_file_offset(&offset, b->file, b->scratch_pool)); + SVN_ERR(svn_io_file_get_offset(&offset, b->file, b->scratch_pool)); rep->size = offset - b->delta_start; /* Fill in the rest of the representation field. */ @@ -2394,12 +2568,12 @@ rep_write_contents_close(void *baton) /* Write out the new node-rev information. */ SVN_ERR(svn_fs_fs__put_node_revision(b->fs, b->noderev->id, b->noderev, FALSE, b->scratch_pool)); - if (!old_rep) + if (!old_rep && svn_fs_fs__use_log_addressing(b->fs)) { svn_fs_fs__p2l_entry_t entry; entry.offset = b->rep_offset; - SVN_ERR(svn_fs_fs__get_file_offset(&offset, b->file, b->scratch_pool)); + SVN_ERR(svn_io_file_get_offset(&offset, b->file, b->scratch_pool)); entry.size = offset - b->rep_offset; entry.type = SVN_FS_FS__ITEM_TYPE_FILE_REP; entry.item.revision = SVN_INVALID_REVNUM; @@ -2523,6 +2697,8 @@ svn_fs_fs__set_proplist(svn_fs_t *fs, { noderev->prop_rep = apr_pcalloc(pool, sizeof(*noderev->prop_rep)); noderev->prop_rep->txn_id = *svn_fs_fs__id_txn_id(noderev->id); + SVN_ERR(set_uniquifier(fs, noderev->prop_rep, pool)); + noderev->prop_rep->revision = SVN_INVALID_REVNUM; SVN_ERR(svn_fs_fs__put_node_revision(fs, noderev->id, noderev, FALSE, pool)); } @@ -2538,6 +2714,8 @@ struct write_container_baton apr_size_t size; svn_checksum_ctx_t *md5_ctx; + + /* SHA1 calculation is optional. If not needed, this will be NULL. */ svn_checksum_ctx_t *sha1_ctx; }; @@ -2552,7 +2730,8 @@ write_container_handler(void *baton, struct write_container_baton *whb = baton; SVN_ERR(svn_checksum_update(whb->md5_ctx, data, *len)); - SVN_ERR(svn_checksum_update(whb->sha1_ctx, data, *len)); + if (whb->sha1_ctx) + SVN_ERR(svn_checksum_update(whb->sha1_ctx, data, *len)); SVN_ERR(svn_stream_write(whb->stream, data, len)); whb->size += *len; @@ -2618,19 +2797,21 @@ write_container_rep(representation_t *rep, struct write_container_baton *whb; svn_checksum_ctx_t *fnv1a_checksum_ctx; apr_off_t offset = 0; - svn_fs_fs__p2l_entry_t entry; - SVN_ERR(svn_fs_fs__get_file_offset(&offset, file, scratch_pool)); + SVN_ERR(svn_io_file_get_offset(&offset, file, scratch_pool)); whb = apr_pcalloc(scratch_pool, sizeof(*whb)); - whb->stream = fnv1a_wrap_stream(&fnv1a_checksum_ctx, - svn_stream_from_aprfile2(file, TRUE, - scratch_pool), - scratch_pool); + whb->stream = svn_stream_from_aprfile2(file, TRUE, scratch_pool); + if (svn_fs_fs__use_log_addressing(fs)) + whb->stream = fnv1a_wrap_stream(&fnv1a_checksum_ctx, whb->stream, + scratch_pool); + else + fnv1a_checksum_ctx = NULL; whb->size = 0; whb->md5_ctx = svn_checksum_ctx_create(svn_checksum_md5, scratch_pool); - whb->sha1_ctx = svn_checksum_ctx_create(svn_checksum_sha1, scratch_pool); + if (item_type != SVN_FS_FS__ITEM_TYPE_DIR_REP) + whb->sha1_ctx = svn_checksum_ctx_create(svn_checksum_sha1, scratch_pool); stream = svn_stream_create(whb, scratch_pool); svn_stream_set_write(stream, write_container_handler); @@ -2671,17 +2852,22 @@ write_container_rep(representation_t *rep, SVN_ERR(allocate_item_index(&rep->item_index, fs, &rep->txn_id, offset, scratch_pool)); - entry.offset = offset; - SVN_ERR(svn_fs_fs__get_file_offset(&offset, file, scratch_pool)); - entry.size = offset - entry.offset; - entry.type = item_type; - entry.item.revision = SVN_INVALID_REVNUM; - entry.item.number = rep->item_index; - SVN_ERR(fnv1a_checksum_finalize(&entry.fnv1_checksum, - fnv1a_checksum_ctx, - scratch_pool)); + if (svn_fs_fs__use_log_addressing(fs)) + { + svn_fs_fs__p2l_entry_t entry; - SVN_ERR(store_p2l_index_entry(fs, &rep->txn_id, &entry, scratch_pool)); + entry.offset = offset; + SVN_ERR(svn_io_file_get_offset(&offset, file, scratch_pool)); + entry.size = offset - entry.offset; + entry.type = item_type; + entry.item.revision = SVN_INVALID_REVNUM; + entry.item.number = rep->item_index; + SVN_ERR(fnv1a_checksum_finalize(&entry.fnv1_checksum, + fnv1a_checksum_ctx, + scratch_pool)); + + SVN_ERR(store_p2l_index_entry(fs, &rep->txn_id, &entry, scratch_pool)); + } return SVN_NO_ERROR; } @@ -2723,15 +2909,12 @@ write_container_delta_rep(representation_t *rep, svn_checksum_ctx_t *fnv1a_checksum_ctx; svn_stream_t *source; svn_fs_fs__rep_header_t header = { 0 }; - svn_fs_fs__p2l_entry_t entry; apr_off_t rep_end = 0; apr_off_t delta_start = 0; apr_off_t offset = 0; struct write_container_baton *whb; - fs_fs_data_t *ffd = fs->fsap_data; - int diff_version = ffd->format >= SVN_FS_FS__MIN_SVNDIFF1_FORMAT ? 1 : 0; svn_boolean_t is_props = (item_type == SVN_FS_FS__ITEM_TYPE_FILE_PROPS) || (item_type == SVN_FS_FS__ITEM_TYPE_DIR_PROPS); @@ -2739,7 +2922,7 @@ write_container_delta_rep(representation_t *rep, SVN_ERR(choose_delta_base(&base_rep, fs, noderev, is_props, scratch_pool)); SVN_ERR(svn_fs_fs__get_contents(&source, fs, base_rep, FALSE, scratch_pool)); - SVN_ERR(svn_fs_fs__get_file_offset(&offset, file, scratch_pool)); + SVN_ERR(svn_io_file_get_offset(&offset, file, scratch_pool)); /* Write out the rep header. */ if (base_rep) @@ -2754,27 +2937,25 @@ write_container_delta_rep(representation_t *rep, header.type = svn_fs_fs__rep_self_delta; } - file_stream = fnv1a_wrap_stream(&fnv1a_checksum_ctx, - svn_stream_from_aprfile2(file, TRUE, - scratch_pool), - scratch_pool); + file_stream = svn_stream_from_aprfile2(file, TRUE, scratch_pool); + if (svn_fs_fs__use_log_addressing(fs)) + file_stream = fnv1a_wrap_stream(&fnv1a_checksum_ctx, file_stream, + scratch_pool); + else + fnv1a_checksum_ctx = NULL; SVN_ERR(svn_fs_fs__write_rep_header(&header, file_stream, scratch_pool)); - SVN_ERR(svn_fs_fs__get_file_offset(&delta_start, file, scratch_pool)); + SVN_ERR(svn_io_file_get_offset(&delta_start, file, scratch_pool)); /* Prepare to write the svndiff data. */ - svn_txdelta_to_svndiff3(&diff_wh, - &diff_whb, - file_stream, - diff_version, - ffd->delta_compression_level, - scratch_pool); + txdelta_to_svndiff(&diff_wh, &diff_whb, file_stream, fs, scratch_pool); whb = apr_pcalloc(scratch_pool, sizeof(*whb)); whb->stream = svn_txdelta_target_push(diff_wh, diff_whb, source, scratch_pool); whb->size = 0; whb->md5_ctx = svn_checksum_ctx_create(svn_checksum_md5, scratch_pool); - whb->sha1_ctx = svn_checksum_ctx_create(svn_checksum_sha1, scratch_pool); + if (item_type != SVN_FS_FS__ITEM_TYPE_DIR_REP) + whb->sha1_ctx = svn_checksum_ctx_create(svn_checksum_sha1, scratch_pool); /* serialize the hash */ stream = svn_stream_create(whb, scratch_pool); @@ -2787,7 +2968,7 @@ write_container_delta_rep(representation_t *rep, SVN_ERR(digests_final(rep, whb->md5_ctx, whb->sha1_ctx, scratch_pool)); /* Update size info. */ - SVN_ERR(svn_fs_fs__get_file_offset(&rep_end, file, scratch_pool)); + SVN_ERR(svn_io_file_get_offset(&rep_end, file, scratch_pool)); rep->size = rep_end - delta_start; rep->expanded_size = whb->size; @@ -2816,17 +2997,22 @@ write_container_delta_rep(representation_t *rep, SVN_ERR(allocate_item_index(&rep->item_index, fs, &rep->txn_id, offset, scratch_pool)); - entry.offset = offset; - SVN_ERR(svn_fs_fs__get_file_offset(&offset, file, scratch_pool)); - entry.size = offset - entry.offset; - entry.type = item_type; - entry.item.revision = SVN_INVALID_REVNUM; - entry.item.number = rep->item_index; - SVN_ERR(fnv1a_checksum_finalize(&entry.fnv1_checksum, - fnv1a_checksum_ctx, - scratch_pool)); + if (svn_fs_fs__use_log_addressing(fs)) + { + svn_fs_fs__p2l_entry_t entry; - SVN_ERR(store_p2l_index_entry(fs, &rep->txn_id, &entry, scratch_pool)); + entry.offset = offset; + SVN_ERR(svn_io_file_get_offset(&offset, file, scratch_pool)); + entry.size = offset - entry.offset; + entry.type = item_type; + entry.item.revision = SVN_INVALID_REVNUM; + entry.item.number = rep->item_index; + SVN_ERR(fnv1a_checksum_finalize(&entry.fnv1_checksum, + fnv1a_checksum_ctx, + scratch_pool)); + + SVN_ERR(store_p2l_index_entry(fs, &rep->txn_id, &entry, scratch_pool)); + } return SVN_NO_ERROR; } @@ -2870,13 +3056,12 @@ validate_root_noderev(svn_fs_t *fs, Normally (rev == root_noderev->predecessor_count), but here we use a more roundabout check that should only trigger on new instances - of the corruption, rather then trigger on each and every new commit + of the corruption, rather than trigger on each and every new commit to a repository that has triggered the bug somewhere in its root noderev's history. */ - if (root_noderev->predecessor_count != -1 - && (root_noderev->predecessor_count - head_predecessor_count) - != (rev - head_revnum)) + if ( (root_noderev->predecessor_count - head_predecessor_count) + != (rev - head_revnum)) { return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, _("predecessor count for " @@ -2929,6 +3114,9 @@ get_final_id(svn_fs_fs__id_part_t *part, INITIAL_OFFSET is the offset of the proto-rev-file on entry to commit_body. + Collect the pair_cache_key_t of all directories written to the + committed cache in DIRECTORY_IDS. + If REPS_TO_CACHE is not NULL, append to it a copy (allocated in REPS_POOL) of each data rep that is new in this revision. @@ -2950,6 +3138,7 @@ write_final_rev(const svn_fs_id_t **new_id_p, apr_uint64_t start_node_id, apr_uint64_t start_copy_id, apr_off_t initial_offset, + apr_array_header_t *directory_ids, apr_array_header_t *reps_to_cache, apr_hash_t *reps_hash, apr_pool_t *reps_pool, @@ -2992,14 +3181,17 @@ write_final_rev(const svn_fs_id_t **new_id_p, svn_pool_clear(subpool); SVN_ERR(write_final_rev(&new_id, file, rev, fs, dirent->id, start_node_id, start_copy_id, initial_offset, - reps_to_cache, reps_hash, reps_pool, FALSE, - subpool)); + directory_ids, reps_to_cache, reps_hash, + reps_pool, FALSE, subpool)); if (new_id && (svn_fs_fs__id_rev(new_id) == rev)) dirent->id = svn_fs_fs__id_copy(new_id, pool); } if (noderev->data_rep && is_txn_rep(noderev->data_rep)) { + pair_cache_key_t *key; + svn_fs_fs__dir_data_t dir_data; + /* Write out the contents of this directory as a text rep. */ noderev->data_rep->revision = rev; if (ffd->deltify_directories) @@ -3016,6 +3208,23 @@ write_final_rev(const svn_fs_id_t **new_id_p, pool)); reset_txn_in_rep(noderev->data_rep); + + /* Cache the new directory contents. Otherwise, subsequent reads + * or commits will likely have to reconstruct, verify and parse + * it again. */ + key = apr_array_push(directory_ids); + key->revision = noderev->data_rep->revision; + key->second = noderev->data_rep->item_index; + + /* Store directory contents under the new revision number but mark + * it as "stale" by setting the file length to 0. Committed dirs + * will report -1, in-txn dirs will report > 0, so that this can + * never match. We reset that to -1 after the commit is complete. + */ + dir_data.entries = entries; + dir_data.txn_filesize = 0; + + SVN_ERR(svn_cache__set(ffd->dir_cache, key, &dir_data, subpool)); } } else @@ -3052,7 +3261,8 @@ write_final_rev(const svn_fs_id_t **new_id_p, ? SVN_FS_FS__ITEM_TYPE_DIR_PROPS : SVN_FS_FS__ITEM_TYPE_FILE_PROPS; SVN_ERR(svn_fs_fs__get_proplist(&proplist, fs, noderev, pool)); - + noderev->prop_rep->txn_id = *txn_id; + SVN_ERR(set_uniquifier(fs, noderev->prop_rep, pool)); noderev->prop_rep->revision = rev; if (ffd->deltify_properties) @@ -3077,7 +3287,7 @@ write_final_rev(const svn_fs_id_t **new_id_p, noderev->copyroot_rev = rev; /* root nodes have a fixed ID in log addressing mode */ - SVN_ERR(svn_fs_fs__get_file_offset(&my_offset, file, pool)); + SVN_ERR(svn_io_file_get_offset(&my_offset, file, pool)); if (svn_fs_fs__use_log_addressing(fs) && at_root) { /* reference the root noderev from the log-to-phys index */ @@ -3121,13 +3331,28 @@ write_final_rev(const svn_fs_id_t **new_id_p, } } - /* don't serialize SHA1 for dirs to disk (waste of space) */ + /* don't serialize SHA1 for dir content to disk (waste of space) */ + /* ### Could clients record bogus last-changed-revisions (issue #4700)? */ if (noderev->data_rep && noderev->kind == svn_node_dir) noderev->data_rep->has_sha1 = FALSE; - /* don't serialize SHA1 for props to disk (waste of space) */ - if (noderev->prop_rep) - noderev->prop_rep->has_sha1 = FALSE; + /* Compatibility: while we don't need to serialize SHA1 for props (it is + not used), older formats can only have representation strings that either + have both the SHA1 value *and* the uniquifier, or don't have them at all. + For such formats, both values get written to the disk only if the SHA1 + is present. + + We cannot omit the uniquifier, as doing so breaks svn_fs_props_changed() + for properties with shared representations, see issues #4623 and #4700. + Therefore, we skip writing SHA1, but only for the newer formats where + this dependency is untied and we can write the uniquifier to the disk + without the SHA1. + */ + if (ffd->format >= SVN_FS_FS__MIN_REP_STRING_OPTIONAL_VALUES_FORMAT && + noderev->prop_rep) + { + noderev->prop_rep->has_sha1 = FALSE; + } /* Workaround issue #4031: is-fresh-txn-root in revision files. */ noderev->is_fresh_txn_root = FALSE; @@ -3136,9 +3361,12 @@ write_final_rev(const svn_fs_id_t **new_id_p, if (at_root) SVN_ERR(validate_root_noderev(fs, noderev, rev, pool)); - file_stream = fnv1a_wrap_stream(&fnv1a_checksum_ctx, - svn_stream_from_aprfile2(file, TRUE, pool), - pool); + file_stream = svn_stream_from_aprfile2(file, TRUE, pool); + if (svn_fs_fs__use_log_addressing(fs)) + file_stream = fnv1a_wrap_stream(&fnv1a_checksum_ctx, file_stream, pool); + else + fnv1a_checksum_ctx = NULL; + SVN_ERR(svn_fs_fs__write_noderev(file_stream, noderev, ffd->format, svn_fs_fs__fs_supports_mergeinfo(fs), pool)); @@ -3150,7 +3378,7 @@ write_final_rev(const svn_fs_id_t **new_id_p, rev_item.revision = SVN_INVALID_REVNUM; entry.offset = my_offset; - SVN_ERR(svn_fs_fs__get_file_offset(&my_offset, file, pool)); + SVN_ERR(svn_io_file_get_offset(&my_offset, file, pool)); entry.size = my_offset - entry.offset; entry.type = SVN_FS_FS__ITEM_TYPE_NODEREV; entry.item = rev_item; @@ -3183,12 +3411,15 @@ write_final_changed_path_info(apr_off_t *offset_p, svn_stream_t *stream; svn_checksum_ctx_t *fnv1a_checksum_ctx; - SVN_ERR(svn_fs_fs__get_file_offset(&offset, file, pool)); + SVN_ERR(svn_io_file_get_offset(&offset, file, pool)); + + /* write to target file & calculate checksum if needed */ + stream = svn_stream_from_aprfile2(file, TRUE, pool); + if (svn_fs_fs__use_log_addressing(fs)) + stream = fnv1a_wrap_stream(&fnv1a_checksum_ctx, stream, pool); + else + fnv1a_checksum_ctx = NULL; - /* write to target file & calculate checksum */ - stream = fnv1a_wrap_stream(&fnv1a_checksum_ctx, - svn_stream_from_aprfile2(file, TRUE, pool), - pool); SVN_ERR(svn_fs_fs__write_changes(stream, fs, changed_paths, TRUE, pool)); *offset_p = offset; @@ -3199,7 +3430,7 @@ write_final_changed_path_info(apr_off_t *offset_p, svn_fs_fs__p2l_entry_t entry; entry.offset = offset; - SVN_ERR(svn_fs_fs__get_file_offset(&offset, file, pool)); + SVN_ERR(svn_io_file_get_offset(&offset, file, pool)); entry.size = offset - entry.offset; entry.type = SVN_FS_FS__ITEM_TYPE_CHANGES; entry.item.revision = SVN_INVALID_REVNUM; @@ -3223,11 +3454,10 @@ write_final_changed_path_info(apr_off_t *offset_p, Intended to be called as the very last step in a commit before 'current' is bumped. This implies that we are holding the write lock. */ static svn_error_t * -verify_as_revision_before_current_plus_plus(svn_fs_t *fs, - svn_revnum_t new_rev, - apr_pool_t *pool) +verify_before_commit(svn_fs_t *fs, + svn_revnum_t new_rev, + apr_pool_t *pool) { -#ifdef SVN_DEBUG fs_fs_data_t *ffd = fs->fsap_data; svn_fs_t *ft; /* fs++ == ft */ svn_fs_root_t *root; @@ -3257,7 +3487,6 @@ verify_as_revision_before_current_plus_plus(svn_fs_t *fs, SVN_ERR_ASSERT(root->is_txn_root == FALSE && root->rev == new_rev); SVN_ERR_ASSERT(ft_ffd->youngest_rev_cache == new_rev); SVN_ERR(svn_fs_fs__verify_root(root, pool)); -#endif /* SVN_DEBUG */ return SVN_NO_ERROR; } @@ -3363,41 +3592,32 @@ verify_locks(svn_fs_t *fs, return SVN_NO_ERROR; } -/* Return in *PATH the path to a file containing the properties that - make up the final revision properties file. This involves setting - svn:date and removing any temporary properties associated with the - commit flags. */ +/* Writes final revision properties to file PATH applying permissions + from file PERMS_REFERENCE. This involves setting svn:date and + removing any temporary properties associated with the commit flags. */ static svn_error_t * -write_final_revprop(const char **path, +write_final_revprop(const char *path, + const char *perms_reference, svn_fs_txn_t *txn, - const svn_fs_fs__id_part_t *txn_id, + svn_boolean_t flush_to_disk, apr_pool_t *pool) { apr_hash_t *txnprops; - svn_boolean_t final_mods = FALSE; svn_string_t date; svn_string_t *client_date; + apr_file_t *revprop_file; + svn_stream_t *stream; SVN_ERR(svn_fs_fs__txn_proplist(&txnprops, txn, pool)); /* Remove any temporary txn props representing 'flags'. */ - if (svn_hash_gets(txnprops, SVN_FS__PROP_TXN_CHECK_OOD)) - { - svn_hash_sets(txnprops, SVN_FS__PROP_TXN_CHECK_OOD, NULL); - final_mods = TRUE; - } - - if (svn_hash_gets(txnprops, SVN_FS__PROP_TXN_CHECK_LOCKS)) - { - svn_hash_sets(txnprops, SVN_FS__PROP_TXN_CHECK_LOCKS, NULL); - final_mods = TRUE; - } + svn_hash_sets(txnprops, SVN_FS__PROP_TXN_CHECK_OOD, NULL); + svn_hash_sets(txnprops, SVN_FS__PROP_TXN_CHECK_LOCKS, NULL); client_date = svn_hash_gets(txnprops, SVN_FS__PROP_TXN_CLIENT_DATE); if (client_date) { svn_hash_sets(txnprops, SVN_FS__PROP_TXN_CLIENT_DATE, NULL); - final_mods = TRUE; } /* Update commit time to ensure that svn:date revprops remain ordered if @@ -3407,18 +3627,23 @@ write_final_revprop(const char **path, date.data = svn_time_to_cstring(apr_time_now(), pool); date.len = strlen(date.data); svn_hash_sets(txnprops, SVN_PROP_REVISION_DATE, &date); - final_mods = TRUE; } - if (final_mods) - { - SVN_ERR(set_txn_proplist(txn->fs, txn_id, txnprops, TRUE, pool)); - *path = path_txn_props_final(txn->fs, txn_id, pool); - } - else - { - *path = path_txn_props(txn->fs, txn_id, pool); - } + /* Create new revprops file. Tell OS to truncate existing file, + since file may already exists from failed transaction. */ + SVN_ERR(svn_io_file_open(&revprop_file, path, + APR_WRITE | APR_CREATE | APR_TRUNCATE + | APR_BUFFERED, APR_OS_DEFAULT, pool)); + + stream = svn_stream_from_aprfile2(revprop_file, TRUE, pool); + SVN_ERR(svn_hash_write2(txnprops, stream, SVN_HASH_TERMINATOR, pool)); + SVN_ERR(svn_stream_close(stream)); + + if (flush_to_disk) + SVN_ERR(svn_io_file_flush_to_disk(revprop_file, pool)); + SVN_ERR(svn_io_file_close(revprop_file, pool)); + + SVN_ERR(svn_io_copy_perms(perms_reference, path, pool)); return SVN_NO_ERROR; } @@ -3464,6 +3689,41 @@ svn_fs_fs__add_index_data(svn_fs_t *fs, return SVN_NO_ERROR; } +/* Mark the directories cached in FS with the keys from DIRECTORY_IDS + * as "valid" now. Use SCRATCH_POOL for temporaries. */ +static svn_error_t * +promote_cached_directories(svn_fs_t *fs, + apr_array_header_t *directory_ids, + apr_pool_t *scratch_pool) +{ + fs_fs_data_t *ffd = fs->fsap_data; + apr_pool_t *iterpool; + int i; + + if (!ffd->dir_cache) + return SVN_NO_ERROR; + + iterpool = svn_pool_create(scratch_pool); + for (i = 0; i < directory_ids->nelts; ++i) + { + const pair_cache_key_t *key + = &APR_ARRAY_IDX(directory_ids, i, pair_cache_key_t); + + svn_pool_clear(iterpool); + + /* Currently, the entry for KEY - if it still exists - is marked + * as "stale" and would not be used. Mark it as current for in- + * revison data. */ + SVN_ERR(svn_cache__set_partial(ffd->dir_cache, key, + svn_fs_fs__reset_txn_filesize, NULL, + iterpool)); + } + + svn_pool_destroy(iterpool); + + return SVN_NO_ERROR; +} + /* Baton used for commit_body below. */ struct commit_baton { svn_revnum_t *new_rev_p; @@ -3483,7 +3743,7 @@ commit_body(void *baton, apr_pool_t *pool) struct commit_baton *cb = baton; fs_fs_data_t *ffd = cb->fs->fsap_data; const char *old_rev_filename, *rev_filename, *proto_filename; - const char *revprop_filename, *final_revprop; + const char *revprop_filename; const svn_fs_id_t *root_id, *new_root_id; apr_uint64_t start_node_id; apr_uint64_t start_copy_id; @@ -3493,6 +3753,8 @@ commit_body(void *baton, apr_pool_t *pool) apr_off_t initial_offset, changed_path_offset; const svn_fs_fs__id_part_t *txn_id = svn_fs_fs__txn_get_id(cb->txn); apr_hash_t *changed_paths; + apr_array_header_t *directory_ids = apr_array_make(pool, 4, + sizeof(pair_cache_key_t)); /* Re-Read the current repository format. All our repo upgrade and config evaluation strategies are such that existing information in @@ -3540,14 +3802,14 @@ commit_body(void *baton, apr_pool_t *pool) /* Get a write handle on the proto revision file. */ SVN_ERR(get_writable_proto_rev(&proto_file, &proto_file_lockcookie, cb->fs, txn_id, pool)); - SVN_ERR(svn_fs_fs__get_file_offset(&initial_offset, proto_file, pool)); + SVN_ERR(svn_io_file_get_offset(&initial_offset, proto_file, pool)); /* Write out all the node-revisions and directory contents. */ root_id = svn_fs_fs__id_txn_create_root(txn_id, pool); SVN_ERR(write_final_rev(&new_root_id, proto_file, new_rev, cb->fs, root_id, start_node_id, start_copy_id, initial_offset, - cb->reps_to_cache, cb->reps_hash, cb->reps_pool, - TRUE, pool)); + directory_ids, cb->reps_to_cache, cb->reps_hash, + cb->reps_pool, TRUE, pool)); /* Write the changed-path information. */ SVN_ERR(write_final_changed_path_info(&changed_path_offset, proto_file, @@ -3575,7 +3837,8 @@ commit_body(void *baton, apr_pool_t *pool) NULL, pool)); } - SVN_ERR(svn_io_file_flush_to_disk(proto_file, pool)); + if (ffd->flush_to_disk) + SVN_ERR(svn_io_file_flush_to_disk(proto_file, pool)); SVN_ERR(svn_io_file_close(proto_file, pool)); /* We don't unlock the prototype revision file immediately to avoid a @@ -3628,7 +3891,8 @@ commit_body(void *baton, apr_pool_t *pool) rev_filename = svn_fs_fs__path_rev(cb->fs, new_rev, pool); proto_filename = svn_fs_fs__path_txn_proto_rev(cb->fs, txn_id, pool); SVN_ERR(svn_fs_fs__move_into_place(proto_filename, rev_filename, - old_rev_filename, pool)); + old_rev_filename, ffd->flush_to_disk, + pool)); /* Now that we've moved the prototype revision file out of the way, we can unlock it (since further attempts to write to the file @@ -3636,15 +3900,19 @@ commit_body(void *baton, apr_pool_t *pool) remove the transaction directory later. */ SVN_ERR(unlock_proto_rev(cb->fs, txn_id, proto_file_lockcookie, pool)); - /* Move the revprops file into place. */ + /* Write final revprops file. */ SVN_ERR_ASSERT(! svn_fs_fs__is_packed_revprop(cb->fs, new_rev)); - SVN_ERR(write_final_revprop(&revprop_filename, cb->txn, txn_id, pool)); - final_revprop = svn_fs_fs__path_revprops(cb->fs, new_rev, pool); - SVN_ERR(svn_fs_fs__move_into_place(revprop_filename, final_revprop, - old_rev_filename, pool)); + revprop_filename = svn_fs_fs__path_revprops(cb->fs, new_rev, pool); + SVN_ERR(write_final_revprop(revprop_filename, old_rev_filename, + cb->txn, ffd->flush_to_disk, pool)); + + /* Run paranoia checks. */ + if (ffd->verify_before_commit) + { + SVN_ERR(verify_before_commit(cb->fs, new_rev, pool)); + } /* Update the 'current' file. */ - SVN_ERR(verify_as_revision_before_current_plus_plus(cb->fs, new_rev, pool)); SVN_ERR(write_final_current(cb->fs, txn_id, new_rev, start_node_id, start_copy_id, pool)); @@ -3657,6 +3925,10 @@ commit_body(void *baton, apr_pool_t *pool) ffd->youngest_rev_cache = new_rev; + /* Make the directory contents alreday cached for the new revision + * visible. */ + SVN_ERR(promote_cached_directories(cb->fs, directory_ids, pool)); + /* Remove this transaction directory. */ SVN_ERR(svn_fs_fs__purge_txn(cb->fs, cb->txn->id, pool)); @@ -3731,7 +4003,7 @@ svn_fs_fs__commit(svn_revnum_t *new_rev_p, err = write_reps_to_cache(fs, cb.reps_to_cache, pool); err = svn_sqlite__finish_transaction(ffd->rep_cache_db, err); - if (svn_error_find_cause(err, SVN_SQLITE__ERR_ROLLBACK_FAILED)) + if (svn_error_find_cause(err, SVN_ERR_SQLITE_ROLLBACK_FAILED)) { /* Failed rollback means that our db connection is unusable, and the only thing we can do is close it. The connection will be @@ -3959,6 +4231,5 @@ svn_fs_fs__begin_txn(svn_fs_txn_t **txn_p, svn_string_create("0", pool)); ftd = (*txn_p)->fsap_data; - return svn_error_trace(set_txn_proplist(fs, &ftd->txn_id, props, FALSE, - pool)); + return svn_error_trace(set_txn_proplist(fs, &ftd->txn_id, props, pool)); } diff --git a/subversion/libsvn_fs_fs/tree.c b/subversion/libsvn_fs_fs/tree.c index 5893da22b0cb..76209f368bf9 100644 --- a/subversion/libsvn_fs_fs/tree.c +++ b/subversion/libsvn_fs_fs/tree.c @@ -209,17 +209,15 @@ auto_clear_dag_cache(fs_fs_dag_cache_t* cache) } } -/* For the given REVISION and PATH, return the respective entry in CACHE. - If the entry is empty, its NODE member will be NULL and the caller - may then set it to the corresponding DAG node allocated in CACHE->POOL. +/* Returns a 32 bit hash value for the given REVISION and PATH of exactly + * PATH_LEN chars. */ -static cache_entry_t * -cache_lookup( fs_fs_dag_cache_t *cache - , svn_revnum_t revision - , const char *path) +static apr_uint32_t +hash_func(svn_revnum_t revision, + const char *path, + apr_size_t path_len) { - apr_size_t i, bucket_index; - apr_size_t path_len = strlen(path); + apr_size_t i; apr_uint32_t hash_value = (apr_uint32_t)revision; #if SVN_UNALIGNED_ACCESS_IS_OK @@ -227,20 +225,7 @@ cache_lookup( fs_fs_dag_cache_t *cache const apr_uint32_t factor = 0xd1f3da69; #endif - /* optimistic lookup: hit the same bucket again? */ - cache_entry_t *result = &cache->buckets[cache->last_hit]; - if ( (result->revision == revision) - && (result->path_len == path_len) - && !memcmp(result->path, path, path_len)) - { - /* Remember the position of the last node we found in this cache. */ - if (result->node) - cache->last_non_empty = cache->last_hit; - - return result; - } - - /* need to do a full lookup. Calculate the hash value + /* Calculate the hash value (HASH_VALUE has been initialized to REVISION). Note that the actual hash function is arbitrary as long as its result @@ -283,6 +268,37 @@ cache_lookup( fs_fs_dag_cache_t *cache */ hash_value = hash_value * 32 + (hash_value + (unsigned char)path[i]); + return hash_value; +} + +/* For the given REVISION and PATH, return the respective node found in + * CACHE. If there is none, return NULL. + */ +static dag_node_t * +cache_lookup( fs_fs_dag_cache_t *cache + , svn_revnum_t revision + , const char *path) +{ + apr_size_t bucket_index; + apr_size_t path_len = strlen(path); + apr_uint32_t hash_value; + + /* optimistic lookup: hit the same bucket again? */ + cache_entry_t *result = &cache->buckets[cache->last_hit]; + if ( (result->revision == revision) + && (result->path_len == path_len) + && !memcmp(result->path, path, path_len)) + { + /* Remember the position of the last node we found in this cache. */ + if (result->node) + cache->last_non_empty = cache->last_hit; + + return result->node; + } + + /* need to do a full lookup. */ + hash_value = hash_func(revision, path, path_len); + bucket_index = hash_value + (hash_value >> 16); bucket_index = (bucket_index + (bucket_index >> 8)) % BUCKET_COUNT; @@ -297,16 +313,7 @@ cache_lookup( fs_fs_dag_cache_t *cache || (result->path_len != path_len) || memcmp(result->path, path, path_len)) { - result->hash_value = hash_value; - result->revision = revision; - if (result->path_len < path_len) - result->path = apr_palloc(cache->pool, path_len + 1); - result->path_len = path_len; - memcpy(result->path, path, path_len + 1); - - result->node = NULL; - - cache->insertions++; + return NULL; } else if (result->node) { @@ -315,7 +322,46 @@ cache_lookup( fs_fs_dag_cache_t *cache cache->last_non_empty = bucket_index; } - return result; + return result->node; +} + +/* Store a copy of NODE in CACHE, taking REVISION and PATH as key. + * This function will clean the cache at regular intervals. + */ +static void +cache_insert(fs_fs_dag_cache_t *cache, + svn_revnum_t revision, + const char *path, + dag_node_t *node) +{ + apr_size_t bucket_index; + apr_size_t path_len = strlen(path); + apr_uint32_t hash_value; + cache_entry_t *entry; + + auto_clear_dag_cache(cache); + + /* calculate the bucket index to use */ + hash_value = hash_func(revision, path, path_len); + + bucket_index = hash_value + (hash_value >> 16); + bucket_index = (bucket_index + (bucket_index >> 8)) % BUCKET_COUNT; + + /* access the corresponding bucket and remember its location */ + entry = &cache->buckets[bucket_index]; + cache->last_hit = bucket_index; + + /* if it is *NOT* a match, clear the bucket, expect the caller to fill + in the node and count it as an insertion */ + entry->hash_value = hash_value; + entry->revision = revision; + if (entry->path_len < path_len) + entry->path = apr_palloc(cache->pool, path_len + 1); + entry->path_len = path_len; + memcpy(entry->path, path, path_len + 1); + + entry->node = svn_fs_fs__dag_dup(node, cache->pool); + cache->insertions++; } /* Optimistic lookup using the last seen non-empty location in CACHE. @@ -393,11 +439,9 @@ dag_node_cache_get(dag_node_t **node_p, /* immutable DAG node. use the global caches for it */ fs_fs_data_t *ffd = root->fs->fsap_data; - cache_entry_t *bucket; - auto_clear_dag_cache(ffd->dag_node_cache); - bucket = cache_lookup(ffd->dag_node_cache, root->rev, path); - if (bucket->node == NULL) + node = cache_lookup(ffd->dag_node_cache, root->rev, path); + if (node == NULL) { locate_cache(&cache, &key, root, path, pool); SVN_ERR(svn_cache__get((void **)&node, &found, cache, key, pool)); @@ -408,14 +452,13 @@ dag_node_cache_get(dag_node_t **node_p, svn_fs_fs__dag_set_fs(node, root->fs); /* Retain the DAG node in L1 cache. */ - bucket->node = svn_fs_fs__dag_dup(node, - ffd->dag_node_cache->pool); + cache_insert(ffd->dag_node_cache, root->rev, path, node); } } else { /* Copy the node from L1 cache into the passed-in POOL. */ - node = svn_fs_fs__dag_dup(bucket->node, pool); + node = svn_fs_fs__dag_dup(node, pool); } } else @@ -1100,8 +1143,28 @@ open_path(parent_path_t **parent_path_p, /* The path isn't finished yet; we'd better be in a directory. */ if (svn_fs_fs__dag_node_kind(child) != svn_node_dir) - SVN_ERR_W(SVN_FS__ERR_NOT_DIRECTORY(fs, path_so_far->data), - apr_psprintf(iterpool, _("Failure opening '%s'"), path)); + { + const char *msg; + + /* Since this is not a directory and we are looking for some + sub-path, that sub-path will not exist. That will be o.k., + if we are just here to check for the path's existence. */ + if (flags & open_path_allow_null) + { + parent_path = NULL; + break; + } + + /* It's really a problem ... */ + msg = root->is_txn_root + ? apr_psprintf(iterpool, + _("Failure opening '%s' in transaction '%s'"), + path, root->txn) + : apr_psprintf(iterpool, + _("Failure opening '%s' in revision %ld"), + path, root->rev); + SVN_ERR_W(SVN_FS__ERR_NOT_DIRECTORY(fs, path_so_far->data), msg); + } rest = next; here = child; @@ -1232,11 +1295,15 @@ get_dag(dag_node_t **dag_node_p, { /* Canonicalize the input PATH. As it turns out, >95% of all paths * seen here during e.g. svnadmin verify are non-canonical, i.e. - * miss the leading '/'. Unconditional canonicalization has a net - * performance benefit over previously checking path for being - * canonical. */ - path = svn_fs__canonicalize_abspath(path, pool); - SVN_ERR(dag_node_cache_get(&node, root, path, pool)); + * miss the leading '/'. Check for those quickly. + * + * For normalized paths, it is much faster to check the path than + * to attempt a second cache lookup (which would fail). */ + if (*path != '/' || !svn_fs__is_canonical_abspath(path)) + { + path = svn_fs__canonicalize_abspath(path, pool); + SVN_ERR(dag_node_cache_get(&node, root, path, pool)); + } if (! node) { @@ -1382,7 +1449,7 @@ fs_node_relation(svn_fs_node_relation_t *relation, /* Noderevs have the same node-ID now. So, they *seem* to be related. * * Special case: Different txns may create the same (txn-local) node ID. - * Only when they are committed can they actually be related to others. */ + * These are not related to each other, nor to any other node ID so far. */ if (different_txn && node_id_a.revision == SVN_INVALID_REVNUM) { *relation = svn_fs_node_unrelated; @@ -1427,29 +1494,6 @@ fs_node_created_path(const char **created_path, return SVN_NO_ERROR; } - -/* Set *KIND_P to the type of node located at PATH under ROOT. - Perform temporary allocations in POOL. */ -static svn_error_t * -node_kind(svn_node_kind_t *kind_p, - svn_fs_root_t *root, - const char *path, - apr_pool_t *pool) -{ - const svn_fs_id_t *node_id; - dag_node_t *node; - - /* Get the node id. */ - SVN_ERR(svn_fs_fs__node_id(&node_id, root, path, pool)); - - /* Use the node id to get the real kind. */ - SVN_ERR(svn_fs_fs__dag_get_node(&node, root->fs, node_id, pool)); - *kind_p = svn_fs_fs__dag_node_kind(node); - - return SVN_NO_ERROR; -} - - /* Set *KIND_P to the type of node present at PATH under ROOT. If PATH does not exist under ROOT, set *KIND_P to svn_node_none. Use POOL for temporary allocation. */ @@ -1459,17 +1503,23 @@ svn_fs_fs__check_path(svn_node_kind_t *kind_p, const char *path, apr_pool_t *pool) { - svn_error_t *err = node_kind(kind_p, root, path, pool); + dag_node_t *node; + svn_error_t *err; + + err = get_dag(&node, root, path, pool); if (err && ((err->apr_err == SVN_ERR_FS_NOT_FOUND) || (err->apr_err == SVN_ERR_FS_NOT_DIRECTORY))) { svn_error_clear(err); - err = SVN_NO_ERROR; *kind_p = svn_node_none; + return SVN_NO_ERROR; } + else if (err) + return svn_error_trace(err); - return svn_error_trace(err); + *kind_p = svn_fs_fs__dag_node_kind(node); + return SVN_NO_ERROR; } /* Set *VALUE_P to the value of the property named PROPNAME of PATH in @@ -3188,23 +3238,18 @@ fs_contents_changed(svn_boolean_t *changed_p, (SVN_ERR_FS_GENERAL, NULL, _("Cannot compare file contents between two different filesystems")); - /* Check that both paths are files. */ - { - svn_node_kind_t kind; - - SVN_ERR(svn_fs_fs__check_path(&kind, root1, path1, pool)); - if (kind != svn_node_file) - return svn_error_createf - (SVN_ERR_FS_GENERAL, NULL, _("'%s' is not a file"), path1); - - SVN_ERR(svn_fs_fs__check_path(&kind, root2, path2, pool)); - if (kind != svn_node_file) - return svn_error_createf - (SVN_ERR_FS_GENERAL, NULL, _("'%s' is not a file"), path2); - } - SVN_ERR(get_dag(&node1, root1, path1, pool)); + /* Make sure that path is file. */ + if (svn_fs_fs__dag_node_kind(node1) != svn_node_file) + return svn_error_createf + (SVN_ERR_FS_NOT_FILE, NULL, _("'%s' is not a file"), path1); + SVN_ERR(get_dag(&node2, root2, path2, pool)); + /* Make sure that path is file. */ + if (svn_fs_fs__dag_node_kind(node2) != svn_node_file) + return svn_error_createf + (SVN_ERR_FS_NOT_FILE, NULL, _("'%s' is not a file"), path2); + return svn_fs_fs__dag_things_different(NULL, changed_p, node1, node2, strict, pool); } @@ -3256,6 +3301,187 @@ fs_paths_changed(apr_hash_t **changed_paths_p, } +/* Copy the contents of ENTRY at PATH with LEN to OUTPUT. */ +static void +convert_path_change(svn_fs_path_change3_t *output, + const char *path, + size_t path_len, + svn_fs_path_change2_t *entry) +{ + output->path.data = path; + output->path.len = path_len; + output->change_kind = entry->change_kind; + output->node_kind = entry->node_kind; + output->text_mod = entry->text_mod; + output->prop_mod = entry->prop_mod; + output->mergeinfo_mod = entry->mergeinfo_mod; + output->copyfrom_known = entry->copyfrom_known; + output->copyfrom_rev = entry->copyfrom_rev; + output->copyfrom_path = entry->copyfrom_path; +} + +/* FSAP data structure for in-txn changes list iterators. */ +typedef struct fs_txn_changes_iterator_data_t +{ + /* Current iterator position. */ + apr_hash_index_t *hi; + + /* For efficiency such that we don't need to dynamically allocate + yet another copy of that data. */ + svn_fs_path_change3_t change; +} fs_txn_changes_iterator_data_t; + +/* Implement changes_iterator_vtable_t.get for in-txn change lists. */ +static svn_error_t * +fs_txn_changes_iterator_get(svn_fs_path_change3_t **change, + svn_fs_path_change_iterator_t *iterator) +{ + fs_txn_changes_iterator_data_t *data = iterator->fsap_data; + + if (data->hi) + { + const void *key; + apr_ssize_t length; + void *value; + apr_hash_this(data->hi, &key, &length, &value); + + convert_path_change(&data->change, key, length, value); + + *change = &data->change; + data->hi = apr_hash_next(data->hi); + } + else + { + *change = NULL; + } + + return SVN_NO_ERROR; +} + +static changes_iterator_vtable_t txn_changes_iterator_vtable = +{ + fs_txn_changes_iterator_get +}; + +/* FSAP data structure for in-revision changes list iterators. */ +typedef struct fs_revision_changes_iterator_data_t +{ + /* Context that tells the lower layers from where to fetch the next + block of changes. */ + svn_fs_fs__changes_context_t *context; + + /* Changes to send. */ + apr_array_header_t *changes; + + /* Current indexes within CHANGES. */ + int idx; + + /* For efficiency such that we don't need to dynamically allocate + yet another copy of that data. */ + svn_fs_path_change3_t change; + + /* A cleanable scratch pool in case we need one. + No further sub-pool creation necessary. */ + apr_pool_t *scratch_pool; +} fs_revision_changes_iterator_data_t; + +/* Implement changes_iterator_vtable_t.get for in-revision change lists. */ +static svn_error_t * +fs_revision_changes_iterator_get(svn_fs_path_change3_t **change, + svn_fs_path_change_iterator_t *iterator) +{ + fs_revision_changes_iterator_data_t *data = iterator->fsap_data; + + /* If we exhausted our block of changes and did not reach the end of the + list, yet, fetch the next block. Note that that block may be empty. */ + if ((data->idx >= data->changes->nelts) && !data->context->eol) + { + apr_pool_t *changes_pool = data->changes->pool; + + /* Drop old changes block, read new block. */ + svn_pool_clear(changes_pool); + SVN_ERR(svn_fs_fs__get_changes(&data->changes, data->context, + changes_pool, data->scratch_pool)); + data->idx = 0; + + /* Immediately release any temporary data. */ + svn_pool_clear(data->scratch_pool); + } + + if (data->idx < data->changes->nelts) + { + change_t *entry = APR_ARRAY_IDX(data->changes, data->idx, change_t *); + convert_path_change(&data->change, entry->path.data, entry->path.len, + &entry->info); + + *change = &data->change; + ++data->idx; + } + else + { + *change = NULL; + } + + return SVN_NO_ERROR; +} + +static changes_iterator_vtable_t rev_changes_iterator_vtable = +{ + fs_revision_changes_iterator_get +}; + +static svn_error_t * +fs_report_changes(svn_fs_path_change_iterator_t **iterator, + svn_fs_root_t *root, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_fs_path_change_iterator_t *result = apr_pcalloc(result_pool, + sizeof(*result)); + if (root->is_txn_root) + { + fs_txn_changes_iterator_data_t *data = apr_pcalloc(result_pool, + sizeof(*data)); + apr_hash_t *changed_paths; + SVN_ERR(svn_fs_fs__txn_changes_fetch(&changed_paths, root->fs, + root_txn_id(root), result_pool)); + + data->hi = apr_hash_first(result_pool, changed_paths); + result->fsap_data = data; + result->vtable = &txn_changes_iterator_vtable; + } + else + { + /* The block of changes that we retrieve need to live in a separately + cleanable pool. */ + apr_pool_t *changes_pool = svn_pool_create(result_pool); + + /* Our iteration context info. */ + fs_revision_changes_iterator_data_t *data = apr_pcalloc(result_pool, + sizeof(*data)); + + /* This pool must remain valid as long as ITERATOR lives but will + be used only for temporary allocations and will be cleaned up + frequently. So, this must be a sub-pool of RESULT_POOL. */ + data->scratch_pool = svn_pool_create(result_pool); + + /* Fetch the first block of data. */ + SVN_ERR(svn_fs_fs__create_changes_context(&data->context, + root->fs, root->rev, + result_pool)); + SVN_ERR(svn_fs_fs__get_changes(&data->changes, data->context, + changes_pool, scratch_pool)); + + /* Return the fully initialized object. */ + result->fsap_data = data; + result->vtable = &rev_changes_iterator_vtable; + } + + *iterator = result; + + return SVN_NO_ERROR; +} + /* Our coolio opaque history object. */ typedef struct fs_history_data_t @@ -3273,6 +3499,14 @@ typedef struct fs_history_data_t /* FALSE until the first call to svn_fs_history_prev(). */ svn_boolean_t is_interesting; + + /* If not SVN_INVALID_REVISION, we know that the next copy operation + is at this revision. */ + svn_revnum_t next_copy; + + /* If not NULL, this is the noderev ID of PATH@REVISION. */ + const svn_fs_id_t *current_id; + } fs_history_data_t; static svn_fs_history_t * @@ -3282,6 +3516,8 @@ assemble_history(svn_fs_t *fs, svn_boolean_t is_interesting, const char *path_hint, svn_revnum_t rev_hint, + svn_revnum_t next_copy, + const svn_fs_id_t *current_id, apr_pool_t *pool); @@ -3308,7 +3544,8 @@ fs_node_history(svn_fs_history_t **history_p, /* Okay, all seems well. Build our history object and return it. */ *history_p = assemble_history(root->fs, path, root->rev, FALSE, NULL, - SVN_INVALID_REVNUM, result_pool); + SVN_INVALID_REVNUM, SVN_INVALID_REVNUM, + NULL, result_pool); return SVN_NO_ERROR; } @@ -3609,10 +3846,50 @@ history_prev(svn_fs_history_t **prev_history, svn_boolean_t reported = fhd->is_interesting; svn_revnum_t copyroot_rev; const char *copyroot_path; + const svn_fs_id_t *pred_id = NULL; /* Initialize our return value. */ *prev_history = NULL; + /* When following history, there tend to be long sections of linear + history where there are no copies at PATH or its parents. Within + these sections, we only need to follow the node history. */ + if ( SVN_IS_VALID_REVNUM(fhd->next_copy) + && revision > fhd->next_copy + && fhd->current_id) + { + /* We know the last reported node (CURRENT_ID) and the NEXT_COPY + revision is somewhat further in the past. */ + node_revision_t *noderev; + assert(reported); + + /* Get the previous node change. If there is none, then we already + reported the initial addition and this history traversal is done. */ + SVN_ERR(svn_fs_fs__get_node_revision(&noderev, fs, fhd->current_id, + scratch_pool, scratch_pool)); + if (! noderev->predecessor_id) + return SVN_NO_ERROR; + + /* If the previous node change is younger than the next copy, it is + part of the linear history section. */ + commit_rev = svn_fs_fs__id_rev(noderev->predecessor_id); + if (commit_rev > fhd->next_copy) + { + /* Within the linear history, simply report all node changes and + continue with the respective predecessor. */ + *prev_history = assemble_history(fs, noderev->created_path, + commit_rev, TRUE, NULL, + SVN_INVALID_REVNUM, + fhd->next_copy, + noderev->predecessor_id, + result_pool); + + return SVN_NO_ERROR; + } + + /* We hit a copy. Fall back to the standard code path. */ + } + /* If our last history report left us hints about where to pickup the chase, then our last report was on the destination of a copy. If we are crossing copies, start from those locations, @@ -3651,7 +3928,9 @@ history_prev(svn_fs_history_t **prev_history, need now to do so) ... */ *prev_history = assemble_history(fs, commit_path, commit_rev, TRUE, NULL, - SVN_INVALID_REVNUM, result_pool); + SVN_INVALID_REVNUM, + SVN_INVALID_REVNUM, NULL, + result_pool); return SVN_NO_ERROR; } else @@ -3659,8 +3938,6 @@ history_prev(svn_fs_history_t **prev_history, /* ... or we *have* reported on this revision, and must now progress toward this node's predecessor (unless there is no predecessor, in which case we're all done!). */ - const svn_fs_id_t *pred_id; - SVN_ERR(svn_fs_fs__dag_get_predecessor_id(&pred_id, node)); if (! pred_id) return SVN_NO_ERROR; @@ -3731,12 +4008,18 @@ history_prev(svn_fs_history_t **prev_history, retry = TRUE; *prev_history = assemble_history(fs, path, dst_rev, ! retry, - src_path, src_rev, result_pool); + src_path, src_rev, + SVN_INVALID_REVNUM, NULL, + result_pool); } else { + /* We know the next copy revision. If we are not at the copy rev + itself, we will also know the predecessor node ID and the next + invocation will use the optimized "linear history" code path. */ *prev_history = assemble_history(fs, commit_path, commit_rev, TRUE, - NULL, SVN_INVALID_REVNUM, result_pool); + NULL, SVN_INVALID_REVNUM, + copyroot_rev, pred_id, result_pool); } return SVN_NO_ERROR; @@ -3767,10 +4050,12 @@ fs_history_prev(svn_fs_history_t **prev_history_p, if (! fhd->is_interesting) prev_history = assemble_history(fs, "/", fhd->revision, 1, NULL, SVN_INVALID_REVNUM, + SVN_INVALID_REVNUM, NULL, result_pool); else if (fhd->revision > 0) prev_history = assemble_history(fs, "/", fhd->revision - 1, 1, NULL, SVN_INVALID_REVNUM, + SVN_INVALID_REVNUM, NULL, result_pool); } else @@ -3830,6 +4115,8 @@ assemble_history(svn_fs_t *fs, svn_boolean_t is_interesting, const char *path_hint, svn_revnum_t rev_hint, + svn_revnum_t next_copy, + const svn_fs_id_t *current_id, apr_pool_t *pool) { svn_fs_history_t *history = apr_pcalloc(pool, sizeof(*history)); @@ -3840,6 +4127,8 @@ assemble_history(svn_fs_t *fs, fhd->path_hint = path_hint ? svn_fs__canonicalize_abspath(path_hint, pool) : NULL; fhd->rev_hint = rev_hint; + fhd->next_copy = next_copy; + fhd->current_id = current_id ? svn_fs_fs__id_copy(current_id, pool) : NULL; fhd->fs = fs; history->vtable = &history_vtable; @@ -3853,21 +4142,19 @@ assemble_history(svn_fs_t *fs, /* DIR_DAG is a directory DAG node which has mergeinfo in its descendants. This function iterates over its children. For each - child with immediate mergeinfo, it adds its mergeinfo to - RESULT_CATALOG. appropriate arguments. For each child with - descendants with mergeinfo, it recurses. Note that it does *not* - call the action on the path for DIR_DAG itself. + child with immediate mergeinfo, call RECEIVER with it and BATON. + For each child with descendants with mergeinfo, it recurses. Note + that it does *not* call the action on the path for DIR_DAG itself. - POOL is used for temporary allocations, including the mergeinfo - hashes passed to actions; RESULT_POOL is used for the mergeinfo added - to RESULT_CATALOG. + SCRATCH_POOL is used for temporary allocations, including the mergeinfo + hashes passed to actions. */ static svn_error_t * crawl_directory_dag_for_mergeinfo(svn_fs_root_t *root, const char *this_path, dag_node_t *dir_dag, - svn_mergeinfo_catalog_t result_catalog, - apr_pool_t *result_pool, + svn_fs_mergeinfo_receiver_t receiver, + void *baton, apr_pool_t *scratch_pool) { apr_array_header_t *entries; @@ -3914,7 +4201,7 @@ crawl_directory_dag_for_mergeinfo(svn_fs_root_t *root, error. */ err = svn_mergeinfo_parse(&kid_mergeinfo, mergeinfo_string->data, - result_pool); + iterpool); if (err) { if (err->apr_err == SVN_ERR_MERGEINFO_PARSE_ERROR) @@ -3924,8 +4211,7 @@ crawl_directory_dag_for_mergeinfo(svn_fs_root_t *root, } else { - svn_hash_sets(result_catalog, apr_pstrdup(result_pool, kid_path), - kid_mergeinfo); + SVN_ERR(receiver(kid_path, kid_mergeinfo, baton, iterpool)); } } @@ -3933,8 +4219,8 @@ crawl_directory_dag_for_mergeinfo(svn_fs_root_t *root, SVN_ERR(crawl_directory_dag_for_mergeinfo(root, kid_path, kid_dag, - result_catalog, - result_pool, + receiver, + baton, iterpool)); } @@ -4118,14 +4404,13 @@ get_mergeinfo_for_path(svn_mergeinfo_t *mergeinfo, return SVN_NO_ERROR; } -/* Adds mergeinfo for each descendant of PATH (but not PATH itself) - under ROOT to RESULT_CATALOG. Returned values are allocated in - RESULT_POOL; temporary values in POOL. */ +/* Invoke RECEIVER with BATON for each mergeinfo found on descendants of + PATH (but not PATH itself). Use SCRATCH_POOL for temporary values. */ static svn_error_t * -add_descendant_mergeinfo(svn_mergeinfo_catalog_t result_catalog, - svn_fs_root_t *root, +add_descendant_mergeinfo(svn_fs_root_t *root, const char *path, - apr_pool_t *result_pool, + svn_fs_mergeinfo_receiver_t receiver, + void *baton, apr_pool_t *scratch_pool) { dag_node_t *this_dag; @@ -4138,27 +4423,28 @@ add_descendant_mergeinfo(svn_mergeinfo_catalog_t result_catalog, SVN_ERR(crawl_directory_dag_for_mergeinfo(root, path, this_dag, - result_catalog, - result_pool, + receiver, + baton, scratch_pool)); return SVN_NO_ERROR; } -/* Get the mergeinfo for a set of paths, returned in - *MERGEINFO_CATALOG. Returned values are allocated in - POOL, while temporary values are allocated in a sub-pool. */ +/* Find all the mergeinfo for a set of PATHS under ROOT and report it + through RECEIVER with BATON. INHERITED, INCLUDE_DESCENDANTS and + ADJUST_INHERITED_MERGEINFO are the same as in the FS API. + + Allocate temporary values are allocated in SCRATCH_POOL. */ static svn_error_t * get_mergeinfos_for_paths(svn_fs_root_t *root, - svn_mergeinfo_catalog_t *mergeinfo_catalog, const apr_array_header_t *paths, svn_mergeinfo_inheritance_t inherit, svn_boolean_t include_descendants, svn_boolean_t adjust_inherited_mergeinfo, - apr_pool_t *result_pool, + svn_fs_mergeinfo_receiver_t receiver, + void *baton, apr_pool_t *scratch_pool) { - svn_mergeinfo_catalog_t result_catalog = svn_hash__make(result_pool); apr_pool_t *iterpool = svn_pool_create(scratch_pool); int i; @@ -4172,7 +4458,7 @@ get_mergeinfos_for_paths(svn_fs_root_t *root, err = get_mergeinfo_for_path(&path_mergeinfo, root, path, inherit, adjust_inherited_mergeinfo, - result_pool, iterpool); + iterpool, iterpool); if (err) { if (err->apr_err == SVN_ERR_MERGEINFO_PARSE_ERROR) @@ -4188,27 +4474,26 @@ get_mergeinfos_for_paths(svn_fs_root_t *root, } if (path_mergeinfo) - svn_hash_sets(result_catalog, path, path_mergeinfo); + SVN_ERR(receiver(path, path_mergeinfo, baton, iterpool)); if (include_descendants) - SVN_ERR(add_descendant_mergeinfo(result_catalog, root, path, - result_pool, scratch_pool)); + SVN_ERR(add_descendant_mergeinfo(root, path, receiver, baton, + iterpool)); } svn_pool_destroy(iterpool); - *mergeinfo_catalog = result_catalog; return SVN_NO_ERROR; } /* Implements svn_fs_get_mergeinfo. */ static svn_error_t * -fs_get_mergeinfo(svn_mergeinfo_catalog_t *catalog, - svn_fs_root_t *root, +fs_get_mergeinfo(svn_fs_root_t *root, const apr_array_header_t *paths, svn_mergeinfo_inheritance_t inherit, svn_boolean_t include_descendants, svn_boolean_t adjust_inherited_mergeinfo, - apr_pool_t *result_pool, + svn_fs_mergeinfo_receiver_t receiver, + void *baton, apr_pool_t *scratch_pool) { fs_fs_data_t *ffd = root->fs->fsap_data; @@ -4226,17 +4511,18 @@ fs_get_mergeinfo(svn_mergeinfo_catalog_t *catalog, SVN_FS_FS__MIN_MERGEINFO_FORMAT, root->fs->path, ffd->format); /* Retrieve a path -> mergeinfo hash mapping. */ - return get_mergeinfos_for_paths(root, catalog, paths, - inherit, + return get_mergeinfos_for_paths(root, paths, inherit, include_descendants, adjust_inherited_mergeinfo, - result_pool, scratch_pool); + receiver, baton, + scratch_pool); } /* The vtable associated with root objects. */ static root_vtable_t root_vtable = { fs_paths_changed, + fs_report_changes, svn_fs_fs__check_path, fs_node_history, svn_fs_fs__node_id, diff --git a/subversion/libsvn_fs_fs/util.c b/subversion/libsvn_fs_fs/util.c index faa1e3d319b2..e19132248035 100644 --- a/subversion/libsvn_fs_fs/util.c +++ b/subversion/libsvn_fs_fs/util.c @@ -428,6 +428,7 @@ svn_fs_fs__write_min_unpacked_rev(svn_fs_t *fs, svn_revnum_t revnum, apr_pool_t *scratch_pool) { + fs_fs_data_t *ffd = fs->fsap_data; const char *final_path; char buf[SVN_INT64_BUFFER_SIZE]; apr_size_t len = svn__i64toa(buf, revnum); @@ -435,8 +436,9 @@ svn_fs_fs__write_min_unpacked_rev(svn_fs_t *fs, final_path = svn_fs_fs__path_min_unpacked_rev(fs, scratch_pool); - SVN_ERR(svn_io_write_atomic(final_path, buf, len + 1, - final_path /* copy_perms */, scratch_pool)); + SVN_ERR(svn_io_write_atomic2(final_path, buf, len + 1, + final_path /* copy_perms */, + ffd->flush_to_disk, scratch_pool)); return SVN_NO_ERROR; } @@ -517,8 +519,9 @@ svn_fs_fs__write_current(svn_fs_t *fs, } name = svn_fs_fs__path_current(fs, pool); - SVN_ERR(svn_io_write_atomic(name, buf, strlen(buf), - name /* copy_perms_path */, pool)); + SVN_ERR(svn_io_write_atomic2(name, buf, strlen(buf), + name /* copy_perms_path */, + ffd->flush_to_disk, pool)); return SVN_NO_ERROR; } @@ -564,22 +567,6 @@ svn_fs_fs__try_stringbuf_from_file(svn_stringbuf_t **content, return svn_error_trace(err); } -svn_error_t * -svn_fs_fs__get_file_offset(apr_off_t *offset_p, - apr_file_t *file, - apr_pool_t *pool) -{ - apr_off_t offset; - - /* Note that, for buffered files, one (possibly surprising) side-effect - of this call is to flush any unwritten data to disk. */ - offset = 0; - SVN_ERR(svn_io_file_seek(file, APR_CUR, &offset, pool)); - *offset_p = offset; - - return SVN_NO_ERROR; -} - svn_error_t * svn_fs_fs__read_content(svn_stringbuf_t **content, const char *fname, @@ -634,54 +621,54 @@ svn_error_t * svn_fs_fs__move_into_place(const char *old_filename, const char *new_filename, const char *perms_reference, + svn_boolean_t flush_to_disk, apr_pool_t *pool) { svn_error_t *err; + apr_file_t *file; + /* Copying permissions is a no-op on WIN32. */ SVN_ERR(svn_io_copy_perms(perms_reference, old_filename, pool)); /* Move the file into place. */ - err = svn_io_file_rename(old_filename, new_filename, pool); + err = svn_io_file_rename2(old_filename, new_filename, flush_to_disk, pool); if (err && APR_STATUS_IS_EXDEV(err->apr_err)) { - apr_file_t *file; - /* Can't rename across devices; fall back to copying. */ svn_error_clear(err); - err = SVN_NO_ERROR; SVN_ERR(svn_io_copy_file(old_filename, new_filename, TRUE, pool)); - /* Flush the target of the copy to disk. */ - SVN_ERR(svn_io_file_open(&file, new_filename, APR_READ, - APR_OS_DEFAULT, pool)); - /* ### BH: Does this really guarantee a flush of the data written - ### via a completely different handle on all operating systems? - ### - ### Maybe we should perform the copy ourselves instead of making - ### apr do that and flush the real handle? */ - SVN_ERR(svn_io_file_flush_to_disk(file, pool)); - SVN_ERR(svn_io_file_close(file, pool)); - } - if (err) - return svn_error_trace(err); + /* Flush the target of the copy to disk. + ### The code below is duplicates svn_io_file_rename2(), because + currently we don't have the svn_io_copy_file2() function with + a flush_to_disk argument. */ + if (flush_to_disk) + { + SVN_ERR(svn_io_file_open(&file, new_filename, APR_WRITE, + APR_OS_DEFAULT, pool)); + SVN_ERR(svn_io_file_flush_to_disk(file, pool)); + SVN_ERR(svn_io_file_close(file, pool)); + } -#ifdef __linux__ - { - /* Linux has the unusual feature that fsync() on a file is not - enough to ensure that a file's directory entries have been - flushed to disk; you have to fsync the directory as well. - On other operating systems, we'd only be asking for trouble - by trying to open and fsync a directory. */ - const char *dirname; - apr_file_t *file; +#ifdef SVN_ON_POSIX + if (flush_to_disk) + { + /* On POSIX, the file name is stored in the file's directory entry. + Hence, we need to fsync() that directory as well. + On other operating systems, we'd only be asking for trouble + by trying to open and fsync a directory. */ + const char *dirname; - dirname = svn_dirent_dirname(new_filename, pool); - SVN_ERR(svn_io_file_open(&file, dirname, APR_READ, APR_OS_DEFAULT, - pool)); - SVN_ERR(svn_io_file_flush_to_disk(file, pool)); - SVN_ERR(svn_io_file_close(file, pool)); - } + dirname = svn_dirent_dirname(new_filename, pool); + SVN_ERR(svn_io_file_open(&file, dirname, APR_READ, APR_OS_DEFAULT, + pool)); + SVN_ERR(svn_io_file_flush_to_disk(file, pool)); + SVN_ERR(svn_io_file_close(file, pool)); + } #endif + } + else if (err) + return svn_error_trace(err); return SVN_NO_ERROR; } diff --git a/subversion/libsvn_fs_fs/util.h b/subversion/libsvn_fs_fs/util.h index 328dfbcff3fd..2d42f97b114e 100644 --- a/subversion/libsvn_fs_fs/util.h +++ b/subversion/libsvn_fs_fs/util.h @@ -363,12 +363,6 @@ svn_fs_fs__try_stringbuf_from_file(svn_stringbuf_t **content, svn_boolean_t last_attempt, apr_pool_t *pool); -/* Fetch the current offset of FILE into *OFFSET_P. */ -svn_error_t * -svn_fs_fs__get_file_offset(apr_off_t *offset_p, - apr_file_t *file, - apr_pool_t *pool); - /* Read the file FNAME and store the contents in *BUF. Allocations are performed in POOL. */ svn_error_t * @@ -394,11 +388,12 @@ svn_fs_fs__read_number_from_stream(apr_int64_t *result, PERMS_REFERENCE. Temporary allocations are from POOL. This function almost duplicates svn_io_file_move(), but it tries to - guarantee a flush. */ + guarantee a flush if FLUSH_TO_DISK is non-zero. */ svn_error_t * svn_fs_fs__move_into_place(const char *old_filename, const char *new_filename, const char *perms_reference, + svn_boolean_t flush_to_disk, apr_pool_t *pool); /* Return TRUE, iff FS uses logical addressing. */ diff --git a/subversion/libsvn_fs_fs/verify.c b/subversion/libsvn_fs_fs/verify.c index 0fa314bfddf4..7fe5ecbbd494 100644 --- a/subversion/libsvn_fs_fs/verify.c +++ b/subversion/libsvn_fs_fs/verify.c @@ -30,6 +30,7 @@ #include "cached_data.h" #include "rep-cache.h" +#include "revprops.h" #include "util.h" #include "index.h" @@ -463,7 +464,8 @@ expect_buffer_nul(apr_file_t *file, /* read the whole data block; error out on failure */ data.chunks[(size - 1)/ sizeof(apr_uint64_t)] = 0; - SVN_ERR(svn_io_file_read_full2(file, data.buffer, size, NULL, NULL, pool)); + SVN_ERR(svn_io_file_read_full2(file, data.buffer, (apr_size_t)size, NULL, + NULL, pool)); /* chunky check */ for (i = 0; i < size / sizeof(apr_uint64_t); ++i) @@ -478,7 +480,7 @@ expect_buffer_nul(apr_file_t *file, apr_off_t offset; SVN_ERR(svn_io_file_name_get(&file_name, file, pool)); - SVN_ERR(svn_fs_fs__get_file_offset(&offset, file, pool)); + SVN_ERR(svn_io_file_get_offset(&offset, file, pool)); offset -= size - i; return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, @@ -671,15 +673,45 @@ compare_p2l_to_rev(svn_fs_t *fs, apr_off_t_toa(pool, offset), apr_off_t_toa(pool, entry->offset)); - /* empty sections must contain NUL bytes only */ + /* Check type <-> item dependencies. */ + + /* Entry types must be within the valid range. */ + if (entry->type >= SVN_FS_FS__ITEM_TYPE_ANY_REP) + return svn_error_createf(SVN_ERR_FS_INDEX_CORRUPTION, + NULL, + _("p2l index entry for revision r%ld" + " at offset %s contains invalid item" + " type %d"), + start, + apr_off_t_toa(pool, offset), + entry->type); + + /* There can be only one changes entry and that has a fixed type + * and item number. Its presence and parse-ability will be checked + * during later stages of the verification process. */ + if ( (entry->type == SVN_FS_FS__ITEM_TYPE_CHANGES) + != (entry->item.number == SVN_FS_FS__ITEM_INDEX_CHANGES)) + return svn_error_createf(SVN_ERR_FS_INDEX_CORRUPTION, + NULL, + _("p2l index entry for changes in" + " revision r%ld is item %ld of type" + " %d at offset %s"), + entry->item.revision, + entry->item.number, + entry->type, + apr_off_t_toa(pool, offset)); + + /* Check contents. */ if (entry->type == SVN_FS_FS__ITEM_TYPE_UNUSED) { - /* skip filler entry at the end of the p2l index */ + /* Empty sections must contain NUL bytes only. + * Beware of the filler at the end of the p2l index. */ if (entry->offset != max_offset) SVN_ERR(read_all_nul(rev_file->file, entry->size, pool)); } else { + /* Generic contents check against checksum. */ if (entry->size < STREAM_THRESHOLD) SVN_ERR(expected_buffered_checksum(rev_file->file, entry, pool)); @@ -720,6 +752,10 @@ verify_revprops(svn_fs_t *fs, svn_revnum_t revision; apr_pool_t *iterpool = svn_pool_create(pool); + /* Invalidate the revprop cache once. + * Use the cache inside the loop to speed up packed revprop access. */ + svn_fs_fs__reset_revprop_cache(fs); + for (revision = start; revision < end; ++revision) { svn_string_t *date; @@ -730,7 +766,8 @@ verify_revprops(svn_fs_t *fs, /* Access the svn:date revprop. * This implies parsing all revprops for that revision. */ SVN_ERR(svn_fs_fs__revision_prop(&date, fs, revision, - SVN_PROP_REVISION_DATE, iterpool)); + SVN_PROP_REVISION_DATE, FALSE, + iterpool, iterpool)); /* The time stamp is the only revprop that, if given, needs to * have a valid content. */ @@ -857,13 +894,15 @@ svn_fs_fs__verify(svn_fs_t *fs, apr_pool_t *pool) { fs_fs_data_t *ffd = fs->fsap_data; - svn_revnum_t youngest = ffd->youngest_rev_cache; /* cache is current */ /* Input validation. */ if (! SVN_IS_VALID_REVNUM(start)) start = 0; if (! SVN_IS_VALID_REVNUM(end)) - end = youngest; + { + SVN_ERR(svn_fs_fs__youngest_rev(&end, fs, pool)); + } + SVN_ERR(svn_fs_fs__ensure_revision_exists(start, fs, pool)); SVN_ERR(svn_fs_fs__ensure_revision_exists(end, fs, pool)); diff --git a/subversion/libsvn_fs_util/fs-util.c b/subversion/libsvn_fs_util/fs-util.c index 1e7ed4fde743..b9d1de0a2bcf 100644 --- a/subversion/libsvn_fs_util/fs-util.c +++ b/subversion/libsvn_fs_util/fs-util.c @@ -212,6 +212,21 @@ svn_fs__path_change_create_internal(const svn_fs_id_t *node_rev_id, return change; } +svn_fs_path_change3_t * +svn_fs__path_change_create_internal2(svn_fs_path_change_kind_t change_kind, + apr_pool_t *result_pool) +{ + svn_fs_path_change3_t *change; + + change = apr_pcalloc(result_pool, sizeof(*change)); + change->path.data = ""; + change->change_kind = change_kind; + change->mergeinfo_mod = svn_tristate_unknown; + change->copyfrom_rev = SVN_INVALID_REVNUM; + + return change; +} + svn_error_t * svn_fs__append_to_merged_froms(svn_mergeinfo_t *output, svn_mergeinfo_t input, diff --git a/subversion/libsvn_fs_x/batch_fsync.c b/subversion/libsvn_fs_x/batch_fsync.c new file mode 100644 index 000000000000..4116d7d7614c --- /dev/null +++ b/subversion/libsvn_fs_x/batch_fsync.c @@ -0,0 +1,588 @@ +/* batch_fsync.c --- efficiently fsync multiple targets + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#include +#include + +#include "batch_fsync.h" +#include "svn_pools.h" +#include "svn_hash.h" +#include "svn_dirent_uri.h" +#include "svn_private_config.h" + +#include "private/svn_atomic.h" +#include "private/svn_dep_compat.h" +#include "private/svn_mutex.h" +#include "private/svn_subr_private.h" + +/* Handy macro to check APR function results and turning them into + * svn_error_t upon failure. */ +#define WRAP_APR_ERR(x,msg) \ + { \ + apr_status_t status_ = (x); \ + if (status_) \ + return svn_error_wrap_apr(status_, msg); \ + } + + +/* A simple SVN-wrapper around the apr_thread_cond_* API */ +#if APR_HAS_THREADS +typedef apr_thread_cond_t svn_thread_cond__t; +#else +typedef int svn_thread_cond__t; +#endif + +static svn_error_t * +svn_thread_cond__create(svn_thread_cond__t **cond, + apr_pool_t *result_pool) +{ +#if APR_HAS_THREADS + + WRAP_APR_ERR(apr_thread_cond_create(cond, result_pool), + _("Can't create condition variable")); + +#else + + *cond = apr_pcalloc(result_pool, sizeof(**cond)); + +#endif + + return SVN_NO_ERROR; +} + +static svn_error_t * +svn_thread_cond__broadcast(svn_thread_cond__t *cond) +{ +#if APR_HAS_THREADS + + WRAP_APR_ERR(apr_thread_cond_broadcast(cond), + _("Can't broadcast condition variable")); + +#endif + + return SVN_NO_ERROR; +} + +static svn_error_t * +svn_thread_cond__wait(svn_thread_cond__t *cond, + svn_mutex__t *mutex) +{ +#if APR_HAS_THREADS + + WRAP_APR_ERR(apr_thread_cond_wait(cond, svn_mutex__get(mutex)), + _("Can't broadcast condition variable")); + +#endif + + return SVN_NO_ERROR; +} + +/* Utility construct: Clients can efficiently wait for the encapsulated + * counter to reach a certain value. Currently, only increments have been + * implemented. This whole structure can be opaque to the API users. + */ +typedef struct waitable_counter_t +{ + /* Current value, initialized to 0. */ + int value; + + /* Synchronization objects. */ + svn_thread_cond__t *cond; + svn_mutex__t *mutex; +} waitable_counter_t; + +/* Set *COUNTER_P to a new waitable_counter_t instance allocated in + * RESULT_POOL. The initial counter value is 0. */ +static svn_error_t * +waitable_counter__create(waitable_counter_t **counter_p, + apr_pool_t *result_pool) +{ + waitable_counter_t *counter = apr_pcalloc(result_pool, sizeof(*counter)); + counter->value = 0; + + SVN_ERR(svn_thread_cond__create(&counter->cond, result_pool)); + SVN_ERR(svn_mutex__init(&counter->mutex, TRUE, result_pool)); + + *counter_p = counter; + + return SVN_NO_ERROR; +} + +/* Increment the value in COUNTER by 1. */ +static svn_error_t * +waitable_counter__increment(waitable_counter_t *counter) +{ + SVN_ERR(svn_mutex__lock(counter->mutex)); + counter->value++; + + SVN_ERR(svn_thread_cond__broadcast(counter->cond)); + SVN_ERR(svn_mutex__unlock(counter->mutex, SVN_NO_ERROR)); + + return SVN_NO_ERROR; +} + +/* Efficiently wait for COUNTER to assume VALUE. */ +static svn_error_t * +waitable_counter__wait_for(waitable_counter_t *counter, + int value) +{ + svn_boolean_t done = FALSE; + + /* This loop implicitly handles spurious wake-ups. */ + do + { + SVN_ERR(svn_mutex__lock(counter->mutex)); + + if (counter->value == value) + done = TRUE; + else + SVN_ERR(svn_thread_cond__wait(counter->cond, counter->mutex)); + + SVN_ERR(svn_mutex__unlock(counter->mutex, SVN_NO_ERROR)); + } + while (!done); + + return SVN_NO_ERROR; +} + +/* Set the value in COUNTER to 0. */ +static svn_error_t * +waitable_counter__reset(waitable_counter_t *counter) +{ + SVN_ERR(svn_mutex__lock(counter->mutex)); + counter->value = 0; + SVN_ERR(svn_mutex__unlock(counter->mutex, SVN_NO_ERROR)); + + SVN_ERR(svn_thread_cond__broadcast(counter->cond)); + + return SVN_NO_ERROR; +} + +/* Entry type for the svn_fs_x__batch_fsync_t collection. There is one + * instance per file handle. + */ +typedef struct to_sync_t +{ + /* Open handle of the file / directory to fsync. */ + apr_file_t *file; + + /* Pool to use with FILE. It is private to FILE such that it can be + * used safely together with FILE in a separate thread. */ + apr_pool_t *pool; + + /* Result of the file operations. */ + svn_error_t *result; + + /* Counter to increment when we completed the task. */ + waitable_counter_t *counter; +} to_sync_t; + +/* The actual collection object. */ +struct svn_fs_x__batch_fsync_t +{ + /* Maps open file handles: C-string path to to_sync_t *. */ + apr_hash_t *files; + + /* Counts the number of completed fsync tasks. */ + waitable_counter_t *counter; + + /* Perform fsyncs only if this flag has been set. */ + svn_boolean_t flush_to_disk; +}; + +/* Data structures for concurrent fsync execution are only available if + * we have threading support. + */ +#if APR_HAS_THREADS + +/* Number of microseconds that an unused thread remains in the pool before + * being terminated. + * + * Higher values are useful if clients frequently send small requests and + * you want to minimize the latency for those. + */ +#define THREADPOOL_THREAD_IDLE_LIMIT 1000000 + +/* Maximum number of threads in THREAD_POOL, i.e. number of paths we can + * fsync concurrently throughout the process. */ +#define MAX_THREADS 16 + +/* Thread pool to execute the fsync tasks. */ +static apr_thread_pool_t *thread_pool = NULL; + +#endif + +/* Keep track on whether we already created the THREAD_POOL . */ +static svn_atomic_t thread_pool_initialized = FALSE; + +/* We open non-directory files with these flags. */ +#define FILE_FLAGS (APR_READ | APR_WRITE | APR_BUFFERED | APR_CREATE) + +#if APR_HAS_THREADS + +/* Destructor function that implicitly cleans up any running threads + in the TRHEAD_POOL *once*. + + Must be run as a pre-cleanup hook. + */ +static apr_status_t +thread_pool_pre_cleanup(void *data) +{ + apr_thread_pool_t *tp = thread_pool; + if (!thread_pool) + return APR_SUCCESS; + + thread_pool = NULL; + thread_pool_initialized = FALSE; + + return apr_thread_pool_destroy(tp); +} + +#endif + +/* Core implementation of svn_fs_x__batch_fsync_init. */ +static svn_error_t * +create_thread_pool(void *baton, + apr_pool_t *owning_pool) +{ +#if APR_HAS_THREADS + /* The thread-pool must be allocated from a thread-safe pool. + GLOBAL_POOL may be single-threaded, though. */ + apr_pool_t *pool = svn_pool_create(NULL); + + /* This thread pool will get cleaned up automatically when GLOBAL_POOL + gets cleared. No additional cleanup callback is needed. */ + WRAP_APR_ERR(apr_thread_pool_create(&thread_pool, 0, MAX_THREADS, pool), + _("Can't create fsync thread pool in FSX")); + + /* Work around an APR bug: The cleanup must happen in the pre-cleanup + hook instead of the normal cleanup hook. Otherwise, the sub-pools + containing the thread objects would already be invalid. */ + apr_pool_pre_cleanup_register(pool, NULL, thread_pool_pre_cleanup); + apr_pool_pre_cleanup_register(owning_pool, NULL, thread_pool_pre_cleanup); + + /* let idle threads linger for a while in case more requests are + coming in */ + apr_thread_pool_idle_wait_set(thread_pool, THREADPOOL_THREAD_IDLE_LIMIT); + + /* don't queue requests unless we reached the worker thread limit */ + apr_thread_pool_threshold_set(thread_pool, 0); + +#endif + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_fs_x__batch_fsync_init(apr_pool_t *owning_pool) +{ + /* Protect against multiple calls. */ + return svn_error_trace(svn_atomic__init_once(&thread_pool_initialized, + create_thread_pool, + NULL, owning_pool)); +} + +/* Destructor for svn_fs_x__batch_fsync_t. Releases all global pool memory + * and closes all open file handles. */ +static apr_status_t +fsync_batch_cleanup(void *data) +{ + svn_fs_x__batch_fsync_t *batch = data; + apr_hash_index_t *hi; + + /* Close all files (implicitly) and release memory. */ + for (hi = apr_hash_first(apr_hash_pool_get(batch->files), batch->files); + hi; + hi = apr_hash_next(hi)) + { + to_sync_t *to_sync = apr_hash_this_val(hi); + svn_pool_destroy(to_sync->pool); + } + + return APR_SUCCESS; +} + +svn_error_t * +svn_fs_x__batch_fsync_create(svn_fs_x__batch_fsync_t **result_p, + svn_boolean_t flush_to_disk, + apr_pool_t *result_pool) +{ + svn_fs_x__batch_fsync_t *result = apr_pcalloc(result_pool, sizeof(*result)); + result->files = svn_hash__make(result_pool); + result->flush_to_disk = flush_to_disk; + + SVN_ERR(waitable_counter__create(&result->counter, result_pool)); + apr_pool_cleanup_register(result_pool, result, fsync_batch_cleanup, + apr_pool_cleanup_null); + + *result_p = result; + + return SVN_NO_ERROR; +} + +/* If BATCH does not contain a handle for PATH, yet, create one with FLAGS + * and add it to BATCH. Set *FILE to the open file handle. + * Use SCRATCH_POOL for temporaries. + */ +static svn_error_t * +internal_open_file(apr_file_t **file, + svn_fs_x__batch_fsync_t *batch, + const char *path, + apr_int32_t flags, + apr_pool_t *scratch_pool) +{ + svn_error_t *err; + apr_pool_t *pool; + to_sync_t *to_sync; +#ifdef SVN_ON_POSIX + svn_boolean_t is_new_file; +#endif + + /* If we already have a handle for PATH, return that. */ + to_sync = svn_hash_gets(batch->files, path); + if (to_sync) + { + *file = to_sync->file; + return SVN_NO_ERROR; + } + + /* Calling fsync in PATH is going to be expensive in any case, so we can + * allow for some extra overhead figuring out whether the file already + * exists. If it doesn't, be sure to schedule parent folder updates, if + * required on this platform. + * + * See svn_fs_x__batch_fsync_new_path() for when such extra fsyncs may be + * needed at all. */ + +#ifdef SVN_ON_POSIX + + is_new_file = FALSE; + if (flags & APR_CREATE) + { + svn_node_kind_t kind; + /* We might actually be about to create a new file. + * Check whether the file already exists. */ + SVN_ERR(svn_io_check_path(path, &kind, scratch_pool)); + is_new_file = kind == svn_node_none; + } + +#endif + + /* To be able to process each file in a separate thread, they must use + * separate, thread-safe pools. Allocating a sub-pool from the standard + * memory pool achieves exactly that. */ + pool = svn_pool_create(NULL); + err = svn_io_file_open(file, path, flags, APR_OS_DEFAULT, pool); + if (err) + { + svn_pool_destroy(pool); + return svn_error_trace(err); + } + + to_sync = apr_pcalloc(pool, sizeof(*to_sync)); + to_sync->file = *file; + to_sync->pool = pool; + to_sync->result = SVN_NO_ERROR; + to_sync->counter = batch->counter; + + svn_hash_sets(batch->files, + apr_pstrdup(apr_hash_pool_get(batch->files), path), + to_sync); + + /* If we just created a new file, schedule any additional necessary fsyncs. + * Note that this can only recurse once since the parent folder already + * exists on disk. */ +#ifdef SVN_ON_POSIX + + if (is_new_file) + SVN_ERR(svn_fs_x__batch_fsync_new_path(batch, path, scratch_pool)); + +#endif + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_fs_x__batch_fsync_open_file(apr_file_t **file, + svn_fs_x__batch_fsync_t *batch, + const char *filename, + apr_pool_t *scratch_pool) +{ + apr_off_t offset = 0; + + SVN_ERR(internal_open_file(file, batch, filename, FILE_FLAGS, + scratch_pool)); + SVN_ERR(svn_io_file_seek(*file, APR_SET, &offset, scratch_pool)); + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_fs_x__batch_fsync_new_path(svn_fs_x__batch_fsync_t *batch, + const char *path, + apr_pool_t *scratch_pool) +{ + apr_file_t *file; + +#ifdef SVN_ON_POSIX + + /* On POSIX, we need to sync the parent directory because it contains + * the name for the file / folder given by PATH. */ + path = svn_dirent_dirname(path, scratch_pool); + SVN_ERR(internal_open_file(&file, batch, path, APR_READ, scratch_pool)); + +#else + + svn_node_kind_t kind; + + /* On non-POSIX systems, we assume that sync'ing the given PATH is the + * right thing to do. Also, we assume that only files may be sync'ed. */ + SVN_ERR(svn_io_check_path(path, &kind, scratch_pool)); + if (kind == svn_node_file) + SVN_ERR(internal_open_file(&file, batch, path, FILE_FLAGS, + scratch_pool)); + +#endif + + return SVN_NO_ERROR; +} + +/* Thread-pool task Flush the to_sync_t instance given by DATA. */ +static void * APR_THREAD_FUNC +flush_task(apr_thread_t *tid, + void *data) +{ + to_sync_t *to_sync = data; + + to_sync->result = svn_error_trace(svn_io_file_flush_to_disk + (to_sync->file, to_sync->pool)); + + /* As soon as the increment call returns, TO_SYNC may be invalid + (the main thread may have woken up and released the struct. + + Therefore, we cannot chain this error into TO_SYNC->RESULT. + OTOH, the main thread will probably deadlock anyway if we got + an error here, thus there is no point in trying to tell the + main thread what the problem was. */ + svn_error_clear(waitable_counter__increment(to_sync->counter)); + + return NULL; +} + +svn_error_t * +svn_fs_x__batch_fsync_run(svn_fs_x__batch_fsync_t *batch, + apr_pool_t *scratch_pool) +{ + apr_hash_index_t *hi; + + /* Number of tasks sent to the thread pool. */ + int tasks = 0; + + /* Because we allocated the open files from our global pool, don't bail + * out on the first error. Instead, process all files and but accumulate + * the errors in this chain. + */ + svn_error_t *chain = SVN_NO_ERROR; + + /* First, flush APR-internal buffers. This should minimize / prevent the + * introduction of additional meta-data changes during the next phase. + * We might otherwise issue redundant fsyncs. + */ + for (hi = apr_hash_first(scratch_pool, batch->files); + hi; + hi = apr_hash_next(hi)) + { + to_sync_t *to_sync = apr_hash_this_val(hi); + to_sync->result = svn_error_trace(svn_io_file_flush + (to_sync->file, to_sync->pool)); + } + + /* Make sure the task completion counter is set to 0. */ + chain = svn_error_compose_create(chain, + waitable_counter__reset(batch->counter)); + + /* Start the actual fsyncing process. */ + if (batch->flush_to_disk) + { + for (hi = apr_hash_first(scratch_pool, batch->files); + hi; + hi = apr_hash_next(hi)) + { + to_sync_t *to_sync = apr_hash_this_val(hi); + +#if APR_HAS_THREADS + + /* Forgot to call _init() or cleaned up the owning pool too early? + */ + SVN_ERR_ASSERT(thread_pool); + + /* If there are multiple fsyncs to perform, run them in parallel. + * Otherwise, skip the thread-pool and synchronization overhead. */ + if (apr_hash_count(batch->files) > 1) + { + apr_status_t status = APR_SUCCESS; + status = apr_thread_pool_push(thread_pool, flush_task, to_sync, + 0, NULL); + if (status) + to_sync->result = svn_error_wrap_apr(status, + _("Can't push task")); + else + tasks++; + } + else + +#endif + + { + to_sync->result = svn_error_trace(svn_io_file_flush_to_disk + (to_sync->file, + to_sync->pool)); + } + } + } + + /* Wait for all outstanding flush operations to complete. */ + chain = svn_error_compose_create(chain, + waitable_counter__wait_for(batch->counter, + tasks)); + + /* Collect the results, close all files and release memory. */ + for (hi = apr_hash_first(scratch_pool, batch->files); + hi; + hi = apr_hash_next(hi)) + { + to_sync_t *to_sync = apr_hash_this_val(hi); + if (batch->flush_to_disk) + chain = svn_error_compose_create(chain, to_sync->result); + + chain = svn_error_compose_create(chain, + svn_io_file_close(to_sync->file, + scratch_pool)); + svn_pool_destroy(to_sync->pool); + } + + /* Don't process any file / folder twice. */ + apr_hash_clear(batch->files); + + /* Report the errors that we encountered. */ + return svn_error_trace(chain); +} diff --git a/subversion/libsvn_fs_x/batch_fsync.h b/subversion/libsvn_fs_x/batch_fsync.h new file mode 100644 index 000000000000..e3c6a289ff0d --- /dev/null +++ b/subversion/libsvn_fs_x/batch_fsync.h @@ -0,0 +1,92 @@ +/* batch_fsync.h --- efficiently fsync multiple targets + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#ifndef SVN_LIBSVN_FS_X__BATCH_FSYNC_H +#define SVN_LIBSVN_FS_X__BATCH_FSYNC_H + +#include "svn_error.h" + +/* Infrastructure for efficiently calling fsync on files and directories. + * + * The idea is to have a container of open file handles (including + * directory handles on POSIX), at most one per file. During the course + * of an FS operation that needs to be fsync'ed, all touched files and + * folders accumulate in the container. + * + * At the end of the FS operation, all file changes will be written the + * physical disk, once per file and folder. Afterwards, all handles will + * be closed and the container is ready for reuse. + * + * To minimize the delay caused by the batch flush, run all fsync calls + * concurrently - if the OS supports multi-threading. + */ + +/* Opaque container type. + */ +typedef struct svn_fs_x__batch_fsync_t svn_fs_x__batch_fsync_t; + +/* Initialize the concurrent fsync infrastructure. Clean it up when + * OWNING_POOL gets cleared. + * + * This function must be called before using any of the other functions in + * in this module. It should only be called once. + */ +svn_error_t * +svn_fs_x__batch_fsync_init(apr_pool_t *owning_pool); + +/* Set *RESULT_P to a new batch fsync structure, allocated in RESULT_POOL. + * If FLUSH_TO_DISK is not set, the resulting struct will not actually use + * fsync. */ +svn_error_t * +svn_fs_x__batch_fsync_create(svn_fs_x__batch_fsync_t **result_p, + svn_boolean_t flush_to_disk, + apr_pool_t *result_pool); + +/* Open the file at FILENAME for read and write access. Return it in *FILE + * and schedule it for fsync in BATCH. If BATCH already contains an open + * file for FILENAME, return that instead creating a new instance. + * + * Use SCRATCH_POOL for temporaries. */ +svn_error_t * +svn_fs_x__batch_fsync_open_file(apr_file_t **file, + svn_fs_x__batch_fsync_t *batch, + const char *filename, + apr_pool_t *scratch_pool); + +/* Inform the BATCH that a file or directory has been created at PATH. + * "Created" means either newly created to renamed to PATH - even if another + * item with the same name existed before. Depending on the OS, the correct + * path will scheduled for fsync. + * + * Use SCRATCH_POOL for temporaries. */ +svn_error_t * +svn_fs_x__batch_fsync_new_path(svn_fs_x__batch_fsync_t *batch, + const char *path, + apr_pool_t *scratch_pool); + +/* For all files and directories in BATCH, flush all changes to disk and + * close the file handles. Use SCRATCH_POOL for temporaries. */ +svn_error_t * +svn_fs_x__batch_fsync_run(svn_fs_x__batch_fsync_t *batch, + apr_pool_t *scratch_pool); + +#endif diff --git a/subversion/libsvn_fs_x/cached_data.c b/subversion/libsvn_fs_x/cached_data.c index 2fdf5699962b..909842e5c456 100644 --- a/subversion/libsvn_fs_x/cached_data.c +++ b/subversion/libsvn_fs_x/cached_data.c @@ -30,6 +30,7 @@ #include "private/svn_io_private.h" #include "private/svn_sorts_private.h" +#include "private/svn_string_private.h" #include "private/svn_subr_private.h" #include "private/svn_temp_serializer.h" @@ -54,6 +55,7 @@ block_read(void **result, svn_fs_t *fs, const svn_fs_x__id_t *id, svn_fs_x__revision_file_t *revision_file, + void *baton, apr_pool_t *result_pool, apr_pool_t *scratch_pool); @@ -67,7 +69,7 @@ block_read(void **result, * contents if not NULL. Use SCRATCH_POOL for temporary allocations. */ static svn_error_t * -dgb__log_access(svn_fs_t *fs, +dbg__log_access(svn_fs_t *fs, const svn_fs_x__id_t *id, void *item, apr_uint32_t item_type, @@ -173,21 +175,6 @@ dgb__log_access(svn_fs_t *fs, return SVN_NO_ERROR; } -/* Convenience wrapper around svn_io_file_aligned_seek, taking filesystem - FS instead of a block size. */ -static svn_error_t * -aligned_seek(svn_fs_t *fs, - apr_file_t *file, - apr_off_t *buffer_start, - apr_off_t offset, - apr_pool_t *scratch_pool) -{ - svn_fs_x__data_t *ffd = fs->fsap_data; - return svn_error_trace(svn_io_file_aligned_seek(file, ffd->block_size, - buffer_start, offset, - scratch_pool)); -} - /* Open the revision file for the item given by ID in filesystem FS and store the newly opened file in FILE. Seek to the item's location before returning. @@ -207,11 +194,10 @@ open_and_seek_revision(svn_fs_x__revision_file_t **file, SVN_ERR(svn_fs_x__ensure_revision_exists(rev, fs, scratch_pool)); - SVN_ERR(svn_fs_x__open_pack_or_rev_file(&rev_file, fs, rev, result_pool, - scratch_pool)); + SVN_ERR(svn_fs_x__rev_file_init(&rev_file, fs, rev, result_pool)); SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, rev_file, id, scratch_pool)); - SVN_ERR(aligned_seek(fs, rev_file->file, NULL, offset, scratch_pool)); + SVN_ERR(svn_fs_x__rev_file_seek(rev_file, NULL, offset)); *file = rev_file; @@ -233,12 +219,12 @@ open_and_seek_transaction(svn_fs_x__revision_file_t **file, apr_uint32_t sub_item = 0; apr_int64_t txn_id = svn_fs_x__get_txn_id(rep->id.change_set); - SVN_ERR(svn_fs_x__open_proto_rev_file(file, fs, txn_id, result_pool, - scratch_pool)); + SVN_ERR(svn_fs_x__rev_file_open_proto_rev(file, fs, txn_id, result_pool, + scratch_pool)); SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, *file, &rep->id, scratch_pool)); - SVN_ERR(aligned_seek(fs, (*file)->file, NULL, offset, scratch_pool)); + SVN_ERR(svn_fs_x__rev_file_seek(*file, NULL, offset)); return SVN_NO_ERROR; } @@ -294,6 +280,7 @@ get_node_revision_body(svn_fs_x__noderev_t **noderev_p, if (svn_fs_x__is_txn(id->change_set)) { apr_file_t *file; + svn_stream_t *stream; /* This is a transaction node-rev. Its storage logic is very different from that of rev / pack files. */ @@ -303,21 +290,19 @@ get_node_revision_body(svn_fs_x__noderev_t **noderev_p, scratch_pool), APR_READ | APR_BUFFERED, APR_OS_DEFAULT, scratch_pool); - if (err) + if (err && APR_STATUS_IS_ENOENT(err->apr_err)) + { + svn_error_clear(err); + return svn_error_trace(err_dangling_id(fs, id)); + } + else if (err) { - if (APR_STATUS_IS_ENOENT(err->apr_err)) - { - svn_error_clear(err); - return svn_error_trace(err_dangling_id(fs, id)); - } - return svn_error_trace(err); } - SVN_ERR(svn_fs_x__read_noderev(noderev_p, - svn_stream_from_aprfile2(file, - FALSE, - scratch_pool), + /* Be sure to close the file ASAP. */ + stream = svn_stream_from_aprfile2(file, FALSE, scratch_pool); + SVN_ERR(svn_fs_x__read_noderev(noderev_p, stream, result_pool, scratch_pool)); } else @@ -328,8 +313,8 @@ get_node_revision_body(svn_fs_x__noderev_t **noderev_p, svn_revnum_t revision = svn_fs_x__get_revnum(id->change_set); svn_fs_x__pair_cache_key_t key; - SVN_ERR(svn_fs_x__open_pack_or_rev_file(&revision_file, fs, revision, - scratch_pool, scratch_pool)); + SVN_ERR(svn_fs_x__rev_file_init(&revision_file, fs, revision, + scratch_pool)); /* First, try a noderevs container cache lookup. */ if ( svn_fs_x__is_packed_rev(fs, revision) @@ -355,22 +340,20 @@ get_node_revision_body(svn_fs_x__noderev_t **noderev_p, /* Not found or not applicable. Try a noderev cache lookup. * If that succeeds, we are done here. */ - if (ffd->node_revision_cache) - { - SVN_ERR(svn_cache__get((void **) noderev_p, - &is_cached, - ffd->node_revision_cache, - &key, - result_pool)); - if (is_cached) - return SVN_NO_ERROR; - } + SVN_ERR(svn_cache__get((void **) noderev_p, + &is_cached, + ffd->node_revision_cache, + &key, + result_pool)); + if (is_cached) + return SVN_NO_ERROR; /* block-read will parse the whole block and will also return the one noderev that we need right now. */ SVN_ERR(block_read((void **)noderev_p, fs, id, revision_file, + NULL, result_pool, scratch_pool)); SVN_ERR(svn_fs_x__close_revision_file(revision_file)); @@ -396,7 +379,7 @@ svn_fs_x__get_node_revision(svn_fs_x__noderev_t **noderev_p, id_string->data); } - SVN_ERR(dgb__log_access(fs, id, *noderev_p, + SVN_ERR(dbg__log_access(fs, id, *noderev_p, SVN_FS_X__ITEM_TYPE_NODEREV, scratch_pool)); return svn_error_trace(err); @@ -423,8 +406,8 @@ svn_fs_x__get_mergeinfo_count(apr_int64_t *count, svn_revnum_t revision = svn_fs_x__get_revnum(id->change_set); svn_fs_x__revision_file_t *rev_file; - SVN_ERR(svn_fs_x__open_pack_or_rev_file(&rev_file, fs, revision, - scratch_pool, scratch_pool)); + SVN_ERR(svn_fs_x__rev_file_init(&rev_file, fs, revision, + scratch_pool)); if ( svn_fs_x__is_packed_rev(fs, revision) && ffd->noderevs_container_cache) @@ -505,39 +488,13 @@ typedef struct rep_state_t int chunk_index; /* number of the window to read */ } rep_state_t; -/* Simple wrapper around svn_fs_x__get_file_offset to simplify callers. */ -static svn_error_t * -get_file_offset(apr_off_t *offset, - rep_state_t *rs, - apr_pool_t *scratch_pool) -{ - return svn_error_trace(svn_fs_x__get_file_offset(offset, - rs->sfile->rfile->file, - scratch_pool)); -} - -/* Simple wrapper around svn_io_file_aligned_seek to simplify callers. */ -static svn_error_t * -rs_aligned_seek(rep_state_t *rs, - apr_off_t *buffer_start, - apr_off_t offset, - apr_pool_t *scratch_pool) -{ - svn_fs_x__data_t *ffd = rs->sfile->fs->fsap_data; - return svn_error_trace(svn_io_file_aligned_seek(rs->sfile->rfile->file, - ffd->block_size, - buffer_start, offset, - scratch_pool)); -} - /* Open FILE->FILE and FILE->STREAM if they haven't been opened, yet. */ static svn_error_t* auto_open_shared_file(shared_file_t *file) { if (file->rfile == NULL) - SVN_ERR(svn_fs_x__open_pack_or_rev_file(&file->rfile, file->fs, - file->revision, file->pool, - file->pool)); + SVN_ERR(svn_fs_x__rev_file_init(&file->rfile, file->fs, + file->revision, file->pool)); return SVN_NO_ERROR; } @@ -571,9 +528,8 @@ auto_read_diff_version(rep_state_t *rs, if (rs->ver == -1) { char buf[4]; - SVN_ERR(rs_aligned_seek(rs, NULL, rs->start, scratch_pool)); - SVN_ERR(svn_io_file_read_full2(rs->sfile->rfile->file, buf, - sizeof(buf), NULL, NULL, scratch_pool)); + SVN_ERR(svn_fs_x__rev_file_seek(rs->sfile->rfile, NULL, rs->start)); + SVN_ERR(svn_fs_x__rev_file_read(rs->sfile->rfile, buf, sizeof(buf))); /* ### Layering violation */ if (! ((buf[0] == 'S') && (buf[1] == 'V') && (buf[2] == 'N'))) @@ -655,7 +611,7 @@ create_rep_state_body(rep_state_t **rep_state, : NULL; /* cache lookup, i.e. skip reading the rep header if possible */ - if (ffd->rep_header_cache && SVN_IS_VALID_REVNUM(revision)) + if (SVN_IS_VALID_REVNUM(revision)) SVN_ERR(svn_cache__get((void **) &rh, &is_cached, ffd->rep_header_cache, &key, result_pool)); @@ -680,6 +636,8 @@ create_rep_state_body(rep_state_t **rep_state, /* read rep header, if necessary */ if (!is_cached) { + svn_stream_t *stream; + /* we will need the on-disk location for non-txn reps */ apr_off_t offset; svn_boolean_t in_container = TRUE; @@ -731,26 +689,26 @@ create_rep_state_body(rep_state_t **rep_state, return SVN_NO_ERROR; } - SVN_ERR(rs_aligned_seek(rs, NULL, offset, scratch_pool)); + SVN_ERR(svn_fs_x__rev_file_seek(rs->sfile->rfile, NULL, offset)); } - SVN_ERR(svn_fs_x__read_rep_header(&rh, rs->sfile->rfile->stream, + SVN_ERR(svn_fs_x__rev_file_stream(&stream, rs->sfile->rfile)); + SVN_ERR(svn_fs_x__read_rep_header(&rh, stream, result_pool, scratch_pool)); - SVN_ERR(get_file_offset(&rs->start, rs, result_pool)); + SVN_ERR(svn_fs_x__rev_file_offset(&rs->start, rs->sfile->rfile)); /* populate the cache if appropriate */ if (SVN_IS_VALID_REVNUM(revision)) { - SVN_ERR(block_read(NULL, fs, &rs->rep_id, rs->sfile->rfile, + SVN_ERR(block_read(NULL, fs, &rs->rep_id, rs->sfile->rfile, NULL, result_pool, scratch_pool)); - if (ffd->rep_header_cache) - SVN_ERR(svn_cache__set(ffd->rep_header_cache, &key, rh, - scratch_pool)); + SVN_ERR(svn_cache__set(ffd->rep_header_cache, &key, rh, + scratch_pool)); } } /* finalize */ - SVN_ERR(dgb__log_access(fs, &rs->rep_id, rh, SVN_FS_X__ITEM_TYPE_ANY_REP, + SVN_ERR(dbg__log_access(fs, &rs->rep_id, rh, SVN_FS_X__ITEM_TYPE_ANY_REP, scratch_pool)); rs->header_size = rh->header_size; @@ -820,8 +778,7 @@ svn_fs_x__check_rep(svn_fs_x__representation_t *rep, svn_revnum_t revision = svn_fs_x__get_revnum(rep->id.change_set); svn_fs_x__revision_file_t *rev_file; - SVN_ERR(svn_fs_x__open_pack_or_rev_file(&rev_file, fs, revision, - scratch_pool, scratch_pool)); + SVN_ERR(svn_fs_x__rev_file_init(&rev_file, fs, revision, scratch_pool)); /* Does REP->ID refer to an actual item? Which one is it? */ SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, rev_file, &rep->id, @@ -1075,22 +1032,14 @@ get_cached_window_sizes(window_sizes_t **sizes, svn_boolean_t *is_cached, apr_pool_t *pool) { - if (! rs->window_cache) - { - /* txdelta window has not been enabled */ - *is_cached = FALSE; - } - else - { - svn_fs_x__window_cache_key_t key = { 0 }; - SVN_ERR(svn_cache__get_partial((void **)sizes, - is_cached, - rs->window_cache, - get_window_key(&key, rs), - get_cached_window_sizes_func, - NULL, - pool)); - } + svn_fs_x__window_cache_key_t key = { 0 }; + SVN_ERR(svn_cache__get_partial((void **)sizes, + is_cached, + rs->window_cache, + get_window_key(&key, rs), + get_cached_window_sizes_func, + NULL, + pool)); return SVN_NO_ERROR; } @@ -1103,33 +1052,25 @@ get_cached_window(svn_txdelta_window_t **window_p, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - if (! rs->window_cache) - { - /* txdelta window has not been enabled */ - *is_cached = FALSE; - } - else - { - /* ask the cache for the desired txdelta window */ - svn_fs_x__txdelta_cached_window_t *cached_window; - svn_fs_x__window_cache_key_t key = { 0 }; - get_window_key(&key, rs); - key.chunk_index = chunk_index; - SVN_ERR(svn_cache__get((void **) &cached_window, - is_cached, - rs->window_cache, - &key, - result_pool)); + /* ask the cache for the desired txdelta window */ + svn_fs_x__txdelta_cached_window_t *cached_window; + svn_fs_x__window_cache_key_t key = { 0 }; + get_window_key(&key, rs); + key.chunk_index = chunk_index; + SVN_ERR(svn_cache__get((void **) &cached_window, + is_cached, + rs->window_cache, + &key, + result_pool)); - if (*is_cached) - { - /* found it. Pass it back to the caller. */ - *window_p = cached_window->window; + if (*is_cached) + { + /* found it. Pass it back to the caller. */ + *window_p = cached_window->window; - /* manipulate the RS as if we just read the data */ - rs->current = cached_window->end_offset; - rs->chunk_index = chunk_index; - } + /* manipulate the RS as if we just read the data */ + rs->current = cached_window->end_offset; + rs->chunk_index = chunk_index; } return SVN_NO_ERROR; @@ -1145,23 +1086,20 @@ set_cached_window(svn_txdelta_window_t *window, apr_off_t start_offset, apr_pool_t *scratch_pool) { - if (rs->window_cache) - { - /* store the window and the first offset _past_ it */ - svn_fs_x__txdelta_cached_window_t cached_window; - svn_fs_x__window_cache_key_t key = {0}; + /* store the window and the first offset _past_ it */ + svn_fs_x__txdelta_cached_window_t cached_window; + svn_fs_x__window_cache_key_t key = {0}; - cached_window.window = window; - cached_window.start_offset = start_offset - rs->start; - cached_window.end_offset = rs->current; + cached_window.window = window; + cached_window.start_offset = start_offset - rs->start; + cached_window.end_offset = rs->current; - /* but key it with the start offset because that is the known state - * when we will look it up */ - SVN_ERR(svn_cache__set(rs->window_cache, - get_window_key(&key, rs), - &cached_window, - scratch_pool)); - } + /* but key it with the start offset because that is the known state + * when we will look it up */ + SVN_ERR(svn_cache__set(rs->window_cache, + get_window_key(&key, rs), + &cached_window, + scratch_pool)); return SVN_NO_ERROR; } @@ -1178,23 +1116,13 @@ get_cached_combined_window(svn_stringbuf_t **window_p, svn_boolean_t *is_cached, apr_pool_t *pool) { - if (! rs->combined_cache) - { - /* txdelta window has not been enabled */ - *is_cached = FALSE; - } - else - { - /* ask the cache for the desired txdelta window */ - svn_fs_x__window_cache_key_t key = { 0 }; - return svn_cache__get((void **)window_p, - is_cached, - rs->combined_cache, - get_window_key(&key, rs), - pool); - } - - return SVN_NO_ERROR; + /* ask the cache for the desired txdelta window */ + svn_fs_x__window_cache_key_t key = { 0 }; + return svn_cache__get((void **)window_p, + is_cached, + rs->combined_cache, + get_window_key(&key, rs), + pool); } /* Store the WINDOW read for the rep state RS in the current FSX session's @@ -1205,18 +1133,13 @@ set_cached_combined_window(svn_stringbuf_t *window, rep_state_t *rs, apr_pool_t *scratch_pool) { - if (rs->combined_cache) - { - /* but key it with the start offset because that is the known state - * when we will look it up */ - svn_fs_x__window_cache_key_t key = { 0 }; - return svn_cache__set(rs->combined_cache, - get_window_key(&key, rs), - window, - scratch_pool); - } - - return SVN_NO_ERROR; + /* but key it with the start offset because that is the known state + * when we will look it up */ + svn_fs_x__window_cache_key_t key = { 0 }; + return svn_cache__set(rs->combined_cache, + get_window_key(&key, rs), + window, + scratch_pool); } /* Build an array of rep_state structures in *LIST giving the delta @@ -1264,7 +1187,8 @@ build_rep_list(apr_array_header_t **list, /* for txn reps and containered reps, there won't be a cached * combined window */ if (svn_fs_x__is_revision(rep.id.change_set) - && rep_header->type != svn_fs_x__rep_container) + && rep_header->type != svn_fs_x__rep_container + && rs->combined_cache) SVN_ERR(get_cached_combined_window(window_p, rs, &is_cached, result_pool)); @@ -1364,30 +1288,37 @@ read_delta_window(svn_txdelta_window_t **nwin, int this_chunk, apr_off_t start_offset; apr_off_t end_offset; apr_pool_t *iterpool; + svn_stream_t *stream; + svn_fs_x__revision_file_t *file; + svn_boolean_t cacheable = rs->chunk_index == 0 + && svn_fs_x__is_revision(rs->rep_id.change_set) + && rs->window_cache; SVN_ERR_ASSERT(rs->chunk_index <= this_chunk); - SVN_ERR(dgb__log_access(rs->sfile->fs, &rs->rep_id, NULL, + SVN_ERR(dbg__log_access(rs->sfile->fs, &rs->rep_id, NULL, SVN_FS_X__ITEM_TYPE_ANY_REP, scratch_pool)); /* Read the next window. But first, try to find it in the cache. */ - SVN_ERR(get_cached_window(nwin, rs, this_chunk, &is_cached, - result_pool, scratch_pool)); - if (is_cached) - return SVN_NO_ERROR; + if (cacheable) + { + SVN_ERR(get_cached_window(nwin, rs, this_chunk, &is_cached, + result_pool, scratch_pool)); + if (is_cached) + return SVN_NO_ERROR; + } /* someone has to actually read the data from file. Open it */ SVN_ERR(auto_open_shared_file(rs->sfile)); + file = rs->sfile->rfile; /* invoke the 'block-read' feature for non-txn data. However, don't do that if we are in the middle of some representation, because the block is unlikely to contain other data. */ - if ( rs->chunk_index == 0 - && svn_fs_x__is_revision(rs->rep_id.change_set) - && rs->window_cache) + if (cacheable) { - SVN_ERR(block_read(NULL, rs->sfile->fs, &rs->rep_id, - rs->sfile->rfile, result_pool, scratch_pool)); + SVN_ERR(block_read(NULL, rs->sfile->fs, &rs->rep_id, file, NULL, + result_pool, scratch_pool)); /* reading the whole block probably also provided us with the desired txdelta window */ @@ -1405,18 +1336,19 @@ read_delta_window(svn_txdelta_window_t **nwin, int this_chunk, /* RS->FILE may be shared between RS instances -> make sure we point * to the right data. */ start_offset = rs->start + rs->current; - SVN_ERR(rs_aligned_seek(rs, NULL, start_offset, scratch_pool)); + SVN_ERR(svn_fs_x__rev_file_seek(file, NULL, start_offset)); /* Skip windows to reach the current chunk if we aren't there yet. */ iterpool = svn_pool_create(scratch_pool); while (rs->chunk_index < this_chunk) { - apr_file_t *file = rs->sfile->rfile->file; + apr_file_t *apr_file; svn_pool_clear(iterpool); - SVN_ERR(svn_txdelta_skip_svndiff_window(file, rs->ver, iterpool)); + SVN_ERR(svn_fs_x__rev_file_get(&apr_file, file)); + SVN_ERR(svn_txdelta_skip_svndiff_window(apr_file, rs->ver, iterpool)); rs->chunk_index++; - SVN_ERR(svn_fs_x__get_file_offset(&start_offset, file, iterpool)); + SVN_ERR(svn_io_file_get_offset(&start_offset, apr_file, iterpool)); rs->current = start_offset - rs->start; if (rs->current >= rs->size) @@ -1428,9 +1360,10 @@ read_delta_window(svn_txdelta_window_t **nwin, int this_chunk, svn_pool_destroy(iterpool); /* Actually read the next window. */ - SVN_ERR(svn_txdelta_read_svndiff_window(nwin, rs->sfile->rfile->stream, - rs->ver, result_pool)); - SVN_ERR(get_file_offset(&end_offset, rs, scratch_pool)); + SVN_ERR(svn_fs_x__rev_file_stream(&stream, file)); + SVN_ERR(svn_txdelta_read_svndiff_window(nwin, stream, rs->ver, + result_pool)); + SVN_ERR(svn_fs_x__rev_file_offset(&end_offset, file)); rs->current = end_offset - rs->start; if (rs->current > rs->size) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, @@ -1439,7 +1372,7 @@ read_delta_window(svn_txdelta_window_t **nwin, int this_chunk, /* the window has not been cached before, thus cache it now * (if caching is used for them at all) */ - if (svn_fs_x__is_revision(rs->rep_id.change_set)) + if (cacheable) SVN_ERR(set_cached_window(*nwin, rs, start_offset, scratch_pool)); return SVN_NO_ERROR; @@ -1458,31 +1391,29 @@ read_container_window(svn_stringbuf_t **nwin, svn_fs_x__data_t *ffd = fs->fsap_data; svn_fs_x__pair_cache_key_t key; svn_revnum_t revision = svn_fs_x__get_revnum(rs->rep_id.change_set); + svn_boolean_t is_cached = FALSE; + svn_fs_x__reps_baton_t baton; SVN_ERR(auto_set_start_offset(rs, scratch_pool)); key.revision = svn_fs_x__packed_base_rev(fs, revision); key.second = rs->start; /* already in cache? */ - if (ffd->reps_container_cache) - { - svn_boolean_t is_cached = FALSE; - svn_fs_x__reps_baton_t baton; - baton.fs = fs; - baton.idx = rs->sub_item; + baton.fs = fs; + baton.idx = rs->sub_item; - SVN_ERR(svn_cache__get_partial((void**)&extractor, &is_cached, - ffd->reps_container_cache, &key, - svn_fs_x__reps_get_func, &baton, - result_pool)); - } + SVN_ERR(svn_cache__get_partial((void**)&extractor, &is_cached, + ffd->reps_container_cache, &key, + svn_fs_x__reps_get_func, &baton, + result_pool)); /* read from disk, if necessary */ if (extractor == NULL) { SVN_ERR(auto_open_shared_file(rs->sfile)); SVN_ERR(block_read((void **)&extractor, fs, &rs->rep_id, - rs->sfile->rfile, result_pool, scratch_pool)); + rs->sfile->rfile, NULL, + result_pool, scratch_pool)); } SVN_ERR(svn_fs_x__extractor_drive(nwin, extractor, rs->current, size, @@ -1569,7 +1500,8 @@ get_combined_window(svn_stringbuf_t **result, single chunk. Only then will no other chunk need a deeper RS list than the cached chunk. */ if ( (rb->chunk_index == 0) && (rs->current == rs->size) - && svn_fs_x__is_revision(rs->rep_id.change_set)) + && svn_fs_x__is_revision(rs->rep_id.change_set) + && rs->combined_cache) SVN_ERR(set_cached_combined_window(buf, rs, new_pool)); rs->chunk_index++; @@ -1587,7 +1519,7 @@ get_combined_window(svn_stringbuf_t **result, } /* Returns whether or not the expanded fulltext of the file is cachable - * based on its size SIZE. The decision depends on the cache used by RB. + * based on its size SIZE. The decision depends on the cache used by FFD. */ static svn_boolean_t fulltext_size_is_cachable(svn_fs_x__data_t *ffd, @@ -1690,23 +1622,23 @@ cache_windows(svn_filesize_t *fulltext_len, else { svn_txdelta_window_t *window; + svn_fs_x__revision_file_t *file = rs->sfile->rfile; + svn_stream_t *stream; apr_off_t start_offset = rs->start + rs->current; apr_off_t end_offset; apr_off_t block_start; /* navigate to & read the current window */ - SVN_ERR(rs_aligned_seek(rs, &block_start, start_offset, iterpool)); - SVN_ERR(svn_txdelta_read_svndiff_window(&window, - rs->sfile->rfile->stream, - rs->ver, iterpool)); + SVN_ERR(svn_fs_x__rev_file_stream(&stream, file)); + SVN_ERR(svn_fs_x__rev_file_seek(file, &block_start, start_offset)); + SVN_ERR(svn_txdelta_read_svndiff_window(&window, stream, rs->ver, + iterpool)); /* aggregate expanded window size */ *fulltext_len += window->tview_len; /* determine on-disk window size */ - SVN_ERR(svn_fs_x__get_file_offset(&end_offset, - rs->sfile->rfile->file, - iterpool)); + SVN_ERR(svn_fs_x__rev_file_offset(&end_offset, rs->sfile->rfile)); rs->current = end_offset - rs->start; if (rs->current > rs->size) return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, @@ -1735,25 +1667,22 @@ cache_windows(svn_filesize_t *fulltext_len, static svn_error_t * read_rep_header(svn_fs_x__rep_header_t **rep_header, svn_fs_t *fs, - svn_stream_t *stream, + svn_fs_x__revision_file_t *file, svn_fs_x__representation_cache_key_t *key, apr_pool_t *pool) { svn_fs_x__data_t *ffd = fs->fsap_data; + svn_stream_t *stream; svn_boolean_t is_cached = FALSE; - if (ffd->rep_header_cache) - { - SVN_ERR(svn_cache__get((void**)rep_header, &is_cached, - ffd->rep_header_cache, key, pool)); - if (is_cached) - return SVN_NO_ERROR; - } + SVN_ERR(svn_cache__get((void**)rep_header, &is_cached, + ffd->rep_header_cache, key, pool)); + if (is_cached) + return SVN_NO_ERROR; + SVN_ERR(svn_fs_x__rev_file_stream(&stream, file)); SVN_ERR(svn_fs_x__read_rep_header(rep_header, stream, pool, pool)); - - if (ffd->rep_header_cache) - SVN_ERR(svn_cache__set(ffd->rep_header_cache, key, *rep_header, pool)); + SVN_ERR(svn_cache__set(ffd->rep_header_cache, key, *rep_header, pool)); return SVN_NO_ERROR; } @@ -1779,8 +1708,7 @@ svn_fs_x__get_representation_length(svn_filesize_t *packed_len, key.revision = svn_fs_x__get_revnum(entry->items[0].change_set); key.is_packed = svn_fs_x__is_packed_rev(fs, key.revision); key.item_index = entry->items[0].number; - SVN_ERR(read_rep_header(&rep_header, fs, rev_file->stream, &key, - scratch_pool)); + SVN_ERR(read_rep_header(&rep_header, fs, rev_file, &key, scratch_pool)); /* prepare representation reader state (rs) structure */ SVN_ERR(init_rep_state(&rs, rep_header, fs, rev_file, entry, @@ -1829,10 +1757,10 @@ get_contents_from_windows(rep_read_baton_t *rb, This is where we need the pseudo rep_state created by build_rep_list(). */ apr_size_t offset = (apr_size_t)rs->current; - if (copy_len + offset > rb->base_window->len) - copy_len = offset < rb->base_window->len - ? rb->base_window->len - offset - : 0ul; + if (offset >= rb->base_window->len) + copy_len = 0ul; + else if (copy_len > rb->base_window->len - offset) + copy_len = rb->base_window->len - offset; memcpy (cur, rb->base_window->data + offset, copy_len); } @@ -2052,6 +1980,16 @@ skip_contents(rep_read_baton_t *baton, len -= to_read; buffer += to_read; } + + /* Make the MD5 calculation catch up with the data delivered + * (we did not run MD5 on the data that we took from the cache). */ + if (!err) + { + SVN_ERR(svn_checksum_update(baton->md5_checksum_ctx, + baton->current_fulltext->data, + baton->current_fulltext->len)); + baton->off += baton->current_fulltext->len; + } } else if (len > 0) { @@ -2067,6 +2005,15 @@ skip_contents(rep_read_baton_t *baton, err = get_contents_from_windows(baton, buffer, &to_read); len -= to_read; + + /* Make the MD5 calculation catch up with the data delivered + * (we did not run MD5 on the data that we took from the cache). */ + if (!err) + { + SVN_ERR(svn_checksum_update(baton->md5_checksum_ctx, + buffer, to_read)); + baton->off += to_read; + } } svn_pool_destroy(subpool); @@ -2112,8 +2059,13 @@ rep_read_contents(void *baton, SVN_ERR(skip_contents(rb, rb->fulltext_delivered)); } - /* Get the next block of data. */ - SVN_ERR(get_contents_from_windows(rb, buf, len)); + /* Get the next block of data. + * Keep in mind that the representation might be empty and leave us + * already positioned at the end of the rep. */ + if (rb->off == rb->len) + *len = 0; + else + SVN_ERR(get_contents_from_windows(rb, buf, len)); if (rb->current_fulltext) svn_stringbuf_appendbytes(rb->current_fulltext, buf, *len); @@ -2186,7 +2138,7 @@ svn_fs_x__get_contents(svn_stream_t **contents_p, /* Make the stream attempt fulltext cache lookups if the fulltext * is cacheable. If it is not, then also don't try to buffer and * cache it. */ - if (ffd->fulltext_cache && cache_fulltext + if ( cache_fulltext && SVN_IS_VALID_REVNUM(revision) && fulltext_size_is_cachable(ffd, len)) { @@ -2208,6 +2160,86 @@ svn_fs_x__get_contents(svn_stream_t **contents_p, return SVN_NO_ERROR; } +svn_error_t * +svn_fs_x__get_contents_from_file(svn_stream_t **contents_p, + svn_fs_t *fs, + svn_fs_x__representation_t *rep, + apr_file_t *file, + apr_off_t offset, + apr_pool_t *pool) +{ + rep_read_baton_t *rb; + svn_fs_x__pair_cache_key_t fulltext_cache_key = { SVN_INVALID_REVNUM, 0 }; + rep_state_t *rs = apr_pcalloc(pool, sizeof(*rs)); + svn_fs_x__rep_header_t *rh; + svn_stream_t *stream; + + /* Initialize the reader baton. Some members may added lazily + * while reading from the stream. */ + SVN_ERR(rep_read_get_baton(&rb, fs, rep, fulltext_cache_key, pool)); + + /* Continue constructing RS. Leave caches as NULL. */ + rs->size = rep->size; + rs->rep_id = rep->id; + rs->ver = -1; + rs->start = -1; + + /* Provide just enough file access info to allow for a basic read from + * FILE but leave all index / footer info with empty values b/c FILE + * probably is not a complete revision file. */ + rs->sfile = apr_pcalloc(pool, sizeof(*rs->sfile)); + rs->sfile->revision = SVN_INVALID_REVNUM; + rs->sfile->pool = pool; + rs->sfile->fs = fs; + SVN_ERR(svn_fs_x__rev_file_wrap_temp(&rs->sfile->rfile, fs, file, pool)); + + /* Read the rep header. */ + SVN_ERR(svn_fs_x__rev_file_seek(rs->sfile->rfile, NULL, offset)); + SVN_ERR(svn_fs_x__rev_file_stream(&stream, rs->sfile->rfile)); + SVN_ERR(svn_fs_x__read_rep_header(&rh, stream, pool, pool)); + SVN_ERR(svn_fs_x__rev_file_offset(&rs->start, rs->sfile->rfile)); + rs->header_size = rh->header_size; + + /* Log the access. */ + SVN_ERR(dbg__log_access(fs, &rep->id, rh, + SVN_FS_X__ITEM_TYPE_ANY_REP, pool)); + + /* Build the representation list (delta chain). */ + if (rh->type == svn_fs_x__rep_self_delta) + { + rb->rs_list = apr_array_make(pool, 1, sizeof(rep_state_t *)); + APR_ARRAY_PUSH(rb->rs_list, rep_state_t *) = rs; + rb->src_state = NULL; + } + else + { + svn_fs_x__representation_t next_rep = { 0 }; + + /* skip "SVNx" diff marker */ + rs->current = 4; + + /* REP's base rep is inside a proper revision. + * It can be reconstructed in the usual way. */ + next_rep.id.change_set = svn_fs_x__change_set_by_rev(rh->base_revision); + next_rep.id.number = rh->base_item_index; + next_rep.size = rh->base_length; + + SVN_ERR(build_rep_list(&rb->rs_list, &rb->base_window, + &rb->src_state, rb->fs, &next_rep, + rb->filehandle_pool, rb->scratch_pool)); + + /* Insert the access to REP as the first element of the delta chain. */ + svn_sort__array_insert(rb->rs_list, &rs, 0); + } + + /* Now, the baton is complete and we can assemble the stream around it. */ + *contents_p = svn_stream_create(rb, pool); + svn_stream_set_read2(*contents_p, NULL /* only full read support */, + rep_read_contents); + svn_stream_set_close(*contents_p, rep_read_contents_close); + + return SVN_NO_ERROR; +} /* Baton for cache_access_wrapper. Wraps the original parameters of * svn_fs_x__try_process_file_content(). @@ -2257,8 +2289,7 @@ svn_fs_x__try_process_file_contents(svn_boolean_t *success, fulltext_cache_key.revision = svn_fs_x__get_revnum(rep->id.change_set); fulltext_cache_key.second = rep->id.number; - if (ffd->fulltext_cache - && SVN_IS_VALID_REVNUM(fulltext_cache_key.revision) + if ( SVN_IS_VALID_REVNUM(fulltext_cache_key.revision) && fulltext_size_is_cachable(ffd, rep->expanded_size)) { cache_access_wrapper_baton_t wrapper_baton; @@ -2344,12 +2375,11 @@ svn_fs_x__get_file_delta_stream(svn_txdelta_stream_t **stream_p, svn_stream_t *source_stream, *target_stream; rep_state_t *rep_state; svn_fs_x__rep_header_t *rep_header; - svn_fs_x__data_t *ffd = fs->fsap_data; /* Try a shortcut: if the target is stored as a delta against the source, then just use that delta. However, prefer using the fulltext cache whenever that is available. */ - if (target->data_rep && (source || !ffd->fulltext_cache)) + if (target->data_rep && source) { /* Read target's base rep if any. */ SVN_ERR(create_rep_state(&rep_state, &rep_header, NULL, @@ -2449,117 +2479,147 @@ compare_dirent_name(const void *a, return strcmp(lhs->name, rhs); } -/* Into ENTRIES, read all directories entries from the key-value text in - * STREAM. If INCREMENTAL is TRUE, read until the end of the STREAM and +/* Into ENTRIES, parse all directories entries from the serialized form in + * DATA. If INCREMENTAL is TRUE, read until the end of the STREAM and * update the data. ID is provided for nicer error messages. + * + * The contents of DATA will be shared with the items in ENTRIES, i.e. it + * must not be modified afterwards and must remain valid as long as ENTRIES + * is valid. Use SCRATCH_POOL for temporary allocations. */ static svn_error_t * -read_dir_entries(apr_array_header_t *entries, - svn_stream_t *stream, - svn_boolean_t incremental, - const svn_fs_x__id_t *id, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) +parse_dir_entries(apr_array_header_t **entries_p, + const svn_stringbuf_t *data, + svn_boolean_t incremental, + const svn_fs_x__id_t *id, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { - apr_pool_t *iterpool = svn_pool_create(scratch_pool); + const apr_byte_t *p = (const apr_byte_t *)data->data; + const apr_byte_t *end = p + data->len; + apr_uint64_t count; apr_hash_t *hash = incremental ? svn_hash__make(scratch_pool) : NULL; - const char *terminator = SVN_HASH_TERMINATOR; + apr_array_header_t *entries; - /* Read until the terminator (non-incremental) or the end of STREAM - (incremental mode). In the latter mode, we use a temporary HASH - to make updating and removing entries cheaper. */ - while (1) + /* Construct the resulting container. */ + p = svn__decode_uint(&count, p, end); + if (count > INT_MAX) + return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, + _("Directory for '%s' is too large"), + svn_fs_x__id_unparse(id, scratch_pool)->data); + + entries = apr_array_make(result_pool, (int)count, + sizeof(svn_fs_x__dirent_t *)); + + while (p != end) { - svn_hash__entry_t entry; + apr_size_t len; svn_fs_x__dirent_t *dirent; - char *str; - - svn_pool_clear(iterpool); - SVN_ERR(svn_hash__read_entry(&entry, stream, terminator, - incremental, iterpool)); - - /* End of directory? */ - if (entry.key == NULL) - { - /* In incremental mode, we skip the terminator and read the - increments following it until the end of the stream. */ - if (incremental && terminator) - terminator = NULL; - else - break; - } - - /* Deleted entry? */ - if (entry.val == NULL) - { - /* We must be in incremental mode */ - assert(hash); - apr_hash_set(hash, entry.key, entry.keylen, NULL); - continue; - } - - /* Add a new directory entry. */ dirent = apr_pcalloc(result_pool, sizeof(*dirent)); - dirent->name = apr_pstrmemdup(result_pool, entry.key, entry.keylen); - str = svn_cstring_tokenize(" ", &entry.val); - if (str == NULL) + /* The part of the serialized entry that is not the name will be + * about 6 bytes or less. Since APR allocates with an 8 byte + * alignment (4 bytes loss on average per string), simply using + * the name string in DATA already gives us near-optimal memory + * usage. */ + dirent->name = (const char *)p; + len = strlen(dirent->name); + p += len + 1; + if (p == end) return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, - _("Directory entry corrupt in '%s'"), - svn_fs_x__id_unparse(id, scratch_pool)->data); + _("Directory entry missing kind in '%s'"), + svn_fs_x__id_unparse(id, scratch_pool)->data); - if (strcmp(str, SVN_FS_X__KIND_FILE) == 0) - { - dirent->kind = svn_node_file; - } - else if (strcmp(str, SVN_FS_X__KIND_DIR) == 0) - { - dirent->kind = svn_node_dir; - } - else - { - return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, - _("Directory entry corrupt in '%s'"), - svn_fs_x__id_unparse(id, scratch_pool)->data); - } - - str = svn_cstring_tokenize(" ", &entry.val); - if (str == NULL) + dirent->kind = (svn_node_kind_t)*(p++); + if (p == end) return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, - _("Directory entry corrupt in '%s'"), - svn_fs_x__id_unparse(id, scratch_pool)->data); + _("Directory entry missing change set in '%s'"), + svn_fs_x__id_unparse(id, scratch_pool)->data); - SVN_ERR(svn_fs_x__id_parse(&dirent->id, str)); + p = svn__decode_int(&dirent->id.change_set, p, end); + if (p == end) + return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, + _("Directory entry missing item number in '%s'"), + svn_fs_x__id_unparse(id, scratch_pool)->data); + + p = svn__decode_uint(&dirent->id.number, p, end); /* In incremental mode, update the hash; otherwise, write to the * final array. */ if (incremental) - apr_hash_set(hash, dirent->name, entry.keylen, dirent); + { + /* Insertion / update or a deletion? */ + if (svn_fs_x__id_used(&dirent->id)) + apr_hash_set(hash, dirent->name, len, dirent); + else + apr_hash_set(hash, dirent->name, len, NULL); + } else - APR_ARRAY_PUSH(entries, svn_fs_x__dirent_t *) = dirent; + { + APR_ARRAY_PUSH(entries, svn_fs_x__dirent_t *) = dirent; + } } - /* Convert container to a sorted array. */ if (incremental) { + /* Convert container into a sorted array. */ apr_hash_index_t *hi; - for (hi = apr_hash_first(iterpool, hash); hi; hi = apr_hash_next(hi)) + for (hi = apr_hash_first(scratch_pool, hash); hi; hi = apr_hash_next(hi)) APR_ARRAY_PUSH(entries, svn_fs_x__dirent_t *) = apr_hash_this_val(hi); + + if (!sorted(entries)) + svn_sort__array(entries, compare_dirents); + } + else + { + /* Check that we read the expected amount of entries. */ + if ((apr_uint64_t)entries->nelts != count) + return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, + _("Directory length mismatch in '%s'"), + svn_fs_x__id_unparse(id, scratch_pool)->data); } - if (!sorted(entries)) - svn_sort__array(entries, compare_dirents); - - svn_pool_destroy(iterpool); + *entries_p = entries; return SVN_NO_ERROR; } -/* Fetch the contents of a directory into ENTRIES. Values are stored +/* For directory NODEREV in FS, return the *FILESIZE of its in-txn + * representation. If the directory representation is comitted data, + * set *FILESIZE to SVN_INVALID_FILESIZE. Use SCRATCH_POOL for temporaries. + */ +static svn_error_t * +get_txn_dir_info(svn_filesize_t *filesize, + svn_fs_t *fs, + svn_fs_x__noderev_t *noderev, + apr_pool_t *scratch_pool) +{ + if (noderev->data_rep + && ! svn_fs_x__is_revision(noderev->data_rep->id.change_set)) + { + const svn_io_dirent2_t *dirent; + const char *filename; + + filename = svn_fs_x__path_txn_node_children(fs, &noderev->noderev_id, + scratch_pool, scratch_pool); + + SVN_ERR(svn_io_stat_dirent2(&dirent, filename, FALSE, FALSE, + scratch_pool, scratch_pool)); + *filesize = dirent->filesize; + } + else + { + *filesize = SVN_INVALID_FILESIZE; + } + + return SVN_NO_ERROR; +} + +/* Fetch the contents of a directory into DIR. Values are stored as filename to string mappings; further conversion is necessary to convert them into svn_fs_x__dirent_t values. */ static svn_error_t * -get_dir_contents(apr_array_header_t **entries, +get_dir_contents(svn_fs_x__dir_data_t *dir, svn_fs_t *fs, svn_fs_x__noderev_t *noderev, apr_pool_t *result_pool, @@ -2567,43 +2627,66 @@ get_dir_contents(apr_array_header_t **entries, { svn_stream_t *contents; const svn_fs_x__id_t *id = &noderev->noderev_id; + apr_size_t len; + svn_stringbuf_t *text; + svn_boolean_t incremental; - *entries = apr_array_make(result_pool, 16, sizeof(svn_fs_x__dirent_t *)); + /* Initialize the result. */ + dir->txn_filesize = SVN_INVALID_FILESIZE; + + /* Read dir contents - unless there is none in which case we are done. */ if (noderev->data_rep && ! svn_fs_x__is_revision(noderev->data_rep->id.change_set)) { - const char *filename - = svn_fs_x__path_txn_node_children(fs, id, scratch_pool, - scratch_pool); + /* Get location & current size of the directory representation. */ + const char *filename; + apr_file_t *file; + + filename = svn_fs_x__path_txn_node_children(fs, id, scratch_pool, + scratch_pool); /* The representation is mutable. Read the old directory contents from the mutable children file, followed by the changes we've made in this transaction. */ - SVN_ERR(svn_stream_open_readonly(&contents, filename, scratch_pool, - scratch_pool)); - SVN_ERR(read_dir_entries(*entries, contents, TRUE, id, - result_pool, scratch_pool)); - SVN_ERR(svn_stream_close(contents)); + SVN_ERR(svn_io_file_open(&file, filename, APR_READ | APR_BUFFERED, + APR_OS_DEFAULT, scratch_pool)); + + /* Obtain txn children file size. */ + SVN_ERR(svn_io_file_size_get(&dir->txn_filesize, file, scratch_pool)); + len = (apr_size_t)dir->txn_filesize; + + /* Finally, provide stream access to FILE. */ + contents = svn_stream_from_aprfile2(file, FALSE, scratch_pool); + incremental = TRUE; } else if (noderev->data_rep) { - /* Undeltify content before parsing it. Otherwise, we could only - * parse it byte-by-byte. - */ - apr_size_t len = noderev->data_rep->expanded_size; - svn_stringbuf_t *text; - /* The representation is immutable. Read it normally. */ + len = noderev->data_rep->expanded_size; SVN_ERR(svn_fs_x__get_contents(&contents, fs, noderev->data_rep, FALSE, scratch_pool)); - SVN_ERR(svn_stringbuf_from_stream(&text, contents, len, scratch_pool)); - SVN_ERR(svn_stream_close(contents)); - - /* de-serialize hash */ - contents = svn_stream_from_stringbuf(text, scratch_pool); - SVN_ERR(read_dir_entries(*entries, contents, FALSE, id, - result_pool, scratch_pool)); + incremental = FALSE; } + else + { + /* Empty representation == empty directory. */ + dir->entries = apr_array_make(result_pool, 0, + sizeof(svn_fs_x__dirent_t *)); + return SVN_NO_ERROR; + } + + /* Read the whole stream contents into a single buffer. + * Due to our LEN hint, no allocation overhead occurs. + * + * Also, a large portion of TEXT will be file / dir names which we + * directly reference from DIR->ENTRIES instead of copying them. + * Hence, we need to use the RESULT_POOL here. */ + SVN_ERR(svn_stringbuf_from_stream(&text, contents, len, result_pool)); + SVN_ERR(svn_stream_close(contents)); + + /* de-serialize hash */ + SVN_ERR(parse_dir_entries(&dir->entries, text, incremental, id, + result_pool, scratch_pool)); return SVN_NO_ERROR; } @@ -2618,26 +2701,24 @@ locate_dir_cache(svn_fs_t *fs, svn_fs_x__noderev_t *noderev) { svn_fs_x__data_t *ffd = fs->fsap_data; - if (svn_fs_x__is_txn(noderev->noderev_id.change_set)) + + if (!noderev->data_rep) { - /* data in txns must be addressed by ID since the representation has - not been created, yet. */ + /* no data rep -> empty directory. + Use a key that does definitely not clash with non-NULL reps. */ + key->change_set = SVN_FS_X__INVALID_CHANGE_SET; + key->number = SVN_FS_X__ITEM_INDEX_UNUSED; + } + else if (svn_fs_x__is_txn(noderev->noderev_id.change_set)) + { + /* data in txns must be addressed by noderev ID since the + representation has not been created, yet. */ *key = noderev->noderev_id; } else { /* committed data can use simple rev,item pairs */ - if (noderev->data_rep) - { - *key = noderev->data_rep->id; - } - else - { - /* no data rep -> empty directory. - Use a key that does definitely not clash with non-NULL reps. */ - key->change_set = SVN_FS_X__INVALID_CHANGE_SET; - key->number = SVN_FS_X__ITEM_INDEX_UNUSED; - } + *key = noderev->data_rep->id; } return ffd->dir_cache; @@ -2651,26 +2732,40 @@ svn_fs_x__rep_contents_dir(apr_array_header_t **entries_p, apr_pool_t *scratch_pool) { svn_fs_x__id_t key; + svn_fs_x__dir_data_t *dir; /* find the cache we may use */ svn_cache__t *cache = locate_dir_cache(fs, &key, noderev); - if (cache) - { - svn_boolean_t found; + svn_boolean_t found; - SVN_ERR(svn_cache__get((void **)entries_p, &found, cache, &key, - result_pool)); - if (found) - return SVN_NO_ERROR; + SVN_ERR(svn_cache__get((void **)&dir, &found, cache, &key, result_pool)); + if (found) + { + /* Verify that the cached dir info is not stale + * (no-op for committed data). */ + svn_filesize_t filesize; + SVN_ERR(get_txn_dir_info(&filesize, fs, noderev, scratch_pool)); + + if (filesize == dir->txn_filesize) + { + /* Still valid. Done. */ + *entries_p = dir->entries; + return SVN_NO_ERROR; + } } /* Read in the directory contents. */ - SVN_ERR(get_dir_contents(entries_p, fs, noderev, result_pool, - scratch_pool)); + dir = apr_pcalloc(scratch_pool, sizeof(*dir)); + SVN_ERR(get_dir_contents(dir, fs, noderev, result_pool, scratch_pool)); + *entries_p = dir->entries; - /* Update the cache, if we are to use one. */ - if (cache) - SVN_ERR(svn_cache__set(cache, &key, *entries_p, scratch_pool)); + /* Update the cache, if we are to use one. + * + * Don't even attempt to serialize very large directories; it would cause + * an unnecessary memory allocation peak. 100 bytes/entry is about right. + */ + if (svn_cache__is_cachable(cache, 100 * dir->entries->nelts)) + SVN_ERR(svn_cache__set(cache, &key, dir, scratch_pool)); return SVN_NO_ERROR; } @@ -2699,40 +2794,49 @@ svn_fs_x__rep_contents_dir_entry(svn_fs_x__dirent_t **dirent, /* find the cache we may use */ svn_fs_x__id_t key; svn_cache__t *cache = locate_dir_cache(fs, &key, noderev); - if (cache) - { - svn_fs_x__ede_baton_t baton; - baton.hint = *hint; - baton.name = name; + svn_fs_x__ede_baton_t baton; - /* Cache lookup. */ - SVN_ERR(svn_cache__get_partial((void **)dirent, - &found, - cache, - &key, - svn_fs_x__extract_dir_entry, - &baton, - result_pool)); + svn_filesize_t filesize; + SVN_ERR(get_txn_dir_info(&filesize, fs, noderev, scratch_pool)); - /* Remember the new clue only if we found something at that spot. */ - if (found) - *hint = baton.hint; - } + /* Cache lookup. */ + baton.hint = *hint; + baton.name = name; + baton.txn_filesize = filesize; + + SVN_ERR(svn_cache__get_partial((void **)dirent, + &found, + cache, + &key, + svn_fs_x__extract_dir_entry, + &baton, + result_pool)); + + /* Remember the new clue only if we found something at that spot. */ + if (found) + *hint = baton.hint; /* fetch data from disk if we did not find it in the cache */ - if (! found) + if (! found || baton.out_of_date) { - apr_array_header_t *entries; svn_fs_x__dirent_t *entry; svn_fs_x__dirent_t *entry_copy = NULL; + svn_fs_x__dir_data_t dir; - /* read the dir from the file system. It will probably be put it - into the cache for faster lookup in future calls. */ - SVN_ERR(svn_fs_x__rep_contents_dir(&entries, fs, noderev, - scratch_pool, scratch_pool)); + /* Read in the directory contents. */ + SVN_ERR(get_dir_contents(&dir, fs, noderev, scratch_pool, + scratch_pool)); + + /* Update the cache, if we are to use one. + * + * Don't even attempt to serialize very large directories; it would + * cause an unnecessary memory allocation peak. 150 bytes / entry is + * about right. */ + if (cache && svn_cache__is_cachable(cache, 150 * dir.entries->nelts)) + SVN_ERR(svn_cache__set(cache, &key, &dir, scratch_pool)); /* find desired entry and return a copy in POOL, if found */ - entry = svn_fs_x__find_dir_entry(entries, name, NULL); + entry = svn_fs_x__find_dir_entry(dir.entries, name, NULL); if (entry) { entry_copy = apr_pmemdup(result_pool, entry, sizeof(*entry_copy)); @@ -2746,140 +2850,168 @@ svn_fs_x__rep_contents_dir_entry(svn_fs_x__dirent_t **dirent, } svn_error_t * -svn_fs_x__get_proplist(apr_hash_t **proplist_p, +svn_fs_x__get_proplist(apr_hash_t **proplist, svn_fs_t *fs, svn_fs_x__noderev_t *noderev, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - apr_hash_t *proplist; svn_stream_t *stream; const svn_fs_x__id_t *noderev_id = &noderev->noderev_id; if (noderev->prop_rep && !svn_fs_x__is_revision(noderev->prop_rep->id.change_set)) { + svn_stringbuf_t *content; + svn_string_t *as_string; const char *filename = svn_fs_x__path_txn_node_props(fs, noderev_id, scratch_pool, scratch_pool); - proplist = apr_hash_make(result_pool); + SVN_ERR(svn_stringbuf_from_file2(&content, filename, result_pool)); - SVN_ERR(svn_stream_open_readonly(&stream, filename, scratch_pool, - scratch_pool)); - SVN_ERR(svn_hash_read2(proplist, stream, SVN_HASH_TERMINATOR, - result_pool)); - SVN_ERR(svn_stream_close(stream)); + as_string = svn_stringbuf__morph_into_string(content); + SVN_ERR_W(svn_fs_x__parse_properties(proplist, as_string, result_pool), + apr_psprintf(scratch_pool, + "malformed property list for node-revision '%s' in '%s'", + svn_fs_x__id_unparse(&noderev->noderev_id, + scratch_pool)->data, + filename)); } else if (noderev->prop_rep) { svn_fs_x__data_t *ffd = fs->fsap_data; svn_fs_x__representation_t *rep = noderev->prop_rep; svn_fs_x__pair_cache_key_t key = { 0 }; + svn_string_t *content; + svn_boolean_t is_cached; key.revision = svn_fs_x__get_revnum(rep->id.change_set); key.second = rep->id.number; - if (ffd->properties_cache && SVN_IS_VALID_REVNUM(key.revision)) - { - svn_boolean_t is_cached; - SVN_ERR(svn_cache__get((void **) proplist_p, &is_cached, - ffd->properties_cache, &key, result_pool)); - if (is_cached) - return SVN_NO_ERROR; - } + SVN_ERR(svn_cache__get((void **) proplist, &is_cached, + ffd->properties_cache, &key, result_pool)); + if (is_cached) + return SVN_NO_ERROR; - proplist = apr_hash_make(result_pool); - SVN_ERR(svn_fs_x__get_contents(&stream, fs, noderev->prop_rep, FALSE, - scratch_pool)); - SVN_ERR(svn_hash_read2(proplist, stream, SVN_HASH_TERMINATOR, - result_pool)); - SVN_ERR(svn_stream_close(stream)); + SVN_ERR(svn_fs_x__get_contents(&stream, fs, rep, FALSE, scratch_pool)); + SVN_ERR(svn_string_from_stream2(&content, stream, rep->expanded_size, + result_pool)); - if (ffd->properties_cache && SVN_IS_VALID_REVNUM(rep->id.change_set)) - SVN_ERR(svn_cache__set(ffd->properties_cache, &key, proplist, - scratch_pool)); + SVN_ERR_W(svn_fs_x__parse_properties(proplist, content, result_pool), + apr_psprintf(scratch_pool, + "malformed property list for node-revision '%s'", + svn_fs_x__id_unparse(&noderev->noderev_id, + scratch_pool)->data)); + + SVN_ERR(svn_cache__set(ffd->properties_cache, &key, *proplist, + scratch_pool)); } else { /* return an empty prop list if the node doesn't have any props */ - proplist = apr_hash_make(result_pool); + *proplist = apr_hash_make(result_pool); } - *proplist_p = proplist; - return SVN_NO_ERROR; } +svn_error_t * +svn_fs_x__create_changes_context(svn_fs_x__changes_context_t **context, + svn_fs_t *fs, + svn_revnum_t rev, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_fs_x__changes_context_t *result = apr_pcalloc(result_pool, + sizeof(*result)); + result->fs = fs; + result->revision = rev; + SVN_ERR(svn_fs_x__ensure_revision_exists(rev, fs, scratch_pool)); + SVN_ERR(svn_fs_x__rev_file_init(&result->revision_file, fs, rev, + result_pool)); + + *context = result; + return SVN_NO_ERROR; +} svn_error_t * svn_fs_x__get_changes(apr_array_header_t **changes, - svn_fs_t *fs, - svn_revnum_t rev, - apr_pool_t *result_pool) + svn_fs_x__changes_context_t *context, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { - svn_fs_x__revision_file_t *revision_file; svn_boolean_t found; - svn_fs_x__data_t *ffd = fs->fsap_data; - apr_pool_t *scratch_pool = svn_pool_create(result_pool); + svn_fs_x__data_t *ffd = context->fs->fsap_data; svn_fs_x__id_t id; - id.change_set = svn_fs_x__change_set_by_rev(rev); + id.change_set = svn_fs_x__change_set_by_rev(context->revision); id.number = SVN_FS_X__ITEM_INDEX_CHANGES; - /* Provide revision file. */ - - SVN_ERR(svn_fs_x__ensure_revision_exists(rev, fs, scratch_pool)); - SVN_ERR(svn_fs_x__open_pack_or_rev_file(&revision_file, fs, rev, - scratch_pool, scratch_pool)); - /* try cache lookup first */ - if (ffd->changes_container_cache && svn_fs_x__is_packed_rev(fs, rev)) + if (svn_fs_x__is_packed_rev(context->fs, context->revision)) { apr_off_t offset; - apr_uint32_t sub_item; svn_fs_x__pair_cache_key_t key; + svn_fs_x__changes_get_list_baton_t baton; + baton.start = (int)context->next; + baton.eol = &context->eol; - SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, revision_file, + SVN_ERR(svn_fs_x__item_offset(&offset, &baton.sub_item, context->fs, + context->revision_file, &id, scratch_pool)); - key.revision = svn_fs_x__packed_base_rev(fs, rev); + key.revision = svn_fs_x__packed_base_rev(context->fs, + context->revision); key.second = offset; SVN_ERR(svn_cache__get_partial((void **)changes, &found, ffd->changes_container_cache, &key, svn_fs_x__changes_get_list_func, - &sub_item, result_pool)); - } - else if (ffd->changes_cache) - { - SVN_ERR(svn_cache__get((void **) changes, &found, ffd->changes_cache, - &rev, result_pool)); + &baton, result_pool)); } else { - found = FALSE; + svn_fs_x__changes_list_t *changes_list; + svn_fs_x__pair_cache_key_t key; + key.revision = context->revision; + key.second = context->next; + + SVN_ERR(svn_cache__get((void **)&changes_list, &found, + ffd->changes_cache, &key, result_pool)); + + if (found) + { + /* Where to look next - if there is more data. */ + context->eol = changes_list->eol; + context->next_offset = changes_list->end_offset; + + /* Return the block as a "proper" APR array. */ + (*changes) = apr_array_make(result_pool, 0, sizeof(void *)); + (*changes)->elts = (char *)changes_list->changes; + (*changes)->nelts = changes_list->count; + (*changes)->nalloc = changes_list->count; + } } if (!found) { /* 'block-read' will also provide us with the desired data */ - SVN_ERR(block_read((void **)changes, fs, &id, revision_file, + SVN_ERR(block_read((void **)changes, context->fs, &id, + context->revision_file, context, result_pool, scratch_pool)); - - SVN_ERR(svn_fs_x__close_revision_file(revision_file)); } - SVN_ERR(dgb__log_access(fs, &id, *changes, SVN_FS_X__ITEM_TYPE_CHANGES, - scratch_pool)); + context->next += (*changes)->nelts; + + SVN_ERR(dbg__log_access(context->fs, &id, *changes, + SVN_FS_X__ITEM_TYPE_CHANGES, scratch_pool)); - svn_pool_destroy(scratch_pool); return SVN_NO_ERROR; } /* Fetch the representation data (header, txdelta / plain windows) - * addressed by ENTRY->ITEM in FS and cache it if caches are enabled. - * Read the data from the already open FILE and the wrapping - * STREAM object. If MAX_OFFSET is not -1, don't read windows that start + * addressed by ENTRY->ITEM in FS and cache it under KEY. Read the data + * from REV_FILE. If MAX_OFFSET is not -1, don't read windows that start * at or beyond that offset. Use SCRATCH_POOL for temporary allocations. */ static svn_error_t * @@ -2890,20 +3022,16 @@ block_read_contents(svn_fs_t *fs, apr_off_t max_offset, apr_pool_t *scratch_pool) { - svn_fs_x__data_t *ffd = fs->fsap_data; svn_fs_x__representation_cache_key_t header_key = { 0 }; rep_state_t rs = { 0 }; svn_filesize_t fulltext_len; svn_fs_x__rep_header_t *rep_header; - if (!ffd->txdelta_window_cache || !ffd->combined_window_cache) - return SVN_NO_ERROR; - header_key.revision = (apr_int32_t)key->revision; header_key.is_packed = svn_fs_x__is_packed_rev(fs, header_key.revision); header_key.item_index = key->second; - SVN_ERR(read_rep_header(&rep_header, fs, rev_file->stream, &header_key, + SVN_ERR(read_rep_header(&rep_header, fs, rev_file, &header_key, scratch_pool)); SVN_ERR(init_rep_state(&rs, rep_header, fs, rev_file, entry, scratch_pool)); SVN_ERR(cache_windows(&fulltext_len, fs, &rs, max_offset, scratch_pool)); @@ -2913,28 +3041,28 @@ block_read_contents(svn_fs_t *fs, /* For the given REV_FILE in FS, in *STREAM return a stream covering the * item specified by ENTRY. Also, verify the item's content by low-level - * checksum. Allocate the result in POOL. + * checksum. Allocate the result in RESULT_POOL. */ static svn_error_t * read_item(svn_stream_t **stream, svn_fs_t *fs, svn_fs_x__revision_file_t *rev_file, svn_fs_x__p2l_entry_t* entry, - apr_pool_t *pool) + apr_pool_t *result_pool) { apr_uint32_t digest; svn_checksum_t *expected, *actual; apr_uint32_t plain_digest; + svn_stringbuf_t *text; /* Read item into string buffer. */ - svn_stringbuf_t *text = svn_stringbuf_create_ensure(entry->size, pool); + text = svn_stringbuf_create_ensure(entry->size, result_pool); text->len = entry->size; text->data[text->len] = 0; - SVN_ERR(svn_io_file_read_full2(rev_file->file, text->data, text->len, - NULL, NULL, pool)); + SVN_ERR(svn_fs_x__rev_file_read(rev_file, text->data, text->len)); /* Return (construct, calculate) stream and checksum. */ - *stream = svn_stream_from_stringbuf(text, pool); + *stream = svn_stream_from_stringbuf(text, result_pool); digest = svn__fnv1a_32x4(text->data, text->len); /* Checksums will match most of the time. */ @@ -2945,84 +3073,114 @@ read_item(svn_stream_t **stream, * nice error messages. */ plain_digest = htonl(entry->fnv1_checksum); expected = svn_checksum__from_digest_fnv1a_32x4( - (const unsigned char *)&plain_digest, pool); + (const unsigned char *)&plain_digest, result_pool); plain_digest = htonl(digest); actual = svn_checksum__from_digest_fnv1a_32x4( - (const unsigned char *)&plain_digest, pool); + (const unsigned char *)&plain_digest, result_pool); /* Construct the full error message with all the info we have. */ - return svn_checksum_mismatch_err(expected, actual, pool, + return svn_checksum_mismatch_err(expected, actual, result_pool, _("Low-level checksum mismatch while reading\n" "%s bytes of meta data at offset %s "), - apr_psprintf(pool, "%" APR_OFF_T_FMT, entry->size), - apr_psprintf(pool, "%" APR_OFF_T_FMT, entry->offset)); + apr_off_t_toa(result_pool, entry->size), + apr_off_t_toa(result_pool, entry->offset)); } -/* Read all txdelta / plain windows following REP_HEADER in FS as described - * by ENTRY. Read the data from the already open FILE and the wrapping - * STREAM object. If MAX_OFFSET is not -1, don't read windows that start - * at or beyond that offset. Use SCRATCH_POOL for temporary allocations. - * If caching is not enabled, this is a no-op. +/* If not already cached or if MUST_READ is set, read the changed paths + * list addressed by ENTRY in FS and retúrn it in *CHANGES. Cache the + * result if caching is enabled. Read the data from REV_FILE. Trim the + * data in *CHANGES to the range given by CONTEXT. Allocate *CHANGES in + * RESUSLT_POOL and allocate temporaries in SCRATCH_POOL. */ static svn_error_t * block_read_changes(apr_array_header_t **changes, svn_fs_t *fs, svn_fs_x__revision_file_t *rev_file, svn_fs_x__p2l_entry_t* entry, + svn_fs_x__changes_context_t *context, svn_boolean_t must_read, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { svn_fs_x__data_t *ffd = fs->fsap_data; svn_stream_t *stream; - svn_revnum_t revision = svn_fs_x__get_revnum(entry->items[0].change_set); - if (!must_read && !ffd->changes_cache) - return SVN_NO_ERROR; + svn_fs_x__pair_cache_key_t key; + svn_fs_x__changes_list_t changes_list; + + /* If we don't have to return any data, just read and cache the first + block. This means we won't cache the remaining blocks from longer + lists right away but only if they are actually needed. */ + apr_size_t next = must_read ? context->next : 0; + apr_size_t next_offset = must_read ? context->next_offset : 0; /* we don't support containers, yet */ SVN_ERR_ASSERT(entry->item_count == 1); + /* The item to read / write. */ + key.revision = svn_fs_x__get_revnum(entry->items[0].change_set); + key.second = next; + /* already in cache? */ - if (!must_read && ffd->changes_cache) + if (!must_read) { svn_boolean_t is_cached = FALSE; - SVN_ERR(svn_cache__has_key(&is_cached, ffd->changes_cache, &revision, + SVN_ERR(svn_cache__has_key(&is_cached, ffd->changes_cache, &key, scratch_pool)); if (is_cached) return SVN_NO_ERROR; } - SVN_ERR(read_item(&stream, fs, rev_file, entry, scratch_pool)); + /* Verify the whole list only once. We don't use the STREAM any further. */ + if (!must_read || next == 0) + SVN_ERR(read_item(&stream, fs, rev_file, entry, scratch_pool)); + + /* Seek to the block to read within the changes list. */ + SVN_ERR(svn_fs_x__rev_file_seek(rev_file, NULL, + entry->offset + next_offset)); + SVN_ERR(svn_fs_x__rev_file_stream(&stream, rev_file)); /* read changes from revision file */ + SVN_ERR(svn_fs_x__read_changes(changes, stream, SVN_FS_X__CHANGES_BLOCK_SIZE, + result_pool, scratch_pool)); - SVN_ERR(svn_fs_x__read_changes(changes, stream, result_pool, scratch_pool)); + SVN_ERR(svn_fs_x__rev_file_offset(&changes_list.end_offset, rev_file)); + changes_list.end_offset -= entry->offset; + changes_list.start_offset = next_offset; + changes_list.count = (*changes)->nelts; + changes_list.changes = (svn_fs_x__change_t **)(*changes)->elts; + changes_list.eol = (changes_list.count < SVN_FS_X__CHANGES_BLOCK_SIZE) + || (changes_list.end_offset + 1 >= entry->size); /* cache for future reference */ - if (ffd->changes_cache) - { - /* Guesstimate for the size of the in-cache representation. */ - apr_size_t estimated_size = (apr_size_t)250 * (*changes)->nelts; + SVN_ERR(svn_cache__set(ffd->changes_cache, &key, &changes_list, + scratch_pool)); - /* Don't even serialize data that probably won't fit into the - * cache. This often implies that either CHANGES is very - * large, memory is scarce or both. Having a huge temporary - * copy would not be a good thing in either case. */ - if (svn_cache__is_cachable(ffd->changes_cache, estimated_size)) - SVN_ERR(svn_cache__set(ffd->changes_cache, &revision, *changes, - scratch_pool)); + /* Trim the result: + * Remove the entries that already been reported. */ + if (must_read) + { + context->next_offset = changes_list.end_offset; + context->eol = changes_list.eol; } return SVN_NO_ERROR; } +/* If not already cached or if MUST_READ is set, read the changed paths + * list container addressed by ENTRY in FS. Return the changes list + * identified by SUB_ITEM in *CHANGES, using CONTEXT to select a sub-range + * within that list. Read the data from REV_FILE and cache the result. + * + * Allocate *CHANGES in RESUSLT_POOL and everything else in SCRATCH_POOL. + */ static svn_error_t * block_read_changes_container(apr_array_header_t **changes, svn_fs_t *fs, svn_fs_x__revision_file_t *rev_file, svn_fs_x__p2l_entry_t* entry, apr_uint32_t sub_item, + svn_fs_x__changes_context_t *context, svn_boolean_t must_read, apr_pool_t *result_pool, apr_pool_t *scratch_pool) @@ -3037,7 +3195,7 @@ block_read_changes_container(apr_array_header_t **changes, key.second = entry->offset; /* already in cache? */ - if (!must_read && ffd->changes_container_cache) + if (!must_read) { svn_boolean_t is_cached = FALSE; SVN_ERR(svn_cache__has_key(&is_cached, ffd->changes_container_cache, @@ -3057,15 +3215,19 @@ block_read_changes_container(apr_array_header_t **changes, if (must_read) SVN_ERR(svn_fs_x__changes_get_list(changes, container, sub_item, - result_pool)); - - if (ffd->changes_container_cache) - SVN_ERR(svn_cache__set(ffd->changes_container_cache, &key, container, - scratch_pool)); + context, result_pool)); + SVN_ERR(svn_cache__set(ffd->changes_container_cache, &key, container, + scratch_pool)); return SVN_NO_ERROR; } +/* If not already cached or if MUST_READ is set, read the node revision + * addressed by ENTRY in FS and return it in *NODEREV_P. Cache the + * result under KEY if caching is enabled. Read the data from REV_FILE. + * Allocate *NODEREV_P in RESUSLT_POOL and allocate temporaries in + * SCRATCH_POOL. + */ static svn_error_t * block_read_noderev(svn_fs_x__noderev_t **noderev_p, svn_fs_t *fs, @@ -3078,14 +3240,12 @@ block_read_noderev(svn_fs_x__noderev_t **noderev_p, { svn_fs_x__data_t *ffd = fs->fsap_data; svn_stream_t *stream; - if (!must_read && !ffd->node_revision_cache) - return SVN_NO_ERROR; /* we don't support containers, yet */ SVN_ERR_ASSERT(entry->item_count == 1); /* already in cache? */ - if (!must_read && ffd->node_revision_cache) + if (!must_read) { svn_boolean_t is_cached = FALSE; SVN_ERR(svn_cache__has_key(&is_cached, ffd->node_revision_cache, key, @@ -3100,13 +3260,18 @@ block_read_noderev(svn_fs_x__noderev_t **noderev_p, SVN_ERR(svn_fs_x__read_noderev(noderev_p, stream, result_pool, scratch_pool)); - if (ffd->node_revision_cache) - SVN_ERR(svn_cache__set(ffd->node_revision_cache, key, *noderev_p, - scratch_pool)); + SVN_ERR(svn_cache__set(ffd->node_revision_cache, key, *noderev_p, + scratch_pool)); return SVN_NO_ERROR; } +/* If not already cached or if MUST_READ is set, read the node revision + * container addressed by ENTRY in FS. Return the item identified by + * SUB_ITEM in *NODEREV_P. Read the data from REV_FILE and cache it. + * Allocate *NODEREV_P in RESUSLT_POOL and allocate temporaries in + * SCRATCH_POOL. + */ static svn_error_t * block_read_noderevs_container(svn_fs_x__noderev_t **noderev_p, svn_fs_t *fs, @@ -3127,7 +3292,7 @@ block_read_noderevs_container(svn_fs_x__noderev_t **noderev_p, key.second = entry->offset; /* already in cache? */ - if (!must_read && ffd->noderevs_container_cache) + if (!must_read) { svn_boolean_t is_cached = FALSE; SVN_ERR(svn_cache__has_key(&is_cached, ffd->noderevs_container_cache, @@ -3147,13 +3312,18 @@ block_read_noderevs_container(svn_fs_x__noderev_t **noderev_p, SVN_ERR(svn_fs_x__noderevs_get(noderev_p, container, sub_item, result_pool)); - if (ffd->noderevs_container_cache) - SVN_ERR(svn_cache__set(ffd->noderevs_container_cache, &key, container, - scratch_pool)); + SVN_ERR(svn_cache__set(ffd->noderevs_container_cache, &key, container, + scratch_pool)); return SVN_NO_ERROR; } +/* If not already cached or if MUST_READ is set, read the representation + * container addressed by ENTRY in FS. Return an extractor object for the + * item identified by SUB_ITEM in *EXTRACTOR. Read the data from REV_FILE + * and cache it. Allocate *EXTRACTOR in RESUSLT_POOL and all temporaries + * in SCRATCH_POOL. + */ static svn_error_t * block_read_reps_container(svn_fs_x__rep_extractor_t **extractor, svn_fs_t *fs, @@ -3174,7 +3344,7 @@ block_read_reps_container(svn_fs_x__rep_extractor_t **extractor, key.second = entry->offset; /* already in cache? */ - if (!must_read && ffd->reps_container_cache) + if (!must_read) { svn_boolean_t is_cached = FALSE; SVN_ERR(svn_cache__has_key(&is_cached, ffd->reps_container_cache, @@ -3195,18 +3365,30 @@ block_read_reps_container(svn_fs_x__rep_extractor_t **extractor, SVN_ERR(svn_fs_x__reps_get(extractor, fs, container, sub_item, result_pool)); - if (ffd->noderevs_container_cache) - SVN_ERR(svn_cache__set(ffd->reps_container_cache, &key, container, - scratch_pool)); + SVN_ERR(svn_cache__set(ffd->reps_container_cache, &key, container, + scratch_pool)); return SVN_NO_ERROR; } +/* Read the whole (e.g. 64kB) block containing the item identified by ID in + * FS and put all data into cache. If necessary and depending on heuristics, + * neighboring blocks may also get read. The data is being read from + * already open REVISION_FILE, which must be the correct rev / pack file + * w.r.t. ID->CHANGE_SET. + * + * For noderevs and changed path lists, the item fetched can be allocated + * RESULT_POOL and returned in *RESULT. Otherwise, RESULT must be NULL. + * The BATON is passed along to the extractor sub-functions and will be + * used only when constructing the *RESULT. SCRATCH_POOL will be used for + * all temporary allocations. + */ static svn_error_t * block_read(void **result, svn_fs_t *fs, const svn_fs_x__id_t *id, svn_fs_x__revision_file_t *revision_file, + void *baton, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { @@ -3232,8 +3414,7 @@ block_read(void **result, do { /* fetch list of items in the block surrounding OFFSET */ - SVN_ERR(aligned_seek(fs, revision_file->file, &block_start, offset, - iterpool)); + SVN_ERR(svn_fs_x__rev_file_seek(revision_file, &block_start, offset)); SVN_ERR(svn_fs_x__p2l_index_lookup(&entries, fs, revision_file, revision, block_start, ffd->block_size, scratch_pool, @@ -3272,8 +3453,8 @@ block_read(void **result, key.revision = svn_fs_x__get_revnum(entry->items[0].change_set); key.second = entry->items[0].number; - SVN_ERR(svn_io_file_seek(revision_file->file, SEEK_SET, - &entry->offset, iterpool)); + SVN_ERR(svn_fs_x__rev_file_seek(revision_file, NULL, + entry->offset)); switch (entry->type) { case SVN_FS_X__ITEM_TYPE_FILE_REP: @@ -3289,17 +3470,16 @@ block_read(void **result, break; case SVN_FS_X__ITEM_TYPE_NODEREV: - if (ffd->node_revision_cache || is_result) - SVN_ERR(block_read_noderev((svn_fs_x__noderev_t **)&item, - fs, revision_file, - entry, &key, is_result, - pool, iterpool)); + SVN_ERR(block_read_noderev((svn_fs_x__noderev_t **)&item, + fs, revision_file, + entry, &key, is_result, + pool, iterpool)); break; case SVN_FS_X__ITEM_TYPE_CHANGES: SVN_ERR(block_read_changes((apr_array_header_t **)&item, fs, revision_file, - entry, is_result, + entry, baton, is_result, pool, iterpool)); break; @@ -3308,7 +3488,8 @@ block_read(void **result, ((apr_array_header_t **)&item, fs, revision_file, entry, wanted_sub_item, - is_result, pool, iterpool)); + baton, is_result, + pool, iterpool)); break; case SVN_FS_X__ITEM_TYPE_NODEREVS_CONT: @@ -3337,7 +3518,7 @@ block_read(void **result, /* if we crossed a block boundary, read the remainder of * the last block as well */ offset = entry->offset + entry->size; - if (offset > block_start + ffd->block_size) + if (offset - block_start > ffd->block_size) ++run_count; svn_pool_clear(iterpool); diff --git a/subversion/libsvn_fs_x/cached_data.h b/subversion/libsvn_fs_x/cached_data.h index 079303eff004..2bcd2d942054 100644 --- a/subversion/libsvn_fs_x/cached_data.h +++ b/subversion/libsvn_fs_x/cached_data.h @@ -20,8 +20,8 @@ * ==================================================================== */ -#ifndef SVN_LIBSVN_FS__CACHED_DATA_H -#define SVN_LIBSVN_FS__CACHED_DATA_H +#ifndef SVN_LIBSVN_FS_X_CACHED_DATA_H +#define SVN_LIBSVN_FS_X_CACHED_DATA_H #include "svn_pools.h" #include "svn_fs.h" @@ -67,7 +67,7 @@ svn_fs_x__rep_chain_length(int *chain_length, svn_fs_t *fs, apr_pool_t *scratch_pool); -/* Set *CONTENTS to be a readable svn_stream_t that receives the text +/* Set *CONTENTS_P to be a readable svn_stream_t that receives the text representation REP as seen in filesystem FS. If CACHE_FULLTEXT is not set, bypass fulltext cache lookup for this rep and don't put the reconstructed fulltext into cache. @@ -79,6 +79,18 @@ svn_fs_x__get_contents(svn_stream_t **contents_p, svn_boolean_t cache_fulltext, apr_pool_t *result_pool); +/* Set *CONTENTS_P to be a readable svn_stream_t that receives the text + representation REP as seen in filesystem FS. Read the latest element + of the delta chain from FILE at offset OFFSET. + Use POOL for allocations. */ +svn_error_t * +svn_fs_x__get_contents_from_file(svn_stream_t **contents_p, + svn_fs_t *fs, + svn_fs_x__representation_t *rep, + apr_file_t *file, + apr_off_t offset, + apr_pool_t *pool); + /* Determine on-disk and expanded sizes of the representation identified * by ENTRY in FS and return the result in PACKED_LEN and EXPANDED_LEN, * respectively. FILE must point to the start of the representation and @@ -168,13 +180,24 @@ svn_fs_x__get_proplist(apr_hash_t **proplist, apr_pool_t *result_pool, apr_pool_t *scratch_pool); -/* Fetch the list of change in revision REV in FS and return it in *CHANGES. - * Allocate the result in POOL. +/* Create a changes retrieval context object in *RESULT_POOL and return it + * in *CONTEXT. It will allow svn_fs_x__get_changes to fetch consecutive + * blocks (one per invocation) from REV's changed paths list in FS. + * Use SCRATCH_POOL for temporary allocations. */ +svn_error_t * +svn_fs_x__create_changes_context(svn_fs_x__changes_context_t **context, + svn_fs_t *fs, + svn_revnum_t rev, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/* Fetch the block of changes from the CONTEXT and return it in *CHANGES. + * Allocate the result in RESULT_POOL and use SCRATCH_POOL for temporaries. */ svn_error_t * svn_fs_x__get_changes(apr_array_header_t **changes, - svn_fs_t *fs, - svn_revnum_t rev, - apr_pool_t *pool); + svn_fs_x__changes_context_t *context, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); #endif diff --git a/subversion/libsvn_fs_x/caching.c b/subversion/libsvn_fs_x/caching.c index 17e80bddc698..8c65ab11a2a8 100644 --- a/subversion/libsvn_fs_x/caching.c +++ b/subversion/libsvn_fs_x/caching.c @@ -23,8 +23,7 @@ #include "fs.h" #include "fs_x.h" #include "id.h" -#include "dag.h" -#include "tree.h" +#include "dag_cache.h" #include "index.h" #include "changes.h" #include "noderevs.h" @@ -70,9 +69,9 @@ normalize_key_part(const char *original, return normalized->data; } -/* *CACHE_TXDELTAS, *CACHE_FULLTEXTS and *CACHE_REVPROPS flags will be set - according to FS->CONFIG. *CACHE_NAMESPACE receives the cache prefix - to use. +/* *CACHE_TXDELTAS, *CACHE_FULLTEXTS, *CACHE_REVPROPS and *CACHE_NODEPROPS + flags will be set according to FS->CONFIG. *CACHE_NAMESPACE receives + the cache prefix to use. Allocate CACHE_NAMESPACE in RESULT_POOL. */ static svn_error_t * @@ -80,6 +79,7 @@ read_config(const char **cache_namespace, svn_boolean_t *cache_txdeltas, svn_boolean_t *cache_fulltexts, svn_boolean_t *cache_revprops, + svn_boolean_t *cache_nodeprops, svn_fs_t *fs, apr_pool_t *result_pool) { @@ -138,6 +138,15 @@ read_config(const char **cache_namespace, else *cache_revprops = TRUE; + /* by default, cache nodeprops: this will match pre-1.10 + * behavior where node properties caching was controlled + * by SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS configuration option. + */ + *cache_nodeprops + = svn_hash__get_bool(fs->config, + SVN_FS_CONFIG_FSFS_CACHE_NODEPROPS, + TRUE); + return SVN_NO_ERROR; } @@ -260,42 +269,42 @@ init_callbacks(svn_cache__t *cache, svn_cache__error_handler_t error_handler, apr_pool_t *pool) { - if (cache != NULL) - { #ifdef SVN_DEBUG_CACHE_DUMP_STATS - /* schedule printing the access statistics upon pool cleanup, - * i.e. end of FSX session. - */ - dump_cache_baton_t *baton; + /* schedule printing the access statistics upon pool cleanup, + * i.e. end of FSX session. + */ + dump_cache_baton_t *baton; - baton = apr_palloc(pool, sizeof(*baton)); - baton->pool = pool; - baton->cache = cache; + baton = apr_palloc(pool, sizeof(*baton)); + baton->pool = pool; + baton->cache = cache; - apr_pool_cleanup_register(pool, - baton, - dump_cache_statistics, - apr_pool_cleanup_null); + apr_pool_cleanup_register(pool, + baton, + dump_cache_statistics, + apr_pool_cleanup_null); #endif - if (error_handler) - SVN_ERR(svn_cache__set_error_handler(cache, - error_handler, - fs, - pool)); - - } + if (error_handler) + SVN_ERR(svn_cache__set_error_handler(cache, + error_handler, + fs, + pool)); return SVN_NO_ERROR; } /* Sets *CACHE_P to cache instance based on provided options. - * Creates memcache if MEMCACHE is not NULL. Creates membuffer cache if - * MEMBUFFER is not NULL. Fallbacks to inprocess cache if MEMCACHE and - * MEMBUFFER are NULL and pages is non-zero. Sets *CACHE_P to NULL - * otherwise. Use the given PRIORITY class for the new cache. If it - * is 0, then use the default priority class. + * + * If DUMMY_CACHE is set, create a null cache. Otherwise, creates a memcache + * if MEMCACHE is not NULL or a membuffer cache if MEMBUFFER is not NULL. + * Falls back to inprocess cache if no other cache type has been selected + * and PAGES is not 0. Create a null cache otherwise. + * + * Use the given PRIORITY class for the new cache. If PRIORITY is 0, then + * use the default priority class. HAS_NAMESPACE indicates whether we + * prefixed this cache instance with a namespace. * * Unless NO_HANDLER is true, register an error handler that reports errors * as warnings to the FS warning callback. @@ -313,8 +322,10 @@ create_cache(svn_cache__t **cache_p, apr_ssize_t klen, const char *prefix, apr_uint32_t priority, + svn_boolean_t has_namespace, svn_fs_t *fs, svn_boolean_t no_handler, + svn_boolean_t dummy_cache, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { @@ -324,7 +335,11 @@ create_cache(svn_cache__t **cache_p, if (priority == 0) priority = SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY; - if (memcache) + if (dummy_cache) + { + SVN_ERR(svn_cache__create_null(cache_p, prefix, result_pool)); + } + else if (memcache) { SVN_ERR(svn_cache__create_memcache(cache_p, memcache, serializer, deserializer, klen, @@ -335,9 +350,12 @@ create_cache(svn_cache__t **cache_p, } else if (membuffer) { + /* We assume caches with namespaces to be relatively short-lived, + * i.e. their data will not be needed after a while. */ SVN_ERR(svn_cache__create_membuffer_cache( cache_p, membuffer, serializer, deserializer, - klen, prefix, priority, FALSE, result_pool, scratch_pool)); + klen, prefix, priority, FALSE, has_namespace, + result_pool, scratch_pool)); } else if (pages) { @@ -347,7 +365,7 @@ create_cache(svn_cache__t **cache_p, } else { - *cache_p = NULL; + SVN_ERR(svn_cache__create_null(cache_p, prefix, result_pool)); } SVN_ERR(init_callbacks(*cache_p, fs, error_handler, result_pool)); @@ -362,6 +380,7 @@ svn_fs_x__initialize_caches(svn_fs_t *fs, svn_fs_x__data_t *ffd = fs->fsap_data; const char *prefix = apr_pstrcat(scratch_pool, "fsx:", fs->uuid, + "--", ffd->instance_id, "/", normalize_key_part(fs->path, scratch_pool), ":", @@ -371,25 +390,29 @@ svn_fs_x__initialize_caches(svn_fs_t *fs, svn_boolean_t cache_txdeltas; svn_boolean_t cache_fulltexts; svn_boolean_t cache_revprops; + svn_boolean_t cache_nodeprops; const char *cache_namespace; + svn_boolean_t has_namespace; /* Evaluating the cache configuration. */ SVN_ERR(read_config(&cache_namespace, &cache_txdeltas, &cache_fulltexts, &cache_revprops, + &cache_nodeprops, fs, scratch_pool)); prefix = apr_pstrcat(scratch_pool, "ns:", cache_namespace, ":", prefix, SVN_VA_NULL); + has_namespace = strlen(cache_namespace) > 0; membuffer = svn_cache__get_global_membuffer_cache(); /* General rules for assigning cache priorities: * * - Data that can be reconstructed from other elements has low prio - * (e.g. fulltexts, directories etc.) + * (e.g. fulltexts etc.) * - Index data required to find any of the other data has high prio * (e.g. noderevs, L2P and P2L index pages) * - everthing else should use default prio @@ -407,21 +430,6 @@ svn_fs_x__initialize_caches(svn_fs_t *fs, apr_pool_cleanup_null); #endif - /* Rough estimate: revision DAG nodes have size around 320 bytes, so - * let's put 16 on a page. */ - SVN_ERR(create_cache(&(ffd->rev_node_cache), - NULL, - membuffer, - 1024, 16, - svn_fs_x__dag_serialize, - svn_fs_x__dag_deserialize, - APR_HASH_KEY_STRING, - apr_pstrcat(scratch_pool, prefix, "DAG", SVN_VA_NULL), - SVN_CACHE__MEMBUFFER_LOW_PRIORITY, - fs, - no_handler, - fs->pool, scratch_pool)); - /* 1st level DAG node cache */ ffd->dag_node_cache = svn_fs_x__create_dag_cache(fs->pool); @@ -434,25 +442,10 @@ svn_fs_x__initialize_caches(svn_fs_t *fs, svn_fs_x__deserialize_dir_entries, sizeof(svn_fs_x__id_t), apr_pstrcat(scratch_pool, prefix, "DIR", SVN_VA_NULL), - SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY, - fs, - no_handler, - fs->pool, scratch_pool)); - - /* Only 16 bytes per entry (a revision number + the corresponding offset). - Since we want ~8k pages, that means 512 entries per page. */ - SVN_ERR(create_cache(&(ffd->packed_offset_cache), - NULL, - membuffer, - 32, 1, - svn_fs_x__serialize_manifest, - svn_fs_x__deserialize_manifest, - sizeof(svn_revnum_t), - apr_pstrcat(scratch_pool, prefix, "PACK-MANIFEST", - SVN_VA_NULL), SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, + has_namespace, fs, - no_handler, + no_handler, FALSE, fs->pool, scratch_pool)); /* initialize node revision cache, if caching has been enabled */ @@ -466,8 +459,9 @@ svn_fs_x__initialize_caches(svn_fs_t *fs, apr_pstrcat(scratch_pool, prefix, "NODEREVS", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, + has_namespace, fs, - no_handler, + no_handler, FALSE, fs->pool, scratch_pool)); /* initialize representation header cache, if caching has been enabled */ @@ -481,8 +475,9 @@ svn_fs_x__initialize_caches(svn_fs_t *fs, apr_pstrcat(scratch_pool, prefix, "REPHEADER", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY, + has_namespace, fs, - no_handler, + no_handler, FALSE, fs->pool, scratch_pool)); /* initialize node change list cache, if caching has been enabled */ @@ -492,140 +487,94 @@ svn_fs_x__initialize_caches(svn_fs_t *fs, 1, 8, /* 1k / entry; 8 entries total, rarely used */ svn_fs_x__serialize_changes, svn_fs_x__deserialize_changes, - sizeof(svn_revnum_t), + sizeof(svn_fs_x__pair_cache_key_t), apr_pstrcat(scratch_pool, prefix, "CHANGES", SVN_VA_NULL), 0, + has_namespace, fs, - no_handler, + no_handler, FALSE, fs->pool, scratch_pool)); /* if enabled, cache fulltext and other derived information */ - if (cache_fulltexts) - { - SVN_ERR(create_cache(&(ffd->fulltext_cache), - ffd->memcache, - membuffer, - 0, 0, /* Do not use inprocess cache */ - /* Values are svn_stringbuf_t */ - NULL, NULL, - sizeof(svn_fs_x__pair_cache_key_t), - apr_pstrcat(scratch_pool, prefix, "TEXT", - SVN_VA_NULL), - SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY, - fs, - no_handler, - fs->pool, scratch_pool)); + SVN_ERR(create_cache(&(ffd->fulltext_cache), + ffd->memcache, + membuffer, + 0, 0, /* Do not use inprocess cache */ + /* Values are svn_stringbuf_t */ + NULL, NULL, + sizeof(svn_fs_x__pair_cache_key_t), + apr_pstrcat(scratch_pool, prefix, "TEXT", + SVN_VA_NULL), + SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY, + has_namespace, + fs, + no_handler, !cache_fulltexts, + fs->pool, scratch_pool)); - SVN_ERR(create_cache(&(ffd->properties_cache), - NULL, - membuffer, - 0, 0, /* Do not use inprocess cache */ - svn_fs_x__serialize_properties, - svn_fs_x__deserialize_properties, - sizeof(svn_fs_x__pair_cache_key_t), - apr_pstrcat(scratch_pool, prefix, "PROP", - SVN_VA_NULL), - SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY, - fs, - no_handler, - fs->pool, scratch_pool)); - - SVN_ERR(create_cache(&(ffd->mergeinfo_cache), - NULL, - membuffer, - 0, 0, /* Do not use inprocess cache */ - svn_fs_x__serialize_mergeinfo, - svn_fs_x__deserialize_mergeinfo, - APR_HASH_KEY_STRING, - apr_pstrcat(scratch_pool, prefix, "MERGEINFO", - SVN_VA_NULL), - 0, - fs, - no_handler, - fs->pool, scratch_pool)); - - SVN_ERR(create_cache(&(ffd->mergeinfo_existence_cache), - NULL, - membuffer, - 0, 0, /* Do not use inprocess cache */ - /* Values are svn_stringbuf_t */ - NULL, NULL, - APR_HASH_KEY_STRING, - apr_pstrcat(scratch_pool, prefix, "HAS_MERGEINFO", - SVN_VA_NULL), - 0, - fs, - no_handler, - fs->pool, scratch_pool)); - } - else - { - ffd->fulltext_cache = NULL; - ffd->properties_cache = NULL; - ffd->mergeinfo_cache = NULL; - ffd->mergeinfo_existence_cache = NULL; - } + SVN_ERR(create_cache(&(ffd->properties_cache), + NULL, + membuffer, + 0, 0, /* Do not use inprocess cache */ + svn_fs_x__serialize_properties, + svn_fs_x__deserialize_properties, + sizeof(svn_fs_x__pair_cache_key_t), + apr_pstrcat(scratch_pool, prefix, "PROP", + SVN_VA_NULL), + SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY, + has_namespace, + fs, + no_handler, !cache_nodeprops, + fs->pool, scratch_pool)); /* if enabled, cache revprops */ - if (cache_revprops) - { - SVN_ERR(create_cache(&(ffd->revprop_cache), - NULL, - membuffer, - 0, 0, /* Do not use inprocess cache */ - svn_fs_x__serialize_properties, - svn_fs_x__deserialize_properties, - sizeof(svn_fs_x__pair_cache_key_t), - apr_pstrcat(scratch_pool, prefix, "REVPROP", - SVN_VA_NULL), - SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY, - fs, - no_handler, - fs->pool, scratch_pool)); - } - else - { - ffd->revprop_cache = NULL; - } + SVN_ERR(create_cache(&(ffd->revprop_cache), + NULL, + membuffer, + 0, 0, /* Do not use inprocess cache */ + svn_fs_x__serialize_properties, + svn_fs_x__deserialize_properties, + sizeof(svn_fs_x__pair_cache_key_t), + apr_pstrcat(scratch_pool, prefix, "REVPROP", + SVN_VA_NULL), + SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY, + has_namespace, + fs, + no_handler, !cache_revprops, + fs->pool, scratch_pool)); /* if enabled, cache text deltas and their combinations */ - if (cache_txdeltas) - { - SVN_ERR(create_cache(&(ffd->txdelta_window_cache), - NULL, - membuffer, - 0, 0, /* Do not use inprocess cache */ - svn_fs_x__serialize_txdelta_window, - svn_fs_x__deserialize_txdelta_window, - sizeof(svn_fs_x__window_cache_key_t), - apr_pstrcat(scratch_pool, prefix, "TXDELTA_WINDOW", - SVN_VA_NULL), - SVN_CACHE__MEMBUFFER_LOW_PRIORITY, - fs, - no_handler, - fs->pool, scratch_pool)); + SVN_ERR(create_cache(&(ffd->txdelta_window_cache), + NULL, + membuffer, + 0, 0, /* Do not use inprocess cache */ + svn_fs_x__serialize_txdelta_window, + svn_fs_x__deserialize_txdelta_window, + sizeof(svn_fs_x__window_cache_key_t), + apr_pstrcat(scratch_pool, prefix, "TXDELTA_WINDOW", + SVN_VA_NULL), + SVN_CACHE__MEMBUFFER_LOW_PRIORITY, + has_namespace, + fs, + no_handler, !cache_txdeltas, + fs->pool, scratch_pool)); - SVN_ERR(create_cache(&(ffd->combined_window_cache), - NULL, - membuffer, - 0, 0, /* Do not use inprocess cache */ - /* Values are svn_stringbuf_t */ - NULL, NULL, - sizeof(svn_fs_x__window_cache_key_t), - apr_pstrcat(scratch_pool, prefix, "COMBINED_WINDOW", - SVN_VA_NULL), - SVN_CACHE__MEMBUFFER_LOW_PRIORITY, - fs, - no_handler, - fs->pool, scratch_pool)); - } - else - { - ffd->txdelta_window_cache = NULL; - ffd->combined_window_cache = NULL; - } + SVN_ERR(create_cache(&(ffd->combined_window_cache), + NULL, + membuffer, + 0, 0, /* Do not use inprocess cache */ + /* Values are svn_stringbuf_t */ + NULL, NULL, + sizeof(svn_fs_x__window_cache_key_t), + apr_pstrcat(scratch_pool, prefix, "COMBINED_WINDOW", + SVN_VA_NULL), + SVN_CACHE__MEMBUFFER_LOW_PRIORITY, + has_namespace, + fs, + no_handler, !cache_txdeltas, + fs->pool, scratch_pool)); + /* Caches for our various container types. */ SVN_ERR(create_cache(&(ffd->noderevs_container_cache), NULL, membuffer, @@ -636,8 +585,9 @@ svn_fs_x__initialize_caches(svn_fs_t *fs, apr_pstrcat(scratch_pool, prefix, "NODEREVSCNT", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, + has_namespace, fs, - no_handler, + no_handler, FALSE, fs->pool, scratch_pool)); SVN_ERR(create_cache(&(ffd->changes_container_cache), NULL, @@ -649,8 +599,9 @@ svn_fs_x__initialize_caches(svn_fs_t *fs, apr_pstrcat(scratch_pool, prefix, "CHANGESCNT", SVN_VA_NULL), 0, + has_namespace, fs, - no_handler, + no_handler, FALSE, fs->pool, scratch_pool)); SVN_ERR(create_cache(&(ffd->reps_container_cache), NULL, @@ -662,10 +613,12 @@ svn_fs_x__initialize_caches(svn_fs_t *fs, apr_pstrcat(scratch_pool, prefix, "REPSCNT", SVN_VA_NULL), 0, + has_namespace, fs, - no_handler, + no_handler, FALSE, fs->pool, scratch_pool)); + /* Cache index info. */ SVN_ERR(create_cache(&(ffd->l2p_header_cache), NULL, membuffer, @@ -677,8 +630,9 @@ svn_fs_x__initialize_caches(svn_fs_t *fs, apr_pstrcat(scratch_pool, prefix, "L2P_HEADER", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, + has_namespace, fs, - no_handler, + no_handler, FALSE, fs->pool, scratch_pool)); SVN_ERR(create_cache(&(ffd->l2p_page_cache), NULL, @@ -691,8 +645,9 @@ svn_fs_x__initialize_caches(svn_fs_t *fs, apr_pstrcat(scratch_pool, prefix, "L2P_PAGE", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, + has_namespace, fs, - no_handler, + no_handler, FALSE, fs->pool, scratch_pool)); SVN_ERR(create_cache(&(ffd->p2l_header_cache), NULL, @@ -704,8 +659,9 @@ svn_fs_x__initialize_caches(svn_fs_t *fs, apr_pstrcat(scratch_pool, prefix, "P2L_HEADER", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, + has_namespace, fs, - no_handler, + no_handler, FALSE, fs->pool, scratch_pool)); SVN_ERR(create_cache(&(ffd->p2l_page_cache), NULL, @@ -717,8 +673,9 @@ svn_fs_x__initialize_caches(svn_fs_t *fs, apr_pstrcat(scratch_pool, prefix, "P2L_PAGE", SVN_VA_NULL), SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, + has_namespace, fs, - no_handler, + no_handler, FALSE, fs->pool, scratch_pool)); return SVN_NO_ERROR; diff --git a/subversion/libsvn_fs_x/changes.c b/subversion/libsvn_fs_x/changes.c index a7d5ee2fbe52..c385e59da7f6 100644 --- a/subversion/libsvn_fs_x/changes.c +++ b/subversion/libsvn_fs_x/changes.c @@ -21,6 +21,7 @@ */ #include "svn_private_config.h" +#include "svn_sorts.h" #include "private/svn_packed_data.h" @@ -37,8 +38,8 @@ /* the change contains a property modification */ #define CHANGE_PROP_MOD 0x00002 -/* the last part (rev_id) of node revision ID is a transaction ID */ -#define CHANGE_TXN_NODE 0x00004 +/* the change contains a mergeinfo modification */ +#define CHANGE_MERGEINFO_MOD 0x00004 /* (flags & CHANGE_NODE_MASK) >> CHANGE_NODE_SHIFT extracts the node type */ #define CHANGE_NODE_SHIFT 0x00003 @@ -52,16 +53,13 @@ /* (flags & CHANGE_KIND_MASK) >> CHANGE_KIND_SHIFT extracts the change type */ #define CHANGE_KIND_SHIFT 0x00005 -#define CHANGE_KIND_MASK 0x000E0 +#define CHANGE_KIND_MASK 0x00060 /* node types according to svn_fs_path_change_kind_t */ #define CHANGE_KIND_MODIFY 0x00000 #define CHANGE_KIND_ADD 0x00020 #define CHANGE_KIND_DELETE 0x00040 #define CHANGE_KIND_REPLACE 0x00060 -#define CHANGE_KIND_RESET 0x00080 -#define CHANGE_KIND_MOVE 0x000A0 -#define CHANGE_KIND_MOVEREPLACE 0x000C0 /* Our internal representation of a change */ typedef struct binary_change_t @@ -77,10 +75,6 @@ typedef struct binary_change_t svn_revnum_t copyfrom_rev; apr_size_t copyfrom_path; - /* Relevant parts of the node revision ID of the change. - * Empty, if REV_ID is not "used". */ - svn_fs_x__id_t noderev_id; - } binary_change_t; /* The actual container object. Change lists are concatenated into CHANGES @@ -138,20 +132,16 @@ append_change(svn_fs_x__changes_t *changes, svn_fs_x__change_t *change) { binary_change_t binary_change = { 0 }; - svn_boolean_t is_txn_id; /* CHANGE must be sufficiently complete */ SVN_ERR_ASSERT(change); SVN_ERR_ASSERT(change->path.data); - /* Relevant parts of the revision ID of the change. */ - binary_change.noderev_id = change->noderev_id; - /* define the kind of change and what specific information is present */ - is_txn_id = svn_fs_x__is_txn(binary_change.noderev_id.change_set); binary_change.flags = (change->text_mod ? CHANGE_TEXT_MOD : 0) | (change->prop_mod ? CHANGE_PROP_MOD : 0) - | (is_txn_id ? CHANGE_TXN_NODE : 0) + | (change->mergeinfo_mod == svn_tristate_true + ? CHANGE_MERGEINFO_MOD : 0) | ((int)change->change_kind << CHANGE_KIND_SHIFT) | ((int)change->node_kind << CHANGE_NODE_SHIFT); @@ -222,8 +212,11 @@ svn_error_t * svn_fs_x__changes_get_list(apr_array_header_t **list, const svn_fs_x__changes_t *changes, apr_size_t idx, - apr_pool_t *pool) + svn_fs_x__changes_context_t *context, + apr_pool_t *result_pool) { + int list_first; + int list_last; int first; int last; int i; @@ -235,37 +228,46 @@ svn_fs_x__changes_get_list(apr_array_header_t **list, /* validate index */ if (idx + 1 >= (apr_size_t)changes->offsets->nelts) return svn_error_createf(SVN_ERR_FS_CONTAINER_INDEX, NULL, - apr_psprintf(pool, + apr_psprintf(result_pool, _("Changes list index %%%s" " exceeds container size %%d"), APR_SIZE_T_FMT), idx, changes->offsets->nelts - 1); /* range of changes to return */ - first = APR_ARRAY_IDX(changes->offsets, (int)idx, int); - last = APR_ARRAY_IDX(changes->offsets, (int)idx + 1, int); + list_first = APR_ARRAY_IDX(changes->offsets, (int)idx, int); + list_last = APR_ARRAY_IDX(changes->offsets, (int)idx + 1, int); + + /* Restrict it to the sub-range requested by the caller. + * Clip the range to never exceed the list's content. */ + first = MIN(context->next + list_first, list_last); + last = MIN(first + SVN_FS_X__CHANGES_BLOCK_SIZE, list_last); + + /* Indicate to the caller whether the end of the list has been reached. */ + context->eol = last == list_last; /* construct result */ - *list = apr_array_make(pool, last - first, sizeof(svn_fs_x__change_t*)); + *list = apr_array_make(result_pool, last - first, + sizeof(svn_fs_x__change_t*)); for (i = first; i < last; ++i) { const binary_change_t *binary_change = &APR_ARRAY_IDX(changes->changes, i, binary_change_t); /* convert BINARY_CHANGE into a standard FSX svn_fs_x__change_t */ - svn_fs_x__change_t *change = apr_pcalloc(pool, sizeof(*change)); + svn_fs_x__change_t *change = apr_pcalloc(result_pool, sizeof(*change)); change->path.data = svn_fs_x__string_table_get(changes->paths, binary_change->path, &change->path.len, - pool); - - if (binary_change->noderev_id.change_set != SVN_FS_X__INVALID_CHANGE_SET) - change->noderev_id = binary_change->noderev_id; + result_pool); change->change_kind = (svn_fs_path_change_kind_t) ((binary_change->flags & CHANGE_KIND_MASK) >> CHANGE_KIND_SHIFT); change->text_mod = (binary_change->flags & CHANGE_TEXT_MOD) != 0; change->prop_mod = (binary_change->flags & CHANGE_PROP_MOD) != 0; + change->mergeinfo_mod = (binary_change->flags & CHANGE_MERGEINFO_MOD) + ? svn_tristate_true + : svn_tristate_false; change->node_kind = (svn_node_kind_t) ((binary_change->flags & CHANGE_NODE_MASK) >> CHANGE_NODE_SHIFT); @@ -276,7 +278,7 @@ svn_fs_x__changes_get_list(apr_array_header_t **list, = svn_fs_x__string_table_get(changes->paths, binary_change->copyfrom_path, NULL, - pool); + result_pool); /* add it to the result */ APR_ARRAY_PUSH(*list, svn_fs_x__change_t*) = change; @@ -311,8 +313,6 @@ svn_fs_x__write_changes_container(svn_stream_t *stream, svn_packed__create_int_substream(changes_stream, TRUE, FALSE); svn_packed__create_int_substream(changes_stream, TRUE, TRUE); svn_packed__create_int_substream(changes_stream, TRUE, FALSE); - svn_packed__create_int_substream(changes_stream, TRUE, TRUE); - svn_packed__create_int_substream(changes_stream, TRUE, FALSE); /* serialize offsets array */ for (i = 0; i < changes->offsets->nelts; ++i) @@ -330,9 +330,6 @@ svn_fs_x__write_changes_container(svn_stream_t *stream, svn_packed__add_int(changes_stream, change->copyfrom_rev); svn_packed__add_uint(changes_stream, change->copyfrom_path); - - svn_packed__add_int(changes_stream, change->noderev_id.change_set); - svn_packed__add_uint(changes_stream, change->noderev_id.number); } /* write to disk */ @@ -387,9 +384,6 @@ svn_fs_x__read_changes_container(svn_fs_x__changes_t **changes_p, change.copyfrom_rev = (svn_revnum_t)svn_packed__get_int(changes_stream); change.copyfrom_path = (apr_size_t)svn_packed__get_uint(changes_stream); - change.noderev_id.change_set = svn_packed__get_int(changes_stream); - change.noderev_id.number = svn_packed__get_uint(changes_stream); - APR_ARRAY_PUSH(changes->changes, binary_change_t) = change; } @@ -437,14 +431,14 @@ svn_error_t * svn_fs_x__deserialize_changes_container(void **out, void *data, apr_size_t data_len, - apr_pool_t *pool) + apr_pool_t *result_pool) { svn_fs_x__changes_t *changes = (svn_fs_x__changes_t *)data; /* de-serialize sub-structures */ svn_fs_x__deserialize_string_table(changes, &changes->paths); - svn_fs_x__deserialize_apr_array(changes, &changes->changes, pool); - svn_fs_x__deserialize_apr_array(changes, &changes->offsets, pool); + svn_fs_x__deserialize_apr_array(changes, &changes->changes, result_pool); + svn_fs_x__deserialize_apr_array(changes, &changes->offsets, result_pool); /* done */ *out = changes; @@ -464,7 +458,8 @@ svn_fs_x__changes_get_list_func(void **out, int i; apr_array_header_t *list; - apr_uint32_t idx = *(apr_uint32_t *)baton; + svn_fs_x__changes_get_list_baton_t *b = baton; + apr_uint32_t idx = b->sub_item; const svn_fs_x__changes_t *container = data; /* resolve all the sub-container pointers we need */ @@ -495,6 +490,12 @@ svn_fs_x__changes_get_list_func(void **out, first = offsets[idx]; last = offsets[idx+1]; + /* Restrict range to the block requested by the BATON. + * Tell the caller whether we reached the end of the list. */ + first = MIN(first + b->start, last); + last = MIN(first + SVN_FS_X__CHANGES_BLOCK_SIZE, last); + *b->eol = last == offsets[idx+1]; + /* construct result */ list = apr_array_make(pool, last - first, sizeof(svn_fs_x__change_t*)); @@ -508,8 +509,6 @@ svn_fs_x__changes_get_list_func(void **out, = svn_fs_x__string_table_get_func(paths, binary_change->path, &change->path.len, pool); - change->noderev_id = binary_change->noderev_id; - change->change_kind = (svn_fs_path_change_kind_t) ((binary_change->flags & CHANGE_KIND_MASK) >> CHANGE_KIND_SHIFT); change->text_mod = (binary_change->flags & CHANGE_TEXT_MOD) != 0; diff --git a/subversion/libsvn_fs_x/changes.h b/subversion/libsvn_fs_x/changes.h index ccb264761c44..9ba164b3e836 100644 --- a/subversion/libsvn_fs_x/changes.h +++ b/subversion/libsvn_fs_x/changes.h @@ -20,8 +20,8 @@ * ==================================================================== */ -#ifndef SVN_LIBSVN_FS__CHANGES_H -#define SVN_LIBSVN_FS__CHANGES_H +#ifndef SVN_LIBSVN_FS_X_CHANGES_H +#define SVN_LIBSVN_FS_X_CHANGES_H #include "svn_io.h" #include "fs.h" @@ -71,14 +71,16 @@ svn_fs_x__changes_estimate_size(const svn_fs_x__changes_t *changes); /* Read changes containers. */ -/* From CHANGES, extract the change list with the given IDX. Allocate - * the result in POOL and return it in *LIST. +/* From CHANGES, access the change list with the given IDX and extract the + * next entries according to CONTEXT. Allocate the result in RESULT_POOL + * and return it in *LIST. */ svn_error_t * svn_fs_x__changes_get_list(apr_array_header_t **list, const svn_fs_x__changes_t *changes, apr_size_t idx, - apr_pool_t *pool); + svn_fs_x__changes_context_t *context, + apr_pool_t *result_pool); /* I/O interface. */ @@ -114,13 +116,27 @@ svn_error_t * svn_fs_x__deserialize_changes_container(void **out, void *data, apr_size_t data_len, - apr_pool_t *pool); + apr_pool_t *result_pool); + +/* Baton type to be used with svn_fs_x__changes_get_list_func. */ +typedef struct svn_fs_x__changes_get_list_baton_t +{ + /* Sub-item to query */ + apr_uint32_t sub_item; + + /* Deliver data starting from this index within the changes list. */ + int start; + + /* To be set by svn_fs_x__changes_get_list_func: + Did we deliver the last change in that list? */ + svn_boolean_t *eol; +} svn_fs_x__changes_get_list_baton_t; /* Implements svn_cache__partial_getter_func_t for svn_fs_x__changes_t, * setting *OUT to the change list (apr_array_header_t *) selected by - * the apr_uint32_t index passed in as *BATON. This function is similar - * to svn_fs_x__changes_get_list but operates on the cache serialized - * representation of the container. + * the svn_fs_x__changes_get_list_baton_t passed in as *BATON. This + * function is similar to svn_fs_x__changes_get_list but operates on + * the cache serialized representation of the container. */ svn_error_t * svn_fs_x__changes_get_list_func(void **out, diff --git a/subversion/libsvn_fs_x/dag.c b/subversion/libsvn_fs_x/dag.c index 2f5bcb260a6c..5656dbe60034 100644 --- a/subversion/libsvn_fs_x/dag.c +++ b/subversion/libsvn_fs_x/dag.c @@ -1,4 +1,4 @@ -/* dag.c : DAG-like interface filesystem, private to libsvn_fs +/* dag.c : DAG-like interface filesystem * * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one @@ -41,6 +41,7 @@ #include "svn_private_config.h" #include "private/svn_temp_serializer.h" #include "temp_serializer.h" +#include "dag_cache.h" /* Initializing a filesystem. */ @@ -50,34 +51,12 @@ struct dag_node_t /* The filesystem this dag node came from. */ svn_fs_t *fs; - /* The node revision ID for this dag node. */ - svn_fs_x__id_t id; - - /* In the special case that this node is the root of a transaction - that has not yet been modified, the revision of this node is the - respective txn's base rev. Otherwise, this is SVN_INVALID_REVNUM - for txn nodes and the respective crev for committed nodes. - (Used in svn_fs_node_created_rev.) */ - svn_revnum_t revision; - - /* The node's type (file, dir, etc.) */ - svn_node_kind_t kind; - - /* The node's NODE-REVISION, or NULL if we haven't read it in yet. - This is allocated in this node's POOL. - - If you're willing to respect all the rules above, you can munge - this yourself, but you're probably better off just calling - `get_node_revision' and `set_node_revision', which take care of - things for you. */ + /* The node's NODE-REVISION. */ svn_fs_x__noderev_t *node_revision; /* The pool to allocate NODE_REVISION in. */ apr_pool_t *node_pool; - /* the path at which this node was created. */ - const char *created_path; - /* Directory entry lookup hint to speed up consecutive calls to svn_fs_x__rep_contents_dir_entry(). Only used for directory nodes. Any value is legal but should default to APR_SIZE_MAX. */ @@ -90,20 +69,20 @@ struct dag_node_t svn_node_kind_t svn_fs_x__dag_node_kind(dag_node_t *node) { - return node->kind; + return node->node_revision->kind; } const svn_fs_x__id_t * svn_fs_x__dag_get_id(const dag_node_t *node) { - return &node->id; + return &node->node_revision->noderev_id; } const char * svn_fs_x__dag_get_created_path(dag_node_t *node) { - return node->created_path; + return node->node_revision->created_path; } @@ -144,94 +123,35 @@ copy_node_revision(svn_fs_x__noderev_t *noderev, } -/* Set *NODEREV_P to the cached node-revision for NODE. - If the node-revision was not already cached in NODE, read it in, - allocating the cache in NODE->NODE_POOL. - - If you plan to change the contents of NODE, be careful! We're - handing you a pointer directly to our cached node-revision, not - your own copy. If you change it as part of some operation, but - then some Berkeley DB function deadlocks or gets an error, you'll - need to back out your changes, or else the cache will reflect - changes that never got committed. It's probably best not to change - the structure at all. */ -static svn_error_t * -get_node_revision(svn_fs_x__noderev_t **noderev_p, - dag_node_t *node) +const svn_fs_x__id_t * +svn_fs_x__dag_get_node_id(dag_node_t *node) { - /* If we've already got a copy, there's no need to read it in. */ - if (! node->node_revision) - { - svn_fs_x__noderev_t *noderev; - apr_pool_t *scratch_pool = svn_pool_create(node->node_pool); - - SVN_ERR(svn_fs_x__get_node_revision(&noderev, node->fs, &node->id, - node->node_pool, scratch_pool)); - node->node_revision = noderev; - svn_pool_destroy(scratch_pool); - } - - /* Now NODE->node_revision is set. */ - *noderev_p = node->node_revision; - return SVN_NO_ERROR; + return &node->node_revision->node_id; } -/* Return the node revision ID of NODE. The value returned is shared - with NODE, and will be deallocated when NODE is. */ -svn_error_t * -svn_fs_x__dag_get_node_id(svn_fs_x__id_t *node_id, - dag_node_t *node) +const svn_fs_x__id_t * +svn_fs_x__dag_get_copy_id(dag_node_t *node) { - svn_fs_x__noderev_t *noderev; - SVN_ERR(get_node_revision(&noderev, node)); - - *node_id = noderev->node_id; - return SVN_NO_ERROR; + return &node->node_revision->copy_id; } -/* Return the node revision ID of NODE. The value returned is shared - with NODE, and will be deallocated when NODE is. */ -svn_error_t * -svn_fs_x__dag_get_copy_id(svn_fs_x__id_t *copy_id, - dag_node_t *node) -{ - svn_fs_x__noderev_t *noderev; - SVN_ERR(get_node_revision(&noderev, node)); - - *copy_id = noderev->copy_id; - return SVN_NO_ERROR; -} - -/* Return the node ID of NODE. The value returned is shared with NODE, - and will be deallocated when NODE is. */ -svn_error_t * -svn_fs_x__dag_related_node(svn_boolean_t *same, - dag_node_t *lhs, +svn_boolean_t +svn_fs_x__dag_related_node(dag_node_t *lhs, dag_node_t *rhs) { - svn_fs_x__id_t lhs_node, rhs_node; - - SVN_ERR(svn_fs_x__dag_get_node_id(&lhs_node, lhs)); - SVN_ERR(svn_fs_x__dag_get_node_id(&rhs_node, rhs)); - *same = svn_fs_x__id_eq(&lhs_node, &rhs_node); - - return SVN_NO_ERROR; + return svn_fs_x__id_eq(&lhs->node_revision->node_id, + &rhs->node_revision->node_id); } -svn_error_t * -svn_fs_x__dag_same_line_of_history(svn_boolean_t *same, - dag_node_t *lhs, +svn_boolean_t +svn_fs_x__dag_same_line_of_history(dag_node_t *lhs, dag_node_t *rhs) { - svn_fs_x__noderev_t *lhs_noderev, *rhs_noderev; + svn_fs_x__noderev_t *lhs_noderev = lhs->node_revision; + svn_fs_x__noderev_t *rhs_noderev = rhs->node_revision; - SVN_ERR(get_node_revision(&lhs_noderev, lhs)); - SVN_ERR(get_node_revision(&rhs_noderev, rhs)); - - *same = svn_fs_x__id_eq(&lhs_noderev->node_id, &rhs_noderev->node_id) - && svn_fs_x__id_eq(&lhs_noderev->copy_id, &rhs_noderev->copy_id); - - return SVN_NO_ERROR; + return svn_fs_x__id_eq(&lhs_noderev->node_id, &rhs_noderev->node_id) + && svn_fs_x__id_eq(&lhs_noderev->copy_id, &rhs_noderev->copy_id); } svn_boolean_t @@ -240,7 +160,6 @@ svn_fs_x__dag_check_mutable(const dag_node_t *node) return svn_fs_x__is_txn(svn_fs_x__dag_get_id(node)->change_set); } - svn_error_t * svn_fs_x__dag_get_node(dag_node_t **node, svn_fs_t *fs, @@ -254,7 +173,6 @@ svn_fs_x__dag_get_node(dag_node_t **node, /* Construct the node. */ new_node = apr_pcalloc(result_pool, sizeof(*new_node)); new_node->fs = fs; - new_node->id = *id; new_node->hint = APR_SIZE_MAX; /* Grab the contents so we can inspect the node's kind and created path. */ @@ -263,17 +181,6 @@ svn_fs_x__dag_get_node(dag_node_t **node, new_node->node_pool = result_pool; new_node->node_revision = noderev; - /* Initialize the KIND and CREATED_PATH attributes */ - new_node->kind = noderev->kind; - new_node->created_path = noderev->created_path; - - /* Support our quirky svn_fs_node_created_rev API. - Untouched txn roots report the base rev as theirs. */ - new_node->revision - = ( svn_fs_x__is_fresh_txn_root(noderev) - ? svn_fs_x__get_revnum(noderev->predecessor_id.change_set) - : svn_fs_x__get_revnum(id->change_set)); - /* Return a fresh new node */ *node = new_node; return SVN_NO_ERROR; @@ -283,76 +190,50 @@ svn_fs_x__dag_get_node(dag_node_t **node, svn_revnum_t svn_fs_x__dag_get_revision(const dag_node_t *node) { - return node->revision; + svn_fs_x__noderev_t *noderev = node->node_revision; + return ( svn_fs_x__is_fresh_txn_root(noderev) + ? svn_fs_x__get_revnum(noderev->predecessor_id.change_set) + : svn_fs_x__get_revnum(noderev->noderev_id.change_set)); } - -svn_error_t * -svn_fs_x__dag_get_predecessor_id(svn_fs_x__id_t *id_p, - dag_node_t *node) +const svn_fs_x__id_t * +svn_fs_x__dag_get_predecessor_id(dag_node_t *node) { - svn_fs_x__noderev_t *noderev; - - SVN_ERR(get_node_revision(&noderev, node)); - *id_p = noderev->predecessor_id; - - return SVN_NO_ERROR; + return &node->node_revision->predecessor_id; } - -svn_error_t * -svn_fs_x__dag_get_predecessor_count(int *count, - dag_node_t *node) +int +svn_fs_x__dag_get_predecessor_count(dag_node_t *node) { - svn_fs_x__noderev_t *noderev; - - SVN_ERR(get_node_revision(&noderev, node)); - *count = noderev->predecessor_count; - return SVN_NO_ERROR; + return node->node_revision->predecessor_count; } -svn_error_t * -svn_fs_x__dag_get_mergeinfo_count(apr_int64_t *count, - dag_node_t *node) +apr_int64_t +svn_fs_x__dag_get_mergeinfo_count(dag_node_t *node) { - svn_fs_x__noderev_t *noderev; - - SVN_ERR(get_node_revision(&noderev, node)); - *count = noderev->mergeinfo_count; - return SVN_NO_ERROR; + return node->node_revision->mergeinfo_count; } -svn_error_t * -svn_fs_x__dag_has_mergeinfo(svn_boolean_t *has_mergeinfo, - dag_node_t *node) +svn_boolean_t +svn_fs_x__dag_has_mergeinfo(dag_node_t *node) { - svn_fs_x__noderev_t *noderev; - - SVN_ERR(get_node_revision(&noderev, node)); - *has_mergeinfo = noderev->has_mergeinfo; - return SVN_NO_ERROR; + return node->node_revision->has_mergeinfo; } -svn_error_t * -svn_fs_x__dag_has_descendants_with_mergeinfo(svn_boolean_t *do_they, - dag_node_t *node) +svn_boolean_t +svn_fs_x__dag_has_descendants_with_mergeinfo(dag_node_t *node) { - svn_fs_x__noderev_t *noderev; + svn_fs_x__noderev_t *noderev = node->node_revision; - if (node->kind != svn_node_dir) - { - *do_they = FALSE; - return SVN_NO_ERROR; - } + if (noderev->kind != svn_node_dir) + return FALSE; - SVN_ERR(get_node_revision(&noderev, node)); if (noderev->mergeinfo_count > 1) - *do_they = TRUE; + return TRUE; else if (noderev->mergeinfo_count == 1 && !noderev->has_mergeinfo) - *do_they = TRUE; - else - *do_they = FALSE; - return SVN_NO_ERROR; + return TRUE; + + return FALSE; } @@ -362,16 +243,15 @@ svn_fs_x__dag_has_descendants_with_mergeinfo(svn_boolean_t *do_they, /* Set *ID_P to the noderev-id for entry NAME in PARENT. If no such entry, set *ID_P to NULL but do not error. */ -static svn_error_t * -dir_entry_id_from_node(svn_fs_x__id_t *id_p, +svn_error_t * +svn_fs_x__dir_entry_id(svn_fs_x__id_t *id_p, dag_node_t *parent, const char *name, apr_pool_t *scratch_pool) { svn_fs_x__dirent_t *dirent; - svn_fs_x__noderev_t *noderev; + svn_fs_x__noderev_t *noderev = parent->node_revision; - SVN_ERR(get_node_revision(&noderev, parent)); if (noderev->kind != svn_node_dir) return svn_error_create(SVN_ERR_FS_NOT_DIRECTORY, NULL, _("Can't get entries of non-directory")); @@ -411,14 +291,16 @@ set_entry(dag_node_t *parent, svn_fs_x__txn_id_t txn_id, apr_pool_t *scratch_pool) { - svn_fs_x__noderev_t *parent_noderev; - - /* Get the parent's node-revision. */ - SVN_ERR(get_node_revision(&parent_noderev, parent)); + svn_fs_x__noderev_t *parent_noderev = parent->node_revision; /* Set the new entry. */ - return svn_fs_x__set_entry(parent->fs, txn_id, parent_noderev, name, id, - kind, parent->node_pool, scratch_pool); + SVN_ERR(svn_fs_x__set_entry(parent->fs, txn_id, parent_noderev, name, id, + kind, parent->node_pool, scratch_pool)); + + /* Update cached data. */ + svn_fs_x__update_dag_cache(parent); + + return SVN_NO_ERROR; } @@ -439,7 +321,8 @@ make_entry(dag_node_t **child_p, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - svn_fs_x__noderev_t new_noderev, *parent_noderev; + svn_fs_x__noderev_t new_noderev; + svn_fs_x__noderev_t *parent_noderev = parent->node_revision; /* Make sure that NAME is a single path component. */ if (! svn_path_is_single_path_component(name)) @@ -448,7 +331,7 @@ make_entry(dag_node_t **child_p, _("Attempted to create a node with an illegal name '%s'"), name); /* Make sure that parent is a directory */ - if (parent->kind != svn_node_dir) + if (parent_noderev->kind != svn_node_dir) return svn_error_create (SVN_ERR_FS_NOT_DIRECTORY, NULL, _("Attempted to create entry in non-directory parent")); @@ -464,7 +347,6 @@ make_entry(dag_node_t **child_p, new_noderev.kind = is_dir ? svn_node_dir : svn_node_file; new_noderev.created_path = svn_fspath__join(parent_path, name, result_pool); - SVN_ERR(get_node_revision(&parent_noderev, parent)); new_noderev.copyroot_path = apr_pstrdup(result_pool, parent_noderev->copyroot_path); new_noderev.copyroot_rev = parent_noderev->copyroot_rev; @@ -495,9 +377,7 @@ svn_fs_x__dag_dir_entries(apr_array_header_t **entries, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - svn_fs_x__noderev_t *noderev; - - SVN_ERR(get_node_revision(&noderev, node)); + svn_fs_x__noderev_t *noderev = node->node_revision; if (noderev->kind != svn_node_dir) return svn_error_create(SVN_ERR_FS_NOT_DIRECTORY, NULL, @@ -517,7 +397,7 @@ svn_fs_x__dag_set_entry(dag_node_t *node, apr_pool_t *scratch_pool) { /* Check it's a directory. */ - if (node->kind != svn_node_dir) + if (node->node_revision->kind != svn_node_dir) return svn_error_create (SVN_ERR_FS_NOT_DIRECTORY, NULL, _("Attempted to set entry in non-directory node")); @@ -541,16 +421,8 @@ svn_fs_x__dag_get_proplist(apr_hash_t **proplist_p, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - svn_fs_x__noderev_t *noderev; - apr_hash_t *proplist = NULL; - - SVN_ERR(get_node_revision(&noderev, node)); - - SVN_ERR(svn_fs_x__get_proplist(&proplist, node->fs, noderev, result_pool, - scratch_pool)); - - *proplist_p = proplist; - + SVN_ERR(svn_fs_x__get_proplist(proplist_p, node->fs, node->node_revision, + result_pool, scratch_pool)); return SVN_NO_ERROR; } @@ -560,37 +432,51 @@ svn_fs_x__dag_set_proplist(dag_node_t *node, apr_hash_t *proplist, apr_pool_t *scratch_pool) { - svn_fs_x__noderev_t *noderev; - /* Sanity check: this node better be mutable! */ if (! svn_fs_x__dag_check_mutable(node)) { - svn_string_t *idstr = svn_fs_x__id_unparse(&node->id, scratch_pool); + svn_string_t *idstr + = svn_fs_x__id_unparse(&node->node_revision->noderev_id, + scratch_pool); return svn_error_createf (SVN_ERR_FS_NOT_MUTABLE, NULL, "Can't set proplist on *immutable* node-revision %s", idstr->data); } - /* Go get a fresh NODE-REVISION for this node. */ - SVN_ERR(get_node_revision(&noderev, node)); - /* Set the new proplist. */ - return svn_fs_x__set_proplist(node->fs, noderev, proplist, scratch_pool); + SVN_ERR(svn_fs_x__set_proplist(node->fs, node->node_revision, proplist, + scratch_pool)); + svn_fs_x__update_dag_cache(node); + + return SVN_NO_ERROR; } +/* Write NODE's NODEREV element to disk. Update the DAG cache. + Use SCRATCH_POOL for temporary allocations. */ +static svn_error_t * +noderev_changed(dag_node_t *node, + apr_pool_t *scratch_pool) +{ + SVN_ERR(svn_fs_x__put_node_revision(node->fs, node->node_revision, + scratch_pool)); + svn_fs_x__update_dag_cache(node); + + return SVN_NO_ERROR; +} svn_error_t * svn_fs_x__dag_increment_mergeinfo_count(dag_node_t *node, apr_int64_t increment, apr_pool_t *scratch_pool) { - svn_fs_x__noderev_t *noderev; + svn_fs_x__noderev_t *noderev = node->node_revision; /* Sanity check: this node better be mutable! */ if (! svn_fs_x__dag_check_mutable(node)) { - svn_string_t *idstr = svn_fs_x__id_unparse(&node->id, scratch_pool); + svn_string_t *idstr = svn_fs_x__id_unparse(&noderev->noderev_id, + scratch_pool); return svn_error_createf (SVN_ERR_FS_NOT_MUTABLE, NULL, "Can't increment mergeinfo count on *immutable* node-revision %s", @@ -600,13 +486,11 @@ svn_fs_x__dag_increment_mergeinfo_count(dag_node_t *node, if (increment == 0) return SVN_NO_ERROR; - /* Go get a fresh NODE-REVISION for this node. */ - SVN_ERR(get_node_revision(&noderev, node)); - noderev->mergeinfo_count += increment; if (noderev->mergeinfo_count < 0) { - svn_string_t *idstr = svn_fs_x__id_unparse(&node->id, scratch_pool); + svn_string_t *idstr = svn_fs_x__id_unparse(&noderev->noderev_id, + scratch_pool); return svn_error_createf (SVN_ERR_FS_CORRUPT, NULL, apr_psprintf(scratch_pool, @@ -617,7 +501,8 @@ svn_fs_x__dag_increment_mergeinfo_count(dag_node_t *node, } if (noderev->mergeinfo_count > 1 && noderev->kind == svn_node_file) { - svn_string_t *idstr = svn_fs_x__id_unparse(&node->id, scratch_pool); + svn_string_t *idstr = svn_fs_x__id_unparse(&noderev->noderev_id, + scratch_pool); return svn_error_createf (SVN_ERR_FS_CORRUPT, NULL, apr_psprintf(scratch_pool, @@ -628,7 +513,7 @@ svn_fs_x__dag_increment_mergeinfo_count(dag_node_t *node, } /* Flush it out. */ - return svn_fs_x__put_node_revision(node->fs, noderev, scratch_pool); + return noderev_changed(node, scratch_pool); } svn_error_t * @@ -636,55 +521,38 @@ svn_fs_x__dag_set_has_mergeinfo(dag_node_t *node, svn_boolean_t has_mergeinfo, apr_pool_t *scratch_pool) { - svn_fs_x__noderev_t *noderev; - /* Sanity check: this node better be mutable! */ if (! svn_fs_x__dag_check_mutable(node)) { - svn_string_t *idstr = svn_fs_x__id_unparse(&node->id, scratch_pool); + svn_string_t *idstr + = svn_fs_x__id_unparse(&node->node_revision->noderev_id, + scratch_pool); return svn_error_createf (SVN_ERR_FS_NOT_MUTABLE, NULL, "Can't set mergeinfo flag on *immutable* node-revision %s", idstr->data); } - /* Go get a fresh NODE-REVISION for this node. */ - SVN_ERR(get_node_revision(&noderev, node)); - - noderev->has_mergeinfo = has_mergeinfo; + node->node_revision->has_mergeinfo = has_mergeinfo; /* Flush it out. */ - return svn_fs_x__put_node_revision(node->fs, noderev, scratch_pool); + return noderev_changed(node, scratch_pool); } /*** Roots. ***/ svn_error_t * -svn_fs_x__dag_revision_root(dag_node_t **node_p, - svn_fs_t *fs, - svn_revnum_t rev, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) +svn_fs_x__dag_root(dag_node_t **node_p, + svn_fs_t *fs, + svn_fs_x__change_set_t change_set, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { svn_fs_x__id_t root_id; + root_id.change_set = change_set; + root_id.number = SVN_FS_X__ITEM_INDEX_ROOT_NODE; - svn_fs_x__init_rev_root(&root_id, rev); - return svn_fs_x__dag_get_node(node_p, fs, &root_id, result_pool, - scratch_pool); -} - - -svn_error_t * -svn_fs_x__dag_txn_root(dag_node_t **node_p, - svn_fs_t *fs, - svn_fs_x__txn_id_t txn_id, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) -{ - svn_fs_x__id_t root_id; - - svn_fs_x__init_txn_root(&root_id, txn_id); return svn_fs_x__dag_get_node(node_p, fs, &root_id, result_pool, scratch_pool); } @@ -734,14 +602,11 @@ svn_fs_x__dag_clone_child(dag_node_t **child_p, } else { - svn_fs_x__noderev_t *noderev, *parent_noderev; - - /* Go get a fresh NODE-REVISION for current child node. */ - SVN_ERR(get_node_revision(&noderev, cur_entry)); + svn_fs_x__noderev_t *noderev = cur_entry->node_revision; if (is_parent_copyroot) { - SVN_ERR(get_node_revision(&parent_noderev, parent)); + svn_fs_x__noderev_t *parent_noderev = parent->node_revision; noderev->copyroot_rev = parent_noderev->copyroot_rev; noderev->copyroot_path = apr_pstrdup(scratch_pool, parent_noderev->copyroot_path); @@ -796,7 +661,7 @@ delete_if_mutable(svn_fs_t *fs, return SVN_NO_ERROR; /* Else it's mutable. Recurse on directories... */ - if (node->kind == svn_node_dir) + if (node->node_revision->kind == svn_node_dir) { apr_array_header_t *entries; int i; @@ -829,13 +694,13 @@ svn_fs_x__dag_delete(dag_node_t *parent, svn_fs_x__txn_id_t txn_id, apr_pool_t *scratch_pool) { - svn_fs_x__noderev_t *parent_noderev; + svn_fs_x__noderev_t *parent_noderev = parent->node_revision; svn_fs_t *fs = parent->fs; svn_fs_x__dirent_t *dirent; apr_pool_t *subpool; /* Make sure parent is a directory. */ - if (parent->kind != svn_node_dir) + if (parent_noderev->kind != svn_node_dir) return svn_error_createf (SVN_ERR_FS_NOT_DIRECTORY, NULL, "Attempted to delete entry '%s' from *non*-directory node", name); @@ -852,9 +717,9 @@ svn_fs_x__dag_delete(dag_node_t *parent, (SVN_ERR_FS_NOT_SINGLE_PATH_COMPONENT, NULL, "Attempted to delete a node with an illegal name '%s'", name); - /* Get a fresh NODE-REVISION for the parent node. */ - SVN_ERR(get_node_revision(&parent_noderev, parent)); - + /* We allocate a few potentially heavy temporary objects (file buffers + and directories). Make sure we don't keep them around for longer + than necessary. */ subpool = svn_pool_create(scratch_pool); /* Search this directory for a dirent with that NAME. */ @@ -871,13 +736,13 @@ svn_fs_x__dag_delete(dag_node_t *parent, "Delete failed--directory has no entry '%s'", name); /* If mutable, remove it and any mutable children from db. */ - SVN_ERR(delete_if_mutable(parent->fs, &dirent->id, scratch_pool)); - svn_pool_destroy(subpool); + SVN_ERR(delete_if_mutable(parent->fs, &dirent->id, subpool)); /* Remove this entry from its parent's entries list. */ - return svn_fs_x__set_entry(parent->fs, txn_id, parent_noderev, name, - NULL, svn_node_unknown, parent->node_pool, - scratch_pool); + SVN_ERR(set_entry(parent, name, NULL, svn_node_unknown, txn_id, subpool)); + + svn_pool_destroy(subpool); + return SVN_NO_ERROR; } @@ -916,23 +781,16 @@ svn_fs_x__dag_get_contents(svn_stream_t **contents_p, dag_node_t *file, apr_pool_t *result_pool) { - svn_fs_x__noderev_t *noderev; - svn_stream_t *contents; - /* Make sure our node is a file. */ - if (file->kind != svn_node_file) + if (file->node_revision->kind != svn_node_file) return svn_error_createf (SVN_ERR_FS_NOT_FILE, NULL, "Attempted to get textual contents of a *non*-file node"); - /* Go get a fresh node-revision for FILE. */ - SVN_ERR(get_node_revision(&noderev, file)); - /* Get a stream to the contents. */ - SVN_ERR(svn_fs_x__get_contents(&contents, file->fs, - noderev->data_rep, TRUE, result_pool)); - - *contents_p = contents; + SVN_ERR(svn_fs_x__get_contents(contents_p, file->fs, + file->node_revision->data_rep, TRUE, + result_pool)); return SVN_NO_ERROR; } @@ -945,23 +803,16 @@ svn_fs_x__dag_get_file_delta_stream(svn_txdelta_stream_t **stream_p, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - svn_fs_x__noderev_t *src_noderev; - svn_fs_x__noderev_t *tgt_noderev; + svn_fs_x__noderev_t *src_noderev = source ? source->node_revision : NULL; + svn_fs_x__noderev_t *tgt_noderev = target->node_revision; /* Make sure our nodes are files. */ - if ((source && source->kind != svn_node_file) - || target->kind != svn_node_file) + if ((source && src_noderev->kind != svn_node_file) + || tgt_noderev->kind != svn_node_file) return svn_error_createf (SVN_ERR_FS_NOT_FILE, NULL, "Attempted to get textual contents of a *non*-file node"); - /* Go get fresh node-revisions for the nodes. */ - if (source) - SVN_ERR(get_node_revision(&src_noderev, source)); - else - src_noderev = NULL; - SVN_ERR(get_node_revision(&tgt_noderev, target)); - /* Get the delta stream. */ return svn_fs_x__get_file_delta_stream(stream_p, target->fs, src_noderev, tgt_noderev, @@ -976,13 +827,8 @@ svn_fs_x__dag_try_process_file_contents(svn_boolean_t *success, void* baton, apr_pool_t *scratch_pool) { - svn_fs_x__noderev_t *noderev; - - /* Go get fresh node-revisions for the nodes. */ - SVN_ERR(get_node_revision(&noderev, node)); - return svn_fs_x__try_process_file_contents(success, node->fs, - noderev, + node->node_revision, processor, baton, scratch_pool); } @@ -991,18 +837,13 @@ svn_error_t * svn_fs_x__dag_file_length(svn_filesize_t *length, dag_node_t *file) { - svn_fs_x__noderev_t *noderev; - /* Make sure our node is a file. */ - if (file->kind != svn_node_file) + if (file->node_revision->kind != svn_node_file) return svn_error_createf (SVN_ERR_FS_NOT_FILE, NULL, "Attempted to get length of a *non*-file node"); - /* Go get a fresh node-revision for FILE, and . */ - SVN_ERR(get_node_revision(&noderev, file)); - - return svn_fs_x__file_length(length, noderev); + return svn_fs_x__file_length(length, file->node_revision); } @@ -1012,16 +853,13 @@ svn_fs_x__dag_file_checksum(svn_checksum_t **checksum, svn_checksum_kind_t kind, apr_pool_t *result_pool) { - svn_fs_x__noderev_t *noderev; - - if (file->kind != svn_node_file) + if (file->node_revision->kind != svn_node_file) return svn_error_createf (SVN_ERR_FS_NOT_FILE, NULL, "Attempted to get checksum of a *non*-file node"); - SVN_ERR(get_node_revision(&noderev, file)); - - return svn_fs_x__file_checksum(checksum, noderev, kind, result_pool); + return svn_fs_x__file_checksum(checksum, file->node_revision, kind, + result_pool); } @@ -1030,11 +868,8 @@ svn_fs_x__dag_get_edit_stream(svn_stream_t **contents, dag_node_t *file, apr_pool_t *result_pool) { - svn_fs_x__noderev_t *noderev; - svn_stream_t *ws; - /* Make sure our node is a file. */ - if (file->kind != svn_node_file) + if (file->node_revision->kind != svn_node_file) return svn_error_createf (SVN_ERR_FS_NOT_FILE, NULL, "Attempted to set textual contents of a *non*-file node"); @@ -1045,13 +880,8 @@ svn_fs_x__dag_get_edit_stream(svn_stream_t **contents, (SVN_ERR_FS_NOT_MUTABLE, NULL, "Attempted to set textual contents of an immutable node"); - /* Get the node revision. */ - SVN_ERR(get_node_revision(&noderev, file)); - - SVN_ERR(svn_fs_x__set_contents(&ws, file->fs, noderev, result_pool)); - - *contents = ws; - + SVN_ERR(svn_fs_x__set_contents(contents, file->fs, file->node_revision, + result_pool)); return SVN_NO_ERROR; } @@ -1072,9 +902,10 @@ svn_fs_x__dag_finalize_edits(dag_node_t *file, return svn_checksum_mismatch_err(checksum, file_checksum, scratch_pool, _("Checksum mismatch for '%s'"), - file->created_path); + file->node_revision->created_path); } + svn_fs_x__update_dag_cache(file); return SVN_NO_ERROR; } @@ -1086,101 +917,14 @@ svn_fs_x__dag_dup(const dag_node_t *node, /* Allocate our new node. */ dag_node_t *new_node = apr_pmemdup(result_pool, node, sizeof(*new_node)); - /* Only copy cached svn_fs_x__noderev_t for immutable nodes. */ - if (node->node_revision && !svn_fs_x__dag_check_mutable(node)) - { - new_node->node_revision = copy_node_revision(node->node_revision, - result_pool); - new_node->created_path = new_node->node_revision->created_path; - } - else - { - new_node->node_revision = NULL; - new_node->created_path = apr_pstrdup(result_pool, node->created_path); - } - + /* Copy sub-structures. */ + new_node->node_revision = copy_node_revision(node->node_revision, + result_pool); new_node->node_pool = result_pool; return new_node; } -dag_node_t * -svn_fs_x__dag_copy_into_pool(dag_node_t *node, - apr_pool_t *result_pool) -{ - return (node->node_pool == result_pool - ? node - : svn_fs_x__dag_dup(node, result_pool)); -} - -svn_error_t * -svn_fs_x__dag_serialize(void **data, - apr_size_t *data_len, - void *in, - apr_pool_t *pool) -{ - dag_node_t *node = in; - svn_stringbuf_t *serialized; - - /* create an serialization context and serialize the dag node as root */ - svn_temp_serializer__context_t *context = - svn_temp_serializer__init(node, - sizeof(*node), - 1024 - SVN_TEMP_SERIALIZER__OVERHEAD, - pool); - - /* for mutable nodes, we will _never_ cache the noderev */ - if (node->node_revision && !svn_fs_x__dag_check_mutable(node)) - { - svn_fs_x__noderev_serialize(context, &node->node_revision); - } - else - { - svn_temp_serializer__set_null(context, - (const void * const *)&node->node_revision); - svn_temp_serializer__add_string(context, &node->created_path); - } - - /* The deserializer will use its own pool. */ - svn_temp_serializer__set_null(context, - (const void * const *)&node->node_pool); - - /* return serialized data */ - serialized = svn_temp_serializer__get(context); - *data = serialized->data; - *data_len = serialized->len; - - return SVN_NO_ERROR; -} - -svn_error_t * -svn_fs_x__dag_deserialize(void **out, - void *data, - apr_size_t data_len, - apr_pool_t *pool) -{ - dag_node_t *node = (dag_node_t *)data; - if (data_len == 0) - return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, - _("Empty noderev in cache")); - - /* Copy the _full_ buffer as it also contains the sub-structures. */ - node->fs = NULL; - - /* fixup all references to sub-structures */ - svn_fs_x__noderev_deserialize(node, &node->node_revision, pool); - node->node_pool = pool; - - if (node->node_revision) - node->created_path = node->node_revision->created_path; - else - svn_temp_deserializer__resolve(node, (void**)&node->created_path); - - /* return result */ - *out = node; - - return SVN_NO_ERROR; -} svn_error_t * svn_fs_x__dag_open(dag_node_t **child_p, @@ -1192,7 +936,7 @@ svn_fs_x__dag_open(dag_node_t **child_p, svn_fs_x__id_t node_id; /* Ensure that NAME exists in PARENT's entry list. */ - SVN_ERR(dir_entry_id_from_node(&node_id, parent, name, scratch_pool)); + SVN_ERR(svn_fs_x__dir_entry_id(&node_id, parent, name, scratch_pool)); if (! svn_fs_x__id_used(&node_id)) { *child_p = NULL; @@ -1219,13 +963,12 @@ svn_fs_x__dag_copy(dag_node_t *to_node, if (preserve_history) { - svn_fs_x__noderev_t *from_noderev, *to_noderev; + svn_fs_x__noderev_t *to_noderev; svn_fs_x__id_t copy_id; svn_fs_t *fs = svn_fs_x__dag_get_fs(from_node); /* Make a copy of the original node revision. */ - SVN_ERR(get_node_revision(&from_noderev, from_node)); - to_noderev = copy_node_revision(from_noderev, scratch_pool); + to_noderev = copy_node_revision(from_node->node_revision, scratch_pool); /* Reserve a copy ID for this new copy. */ SVN_ERR(svn_fs_x__reserve_copy_id(©_id, fs, txn_id, scratch_pool)); @@ -1253,7 +996,8 @@ svn_fs_x__dag_copy(dag_node_t *to_node, } /* Set the entry in to_node to the new id. */ - return svn_fs_x__dag_set_entry(to_node, entry, id, from_node->kind, + return svn_fs_x__dag_set_entry(to_node, entry, id, + from_node->node_revision->kind, txn_id, scratch_pool); } @@ -1269,7 +1013,8 @@ svn_fs_x__dag_things_different(svn_boolean_t *props_changed, svn_boolean_t strict, apr_pool_t *scratch_pool) { - svn_fs_x__noderev_t *noderev1, *noderev2; + svn_fs_x__noderev_t *noderev1 = node1->node_revision; + svn_fs_x__noderev_t *noderev2 = node2->node_revision; svn_fs_t *fs; svn_boolean_t same; @@ -1280,10 +1025,6 @@ svn_fs_x__dag_things_different(svn_boolean_t *props_changed, fs = svn_fs_x__dag_get_fs(node1); - /* The node revision skels for these two nodes. */ - SVN_ERR(get_node_revision(&noderev1, node1)); - SVN_ERR(get_node_revision(&noderev2, node2)); - /* Compare property keys. */ if (props_changed != NULL) { @@ -1300,48 +1041,25 @@ svn_fs_x__dag_things_different(svn_boolean_t *props_changed, return SVN_NO_ERROR; } -svn_error_t * +void svn_fs_x__dag_get_copyroot(svn_revnum_t *rev, const char **path, dag_node_t *node) { - svn_fs_x__noderev_t *noderev; - - /* Go get a fresh node-revision for NODE. */ - SVN_ERR(get_node_revision(&noderev, node)); - - *rev = noderev->copyroot_rev; - *path = noderev->copyroot_path; - - return SVN_NO_ERROR; + *rev = node->node_revision->copyroot_rev; + *path = node->node_revision->copyroot_path; } -svn_error_t * -svn_fs_x__dag_get_copyfrom_rev(svn_revnum_t *rev, - dag_node_t *node) +svn_revnum_t +svn_fs_x__dag_get_copyfrom_rev(dag_node_t *node) { - svn_fs_x__noderev_t *noderev; - - /* Go get a fresh node-revision for NODE. */ - SVN_ERR(get_node_revision(&noderev, node)); - - *rev = noderev->copyfrom_rev; - - return SVN_NO_ERROR; + return node->node_revision->copyfrom_rev; } -svn_error_t * -svn_fs_x__dag_get_copyfrom_path(const char **path, - dag_node_t *node) +const char * +svn_fs_x__dag_get_copyfrom_path(dag_node_t *node) { - svn_fs_x__noderev_t *noderev; - - /* Go get a fresh node-revision for NODE. */ - SVN_ERR(get_node_revision(&noderev, node)); - - *path = noderev->copyfrom_path; - - return SVN_NO_ERROR; + return node->node_revision->copyfrom_path; } svn_error_t * @@ -1349,20 +1067,17 @@ svn_fs_x__dag_update_ancestry(dag_node_t *target, dag_node_t *source, apr_pool_t *scratch_pool) { - svn_fs_x__noderev_t *source_noderev, *target_noderev; + svn_fs_x__noderev_t *source_noderev = source->node_revision; + svn_fs_x__noderev_t *target_noderev = target->node_revision; if (! svn_fs_x__dag_check_mutable(target)) return svn_error_createf (SVN_ERR_FS_NOT_MUTABLE, NULL, _("Attempted to update ancestry of non-mutable node")); - SVN_ERR(get_node_revision(&source_noderev, source)); - SVN_ERR(get_node_revision(&target_noderev, target)); - target_noderev->predecessor_id = source_noderev->noderev_id; target_noderev->predecessor_count = source_noderev->predecessor_count; target_noderev->predecessor_count++; - return svn_fs_x__put_node_revision(target->fs, target_noderev, - scratch_pool); + return noderev_changed(target, scratch_pool); } diff --git a/subversion/libsvn_fs_x/dag.h b/subversion/libsvn_fs_x/dag.h index 6d5e85baf28d..dd951edcd6f4 100644 --- a/subversion/libsvn_fs_x/dag.h +++ b/subversion/libsvn_fs_x/dag.h @@ -1,4 +1,4 @@ -/* dag.h : DAG-like interface filesystem, private to libsvn_fs +/* dag.h : DAG-like interface filesystem * * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one @@ -20,8 +20,8 @@ * ==================================================================== */ -#ifndef SVN_LIBSVN_FS_DAG_H -#define SVN_LIBSVN_FS_DAG_H +#ifndef SVN_LIBSVN_FS_X_DAG_H +#define SVN_LIBSVN_FS_X_DAG_H #include "svn_fs.h" #include "svn_delta.h" @@ -82,28 +82,6 @@ dag_node_t * svn_fs_x__dag_dup(const dag_node_t *node, apr_pool_t *result_pool); -/* If NODE has been allocated in POOL, return NODE. Otherwise, return - a copy created in RESULT_POOL with svn_fs_fs__dag_dup. */ -dag_node_t * -svn_fs_x__dag_copy_into_pool(dag_node_t *node, - apr_pool_t *result_pool); - -/* Serialize a DAG node, except don't try to preserve the 'fs' member. - Implements svn_cache__serialize_func_t */ -svn_error_t * -svn_fs_x__dag_serialize(void **data, - apr_size_t *data_len, - void *in, - apr_pool_t *pool); - -/* Deserialize a DAG node, leaving the 'fs' member as NULL. - Implements svn_cache__deserialize_func_t */ -svn_error_t * -svn_fs_x__dag_deserialize(void **out, - void *data, - apr_size_t data_len, - apr_pool_t *pool); - /* Return the filesystem containing NODE. */ svn_fs_t * svn_fs_x__dag_get_fs(dag_node_t *node); @@ -128,27 +106,23 @@ svn_fs_x__dag_get_id(const dag_node_t *node); /* Return the node ID of NODE. The value returned is shared with NODE, and will be deallocated when NODE is. */ -svn_error_t * -svn_fs_x__dag_get_node_id(svn_fs_x__id_t *node_id, - dag_node_t *node); +const svn_fs_x__id_t * +svn_fs_x__dag_get_node_id(dag_node_t *node); /* Return the copy ID of NODE. The value returned is shared with NODE, and will be deallocated when NODE is. */ -svn_error_t * -svn_fs_x__dag_get_copy_id(svn_fs_x__id_t *copy_id, - dag_node_t *node); +const svn_fs_x__id_t * +svn_fs_x__dag_get_copy_id(dag_node_t *node); -/* Set *SAME to TRUE, if nodes LHS and RHS have the same node ID. */ -svn_error_t * -svn_fs_x__dag_related_node(svn_boolean_t *same, - dag_node_t *lhs, +/* Return TRUE, iff nodes LHS and RHS have the same node ID. */ +svn_boolean_t +svn_fs_x__dag_related_node(dag_node_t *lhs, dag_node_t *rhs); -/* Set *SAME to TRUE, if nodes LHS and RHS have the same node and copy IDs. +/* Return TRUE, iff nodes LHS and RHS have the same node and copy IDs. */ -svn_error_t * -svn_fs_x__dag_same_line_of_history(svn_boolean_t *same, - dag_node_t *lhs, +svn_boolean_t +svn_fs_x__dag_same_line_of_history(dag_node_t *lhs, dag_node_t *rhs); /* Return the created path of NODE. The value returned is shared @@ -157,41 +131,31 @@ const char * svn_fs_x__dag_get_created_path(dag_node_t *node); -/* Set *ID_P to the node revision ID of NODE's immediate predecessor. +/* Return the node revision ID of NODE's immediate predecessor. */ -svn_error_t * -svn_fs_x__dag_get_predecessor_id(svn_fs_x__id_t *id_p, - dag_node_t *node); +const svn_fs_x__id_t * +svn_fs_x__dag_get_predecessor_id(dag_node_t *node); - -/* Set *COUNT to the number of predecessors NODE has (recursively). +/* Return the number of predecessors NODE has (recursively). */ -/* ### This function is currently only used by 'verify'. */ -svn_error_t * -svn_fs_x__dag_get_predecessor_count(int *count, - dag_node_t *node); +int +svn_fs_x__dag_get_predecessor_count(dag_node_t *node); -/* Set *COUNT to the number of node under NODE (inclusive) with - svn:mergeinfo properties. +/* Return the number of node under NODE (inclusive) with svn:mergeinfo + properties. */ -svn_error_t * -svn_fs_x__dag_get_mergeinfo_count(apr_int64_t *count, - dag_node_t *node); +apr_int64_t +svn_fs_x__dag_get_mergeinfo_count(dag_node_t *node); -/* Set *DO_THEY to a flag indicating whether or not NODE is a - directory with at least one descendant (not including itself) with - svn:mergeinfo. +/* Return TRUE, iff NODE is a directory with at least one descendant (not + including itself) with svn:mergeinfo. */ -svn_error_t * -svn_fs_x__dag_has_descendants_with_mergeinfo(svn_boolean_t *do_they, - dag_node_t *node); +svn_boolean_t +svn_fs_x__dag_has_descendants_with_mergeinfo(dag_node_t *node); -/* Set *HAS_MERGEINFO to a flag indicating whether or not NODE itself - has svn:mergeinfo set on it. - */ -svn_error_t * -svn_fs_x__dag_has_mergeinfo(svn_boolean_t *has_mergeinfo, - dag_node_t *node); +/* Return TRUE, iff NODE itself has svn:mergeinfo set on it. */ +svn_boolean_t +svn_fs_x__dag_has_mergeinfo(dag_node_t *node); /* Return non-zero IFF NODE is currently mutable. */ svn_boolean_t @@ -252,25 +216,15 @@ svn_fs_x__dag_set_has_mergeinfo(dag_node_t *node, /* Revision and transaction roots. */ -/* Open the root of revision REV of filesystem FS, allocating from +/* Open the root of change set CHANGE_SET of filesystem FS, allocating from RESULT_POOL. Set *NODE_P to the new node. Use SCRATCH_POOL for temporary allocations.*/ svn_error_t * -svn_fs_x__dag_revision_root(dag_node_t **node_p, - svn_fs_t *fs, - svn_revnum_t rev, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool); - - -/* Set *NODE_P to the root of transaction TXN_ID in FS, allocating - from RESULT_POOL. Use SCRATCH_POOL for temporary allocations. */ -svn_error_t * -svn_fs_x__dag_txn_root(dag_node_t **node_p, - svn_fs_t *fs, - svn_fs_x__txn_id_t txn_id, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool); +svn_fs_x__dag_root(dag_node_t **node_p, + svn_fs_t *fs, + svn_fs_x__change_set_t change_set, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); /* Directories. */ @@ -289,6 +243,14 @@ svn_fs_x__dag_open(dag_node_t **child_p, apr_pool_t *scratch_pool); +/* Set *ID_P to the noderev-id for entry NAME in PARENT. If no such + entry exists, set *ID_P to "unused" but do not error. */ +svn_error_t * +svn_fs_x__dir_entry_id(svn_fs_x__id_t *id_p, + dag_node_t *parent, + const char *name, + apr_pool_t *scratch_pool); + /* Set *ENTRIES_P to an array of NODE's entries, sorted by entry names, and the values are svn_fs_x__dirent_t. The returned table (and elements) is allocated in RESULT_POOL, temporaries in SCRATCH_POOL. */ @@ -548,22 +510,20 @@ svn_fs_x__dag_things_different(svn_boolean_t *props_changed, /* Set *REV and *PATH to the copyroot revision and path of node NODE, or to SVN_INVALID_REVNUM and NULL if no copyroot exists. */ -svn_error_t * +void svn_fs_x__dag_get_copyroot(svn_revnum_t *rev, const char **path, dag_node_t *node); -/* Set *REV to the copyfrom revision associated with NODE. +/* Return the copyfrom revision associated with NODE. */ -svn_error_t * -svn_fs_x__dag_get_copyfrom_rev(svn_revnum_t *rev, - dag_node_t *node); +svn_revnum_t +svn_fs_x__dag_get_copyfrom_rev(dag_node_t *node); -/* Set *PATH to the copyfrom path associated with NODE. +/* Return the copyfrom path associated with NODE. */ -svn_error_t * -svn_fs_x__dag_get_copyfrom_path(const char **path, - dag_node_t *node); +const char * +svn_fs_x__dag_get_copyfrom_path(dag_node_t *node); /* Update *TARGET so that SOURCE is it's predecessor. @@ -577,4 +537,4 @@ svn_fs_x__dag_update_ancestry(dag_node_t *target, } #endif /* __cplusplus */ -#endif /* SVN_LIBSVN_FS_DAG_H */ +#endif /* SVN_LIBSVN_FS_X_DAG_H */ diff --git a/subversion/libsvn_fs_x/dag_cache.c b/subversion/libsvn_fs_x/dag_cache.c new file mode 100644 index 000000000000..896c56fb3203 --- /dev/null +++ b/subversion/libsvn_fs_x/dag_cache.c @@ -0,0 +1,1103 @@ +/* dag_cache.c : DAG walker and node cache. + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + + +/* The job of this layer is to take a filesystem with lots of node + sharing going on --- the real DAG filesystem as it appears in the + database --- and make it look and act like an ordinary tree + filesystem, with no sharing. + + We do just-in-time cloning: you can walk from some unfinished + transaction's root down into directories and files shared with + committed revisions; as soon as you try to change something, the + appropriate nodes get cloned (and parent directory entries updated) + invisibly, behind your back. Any other references you have to + nodes that have been cloned by other changes, even made by other + processes, are automatically updated to point to the right clones. */ + + +#include +#include +#include +#include +#include + +#include "svn_hash.h" +#include "svn_private_config.h" +#include "svn_pools.h" +#include "svn_error.h" +#include "svn_path.h" +#include "svn_mergeinfo.h" +#include "svn_fs.h" +#include "svn_props.h" +#include "svn_sorts.h" + +#include "fs.h" +#include "dag.h" +#include "dag_cache.h" +#include "lock.h" +#include "tree.h" +#include "fs_x.h" +#include "fs_id.h" +#include "temp_serializer.h" +#include "cached_data.h" +#include "transaction.h" +#include "pack.h" +#include "util.h" + +#include "private/svn_mergeinfo_private.h" +#include "private/svn_subr_private.h" +#include "private/svn_fs_util.h" +#include "private/svn_fspath.h" +#include "../libsvn_fs/fs-loader.h" + + +/*** Path handling ***/ + +/* DAG caching uses "normalized" paths - which are a relaxed form of + canonical relpaths. They omit the leading '/' of the abspath and trim + any trailing '/'. Any sequences of '//' will be kept as the path walker + simply skips over them. + + Non-canonical sections of the path will therefore only impact efficiency + (extra walker iterations and possibly duplicated entries in the cache) + but not correctness. + + Another optimization is that we don't NUL-terminate the path but strictly + use its length info. That way, it can be traversed easily without + chopping it up and patching it together again. ultimately, however, + the path string is NUL-terminated because we wrapped a NUL-terminated + C string. + */ + +/* Set *RESULT to a normalized version of PATH without actually copying any + string contents. + + For convenience, return the RESULT pointer as the function value too. */ +static svn_string_t * +normalize_path(svn_string_t *result, + const char *path) +{ + apr_size_t len; + + if (path[0] == '/') + ++path; + + len = strlen(path); + while (len && path[len-1] == '/') + --len; + + result->data = path; + result->len = len; + + return result; +} + +/* Extend PATH, i.e. increase its LEN, to cover the next segment. Skip + sequences of '/'. Store the segment in ENTRY and return a pointer to + it C string representation. If no segment has been found (end of path), + return NULL. */ +static const char * +next_entry_name(svn_string_t *path, + svn_stringbuf_t *entry) +{ + const char *segment_start; + const char *segment_end; + + /* Moving to the next segment, skip separators + (normalized does not imply canonical). */ + segment_start = path->data + path->len; + while (*segment_start == '/') + ++segment_start; + + /* End of path? */ + if (*segment_start == '\0') + return NULL; + + /* Find the end of this segment. Note that strchr would not give us the + length of the last segment. */ + segment_end = segment_start; + while (*segment_end != '/' && *segment_end != '\0') + ++segment_end; + + /* Copy the segment into the result buffer. */ + svn_stringbuf_setempty(entry); + svn_stringbuf_appendbytes(entry, segment_start, + segment_end - segment_start); + + /* Extend the "visible" part of the path to the end of that segment. */ + path->len = segment_end - path->data; + + /* Indicate that we found something. */ + return entry->data; +} + +/* Split the normalized PATH into its last segment the corresponding parent + directory. Store them in ENTRY and DIRECTORY, respectively. + + If PATH is empty, return FALSE and produce no output. + Otherwise, return TRUE. + */ +static svn_boolean_t +extract_last_segment(const svn_string_t *path, + svn_string_t *directory, + svn_stringbuf_t *entry) +{ + const char *segment_start; + const char *parent_end; + + /* Edge case. We can't navigate in empty paths. */ + if (path->len == 0) + return FALSE; + + /* Find the start of the last segment. Note that normalized paths never + start nor end with a '/'. */ + segment_start = path->data + path->len - 1; + while (*segment_start != '/' && segment_start != path->data) + --segment_start; + + /* At root level already, i.e. no parent? */ + if (segment_start == path->data) + { + /* Construct result. */ + directory->data = ""; + directory->len = 0; + + svn_stringbuf_setempty(entry); + svn_stringbuf_appendbytes(entry, path->data, path->len); + + return TRUE; + } + + /* Find the end of the parent directory. */ + parent_end = segment_start; + while (parent_end[-1] == '/') + --parent_end; + + /* Construct result. */ + directory->data = path->data; + directory->len = parent_end - path->data; + + ++segment_start; /* previously pointed to the last '/'. */ + svn_stringbuf_setempty(entry); + svn_stringbuf_appendbytes(entry, segment_start, + path->len - (segment_start - path->data)); + + return TRUE; +} + + +/*** Node Caching ***/ + +/* 1st level cache */ + +/* An entry in the first-level cache. REVISION and PATH form the key that + will ultimately be matched. + */ +typedef struct cache_entry_t +{ + /* hash value derived from PATH, REVISION. + Used to short-circuit failed lookups. */ + apr_uint32_t hash_value; + + /* change set to which the NODE belongs */ + svn_fs_x__change_set_t change_set; + + /* path of the NODE */ + char *path; + + /* cached value of strlen(PATH). */ + apr_size_t path_len; + + /* the node allocated in the cache's pool. NULL for empty entries. */ + dag_node_t *node; +} cache_entry_t; + +/* Number of entries in the cache. Keep this low to keep pressure on the + CPU caches low as well. A binary value is most efficient. If we walk + a directory tree, we want enough entries to store nodes for all files + without overwriting the nodes for the parent folder. That way, there + will be no unnecessary misses (except for a few random ones caused by + hash collision). + + The actual number of instances may be higher but entries that got + overwritten are no longer visible. + */ +enum { BUCKET_COUNT = 256 }; + +/* The actual cache structure. All nodes will be allocated in POOL. + When the number of INSERTIONS (i.e. objects created form that pool) + exceeds a certain threshold, the pool will be cleared and the cache + with it. + */ +struct svn_fs_x__dag_cache_t +{ + /* fixed number of (possibly empty) cache entries */ + cache_entry_t buckets[BUCKET_COUNT]; + + /* pool used for all node allocation */ + apr_pool_t *pool; + + /* number of entries created from POOL since the last cleanup */ + apr_size_t insertions; + + /* Property lookups etc. have a very high locality (75% re-hit). + Thus, remember the last hit location for optimistic lookup. */ + apr_size_t last_hit; + + /* Position of the last bucket hit that actually had a DAG node in it. + LAST_HIT may refer to a bucket that matches path@rev but has not + its NODE element set, yet. + This value is a mere hint for optimistic lookup and any value is + valid (as long as it is < BUCKET_COUNT). */ + apr_size_t last_non_empty; +}; + +svn_fs_x__dag_cache_t* +svn_fs_x__create_dag_cache(apr_pool_t *result_pool) +{ + svn_fs_x__dag_cache_t *result = apr_pcalloc(result_pool, sizeof(*result)); + result->pool = svn_pool_create(result_pool); + + return result; +} + +/* Clears the CACHE at regular intervals (destroying all cached nodes). + * Return TRUE if the cache got cleared and previously obtained references + * to cache contents have become invalid. + */ +static svn_boolean_t +auto_clear_dag_cache(svn_fs_x__dag_cache_t* cache) +{ + if (cache->insertions <= BUCKET_COUNT) + return FALSE; + + svn_pool_clear(cache->pool); + + memset(cache->buckets, 0, sizeof(cache->buckets)); + cache->insertions = 0; + + return TRUE; +} + +/* For the given CHANGE_SET and PATH, return the respective entry in CACHE. + If the entry is empty, its NODE member will be NULL and the caller + may then set it to the corresponding DAG node allocated in CACHE->POOL. + */ +static cache_entry_t * +cache_lookup(svn_fs_x__dag_cache_t *cache, + svn_fs_x__change_set_t change_set, + const svn_string_t *path) +{ + apr_size_t i, bucket_index; + apr_size_t path_len = path->len; + apr_uint32_t hash_value = (apr_uint32_t)(apr_uint64_t)change_set; + +#if SVN_UNALIGNED_ACCESS_IS_OK + /* "randomizing" / distributing factor used in our hash function */ + const apr_uint32_t factor = 0xd1f3da69; +#endif + + /* optimistic lookup: hit the same bucket again? */ + cache_entry_t *result = &cache->buckets[cache->last_hit]; + if ( (result->change_set == change_set) + && (result->path_len == path_len) + && !memcmp(result->path, path->data, path_len)) + { + /* Remember the position of the last node we found in this cache. */ + if (result->node) + cache->last_non_empty = cache->last_hit; + + return result; + } + + /* need to do a full lookup. Calculate the hash value + (HASH_VALUE has been initialized to REVISION). */ + i = 0; +#if SVN_UNALIGNED_ACCESS_IS_OK + /* We relax the dependency chain between iterations by processing + two chunks from the input per hash_value self-multiplication. + The HASH_VALUE update latency is now 1 MUL latency + 1 ADD latency + per 2 chunks instead of 1 chunk. + */ + for (; i + 8 <= path_len; i += 8) + hash_value = hash_value * factor * factor + + ( *(const apr_uint32_t*)(path->data + i) * factor + + *(const apr_uint32_t*)(path->data + i + 4)); +#endif + + for (; i < path_len; ++i) + /* Help GCC to minimize the HASH_VALUE update latency by splitting the + MUL 33 of the naive implementation: h = h * 33 + path[i]. This + shortens the dependency chain from 1 shift + 2 ADDs to 1 shift + 1 ADD. + */ + hash_value = hash_value * 32 + (hash_value + (apr_byte_t)path->data[i]); + + bucket_index = hash_value + (hash_value >> 16); + bucket_index = (bucket_index + (bucket_index >> 8)) % BUCKET_COUNT; + + /* access the corresponding bucket and remember its location */ + result = &cache->buckets[bucket_index]; + cache->last_hit = bucket_index; + + /* if it is *NOT* a match, clear the bucket, expect the caller to fill + in the node and count it as an insertion */ + if ( (result->hash_value != hash_value) + || (result->change_set != change_set) + || (result->path_len != path_len) + || memcmp(result->path, path->data, path_len)) + { + result->hash_value = hash_value; + result->change_set = change_set; + + if (result->path_len < path_len || result->path_len == 0) + result->path = apr_palloc(cache->pool, path_len + 1); + result->path_len = path_len; + + memcpy(result->path, path->data, path_len); + result->path[path_len] = 0; + + result->node = NULL; + + cache->insertions++; + } + else if (result->node) + { + /* This bucket is valid & has a suitable DAG node in it. + Remember its location. */ + cache->last_non_empty = bucket_index; + } + + return result; +} + +/* Optimistic lookup using the last seen non-empty location in CACHE. + Return the node of that entry, if it is still in use and matches PATH. + Return NULL otherwise. */ +static dag_node_t * +cache_lookup_last_path(svn_fs_x__dag_cache_t *cache, + const svn_string_t *path) +{ + cache_entry_t *result = &cache->buckets[cache->last_non_empty]; + + if ( result->node + && (result->path_len == path->len) + && !memcmp(result->path, path->data, path->len)) + { + return result->node; + } + + return NULL; +} + +/* Return the cached DAG node for PATH from ROOT's node cache, or NULL if + the node isn't cached. + */ +static dag_node_t * +dag_node_cache_get(svn_fs_root_t *root, + const svn_string_t *path) +{ + svn_fs_x__data_t *ffd = root->fs->fsap_data; + svn_fs_x__change_set_t change_set = svn_fs_x__root_change_set(root); + + auto_clear_dag_cache(ffd->dag_node_cache); + return cache_lookup(ffd->dag_node_cache, change_set, path)->node; +} + + +void +svn_fs_x__update_dag_cache(dag_node_t *node) +{ + svn_fs_x__data_t *ffd = svn_fs_x__dag_get_fs(node)->fsap_data; + const char *path = svn_fs_x__dag_get_created_path(node); + svn_fs_x__dag_cache_t *cache = ffd->dag_node_cache; + + cache_entry_t *bucket; + svn_string_t normalized; + + auto_clear_dag_cache(cache); + bucket = cache_lookup(cache, svn_fs_x__dag_get_id(node)->change_set, + normalize_path(&normalized, path)); + bucket->node = svn_fs_x__dag_dup(node, cache->pool); +} + +void +svn_fs_x__invalidate_dag_cache(svn_fs_root_t *root, + const char *path) +{ + svn_fs_x__data_t *ffd = root->fs->fsap_data; + svn_fs_x__dag_cache_t *cache = ffd->dag_node_cache; + svn_fs_x__change_set_t change_set = svn_fs_x__root_change_set(root); + + apr_size_t i; + for (i = 0; i < BUCKET_COUNT; ++i) + { + cache_entry_t *bucket = &cache->buckets[i]; + if (bucket->change_set == change_set && bucket->node) + { + /* The call to svn_relpath_skip_ancestor() will require both + parameters to be canonical. Since we allow for non-canonical + paths in our cache (unlikely to actually happen), we drop all + such entries. + */ + if (!svn_relpath_is_canonical(bucket->path) + || svn_relpath_skip_ancestor(path + 1, bucket->path)) + bucket->node = NULL; + } + } +} + + +/* Traversing directory paths. */ + +/* Try a short-cut for the open_path() function using the last node accessed. + * If that ROOT is that nodes's "created rev" and PATH matches its "created- + * path", return the node in *NODE_P. Set it to NULL otherwise. + * + * This function is used to support ra_serf-style access patterns where we + * are first asked for path@rev and then for path@c_rev of the same node. + * The shortcut works by ignoring the "rev" part of the cache key and then + * checking whether we got lucky. Lookup and verification are both quick + * plus there are many early outs for common types of mismatch. + */ +static svn_error_t * +try_match_last_node(dag_node_t **node_p, + svn_fs_root_t *root, + const svn_string_t *path) +{ + svn_fs_x__data_t *ffd = root->fs->fsap_data; + + /* Optimistic lookup: if the last node returned from the cache applied to + the same PATH, return it in NODE. */ + dag_node_t *node = cache_lookup_last_path(ffd->dag_node_cache, path); + + /* Did we get a bucket with a committed node? */ + if (node && !svn_fs_x__dag_check_mutable(node)) + { + /* Get the path&rev pair at which this node was created. + This is repository location for which this node is _known_ to be + the right lookup result irrespective of how we found it. */ + const char *created_path + = svn_fs_x__dag_get_created_path(node) + 1; + svn_revnum_t revision = svn_fs_x__dag_get_revision(node); + + /* Is it an exact match? */ + if ( revision == root->rev + && strlen(created_path) == path->len + && memcmp(created_path, path->data, path->len) == 0) + { + svn_fs_x__dag_cache_t *cache = ffd->dag_node_cache; + + /* Insert NODE into the cache at a second location. + In a fraction of all calls, the auto-cleanup may + cause NODE to become invalid. */ + if (!auto_clear_dag_cache(cache)) + { + /* Cache it under its full path@rev access path. */ + svn_fs_x__change_set_t change_set + = svn_fs_x__change_set_by_rev(revision); + cache_entry_t *bucket = cache_lookup(cache, change_set, path); + bucket->node = node; + + *node_p = node; + return SVN_NO_ERROR; + } + } + } + + *node_p = NULL; + return SVN_NO_ERROR; +} + + +/* From directory node PARENT, under ROOT, go one step down to the entry + NAME and return a reference to it in *CHILD_P. + + PATH is the combination of PARENT's path and NAME and is provided by + the caller such that we don't have to construct it here ourselves. + Similarly, CHANGE_SET is redundant with ROOT. + + If the directory entry cannot be found, instead of returning an error, + *CHILD_P will be set to NULL if ALLOW_EMPTY is TRUE. + + NOTE: *NODE_P will live within the DAG cache and we merely return a + reference to it. Hence, it will invalid upon the next cache insertion. + Callers must create a copy if they want a non-temporary object. +*/ +static svn_error_t * +dag_step(dag_node_t **child_p, + svn_fs_root_t *root, + dag_node_t *parent, + const char *name, + const svn_string_t *path, + svn_fs_x__change_set_t change_set, + svn_boolean_t allow_empty, + apr_pool_t *scratch_pool) +{ + svn_fs_t *fs = svn_fs_x__dag_get_fs(parent); + svn_fs_x__data_t *ffd = fs->fsap_data; + cache_entry_t *bucket; + svn_fs_x__id_t node_id; + + /* Locate the corresponding cache entry. We may need PARENT to remain + valid for later use, so don't call auto_clear_dag_cache() here. */ + bucket = cache_lookup(ffd->dag_node_cache, change_set, path); + if (bucket->node) + { + /* Already cached. Return a reference to the cached object. */ + *child_p = bucket->node; + return SVN_NO_ERROR; + } + + /* Get the ID of the node we are looking for. The function call checks + for various error conditions such like PARENT not being a directory. */ + SVN_ERR(svn_fs_x__dir_entry_id(&node_id, parent, name, scratch_pool)); + if (! svn_fs_x__id_used(&node_id)) + { + const char *dir; + + /* No such directory entry. Is a simple NULL result o.k.? */ + if (allow_empty) + { + *child_p = NULL; + return SVN_NO_ERROR; + } + + /* Produce an appropriate error message. */ + dir = apr_pstrmemdup(scratch_pool, path->data, path->len); + dir = svn_fs__canonicalize_abspath(dir, scratch_pool); + + return SVN_FS__NOT_FOUND(root, dir); + } + + /* We are about to add a new entry to the cache. Periodically clear it. + If we had to clear it just now (< 1% chance), re-add the entry for our + item. */ + if (auto_clear_dag_cache(ffd->dag_node_cache)) + bucket = cache_lookup(ffd->dag_node_cache, change_set, path); + + /* Construct the DAG node object for NODE_ID. Let it live in the cache. */ + SVN_ERR(svn_fs_x__dag_get_node(&bucket->node, fs, &node_id, + ffd->dag_node_cache->pool, + scratch_pool)); + + /* Return a reference to the cached object. */ + *child_p = bucket->node; + return SVN_NO_ERROR; +} + +/* Return the CHANGE_SET's root node in *NODE_P. ROOT is the FS API root + object for CHANGE_SET. Use SCRATCH_POOL for temporary allocations. + + NOTE: *NODE_P will live within the DAG cache and we merely return a + reference to it. Hence, it will invalid upon the next cache insertion. + Callers must create a copy if they want a non-temporary object. + */ +static svn_error_t * +get_root_node(dag_node_t **node_p, + svn_fs_root_t *root, + svn_fs_x__change_set_t change_set, + apr_pool_t *scratch_pool) +{ + svn_fs_t *fs = root->fs; + svn_fs_x__data_t *ffd = fs->fsap_data; + cache_entry_t *bucket; + const svn_string_t path = { "", 0 }; + + /* Auto-insert the node in the cache. */ + auto_clear_dag_cache(ffd->dag_node_cache); + bucket = cache_lookup(ffd->dag_node_cache, change_set, &path); + + /* If it is not already cached, construct the DAG node object for NODE_ID. + Let it live in the cache. Sadly, we often can't reuse txn DAG nodes. */ + if (bucket->node == NULL) + SVN_ERR(svn_fs_x__dag_root(&bucket->node, fs, change_set, + ffd->dag_node_cache->pool, scratch_pool)); + + /* Return a reference to the cached object. */ + *node_p = bucket->node; + return SVN_NO_ERROR; +} + +/* Walk the DAG starting at ROOT, following PATH and return a reference to + the target node in *NODE_P. Use SCRATCH_POOL for temporary allocations. + + NOTE: *NODE_P will live within the DAG cache and we merely return a + reference to it. Hence, it will invalid upon the next cache insertion. + Callers must create a copy if they want a non-temporary object. +*/ +static svn_error_t * +walk_dag_path(dag_node_t **node_p, + svn_fs_root_t *root, + svn_string_t *path, + apr_pool_t *scratch_pool) +{ + dag_node_t *here = NULL; /* The directory we're currently looking at. */ + apr_pool_t *iterpool; + svn_fs_x__change_set_t change_set = svn_fs_x__root_change_set(root); + const char *entry; + svn_string_t directory; + svn_stringbuf_t *entry_buffer; + + /* Special case: root directory. + We will later assume that all paths have at least one parent level, + so we must check here for those that don't. */ + if (path->len == 0) + return svn_error_trace(get_root_node(node_p, root, change_set, + scratch_pool)); + + /* Callers often traverse the DAG in some path-based order or along the + history segments. That allows us to try a few guesses about where to + find the next item. This is only useful if the caller didn't request + the full parent chain. */ + + /* First attempt: Assume that we access the DAG for the same path as + in the last lookup but for a different revision that happens to be + the last revision that touched the respective node. This is a + common pattern when e.g. checking out over ra_serf. Note that this + will only work for committed data as the revision info for nodes in + txns is bogus. + + This shortcut is quick and will exit this function upon success. + So, try it first. */ + if (!root->is_txn_root) + { + SVN_ERR(try_match_last_node(node_p, root, path)); + + /* Did the shortcut work? */ + if (*node_p) + return SVN_NO_ERROR; + } + + /* Second attempt: Try starting the lookup immediately at the parent + node. We will often have recently accessed either a sibling or + said parent directory itself for the same revision. ENTRY will + point to the last '/' in PATH. */ + entry_buffer = svn_stringbuf_create_ensure(64, scratch_pool); + if (extract_last_segment(path, &directory, entry_buffer)) + { + here = dag_node_cache_get(root, &directory); + + /* Did the shortcut work? */ + if (here) + return svn_error_trace(dag_step(node_p, root, here, + entry_buffer->data, path, + change_set, FALSE, scratch_pool)); + } + + /* Now there is something to iterate over. Thus, create the ITERPOOL. */ + iterpool = svn_pool_create(scratch_pool); + + /* Make a parent_path item for the root node, using its own current + copy id. */ + SVN_ERR(get_root_node(&here, root, change_set, iterpool)); + path->len = 0; + + /* Walk the path segment by segment. */ + for (entry = next_entry_name(path, entry_buffer); + entry; + entry = next_entry_name(path, entry_buffer)) + { + svn_pool_clear(iterpool); + + /* Note that HERE is allocated from the DAG node cache and will + therefore survive the ITERPOOL cleanup. */ + SVN_ERR(dag_step(&here, root, here, entry, path, change_set, FALSE, + iterpool)); + } + + svn_pool_destroy(iterpool); + *node_p = here; + + return SVN_NO_ERROR; +} + + +/* Return a text string describing the absolute path of parent path + DAG_PATH. It will be allocated in POOL. */ +static const char * +parent_path_path(svn_fs_x__dag_path_t *dag_path, + apr_pool_t *pool) +{ + const char *path_so_far = "/"; + if (dag_path->parent) + path_so_far = parent_path_path(dag_path->parent, pool); + return dag_path->entry + ? svn_fspath__join(path_so_far, dag_path->entry, pool) + : path_so_far; +} + + +/* Choose a copy ID inheritance method *INHERIT_P to be used in the + event that immutable node CHILD in FS needs to be made mutable. If + the inheritance method is copy_id_inherit_new, also return a + *COPY_SRC_PATH on which to base the new copy ID (else return NULL + for that path). CHILD must have a parent (it cannot be the root + node). Temporary allocations are taken from SCRATCH_POOL. */ +static svn_error_t * +get_copy_inheritance(svn_fs_x__copy_id_inherit_t *inherit_p, + const char **copy_src_path, + svn_fs_t *fs, + svn_fs_x__dag_path_t *child, + apr_pool_t *scratch_pool) +{ + svn_fs_x__id_t child_copy_id, parent_copy_id; + const char *id_path = NULL; + svn_fs_root_t *copyroot_root; + dag_node_t *copyroot_node; + svn_revnum_t copyroot_rev; + const char *copyroot_path; + + SVN_ERR_ASSERT(child && child->parent); + + /* Initialize some convenience variables. */ + child_copy_id = *svn_fs_x__dag_get_copy_id(child->node); + parent_copy_id = *svn_fs_x__dag_get_copy_id(child->parent->node); + + /* By default, there is no copy source. */ + *copy_src_path = NULL; + + /* If this child is already mutable, we have nothing to do. */ + if (svn_fs_x__dag_check_mutable(child->node)) + { + *inherit_p = svn_fs_x__copy_id_inherit_self; + return SVN_NO_ERROR; + } + + /* From this point on, we'll assume that the child will just take + its copy ID from its parent. */ + *inherit_p = svn_fs_x__copy_id_inherit_parent; + + /* Special case: if the child's copy ID is '0', use the parent's + copy ID. */ + if (svn_fs_x__id_is_root(&child_copy_id)) + return SVN_NO_ERROR; + + /* Compare the copy IDs of the child and its parent. If they are + the same, then the child is already on the same branch as the + parent, and should use the same mutability copy ID that the + parent will use. */ + if (svn_fs_x__id_eq(&child_copy_id, &parent_copy_id)) + return SVN_NO_ERROR; + + /* If the child is on the same branch that the parent is on, the + child should just use the same copy ID that the parent would use. + Else, the child needs to generate a new copy ID to use should it + need to be made mutable. We will claim that child is on the same + branch as its parent if the child itself is not a branch point, + or if it is a branch point that we are accessing via its original + copy destination path. */ + svn_fs_x__dag_get_copyroot(©root_rev, ©root_path, child->node); + SVN_ERR(svn_fs_x__revision_root(©root_root, fs, copyroot_rev, + scratch_pool)); + SVN_ERR(svn_fs_x__get_temp_dag_node(©root_node, copyroot_root, + copyroot_path, scratch_pool)); + + if (!svn_fs_x__dag_related_node(copyroot_node, child->node)) + return SVN_NO_ERROR; + + /* Determine if we are looking at the child via its original path or + as a subtree item of a copied tree. */ + id_path = svn_fs_x__dag_get_created_path(child->node); + if (strcmp(id_path, parent_path_path(child, scratch_pool)) == 0) + { + *inherit_p = svn_fs_x__copy_id_inherit_self; + return SVN_NO_ERROR; + } + + /* We are pretty sure that the child node is an unedited nested + branched node. When it needs to be made mutable, it should claim + a new copy ID. */ + *inherit_p = svn_fs_x__copy_id_inherit_new; + *copy_src_path = id_path; + return SVN_NO_ERROR; +} + +/* Allocate a new svn_fs_x__dag_path_t node from RESULT_POOL, containing + NODE, ENTRY and PARENT, all copied into RESULT_POOL as well. */ +static svn_fs_x__dag_path_t * +make_parent_path(dag_node_t *node, + const svn_stringbuf_t *entry, + svn_fs_x__dag_path_t *parent, + apr_pool_t *result_pool) +{ + svn_fs_x__dag_path_t *dag_path + = apr_pcalloc(result_pool, sizeof(*dag_path)); + if (node) + dag_path->node = svn_fs_x__dag_dup(node, result_pool); + dag_path->entry = apr_pstrmemdup(result_pool, entry->data, entry->len); + dag_path->parent = parent; + dag_path->copy_inherit = svn_fs_x__copy_id_inherit_unknown; + dag_path->copy_src_path = NULL; + return dag_path; +} + +svn_error_t * +svn_fs_x__get_dag_path(svn_fs_x__dag_path_t **dag_path_p, + svn_fs_root_t *root, + const char *fs_path, + int flags, + svn_boolean_t is_txn_path, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_fs_t *fs = root->fs; + dag_node_t *here = NULL; /* The directory we're currently looking at. */ + svn_fs_x__dag_path_t *dag_path; /* The path from HERE up to the root. */ + apr_pool_t *iterpool = svn_pool_create(scratch_pool); + + svn_fs_x__change_set_t change_set = svn_fs_x__root_change_set(root); + const char *entry; + svn_string_t path; + svn_stringbuf_t *entry_buffer = svn_stringbuf_create_ensure(64, + scratch_pool); + apr_size_t path_len; + + /* Normalize the FS_PATH to be compatible with our DAG walk utils. */ + normalize_path(&path, fs_path); /* "" */ + + /* Make a DAG_PATH for the root node, using its own current copy id. */ + SVN_ERR(get_root_node(&here, root, change_set, iterpool)); + dag_path = make_parent_path(here, entry_buffer, NULL, result_pool); + dag_path->copy_inherit = svn_fs_x__copy_id_inherit_self; + + path_len = path.len; + path.len = 0; + + /* Walk the path segment by segment. Add to the DAG_PATH as we go. */ + for (entry = next_entry_name(&path, entry_buffer); + entry; + entry = next_entry_name(&path, entry_buffer)) + { + svn_pool_clear(iterpool); + + /* If the current node is not a directory and we are just here to + * check for the path's existence, then that's o.k. + * Otherwise, non-dir nodes will cause an error in dag_step. */ + if ( (flags & svn_fs_x__dag_path_allow_null) + && (svn_fs_x__dag_node_kind(dag_path->node) != svn_node_dir)) + { + dag_path = NULL; + break; + } + + /* Find the sub-node. */ + SVN_ERR(dag_step(&here, root, dag_path->node, entry, &path, change_set, + TRUE, iterpool)); + + /* "node not found" requires special handling. */ + if (here == NULL) + { + /* If this was the last path component, and the caller + said it was optional, then don't return an error; + just put a NULL node pointer in the path. + */ + if ((flags & svn_fs_x__dag_path_last_optional) + && (path_len == path.len)) + { + dag_path = make_parent_path(NULL, entry_buffer, dag_path, + result_pool); + break; + } + else if (flags & svn_fs_x__dag_path_allow_null) + { + dag_path = NULL; + break; + } + else + { + /* Build a better error message than svn_fs_x__dag_open + can provide, giving the root and full path name. */ + return SVN_FS__NOT_FOUND(root, fs_path); + } + } + + /* Now, make a parent_path item for CHILD. */ + dag_path = make_parent_path(here, entry_buffer, dag_path, result_pool); + if (is_txn_path) + { + SVN_ERR(get_copy_inheritance(&dag_path->copy_inherit, + &dag_path->copy_src_path, + fs, dag_path, iterpool)); + } + } + + svn_pool_destroy(iterpool); + *dag_path_p = dag_path; + return SVN_NO_ERROR; +} + +/* Set *NODE_P to a mutable root directory for ROOT, cloning if + necessary, allocating in RESULT_POOL. ROOT must be a transaction root. + Use ERROR_PATH in error messages. Use SCRATCH_POOL for temporaries.*/ +static svn_error_t * +mutable_root_node(dag_node_t **node_p, + svn_fs_root_t *root, + const char *error_path, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + /* If it's not a transaction root, we can't change its contents. */ + if (!root->is_txn_root) + return SVN_FS__ERR_NOT_MUTABLE(root->fs, root->rev, error_path); + + /* It's a transaction root. + Get the appropriate DAG root node and copy it into RESULT_POOL. */ + SVN_ERR(get_root_node(node_p, root, svn_fs_x__root_change_set(root), + scratch_pool)); + *node_p = svn_fs_x__dag_dup(*node_p, result_pool); + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_fs_x__make_path_mutable(svn_fs_root_t *root, + svn_fs_x__dag_path_t *parent_path, + const char *error_path, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + dag_node_t *clone; + svn_fs_x__txn_id_t txn_id = svn_fs_x__root_txn_id(root); + + /* Is the node mutable already? */ + if (svn_fs_x__dag_check_mutable(parent_path->node)) + return SVN_NO_ERROR; + + /* Are we trying to clone the root, or somebody's child node? */ + if (parent_path->parent) + { + svn_fs_x__id_t copy_id = { SVN_INVALID_REVNUM, 0 }; + svn_fs_x__id_t *copy_id_ptr = ©_id; + svn_fs_x__copy_id_inherit_t inherit = parent_path->copy_inherit; + const char *clone_path, *copyroot_path; + svn_revnum_t copyroot_rev; + svn_boolean_t is_parent_copyroot = FALSE; + svn_fs_root_t *copyroot_root; + dag_node_t *copyroot_node; + apr_pool_t *subpool; + + /* We're trying to clone somebody's child. Make sure our parent + is mutable. */ + SVN_ERR(svn_fs_x__make_path_mutable(root, parent_path->parent, + error_path, result_pool, + scratch_pool)); + + /* Allocate all temporaries in a sub-pool that we control locally. + That way, we keep only the data of one level of recursion around + at any time. */ + subpool = svn_pool_create(scratch_pool); + switch (inherit) + { + case svn_fs_x__copy_id_inherit_parent: + copy_id = *svn_fs_x__dag_get_copy_id(parent_path->parent->node); + break; + + case svn_fs_x__copy_id_inherit_new: + SVN_ERR(svn_fs_x__reserve_copy_id(©_id, root->fs, txn_id, + subpool)); + break; + + case svn_fs_x__copy_id_inherit_self: + copy_id_ptr = NULL; + break; + + case svn_fs_x__copy_id_inherit_unknown: + default: + SVN_ERR_MALFUNCTION(); /* uh-oh -- somebody didn't calculate copy-ID + inheritance data. */ + } + + /* Determine what copyroot our new child node should use. */ + svn_fs_x__dag_get_copyroot(©root_rev, ©root_path, + parent_path->node); + SVN_ERR(svn_fs_x__revision_root(©root_root, root->fs, + copyroot_rev, subpool)); + SVN_ERR(svn_fs_x__get_temp_dag_node(©root_node, copyroot_root, + copyroot_path, subpool)); + + if (!svn_fs_x__dag_related_node(copyroot_node, parent_path->node)) + is_parent_copyroot = TRUE; + + /* Now make this node mutable. */ + clone_path = parent_path_path(parent_path->parent, subpool); + SVN_ERR(svn_fs_x__dag_clone_child(&clone, + parent_path->parent->node, + clone_path, + parent_path->entry, + copy_id_ptr, txn_id, + is_parent_copyroot, + result_pool, + subpool)); + + /* Update the path cache. */ + svn_fs_x__update_dag_cache(clone); + svn_pool_destroy(subpool); + } + else + { + /* We're trying to clone the root directory. */ + SVN_ERR(mutable_root_node(&clone, root, error_path, result_pool, + scratch_pool)); + } + + /* Update the PARENT_PATH link to refer to the clone. */ + parent_path->node = clone; + + return SVN_NO_ERROR; +} + + +svn_error_t * +svn_fs_x__get_temp_dag_node(dag_node_t **node_p, + svn_fs_root_t *root, + const char *path, + apr_pool_t *scratch_pool) +{ + svn_string_t normalized; + + /* First we look for the DAG in our cache. */ + *node_p = dag_node_cache_get(root, normalize_path(&normalized, path)); + + /* If it is not there, walk the DAG and fill the cache. */ + if (! *node_p) + SVN_ERR(walk_dag_path(node_p, root, &normalized, scratch_pool)); + + return SVN_NO_ERROR; +} + + +svn_error_t * +svn_fs_x__get_dag_node(dag_node_t **dag_node_p, + svn_fs_root_t *root, + const char *path, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + dag_node_t *node = NULL; + SVN_ERR(svn_fs_x__get_temp_dag_node(&node, root, path, scratch_pool)); + + /* We want the returned node to live in POOL. */ + *dag_node_p = svn_fs_x__dag_dup(node, result_pool); + + return SVN_NO_ERROR; +} diff --git a/subversion/libsvn_fs_x/dag_cache.h b/subversion/libsvn_fs_x/dag_cache.h new file mode 100644 index 000000000000..fd78bb74f9e8 --- /dev/null +++ b/subversion/libsvn_fs_x/dag_cache.h @@ -0,0 +1,174 @@ +/* dag_cache.h : Interface to the DAG walker and node cache. + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#ifndef SVN_LIBSVN_FS_X_DAG_CACHE_H +#define SVN_LIBSVN_FS_X_DAG_CACHE_H + +#include "dag.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* In RESULT_POOL, create an instance of a DAG node cache. */ +svn_fs_x__dag_cache_t* +svn_fs_x__create_dag_cache(apr_pool_t *result_pool); + +/* Invalidate cache entries for PATH within ROOT and any of its children. */ +void +svn_fs_x__invalidate_dag_cache(svn_fs_root_t *root, + const char *path); + +/* Flag type used in svn_fs_x__dag_path_t to determine where the + respective node got its copy ID from. */ +typedef enum svn_fs_x__copy_id_inherit_t +{ + svn_fs_x__copy_id_inherit_unknown = 0, + svn_fs_x__copy_id_inherit_self, + svn_fs_x__copy_id_inherit_parent, + svn_fs_x__copy_id_inherit_new + +} svn_fs_x__copy_id_inherit_t; + +/* Flags for svn_fs_x__get_dag_path. */ +typedef enum svn_fs_x__dag_path_flags_t { + + /* The last component of the PATH need not exist. (All parent + directories must exist, as usual.) If the last component doesn't + exist, simply leave the `node' member of the bottom parent_path + component zero. */ + svn_fs_x__dag_path_last_optional = 1, + + /* The caller wants a NULL path object instead of an error if the + path cannot be found. */ + svn_fs_x__dag_path_allow_null = 2 +} svn_fs_x__dag_path_flags_t; + + +/* A linked list representing the path from a node up to a root + directory. We use this for cloning, and for operations that need + to deal with both a node and its parent directory. For example, a + `delete' operation needs to know that the node actually exists, but + also needs to change the parent directory. */ +typedef struct svn_fs_x__dag_path_t +{ + /* A node along the path. This could be the final node, one of its + parents, or the root. Every parent path ends with an element for + the root directory. */ + dag_node_t *node; + + /* The name NODE has in its parent directory. This is zero for the + root directory, which (obviously) has no name in its parent. */ + char *entry; + + /* The parent of NODE, or zero if NODE is the root directory. */ + struct svn_fs_x__dag_path_t *parent; + + /* The copy ID inheritance style. */ + svn_fs_x__copy_id_inherit_t copy_inherit; + + /* If copy ID inheritance style is copy_id_inherit_new, this is the + path which should be implicitly copied; otherwise, this is NULL. */ + const char *copy_src_path; + +} svn_fs_x__dag_path_t; + +/* Open the node identified by PATH in ROOT, allocating in RESULT_POOL. + Set *DAG_PATH_P to a path from the node up to ROOT. The resulting + **DAG_PATH_P value is guaranteed to contain at least one element, + for the root directory. PATH must be in canonical form. Allocate + temporaries from SCRATCH_POOL. + + If resulting *PARENT_PATH_P will eventually be made mutable and + modified, or if copy ID inheritance information is otherwise needed, + IS_TXN_PATH must be set. If IS_TXN_PATH is FALSE, no copy ID + inheritance information will be calculated for the *PARENT_PATH_P chain. + + If FLAGS & open_path_last_optional is zero, return the error + SVN_ERR_FS_NOT_FOUND if the node PATH refers to does not exist. If + non-zero, require all the parent directories to exist as normal, + but if the final path component doesn't exist, simply return a path + whose bottom `node' member is zero. This option is useful for + callers that create new nodes --- we find the parent directory for + them, and tell them whether the entry exists already. + + If FLAGS & svn_fs_x__dag_path_allow_null is non-zero, set the + *PARENT_PATH_P to NULL if any node in the path could not be found. + + NOTE: Public interfaces which only *read* from the filesystem + should not call this function directly, but should instead use + svn_fs_x__get_dag_node(). +*/ +svn_error_t * +svn_fs_x__get_dag_path(svn_fs_x__dag_path_t **dag_path_p, + svn_fs_root_t *root, + const char *path, + int flags, + svn_boolean_t is_txn_path, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/* Make the node referred to by PARENT_PATH mutable, if it isn't already, + allocating from RESULT_POOL. ROOT must be the root from which + PARENT_PATH descends. Clone any parent directories as needed. + Adjust the dag nodes in PARENT_PATH to refer to the clones. Use + ERROR_PATH in error messages. Use SCRATCH_POOL for temporaries. */ +svn_error_t * +svn_fs_x__make_path_mutable(svn_fs_root_t *root, + svn_fs_x__dag_path_t *parent_path, + const char *error_path, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/* Open the node identified by PATH in ROOT. Set *DAG_NODE_P to a temporary + reference to the node we find. That reference will become invalid upon + the next access to the DAG cache. + + Return the error SVN_ERR_FS_NOT_FOUND if this node doesn't exist. + */ +svn_error_t * +svn_fs_x__get_temp_dag_node(dag_node_t **node_p, + svn_fs_root_t *root, + const char *path, + apr_pool_t *scratch_pool); + +/* Open the node identified by PATH in ROOT. Set *DAG_NODE_P to the + node we find, allocated in RESULT_POOL. Return the error + SVN_ERR_FS_NOT_FOUND if this node doesn't exist. Use SCRATCH_POOL + for temporary allocations. + */ +svn_error_t * +svn_fs_x__get_dag_node(dag_node_t **dag_node_p, + svn_fs_root_t *root, + const char *path, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/* Add / update the NODE in the node cache. */ +void +svn_fs_x__update_dag_cache(dag_node_t *node); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SVN_LIBSVN_FS_X_DAG_CACHE_H */ diff --git a/subversion/libsvn_fs_x/fs.c b/subversion/libsvn_fs_x/fs.c index abc564db34dc..7eb0add2def0 100644 --- a/subversion/libsvn_fs_x/fs.c +++ b/subversion/libsvn_fs_x/fs.c @@ -27,12 +27,12 @@ #include #include #include -#include #include "svn_fs.h" #include "svn_delta.h" #include "svn_version.h" #include "svn_pools.h" +#include "batch_fsync.h" #include "fs.h" #include "fs_x.h" #include "pack.h" @@ -137,6 +137,18 @@ x_serialized_init(svn_fs_t *fs, return SVN_NO_ERROR; } +svn_error_t * +svn_fs_x__initialize_shared_data(svn_fs_t *fs, + svn_mutex__t *common_pool_lock, + apr_pool_t *scratch_pool, + apr_pool_t *common_pool) +{ + SVN_MUTEX__WITH_LOCK(common_pool_lock, + x_serialized_init(fs, common_pool, scratch_pool)); + + return SVN_NO_ERROR; +} + /* This function is provided for Subversion 1.0.x compatibility. It @@ -218,20 +230,11 @@ x_info(const void **fsx_info, return SVN_NO_ERROR; } -/* Wrapper around svn_fs_x__revision_prop() adapting between function - signatures. */ static svn_error_t * -x_revision_prop(svn_string_t **value_p, - svn_fs_t *fs, - svn_revnum_t rev, - const char *propname, - apr_pool_t *pool) +x_refresh_revprops(svn_fs_t *fs, + apr_pool_t *scratch_pool) { - apr_pool_t *scratch_pool = svn_pool_create(pool); - SVN_ERR(svn_fs_x__revision_prop(value_p, fs, rev, propname, pool, - scratch_pool)); - svn_pool_destroy(scratch_pool); - + svn_fs_x__invalidate_revprop_generation(fs); return SVN_NO_ERROR; } @@ -241,14 +244,14 @@ static svn_error_t * x_revision_proplist(apr_hash_t **proplist_p, svn_fs_t *fs, svn_revnum_t rev, - apr_pool_t *pool) + svn_boolean_t refresh, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { - apr_pool_t *scratch_pool = svn_pool_create(pool); - /* No need to bypass the caches for r/o access to revprops. */ SVN_ERR(svn_fs_x__get_revision_proplist(proplist_p, fs, rev, FALSE, - pool, scratch_pool)); - svn_pool_destroy(scratch_pool); + refresh, result_pool, + scratch_pool)); return SVN_NO_ERROR; } @@ -262,7 +265,8 @@ x_set_uuid(svn_fs_t *fs, { /* Whenever we set a new UUID, imply that FS will also be a different * instance (on formats that support this). */ - return svn_error_trace(svn_fs_x__set_uuid(fs, uuid, NULL, scratch_pool)); + return svn_error_trace(svn_fs_x__set_uuid(fs, uuid, NULL, TRUE, + scratch_pool)); } /* Wrapper around svn_fs_x__begin_txn() providing the scratch pool. */ @@ -285,7 +289,8 @@ x_begin_txn(svn_fs_txn_t **txn_p, /* The vtable associated with a specific open filesystem. */ static fs_vtable_t fs_vtable = { svn_fs_x__youngest_rev, - x_revision_prop, + x_refresh_revprops, + svn_fs_x__revision_prop, x_revision_proplist, svn_fs_x__change_rev_prop, x_set_uuid, @@ -316,6 +321,9 @@ static svn_error_t * initialize_fs_struct(svn_fs_t *fs) { svn_fs_x__data_t *ffd = apr_pcalloc(fs->pool, sizeof(*ffd)); + ffd->revprop_generation = -1; + ffd->flush_to_disk = TRUE; + fs->vtable = &fs_vtable; fs->fsap_data = ffd; return SVN_NO_ERROR; @@ -500,7 +508,7 @@ x_pack(svn_fs_t *fs, apr_pool_t *common_pool) { SVN_ERR(x_open(fs, path, common_pool_lock, scratch_pool, common_pool)); - return svn_fs_x__pack(fs, notify_func, notify_baton, + return svn_fs_x__pack(fs, 0, notify_func, notify_baton, cancel_func, cancel_baton, scratch_pool); } @@ -536,24 +544,17 @@ x_hotcopy(svn_fs_t *src_fs, if (cancel_func) SVN_ERR(cancel_func(cancel_baton)); - /* Test target repo when in INCREMENTAL mode, initialize it when not. - * For this, we need our FS internal data structures to be temporarily - * available. */ + SVN_ERR(svn_fs__check_fs(dst_fs, FALSE)); SVN_ERR(initialize_fs_struct(dst_fs)); - SVN_ERR(svn_fs_x__hotcopy_prepare_target(src_fs, dst_fs, dst_path, - incremental, scratch_pool)); - uninitialize_fs_struct(dst_fs); - /* Now, the destination repo should open just fine. */ - SVN_ERR(x_open(dst_fs, dst_path, common_pool_lock, scratch_pool, - common_pool)); - if (cancel_func) - SVN_ERR(cancel_func(cancel_baton)); - - /* Now, we may copy data as needed ... */ - return svn_fs_x__hotcopy(src_fs, dst_fs, incremental, - notify_func, notify_baton, - cancel_func, cancel_baton, scratch_pool); + /* In INCREMENTAL mode, svn_fs_x__hotcopy() will open DST_FS. + Otherwise, it's not an FS yet --- possibly just an empty dir --- so + can't be opened. + */ + return svn_fs_x__hotcopy(src_fs, dst_fs, src_path, dst_path, + incremental, notify_func, notify_baton, + cancel_func, cancel_baton, common_pool_lock, + scratch_pool, common_pool); } @@ -664,6 +665,8 @@ svn_fs_x__init(const svn_version_t *loader_version, loader_version->major); SVN_ERR(svn_ver_check_list2(x_version(), checklist, svn_ver_equal)); + SVN_ERR(svn_fs_x__batch_fsync_init(common_pool)); + *vtable = &library_vtable; return SVN_NO_ERROR; } diff --git a/subversion/libsvn_fs_x/fs.h b/subversion/libsvn_fs_x/fs.h index afb4b2a63bf3..7c7a7715567f 100644 --- a/subversion/libsvn_fs_x/fs.h +++ b/subversion/libsvn_fs_x/fs.h @@ -1,4 +1,4 @@ -/* fs.h : interface to Subversion filesystem, private to libsvn_fs +/* fs.h : interface to Subversion filesystem * * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one @@ -20,8 +20,8 @@ * ==================================================================== */ -#ifndef SVN_LIBSVN_FS_X_H -#define SVN_LIBSVN_FS_X_H +#ifndef SVN_LIBSVN_FS_X_FS_H +#define SVN_LIBSVN_FS_X_FS_H #include #include @@ -37,7 +37,7 @@ #include "private/svn_sqlite.h" #include "private/svn_mutex.h" -#include "id.h" +#include "rev_file.h" #ifdef __cplusplus extern "C" { @@ -53,12 +53,11 @@ extern "C" { #define PATH_FORMAT "format" /* Contains format number */ #define PATH_UUID "uuid" /* Contains UUID */ #define PATH_CURRENT "current" /* Youngest revision */ +#define PATH_NEXT "next" /* Revision begin written. */ #define PATH_LOCK_FILE "write-lock" /* Revision lock file */ #define PATH_PACK_LOCK_FILE "pack-lock" /* Pack lock file */ #define PATH_REVS_DIR "revs" /* Directory of revisions */ -#define PATH_REVPROPS_DIR "revprops" /* Directory of revprops */ #define PATH_TXNS_DIR "transactions" /* Directory of transactions */ -#define PATH_NODE_ORIGINS_DIR "node-origins" /* Lazy node-origin cache */ #define PATH_TXN_PROTOS_DIR "txn-protorevs" /* Directory of proto-revs */ #define PATH_TXN_CURRENT "txn-current" /* File with next txn key */ #define PATH_TXN_CURRENT_LOCK "txn-current-lock" /* Lock for txn-current */ @@ -81,8 +80,6 @@ extern "C" { /* Names of special files and file extensions for transactions */ #define PATH_CHANGES "changes" /* Records changes made so far */ #define PATH_TXN_PROPS "props" /* Transaction properties */ -#define PATH_TXN_PROPS_FINAL "props-final" /* Final transaction properties - before moving to revprops */ #define PATH_NEXT_IDS "next-ids" /* Next temporary ID assignments */ #define PATH_PREFIX_NODE "node." /* Prefix for node filename */ #define PATH_EXT_TXN ".txn" /* Extension of txn dir */ @@ -124,7 +121,11 @@ extern "C" { Note: If you bump this, please update the switch statement in svn_fs_x__create() as well. */ -#define SVN_FS_X__FORMAT_NUMBER 1 +#define SVN_FS_X__FORMAT_NUMBER 2 + +/* Latest experimental format number. Experimental formats are only + compatible with themselves. */ +#define SVN_FS_X__EXPERIMENTAL_FORMAT_NUMBER 2 /* On most operating systems apr implements file locks per process, not per file. On Windows apr implements the locking as per file handle @@ -136,6 +137,11 @@ extern "C" { #define SVN_FS_X__USE_LOCK_MUTEX 0 #endif +/* Maximum number of changes we deliver per request when listing the + changed paths for a given revision. Anything > 0 will do. + At 100..300 bytes per entry, this limits the allocation to ~30kB. */ +#define SVN_FS_X__CHANGES_BLOCK_SIZE 100 + /* Private FSX-specific data shared between all svn_txn_t objects that relate to a particular transaction in a filesystem (as identified by transaction id and filesystem UUID). Objects of this type are @@ -179,11 +185,15 @@ typedef struct svn_fs_x__shared_data_t declaration here. Any subset may be acquired and held at any given time but their relative acquisition order must not change. - (lock 'txn-current' before 'pack' before 'write' before 'txn-list') */ + (lock 'pack' before 'write' before 'txn-current' before 'txn-list') */ /* A lock for intra-process synchronization when accessing the TXNS list. */ svn_mutex__t *txn_list_lock; + /* A lock for intra-process synchronization when locking the + txn-current file. */ + svn_mutex__t *txn_current_lock; + /* A lock for intra-process synchronization when grabbing the repository write lock. */ svn_mutex__t *fs_write_lock; @@ -192,10 +202,6 @@ typedef struct svn_fs_x__shared_data_t repository pack operation lock. */ svn_mutex__t *fs_pack_lock; - /* A lock for intra-process synchronization when locking the - txn-current file. */ - svn_mutex__t *txn_current_lock; - /* The common pool, under which this object is allocated, subpools of which are used to allocate the transaction objects. */ apr_pool_t *common_pool; @@ -281,13 +287,9 @@ typedef struct svn_fs_x__data_t e.g. memcached may be ignored as caching is an optional feature. */ svn_boolean_t fail_stop; - /* Caches native dag_node_t* instances and acts as a 1st level cache */ + /* Caches native dag_node_t* instances */ svn_fs_x__dag_cache_t *dag_node_cache; - /* DAG node cache for immutable nodes. Maps (revision, fspath) - to (dag_node_t *). This is the 2nd level cache for DAG nodes. */ - svn_cache__t *rev_node_cache; - /* A cache of the contents of immutable directories; maps from unparsed FS ID to a apr_hash_t * mapping (const char *) dirent names to (svn_fs_x__dirent_t *). */ @@ -297,9 +299,8 @@ typedef struct svn_fs_x__data_t rep key (revision/offset) to svn_stringbuf_t. */ svn_cache__t *fulltext_cache; - /* Access object to the revprop "generation". Will be NULL until - the first access. May be also get closed and set to NULL again. */ - apr_file_t *revprop_generation_file; + /* Revprop generation number. Will be -1 if it has to reread from disk. */ + apr_int64_t revprop_generation; /* Revision property cache. Maps from (rev,generation) to apr_hash_t. */ svn_cache__t *revprop_cache; @@ -307,12 +308,6 @@ typedef struct svn_fs_x__data_t /* Node properties cache. Maps from rep key to apr_hash_t. */ svn_cache__t *properties_cache; - /* Pack manifest cache; a cache mapping (svn_revnum_t) shard number to - a manifest; and a manifest is a mapping from (svn_revnum_t) revision - number offset within a shard to (apr_off_t) byte-offset in the - respective pack file. */ - svn_cache__t *packed_offset_cache; - /* Cache for txdelta_window_t objects; * the key is svn_fs_x__window_cache_key_t */ svn_cache__t *txdelta_window_cache; @@ -329,8 +324,8 @@ typedef struct svn_fs_x__data_t the key is a (pack file revision, file offset) pair */ svn_cache__t *noderevs_container_cache; - /* Cache for change lists as APR arrays of svn_fs_x__change_t * objects; - the key is the revision */ + /* Cache for change lists n blocks as svn_fs_x__changes_list_t * objects; + the key is the (revision, first-element-in-block) pair. */ svn_cache__t *changes_cache; /* Cache for change_list_t containers; @@ -345,15 +340,6 @@ typedef struct svn_fs_x__data_t (revision, item index) pair */ svn_cache__t *rep_header_cache; - /* Cache for svn_mergeinfo_t objects; the key is a combination of - revision, inheritance flags and path. */ - svn_cache__t *mergeinfo_cache; - - /* Cache for presence of svn_mergeinfo_t on a noderev; the key is a - combination of revision, inheritance flags and path; value is "1" - if the node has mergeinfo, "0" if it doesn't. */ - svn_cache__t *mergeinfo_existence_cache; - /* Cache for l2p_header_t objects; the key is (revision, is-packed). Will be NULL for pre-format7 repos */ svn_cache__t *l2p_header_cache; @@ -417,19 +403,19 @@ typedef struct svn_fs_x__data_t or dump / load cycles). */ const char *instance_id; + /* Ensure that all filesystem changes are written to disk. */ + svn_boolean_t flush_to_disk; + /* Pointer to svn_fs_open. */ svn_error_t *(*svn_fs_open_)(svn_fs_t **, const char *, apr_hash_t *, apr_pool_t *, apr_pool_t *); + } svn_fs_x__data_t; /*** Filesystem Transaction ***/ typedef struct svn_fs_x__transaction_t { - /* property list (const char * name, svn_string_t * value). - may be NULL if there are no properties. */ - apr_hash_t *proplist; - /* revision upon which this txn is base. (unfinished only) */ svn_revnum_t base_rev; @@ -503,7 +489,8 @@ typedef struct svn_fs_x__noderev_t /* node kind */ svn_node_kind_t kind; - /* number of predecessors this node revision has (recursively). */ + /* Number of predecessors this node revision has (recursively). + A difference from the BDB backend is that it cannot be -1. */ int predecessor_count; /* representation key for this node's properties. may be NULL if @@ -543,32 +530,46 @@ typedef struct svn_fs_x__dirent_t /*** Change ***/ -typedef struct svn_fs_x__change_t +typedef svn_fs_path_change3_t svn_fs_x__change_t; + +/*** Context for reading changed paths lists iteratively. */ +typedef struct svn_fs_x__changes_context_t { - /* Path of the change. */ - svn_string_t path; + /* Repository to fetch from. */ + svn_fs_t *fs; - /* node revision id of changed path */ - svn_fs_x__id_t noderev_id; + /* Revision that we read from. */ + svn_revnum_t revision; - /* See svn_fs_path_change2_t for a description for the remaining elements. - */ - svn_fs_path_change_kind_t change_kind; + /* Revision file object to use when needed. */ + svn_fs_x__revision_file_t *revision_file; - svn_boolean_t text_mod; - svn_boolean_t prop_mod; - svn_node_kind_t node_kind; + /* Index of the next change to fetch. */ + int next; - svn_boolean_t copyfrom_known; - svn_revnum_t copyfrom_rev; - const char *copyfrom_path; + /* Offset, within the changed paths list on disk, of the next change to + fetch. */ + apr_off_t next_offset; - svn_tristate_t mergeinfo_mod; -} svn_fs_x__change_t; + /* Has the end of the list been reached? */ + svn_boolean_t eol; + +} svn_fs_x__changes_context_t; + +/*** Directory (only used at the cache interface) ***/ +typedef struct svn_fs_x__dir_data_t +{ + /* Contents, i.e. all directory entries, sorted by name. */ + apr_array_header_t *entries; + + /* SVN_INVALID_FILESIZE for committed data, otherwise the length of the + * in-txn on-disk representation of that directory. */ + svn_filesize_t txn_filesize; +} svn_fs_x__dir_data_t; #ifdef __cplusplus } #endif /* __cplusplus */ -#endif /* SVN_LIBSVN_FS_X_H */ +#endif /* SVN_LIBSVN_FS_X_FS_H */ diff --git a/subversion/libsvn_fs_x/fs_init.h b/subversion/libsvn_fs_x/fs_init.h new file mode 100644 index 000000000000..8ecbda34b078 --- /dev/null +++ b/subversion/libsvn_fs_x/fs_init.h @@ -0,0 +1,33 @@ +/* +* libsvn_fs_x/fs_init.h: Exported function of libsvn_fs_x +* +* ==================================================================== +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +* ==================================================================== +*/ + +#ifndef LIBSVN_FS_LOADER_H +#error Please include libsvn_fs/fs_loader.h instead of this file +#else + +svn_error_t *svn_fs_x__init(const svn_version_t *loader_version, + fs_library_vtable_t **vtable, + apr_pool_t* common_pool); + +#endif + diff --git a/subversion/libsvn_fs_x/fs_x.c b/subversion/libsvn_fs_x/fs_x.c index b766b58b2201..ba1982f278bb 100644 --- a/subversion/libsvn_fs_x/fs_x.c +++ b/subversion/libsvn_fs_x/fs_x.c @@ -33,6 +33,7 @@ #include "cached_data.h" #include "id.h" +#include "low_level.h" #include "rep-cache.h" #include "revprops.h" #include "transaction.h" @@ -95,13 +96,27 @@ check_format(int format) { /* Put blacklisted versions here. */ - /* We support all formats from 1-current simultaneously */ - if (1 <= format && format <= SVN_FS_X__FORMAT_NUMBER) + /* We support any format if it matches the current format. */ + if (format == SVN_FS_X__FORMAT_NUMBER) + return SVN_NO_ERROR; + + /* Experimental formats are only supported if they match the current, but + * that case has already been handled. So, reject any experimental format. + */ + if (SVN_FS_X__EXPERIMENTAL_FORMAT_NUMBER >= format) + return svn_error_createf(SVN_ERR_FS_UNSUPPORTED_FORMAT, NULL, + _("Unsupported experimental FSX format '%d' found; current format is '%d'"), + format, SVN_FS_X__FORMAT_NUMBER); + + /* By default, we will support any non-experimental format released so far. + */ + if (format <= SVN_FS_X__FORMAT_NUMBER) return SVN_NO_ERROR; return svn_error_createf(SVN_ERR_FS_UNSUPPORTED_FORMAT, NULL, - _("Expected FS format between '1' and '%d'; found format '%d'"), - SVN_FS_X__FORMAT_NUMBER, format); + _("Expected FSX format between '%d' and '%d'; found format '%d'"), + SVN_FS_X__EXPERIMENTAL_FORMAT_NUMBER + 1, SVN_FS_X__FORMAT_NUMBER, + format); } /* Read the format file at PATH and set *PFORMAT to the format version found @@ -184,8 +199,9 @@ svn_fs_x__write_format(svn_fs_t *fs, } else { - SVN_ERR(svn_io_write_atomic(path, sb->data, sb->len, - NULL /* copy_perms_path */, scratch_pool)); + SVN_ERR(svn_io_write_atomic2(path, sb->data, sb->len, + NULL /* copy_perms_path */, + ffd->flush_to_disk, scratch_pool)); } /* And set the perms to make it read only */ @@ -519,6 +535,20 @@ write_config(svn_fs_t *fs, fsx_conf_contents, scratch_pool); } +/* Read / Evaluate the global configuration in FS->CONFIG to set up + * parameters in FS. */ +static svn_error_t * +read_global_config(svn_fs_t *fs) +{ + svn_fs_x__data_t *ffd = fs->fsap_data; + + ffd->flush_to_disk = !svn_hash__get_bool(fs->config, + SVN_FS_CONFIG_NO_FLUSH_TO_DISK, + FALSE); + + return SVN_NO_ERROR; +} + /* Read FS's UUID file and store the data in the FS struct. */ static svn_error_t * read_uuid(svn_fs_t *fs, @@ -587,8 +617,12 @@ svn_fs_x__open(svn_fs_t *fs, /* Read the configuration file. */ SVN_ERR(read_config(ffd, fs->path, fs->pool, scratch_pool)); - return svn_error_trace(svn_fs_x__read_current(&ffd->youngest_rev_cache, - fs, scratch_pool)); + /* Global configuration options. */ + SVN_ERR(read_global_config(fs)); + + ffd->youngest_rev_cache = 0; + + return SVN_NO_ERROR; } /* Baton type bridging svn_fs_x__upgrade and upgrade_body carrying @@ -840,16 +874,14 @@ static svn_error_t * write_revision_zero(svn_fs_t *fs, apr_pool_t *scratch_pool) { - /* Use an explicit sub-pool to have full control over temp file lifetimes. - * Since we have it, use it for everything else as well. */ - apr_pool_t *subpool = svn_pool_create(scratch_pool); - const char *path_revision_zero = svn_fs_x__path_rev(fs, 0, subpool); + const char *path_revision_zero = svn_fs_x__path_rev(fs, 0, scratch_pool); apr_hash_t *proplist; svn_string_t date; apr_array_header_t *index_entries; svn_fs_x__p2l_entry_t *entry; svn_fs_x__revision_file_t *rev_file; + apr_file_t *apr_file; const char *l2p_proto_index, *p2l_proto_index; /* Construct a skeleton r0 with no indexes. */ @@ -860,62 +892,72 @@ write_revision_zero(svn_fs_t *fs, "count: 0\n" "cpath: /\n" "\n", - subpool); + scratch_pool); svn_string_t *changes_str = svn_string_create("\n", - subpool); - svn_string_t *r0 = svn_string_createf(subpool, "%s%s", + scratch_pool); + svn_string_t *r0 = svn_string_createf(scratch_pool, "%s%s", noderev_str->data, changes_str->data); /* Write skeleton r0 to disk. */ - SVN_ERR(svn_io_file_create(path_revision_zero, r0->data, subpool)); + SVN_ERR(svn_io_file_create(path_revision_zero, r0->data, scratch_pool)); /* Construct the index P2L contents: describe the 2 items we have. Be sure to create them in on-disk order. */ - index_entries = apr_array_make(subpool, 2, sizeof(entry)); + index_entries = apr_array_make(scratch_pool, 2, sizeof(entry)); - entry = apr_pcalloc(subpool, sizeof(*entry)); + entry = apr_pcalloc(scratch_pool, sizeof(*entry)); entry->offset = 0; entry->size = (apr_off_t)noderev_str->len; entry->type = SVN_FS_X__ITEM_TYPE_NODEREV; entry->item_count = 1; - entry->items = apr_pcalloc(subpool, sizeof(*entry->items)); + entry->items = apr_pcalloc(scratch_pool, sizeof(*entry->items)); entry->items[0].change_set = 0; entry->items[0].number = SVN_FS_X__ITEM_INDEX_ROOT_NODE; APR_ARRAY_PUSH(index_entries, svn_fs_x__p2l_entry_t *) = entry; - entry = apr_pcalloc(subpool, sizeof(*entry)); + entry = apr_pcalloc(scratch_pool, sizeof(*entry)); entry->offset = (apr_off_t)noderev_str->len; entry->size = (apr_off_t)changes_str->len; entry->type = SVN_FS_X__ITEM_TYPE_CHANGES; entry->item_count = 1; - entry->items = apr_pcalloc(subpool, sizeof(*entry->items)); + entry->items = apr_pcalloc(scratch_pool, sizeof(*entry->items)); entry->items[0].change_set = 0; entry->items[0].number = SVN_FS_X__ITEM_INDEX_CHANGES; APR_ARRAY_PUSH(index_entries, svn_fs_x__p2l_entry_t *) = entry; /* Now re-open r0, create proto-index files from our entries and - rewrite the index section of r0. */ - SVN_ERR(svn_fs_x__open_pack_or_rev_file_writable(&rev_file, fs, 0, - subpool, subpool)); + rewrite the index section of r0. */ + SVN_ERR(svn_fs_x__rev_file_open_writable(&rev_file, fs, 0, + scratch_pool, scratch_pool)); SVN_ERR(svn_fs_x__p2l_index_from_p2l_entries(&p2l_proto_index, fs, rev_file, index_entries, - subpool, subpool)); + scratch_pool, scratch_pool)); SVN_ERR(svn_fs_x__l2p_index_from_p2l_entries(&l2p_proto_index, fs, index_entries, - subpool, subpool)); - SVN_ERR(svn_fs_x__add_index_data(fs, rev_file->file, l2p_proto_index, - p2l_proto_index, 0, subpool)); + scratch_pool, scratch_pool)); + SVN_ERR(svn_fs_x__rev_file_get(&apr_file, rev_file)); + SVN_ERR(svn_fs_x__add_index_data(fs, apr_file, l2p_proto_index, + p2l_proto_index, 0, scratch_pool)); SVN_ERR(svn_fs_x__close_revision_file(rev_file)); - SVN_ERR(svn_io_set_file_read_only(path_revision_zero, FALSE, fs->pool)); + SVN_ERR(svn_io_set_file_read_only(path_revision_zero, FALSE, scratch_pool)); /* Set a date on revision 0. */ - date.data = svn_time_to_cstring(apr_time_now(), fs->pool); + date.data = svn_time_to_cstring(apr_time_now(), scratch_pool); date.len = strlen(date.data); - proplist = apr_hash_make(fs->pool); + proplist = apr_hash_make(scratch_pool); svn_hash_sets(proplist, SVN_PROP_REVISION_DATE, &date); - return svn_fs_x__set_revision_proplist(fs, 0, proplist, fs->pool); + + SVN_ERR(svn_io_file_open(&apr_file, + svn_fs_x__path_revprops(fs, 0, scratch_pool), + APR_WRITE | APR_CREATE, APR_OS_DEFAULT, + scratch_pool)); + SVN_ERR(svn_fs_x__write_non_packed_revprops(apr_file, proplist, + scratch_pool)); + SVN_ERR(svn_io_file_close(apr_file, scratch_pool)); + + return SVN_NO_ERROR; } svn_error_t * @@ -935,14 +977,9 @@ svn_fs_x__create_file_tree(svn_fs_t *fs, /* Create the revision data directories. */ SVN_ERR(svn_io_make_dir_recursively( - svn_fs_x__path_rev_shard(fs, 0, scratch_pool), + svn_fs_x__path_shard(fs, 0, scratch_pool), scratch_pool)); - /* Create the revprops directory. */ - SVN_ERR(svn_io_make_dir_recursively( - svn_fs_x__path_revprops_shard(fs, 0, scratch_pool), - scratch_pool)); - /* Create the transaction directory. */ SVN_ERR(svn_io_make_dir_recursively( svn_fs_x__path_txns_dir(fs, scratch_pool), @@ -954,19 +991,21 @@ svn_fs_x__create_file_tree(svn_fs_t *fs, scratch_pool)); /* Create the 'current' file. */ - SVN_ERR(svn_io_file_create_empty(svn_fs_x__path_current(fs, scratch_pool), - scratch_pool)); - SVN_ERR(svn_fs_x__write_current(fs, 0, scratch_pool)); + SVN_ERR(svn_io_file_create(svn_fs_x__path_current(fs, scratch_pool), + "0\n", scratch_pool)); /* Create the 'uuid' file. */ SVN_ERR(svn_io_file_create_empty(svn_fs_x__path_lock(fs, scratch_pool), scratch_pool)); - SVN_ERR(svn_fs_x__set_uuid(fs, NULL, NULL, scratch_pool)); + SVN_ERR(svn_fs_x__set_uuid(fs, NULL, NULL, FALSE, scratch_pool)); /* Create the fsfs.conf file. */ SVN_ERR(write_config(fs, scratch_pool)); SVN_ERR(read_config(ffd, fs->path, fs->pool, scratch_pool)); + /* Global configuration options. */ + SVN_ERR(read_global_config(fs)); + /* Add revision 0. */ SVN_ERR(write_revision_zero(fs, scratch_pool)); @@ -984,6 +1023,9 @@ svn_fs_x__create_file_tree(svn_fs_t *fs, scratch_pool)); /* Initialize the revprop caching info. */ + SVN_ERR(svn_io_file_create_empty( + svn_fs_x__path_revprop_generation(fs, scratch_pool), + scratch_pool)); SVN_ERR(svn_fs_x__reset_revprop_generation_file(fs, scratch_pool)); ffd->youngest_rev_cache = 0; @@ -1040,6 +1082,7 @@ svn_error_t * svn_fs_x__set_uuid(svn_fs_t *fs, const char *uuid, const char *instance_id, + svn_boolean_t overwrite, apr_pool_t *scratch_pool) { svn_fs_x__data_t *ffd = fs->fsap_data; @@ -1058,11 +1101,23 @@ svn_fs_x__set_uuid(svn_fs_t *fs, svn_stringbuf_appendcstr(contents, "\n"); /* We use the permissions of the 'current' file, because the 'uuid' - file does not exist during repository creation. */ - SVN_ERR(svn_io_write_atomic(uuid_path, contents->data, contents->len, - /* perms */ - svn_fs_x__path_current(fs, scratch_pool), - scratch_pool)); + file does not exist during repository creation. + + svn_io_write_atomic2() does a load of magic to allow it to + replace version files that already exist. We only need to do + that when we're allowed to overwrite an existing file. */ + if (! overwrite) + { + /* Create the file */ + SVN_ERR(svn_io_file_create(uuid_path, contents->data, scratch_pool)); + } + else + { + SVN_ERR(svn_io_write_atomic2(uuid_path, contents->data, contents->len, + /* perms */ + svn_fs_x__path_current(fs, scratch_pool), + ffd->flush_to_disk, scratch_pool)); + } fs->uuid = apr_pstrdup(fs->pool, uuid); ffd->instance_id = apr_pstrdup(fs->pool, instance_id); @@ -1100,13 +1155,14 @@ svn_fs_x__revision_prop(svn_string_t **value_p, svn_fs_t *fs, svn_revnum_t rev, const char *propname, + svn_boolean_t refresh, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { apr_hash_t *table; SVN_ERR(svn_fs__check_fs(fs, TRUE)); - SVN_ERR(svn_fs_x__get_revision_proplist(&table, fs, rev, FALSE, + SVN_ERR(svn_fs_x__get_revision_proplist(&table, fs, rev, FALSE, refresh, scratch_pool, scratch_pool)); *value_p = svn_string_dup(svn_hash_gets(table, propname), result_pool); @@ -1133,17 +1189,18 @@ change_rev_prop_body(void *baton, { change_rev_prop_baton_t *cb = baton; apr_hash_t *table; + const svn_string_t *present_value; /* Read current revprop values from disk (never from cache). Even if somehow the cache got out of sync, we want to make sure that we read, update and write up-to-date data. */ SVN_ERR(svn_fs_x__get_revision_proplist(&table, cb->fs, cb->rev, TRUE, - scratch_pool, scratch_pool)); + TRUE, scratch_pool, scratch_pool)); + present_value = svn_hash_gets(table, cb->name); if (cb->old_value_p) { const svn_string_t *wanted_value = *cb->old_value_p; - const svn_string_t *present_value = svn_hash_gets(table, cb->name); if ((!wanted_value != !present_value) || (wanted_value && present_value && !svn_string_compare(wanted_value, present_value))) @@ -1156,6 +1213,13 @@ change_rev_prop_body(void *baton, } /* Fall through. */ } + + /* If the prop-set is a no-op, skip the actual write. */ + if ((!present_value && !cb->value) + || (present_value && cb->value + && svn_string_compare(present_value, cb->value))) + return SVN_NO_ERROR; + svn_hash_sets(table, cb->name, cb->value); return svn_fs_x__set_revision_proplist(cb->fs, cb->rev, table, @@ -1205,8 +1269,11 @@ svn_fs_x__info_format(int *fs_format, { case 1: break; + case 2: + (*supports_version)->minor = 10; + break; #ifdef SVN_DEBUG -# if SVN_FS_X__FORMAT_NUMBER != 1 +# if SVN_FS_X__FORMAT_NUMBER != 2 # error "Need to add a 'case' statement here" # endif #endif diff --git a/subversion/libsvn_fs_x/fs_x.h b/subversion/libsvn_fs_x/fs_x.h index 98be702598c2..08d82bd81004 100644 --- a/subversion/libsvn_fs_x/fs_x.h +++ b/subversion/libsvn_fs_x/fs_x.h @@ -1,4 +1,4 @@ -/* fs_x.h : interface to the native filesystem layer +/* fs_x.h : interface to the FSX layer * * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one @@ -20,8 +20,8 @@ * ==================================================================== */ -#ifndef SVN_LIBSVN_FS__FS_X_H -#define SVN_LIBSVN_FS__FS_X_H +#ifndef SVN_LIBSVN_FS_X_FS_X_H +#define SVN_LIBSVN_FS_X_FS_X_H #include "fs.h" @@ -41,6 +41,16 @@ svn_fs_x__open(svn_fs_t *fs, const char *path, apr_pool_t *scratch_pool); +/* Initialize parts of the FS data that are being shared across multiple + filesystem objects. Use COMMON_POOL for process-wide and SCRATCH_POOL + for temporary allocations. Use COMMON_POOL_LOCK to ensure that the + initialization is serialized. */ +svn_error_t * +svn_fs_x__initialize_shared_data(svn_fs_t *fs, + svn_mutex__t *common_pool_lock, + apr_pool_t *scratch_pool, + apr_pool_t *common_pool); + /* Upgrade the fsx filesystem FS. Indicate progress via the optional * NOTIFY_FUNC callback using NOTIFY_BATON. The optional CANCEL_FUNC * will periodically be called with CANCEL_BATON to allow for preemption. @@ -138,11 +148,16 @@ svn_fs_x__create(svn_fs_t *fs, /* Set the uuid of repository FS to UUID and the instance ID to INSTANCE_ID. If any of them is NULL, use a newly generated UUID / ID instead. + + If OVERWRITE is not set, the uuid file must not exist yet implying this + is a fresh repository. + Perform temporary allocations in SCRATCH_POOL. */ svn_error_t * svn_fs_x__set_uuid(svn_fs_t *fs, const char *uuid, const char *instance_id, + svn_boolean_t overwrite, apr_pool_t *scratch_pool); /* Read the format number and maximum number of files per directory @@ -160,12 +175,15 @@ svn_fs_x__write_format(svn_fs_t *fs, /* Find the value of the property named PROPNAME in transaction REV. Return the contents in *VALUE_P, allocated from RESULT_POOL. + If REFRESH is not set, continue using the potentially outdated + revprop generation value in FS->FSAP_DATA. Use SCRATCH_POOL for temporary allocations. */ svn_error_t * svn_fs_x__revision_prop(svn_string_t **value_p, svn_fs_t *fs, svn_revnum_t rev, const char *propname, + svn_boolean_t refresh, apr_pool_t *result_pool, apr_pool_t *scratch_pool); diff --git a/subversion/libsvn_fs_x/hotcopy.c b/subversion/libsvn_fs_x/hotcopy.c index c9f0af2f7d5c..431ecb298768 100644 --- a/subversion/libsvn_fs_x/hotcopy.c +++ b/subversion/libsvn_fs_x/hotcopy.c @@ -243,6 +243,7 @@ hotcopy_io_copy_dir_recursively(svn_boolean_t *skipped_p, * to DST_SUBDIR. Assume a sharding layout based on MAX_FILES_PER_DIR. * Set *SKIPPED_P to FALSE only if the file was copied, do not change the * value in *SKIPPED_P otherwise. SKIPPED_P may be NULL if not required. + * If PROPS is set, copy the revprops file, otherwise copy the rev data file. * Use SCRATCH_POOL for temporary allocations. */ static svn_error_t * hotcopy_copy_shard_file(svn_boolean_t *skipped_p, @@ -250,6 +251,7 @@ hotcopy_copy_shard_file(svn_boolean_t *skipped_p, const char *dst_subdir, svn_revnum_t rev, int max_files_per_dir, + svn_boolean_t props, apr_pool_t *scratch_pool) { const char *src_subdir_shard = src_subdir, @@ -269,7 +271,9 @@ hotcopy_copy_shard_file(svn_boolean_t *skipped_p, SVN_ERR(hotcopy_io_dir_file_copy(skipped_p, src_subdir_shard, dst_subdir_shard, - apr_psprintf(scratch_pool, "%ld", rev), + apr_psprintf(scratch_pool, "%c%ld", + props ? 'p' : 'r', + rev), scratch_pool)); return SVN_NO_ERROR; } @@ -296,9 +300,6 @@ hotcopy_copy_packed_shard(svn_boolean_t *skipped_p, const char *dst_subdir; const char *packed_shard; const char *src_subdir_packed_shard; - svn_revnum_t revprop_rev; - apr_pool_t *iterpool; - svn_fs_x__data_t *src_ffd = src_fs->fsap_data; /* Copy the packed shard. */ src_subdir = svn_dirent_join(src_fs->path, PATH_REVS_DIR, scratch_pool); @@ -313,47 +314,6 @@ hotcopy_copy_packed_shard(svn_boolean_t *skipped_p, NULL /* cancel_func */, NULL, scratch_pool)); - /* Copy revprops belonging to revisions in this pack. */ - src_subdir = svn_dirent_join(src_fs->path, PATH_REVPROPS_DIR, scratch_pool); - dst_subdir = svn_dirent_join(dst_fs->path, PATH_REVPROPS_DIR, scratch_pool); - - if (src_ffd->min_unpacked_rev < rev + max_files_per_dir) - { - /* copy unpacked revprops rev by rev */ - iterpool = svn_pool_create(scratch_pool); - for (revprop_rev = rev; - revprop_rev < rev + max_files_per_dir; - revprop_rev++) - { - svn_pool_clear(iterpool); - - SVN_ERR(hotcopy_copy_shard_file(skipped_p, src_subdir, dst_subdir, - revprop_rev, max_files_per_dir, - iterpool)); - } - svn_pool_destroy(iterpool); - } - else - { - /* revprop for revision 0 will never be packed */ - if (rev == 0) - SVN_ERR(hotcopy_copy_shard_file(skipped_p, src_subdir, dst_subdir, - 0, max_files_per_dir, - scratch_pool)); - - /* packed revprops folder */ - packed_shard = apr_psprintf(scratch_pool, "%ld" PATH_EXT_PACKED_SHARD, - rev / max_files_per_dir); - src_subdir_packed_shard = svn_dirent_join(src_subdir, packed_shard, - scratch_pool); - SVN_ERR(hotcopy_io_copy_dir_recursively(skipped_p, - src_subdir_packed_shard, - dst_subdir, packed_shard, - TRUE /* copy_perms */, - NULL /* cancel_func */, NULL, - scratch_pool)); - } - /* If necessary, update the min-unpacked rev file in the hotcopy. */ if (*dst_min_unpacked_rev < rev + max_files_per_dir) { @@ -379,98 +339,6 @@ hotcopy_remove_file(const char *path, return SVN_NO_ERROR; } - -/* Remove revision or revprop files between START_REV (inclusive) and - * END_REV (non-inclusive) from folder DST_SUBDIR in DST_FS. Assume - * sharding as per MAX_FILES_PER_DIR. - * Use SCRATCH_POOL for temporary allocations. */ -static svn_error_t * -hotcopy_remove_files(svn_fs_t *dst_fs, - const char *dst_subdir, - svn_revnum_t start_rev, - svn_revnum_t end_rev, - int max_files_per_dir, - apr_pool_t *scratch_pool) -{ - const char *shard; - const char *dst_subdir_shard; - svn_revnum_t rev; - apr_pool_t *iterpool; - - /* Pre-compute paths for initial shard. */ - shard = apr_psprintf(scratch_pool, "%ld", start_rev / max_files_per_dir); - dst_subdir_shard = svn_dirent_join(dst_subdir, shard, scratch_pool); - - iterpool = svn_pool_create(scratch_pool); - for (rev = start_rev; rev < end_rev; rev++) - { - svn_pool_clear(iterpool); - - /* If necessary, update paths for shard. */ - if (rev != start_rev && rev % max_files_per_dir == 0) - { - shard = apr_psprintf(iterpool, "%ld", rev / max_files_per_dir); - dst_subdir_shard = svn_dirent_join(dst_subdir, shard, scratch_pool); - } - - /* remove files for REV */ - SVN_ERR(hotcopy_remove_file(svn_dirent_join(dst_subdir_shard, - apr_psprintf(iterpool, - "%ld", rev), - iterpool), - iterpool)); - } - - svn_pool_destroy(iterpool); - - return SVN_NO_ERROR; -} - -/* Remove revisions between START_REV (inclusive) and END_REV (non-inclusive) - * from DST_FS. Assume sharding as per MAX_FILES_PER_DIR. - * Use SCRATCH_POOL for temporary allocations. */ -static svn_error_t * -hotcopy_remove_rev_files(svn_fs_t *dst_fs, - svn_revnum_t start_rev, - svn_revnum_t end_rev, - int max_files_per_dir, - apr_pool_t *scratch_pool) -{ - SVN_ERR_ASSERT(start_rev <= end_rev); - SVN_ERR(hotcopy_remove_files(dst_fs, - svn_dirent_join(dst_fs->path, - PATH_REVS_DIR, - scratch_pool), - start_rev, end_rev, - max_files_per_dir, scratch_pool)); - - return SVN_NO_ERROR; -} - -/* Remove revision properties between START_REV (inclusive) and END_REV - * (non-inclusive) from DST_FS. Assume sharding as per MAX_FILES_PER_DIR. - * Use SCRATCH_POOL for temporary allocations. Revision 0 revprops will - * not be deleted. */ -static svn_error_t * -hotcopy_remove_revprop_files(svn_fs_t *dst_fs, - svn_revnum_t start_rev, - svn_revnum_t end_rev, - int max_files_per_dir, - apr_pool_t *scratch_pool) -{ - SVN_ERR_ASSERT(start_rev <= end_rev); - - /* don't delete rev 0 props */ - SVN_ERR(hotcopy_remove_files(dst_fs, - svn_dirent_join(dst_fs->path, - PATH_REVPROPS_DIR, - scratch_pool), - start_rev ? start_rev : 1, end_rev, - max_files_per_dir, scratch_pool)); - - return SVN_NO_ERROR; -} - /* Verify that DST_FS is a suitable destination for an incremental * hotcopy from SRC_FS. */ static svn_error_t * @@ -506,29 +374,6 @@ hotcopy_incremental_check_preconditions(svn_fs_t *src_fs, return SVN_NO_ERROR; } -/* Remove folder PATH. Ignore errors due to the sub-tree not being empty. - * CANCEL_FUNC and CANCEL_BATON do the usual thing. - * Use SCRATCH_POOL for temporary allocations. - */ -static svn_error_t * -remove_folder(const char *path, - svn_cancel_func_t cancel_func, - void *cancel_baton, - apr_pool_t *scratch_pool) -{ - svn_error_t *err = svn_io_remove_dir2(path, TRUE, - cancel_func, cancel_baton, - scratch_pool); - - if (err && APR_STATUS_IS_ENOTEMPTY(err->apr_err)) - { - svn_error_clear(err); - err = SVN_NO_ERROR; - } - - return svn_error_trace(err); -} - /* Copy the revision and revprop files (possibly sharded / packed) from * SRC_FS to DST_FS. Do not re-copy data which already exists in DST_FS. * When copying packed or unpacked shards, checkpoint the result in DST_FS @@ -545,8 +390,6 @@ hotcopy_revisions(svn_fs_t *src_fs, svn_boolean_t incremental, const char *src_revs_dir, const char *dst_revs_dir, - const char *src_revprops_dir, - const char *dst_revprops_dir, svn_fs_hotcopy_notify_t notify_func, void* notify_baton, svn_cancel_func_t cancel_func, @@ -624,26 +467,10 @@ hotcopy_revisions(svn_fs_t *src_fs, if (notify_func && !skipped) notify_func(notify_baton, rev, pack_end_rev, iterpool); - /* Remove revision files which are now packed. */ - if (incremental) - { - SVN_ERR(hotcopy_remove_rev_files(dst_fs, rev, - rev + max_files_per_dir, - max_files_per_dir, iterpool)); - SVN_ERR(hotcopy_remove_revprop_files(dst_fs, rev, - rev + max_files_per_dir, - max_files_per_dir, - iterpool)); - } - /* Now that all revisions have moved into the pack, the original * rev dir can be removed. */ - SVN_ERR(remove_folder(svn_fs_x__path_rev_shard(dst_fs, rev, iterpool), - cancel_func, cancel_baton, iterpool)); - if (rev > 0) - SVN_ERR(remove_folder(svn_fs_x__path_revprops_shard(dst_fs, rev, - iterpool), - cancel_func, cancel_baton, iterpool)); + SVN_ERR(svn_io_remove_dir2(svn_fs_x__path_shard(dst_fs, rev, iterpool), + TRUE, cancel_func, cancel_baton, iterpool)); } if (cancel_func) @@ -677,13 +504,12 @@ hotcopy_revisions(svn_fs_t *src_fs, /* Copy the rev file. */ SVN_ERR(hotcopy_copy_shard_file(&skipped, src_revs_dir, dst_revs_dir, - rev, max_files_per_dir, + rev, max_files_per_dir, FALSE, iterpool)); /* Copy the revprop file. */ - SVN_ERR(hotcopy_copy_shard_file(&skipped, src_revprops_dir, - dst_revprops_dir, - rev, max_files_per_dir, + SVN_ERR(hotcopy_copy_shard_file(&skipped, src_revs_dir, dst_revs_dir, + rev, max_files_per_dir, TRUE, iterpool)); /* Whenever this revision did not previously exist in the destination, @@ -729,7 +555,7 @@ typedef struct hotcopy_body_baton_t { * An incremental hotcopy copies only changed or new files to the destination, * and removes files from the destination no longer present in the source. * While the incremental hotcopy is running, readers should still be able - * to access the destintation repository without error and should not see + * to access the destination repository without error and should not see * revisions currently in progress of being copied. Readers are able to see * new fully copied revisions even if the entire incremental hotcopy procedure * has not yet completed. @@ -752,8 +578,6 @@ hotcopy_body(void *baton, void* cancel_baton = hbb->cancel_baton; svn_revnum_t src_youngest; svn_revnum_t dst_youngest; - const char *src_revprops_dir; - const char *dst_revprops_dir; const char *src_revs_dir; const char *dst_revs_dir; const char *src_subdir; @@ -793,16 +617,10 @@ hotcopy_body(void *baton, src_revs_dir = svn_dirent_join(src_fs->path, PATH_REVS_DIR, scratch_pool); dst_revs_dir = svn_dirent_join(dst_fs->path, PATH_REVS_DIR, scratch_pool); - src_revprops_dir = svn_dirent_join(src_fs->path, PATH_REVPROPS_DIR, - scratch_pool); - dst_revprops_dir = svn_dirent_join(dst_fs->path, PATH_REVPROPS_DIR, - scratch_pool); /* Ensure that the required folders exist in the destination * before actually copying the revisions and revprops. */ SVN_ERR(svn_io_make_dir_recursively(dst_revs_dir, scratch_pool)); - SVN_ERR(svn_io_make_dir_recursively(dst_revprops_dir, scratch_pool)); - if (cancel_func) SVN_ERR(cancel_func(cancel_baton)); @@ -812,7 +630,6 @@ hotcopy_body(void *baton, * revision number, but also the next-ID counters). */ SVN_ERR(hotcopy_revisions(src_fs, dst_fs, src_youngest, dst_youngest, incremental, src_revs_dir, dst_revs_dir, - src_revprops_dir, dst_revprops_dir, notify_func, notify_baton, cancel_func, cancel_baton, scratch_pool)); SVN_ERR(svn_fs_x__write_current(dst_fs, src_youngest, scratch_pool)); @@ -832,16 +649,6 @@ hotcopy_body(void *baton, cancel_func, cancel_baton, scratch_pool)); - /* Now copy the node-origins cache tree. */ - src_subdir = svn_dirent_join(src_fs->path, PATH_NODE_ORIGINS_DIR, - scratch_pool); - SVN_ERR(svn_io_check_path(src_subdir, &kind, scratch_pool)); - if (kind == svn_node_dir) - SVN_ERR(hotcopy_io_copy_dir_recursively(NULL, src_subdir, dst_fs->path, - PATH_NODE_ORIGINS_DIR, TRUE, - cancel_func, cancel_baton, - scratch_pool)); - /* * NB: Data copied below is only read by writers, not readers. * Writers are still locked out at this point. @@ -857,6 +664,10 @@ hotcopy_body(void *baton, /* Copy the rep cache and then remove entries for revisions * that did not make it into the destination. */ SVN_ERR(svn_sqlite__hotcopy(src_subdir, dst_subdir, scratch_pool)); + + /* The source might have r/o flags set on it - which would be + carried over to the copy. */ + SVN_ERR(svn_io_set_file_read_write(dst_subdir, FALSE, scratch_pool)); SVN_ERR(svn_fs_x__del_rep_reference(dst_fs, src_youngest, scratch_pool)); } @@ -871,64 +682,33 @@ hotcopy_body(void *baton, * used for the named atomics implementation. */ SVN_ERR(svn_fs_x__reset_revprop_generation_file(dst_fs, scratch_pool)); - return SVN_NO_ERROR; -} - -/* Wrapper around hotcopy_body taking out all necessary source repository - * locks. - */ -static svn_error_t * -hotcopy_locking_src_body(void *baton, - apr_pool_t *scratch_pool) -{ - hotcopy_body_baton_t *hbb = baton; - - return svn_error_trace(svn_fs_x__with_pack_lock(hbb->src_fs, hotcopy_body, - baton, scratch_pool)); -} - -/* Create an empty filesystem at DST_FS at DST_PATH with the same - * configuration as SRC_FS (uuid, format, and other parameters). - * After creation DST_FS has no revisions, not even revision zero. */ -static svn_error_t * -hotcopy_create_empty_dest(svn_fs_t *src_fs, - svn_fs_t *dst_fs, - const char *dst_path, - apr_pool_t *scratch_pool) -{ - svn_fs_x__data_t *src_ffd = src_fs->fsap_data; - - /* Create the DST_FS repository with the same layout as SRC_FS. */ - SVN_ERR(svn_fs_x__create_file_tree(dst_fs, dst_path, src_ffd->format, - src_ffd->max_files_per_dir, - scratch_pool)); - - /* Copy the UUID. Hotcopy destination receives a new instance ID, but - * has the same filesystem UUID as the source. */ - SVN_ERR(svn_fs_x__set_uuid(dst_fs, src_fs->uuid, NULL, scratch_pool)); - - /* Remove revision 0 contents. Otherwise, it may not get overwritten - * due to having a newer timestamp. */ - SVN_ERR(hotcopy_remove_file(svn_fs_x__path_rev(dst_fs, 0, scratch_pool), - scratch_pool)); - SVN_ERR(hotcopy_remove_file(svn_fs_x__path_revprops(dst_fs, 0, - scratch_pool), - scratch_pool)); - - /* This filesystem is ready. Stamp it with a format number. Fail if - * the 'format' file should already exist. */ - SVN_ERR(svn_fs_x__write_format(dst_fs, FALSE, scratch_pool)); + /* Hotcopied FS is complete. Stamp it with a format file. */ + SVN_ERR(svn_fs_x__write_format(dst_fs, TRUE, scratch_pool)); return SVN_NO_ERROR; } svn_error_t * -svn_fs_x__hotcopy_prepare_target(svn_fs_t *src_fs, - svn_fs_t *dst_fs, - const char *dst_path, - svn_boolean_t incremental, - apr_pool_t *scratch_pool) +svn_fs_x__hotcopy(svn_fs_t *src_fs, + svn_fs_t *dst_fs, + const char *src_path, + const char *dst_path, + svn_boolean_t incremental, + svn_fs_hotcopy_notify_t notify_func, + void *notify_baton, + svn_cancel_func_t cancel_func, + void *cancel_baton, + svn_mutex__t *common_pool_lock, + apr_pool_t *scratch_pool, + apr_pool_t *common_pool) { + hotcopy_body_baton_t hbb; + + if (cancel_func) + SVN_ERR(cancel_func(cancel_baton)); + + SVN_ERR(svn_fs_x__open(src_fs, src_path, scratch_pool)); + if (incremental) { const char *dst_format_abspath; @@ -942,40 +722,53 @@ svn_fs_x__hotcopy_prepare_target(svn_fs_t *src_fs, scratch_pool)); if (dst_format_kind == svn_node_none) { - /* Destination doesn't exist yet. Perform a normal hotcopy to a - * empty destination using the same configuration as the source. */ - SVN_ERR(hotcopy_create_empty_dest(src_fs, dst_fs, dst_path, - scratch_pool)); - } - else - { - /* Check the existing repository. */ - SVN_ERR(svn_fs_x__open(dst_fs, dst_path, scratch_pool)); - SVN_ERR(hotcopy_incremental_check_preconditions(src_fs, dst_fs)); + /* No destination? Fallback to a non-incremental hotcopy. */ + incremental = FALSE; } } + + if (incremental) + { + /* Check the existing repository. */ + SVN_ERR(svn_fs_x__open(dst_fs, dst_path, scratch_pool)); + SVN_ERR(hotcopy_incremental_check_preconditions(src_fs, dst_fs)); + + SVN_ERR(svn_fs_x__initialize_shared_data(dst_fs, common_pool_lock, + scratch_pool, common_pool)); + SVN_ERR(svn_fs_x__initialize_caches(dst_fs, scratch_pool)); + } else { /* Start out with an empty destination using the same configuration * as the source. */ - SVN_ERR(hotcopy_create_empty_dest(src_fs, dst_fs, dst_path, - scratch_pool)); + svn_fs_x__data_t *src_ffd = src_fs->fsap_data; + + /* Create the DST_FS repository with the same layout as SRC_FS. */ + SVN_ERR(svn_fs_x__create_file_tree(dst_fs, dst_path, src_ffd->format, + src_ffd->max_files_per_dir, + scratch_pool)); + + /* Copy the UUID. Hotcopy destination receives a new instance ID, but + * has the same filesystem UUID as the source. */ + SVN_ERR(svn_fs_x__set_uuid(dst_fs, src_fs->uuid, NULL, TRUE, + scratch_pool)); + + /* Remove revision 0 contents. Otherwise, it may not get overwritten + * due to having a newer timestamp. */ + SVN_ERR(hotcopy_remove_file(svn_fs_x__path_rev(dst_fs, 0, + scratch_pool), + scratch_pool)); + SVN_ERR(hotcopy_remove_file(svn_fs_x__path_revprops(dst_fs, 0, + scratch_pool), + scratch_pool)); + + SVN_ERR(svn_fs_x__initialize_shared_data(dst_fs, common_pool_lock, + scratch_pool, common_pool)); + SVN_ERR(svn_fs_x__initialize_caches(dst_fs, scratch_pool)); } - return SVN_NO_ERROR; -} - -svn_error_t * -svn_fs_x__hotcopy(svn_fs_t *src_fs, - svn_fs_t *dst_fs, - svn_boolean_t incremental, - svn_fs_hotcopy_notify_t notify_func, - void *notify_baton, - svn_cancel_func_t cancel_func, - void *cancel_baton, - apr_pool_t *scratch_pool) -{ - hotcopy_body_baton_t hbb; + if (cancel_func) + SVN_ERR(cancel_func(cancel_baton)); hbb.src_fs = src_fs; hbb.dst_fs = dst_fs; @@ -984,8 +777,16 @@ svn_fs_x__hotcopy(svn_fs_t *src_fs, hbb.notify_baton = notify_baton; hbb.cancel_func = cancel_func; hbb.cancel_baton = cancel_baton; - SVN_ERR(svn_fs_x__with_all_locks(dst_fs, hotcopy_locking_src_body, &hbb, - scratch_pool)); + + /* Lock the destination in the incremental mode. For a non-incremental + * hotcopy, don't take any locks. In that case the destination cannot be + * opened until the hotcopy finishes, and we don't have to worry about + * concurrency. */ + if (incremental) + SVN_ERR(svn_fs_x__with_all_locks(dst_fs, hotcopy_body, &hbb, + scratch_pool)); + else + SVN_ERR(hotcopy_body(&hbb, scratch_pool)); return SVN_NO_ERROR; } diff --git a/subversion/libsvn_fs_x/hotcopy.h b/subversion/libsvn_fs_x/hotcopy.h index 516c66adec8e..b4b42fa4d017 100644 --- a/subversion/libsvn_fs_x/hotcopy.h +++ b/subversion/libsvn_fs_x/hotcopy.h @@ -1,4 +1,4 @@ -/* hotcopy.h : interface to the native filesystem layer +/* hotcopy.h : interface to the hot-copying functionality * * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one @@ -20,34 +20,29 @@ * ==================================================================== */ -#ifndef SVN_LIBSVN_FS__HOTCOPY_H -#define SVN_LIBSVN_FS__HOTCOPY_H +#ifndef SVN_LIBSVN_FS_X_HOTCOPY_H +#define SVN_LIBSVN_FS_X_HOTCOPY_H #include "fs.h" -/* Create an empty copy of the fsfs filesystem SRC_FS into a new DST_FS at - * DST_PATH. If INCREMENTAL is TRUE, perform a few pre-checks only if - * a repo already exists at DST_PATH. - * Use SCRATCH_POOL for temporary allocations. */ -svn_error_t * -svn_fs_x__hotcopy_prepare_target(svn_fs_t *src_fs, - svn_fs_t *dst_fs, - const char *dst_path, - svn_boolean_t incremental, - apr_pool_t *scratch_pool); - -/* Copy the fsfs filesystem SRC_FS into DST_FS. If INCREMENTAL is TRUE, do - * not re-copy data which already exists in DST_FS. Indicate progress via - * the optional NOTIFY_FUNC callback using NOTIFY_BATON. - * Use SCRATCH_POOL for temporary allocations. */ +/* Copy the fsfs filesystem SRC_FS at SRC_PATH into a new copy DST_FS at + * DST_PATH. If INCREMENTAL is TRUE, do not re-copy data which already + * exists in DST_FS. Indicate progress via the optional NOTIFY_FUNC + * callback using NOTIFY_BATON. Use COMMON_POOL for process-wide and + * SCRATCH_POOL for temporary allocations. Use COMMON_POOL_LOCK to ensure + * that the initialization of the shared data is serialized. */ svn_error_t * svn_fs_x__hotcopy(svn_fs_t *src_fs, svn_fs_t *dst_fs, + const char *src_path, + const char *dst_path, svn_boolean_t incremental, svn_fs_hotcopy_notify_t notify_func, void *notify_baton, svn_cancel_func_t cancel_func, void *cancel_baton, - apr_pool_t *scratch_pool); + svn_mutex__t *common_pool_lock, + apr_pool_t *scratch_pool, + apr_pool_t *common_pool); #endif diff --git a/subversion/libsvn_fs_x/index.c b/subversion/libsvn_fs_x/index.c index 7d568f91872f..b7cff19f15bc 100644 --- a/subversion/libsvn_fs_x/index.c +++ b/subversion/libsvn_fs_x/index.c @@ -57,19 +57,13 @@ const apr_uint64_t off_t_max = (sizeof(apr_off_t) == sizeof(apr_int64_t)) : APR_INT32_MAX; /* We store P2L proto-index entries as 6 values, 64 bits each on disk. - * See also svn_fs_fs__p2l_proto_index_add_entry(). + * See also svn_fs_x__p2l_proto_index_add_entry(). */ #define P2L_PROTO_INDEX_ENTRY_SIZE (6 * sizeof(apr_uint64_t)) -/* We put this string in front of the L2P index header. */ -#define L2P_STREAM_PREFIX "L2P-INDEX\n" - -/* We put this string in front of the P2L index header. */ -#define P2L_STREAM_PREFIX "P2L-INDEX\n" - /* Size of the buffer that will fit the index header prefixes. */ -#define STREAM_PREFIX_LEN MAX(sizeof(L2P_STREAM_PREFIX), \ - sizeof(P2L_STREAM_PREFIX)) +#define STREAM_PREFIX_LEN MAX(sizeof(SVN_FS_X__L2P_STREAM_PREFIX), \ + sizeof(SVN_FS_X__P2L_STREAM_PREFIX)) /* Page tables in the log-to-phys index file exclusively contain entries * of this type to describe position and size of a given page. @@ -237,7 +231,7 @@ stream_error_create(svn_fs_x__packed_number_stream_t *stream, apr_off_t offset; SVN_ERR(svn_io_file_name_get(&file_name, stream->file, stream->pool)); - SVN_ERR(svn_fs_x__get_file_offset(&offset, stream->file, stream->pool)); + SVN_ERR(svn_io_file_get_offset(&offset, stream->file, stream->pool)); return svn_error_createf(err, NULL, message, file_name, apr_psprintf(stream->pool, @@ -257,7 +251,7 @@ static svn_error_t * packed_stream_read(svn_fs_x__packed_number_stream_t *stream) { unsigned char buffer[MAX_NUMBER_PREFETCH]; - apr_size_t read = 0; + apr_size_t bytes_read = 0; apr_size_t i; value_position_pair_t *target; apr_off_t block_start = 0; @@ -279,33 +273,34 @@ packed_stream_read(svn_fs_x__packed_number_stream_t *stream) * boundaries. This shall prevent jumping back and forth between two * blocks because the extra data was not actually request _now_. */ - read = sizeof(buffer); + bytes_read = sizeof(buffer); block_left = stream->block_size - (stream->next_offset - block_start); - if (block_left >= 10 && block_left < read) - read = (apr_size_t)block_left; + if (block_left >= 10 && block_left < bytes_read) + bytes_read = (apr_size_t)block_left; /* Don't read beyond the end of the file section that belongs to this * index / stream. */ - read = (apr_size_t)MIN(read, stream->stream_end - stream->next_offset); + bytes_read = (apr_size_t)MIN(bytes_read, + stream->stream_end - stream->next_offset); - err = apr_file_read(stream->file, buffer, &read); + err = apr_file_read(stream->file, buffer, &bytes_read); if (err && !APR_STATUS_IS_EOF(err)) return stream_error_create(stream, err, _("Can't read index file '%s' at offset 0x%")); /* if the last number is incomplete, trim it from the buffer */ - while (read > 0 && buffer[read-1] >= 0x80) - --read; + while (bytes_read > 0 && buffer[bytes_read-1] >= 0x80) + --bytes_read; /* we call read() only if get() requires more data. So, there must be * at least *one* further number. */ - if SVN__PREDICT_FALSE(read == 0) + if SVN__PREDICT_FALSE(bytes_read == 0) return stream_error_create(stream, err, _("Unexpected end of index file %s at offset 0x%")); /* parse file buffer and expand into stream buffer */ target = stream->buffer; - for (i = 0; i < read;) + for (i = 0; i < bytes_read;) { if (buffer[i] < 0x80) { @@ -348,20 +343,15 @@ packed_stream_read(svn_fs_x__packed_number_stream_t *stream) return SVN_NO_ERROR; } -/* Create and open a packed number stream reading from offsets START to - * END in FILE and return it in *STREAM. Access the file in chunks of - * BLOCK_SIZE bytes. Expect the stream to be prefixed by STREAM_PREFIX. - * Allocate *STREAM in RESULT_POOL and use SCRATCH_POOL for temporaries. - */ -static svn_error_t * -packed_stream_open(svn_fs_x__packed_number_stream_t **stream, - apr_file_t *file, - apr_off_t start, - apr_off_t end, - const char *stream_prefix, - apr_size_t block_size, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) +svn_error_t * +svn_fs_x__packed_stream_open(svn_fs_x__packed_number_stream_t **stream, + apr_file_t *file, + apr_off_t start, + apr_off_t end, + const char *stream_prefix, + apr_size_t block_size, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { char buffer[STREAM_PREFIX_LEN + 1] = { 0 }; apr_size_t len = strlen(stream_prefix); @@ -516,13 +506,13 @@ read_uint64_from_proto_index(apr_file_t *proto_index, apr_pool_t *scratch_pool) { apr_byte_t buffer[sizeof(*value_p)]; - apr_size_t read; + apr_size_t bytes_read; /* Read the full 8 bytes or our 64 bit value, unless we hit EOF. * Assert that we never read partial values. */ SVN_ERR(svn_io_file_read_full2(proto_index, buffer, sizeof(buffer), - &read, eof, scratch_pool)); - SVN_ERR_ASSERT((eof && *eof) || read == sizeof(buffer)); + &bytes_read, eof, scratch_pool)); + SVN_ERR_ASSERT((eof && *eof) || bytes_read == sizeof(buffer)); /* If we did not hit EOF, reconstruct the uint64 value and return it. */ if (!eof || !*eof) @@ -702,7 +692,8 @@ svn_fs_x__l2p_proto_index_add_entry(apr_file_t *proto_index, * read operations only. */ static apr_size_t -encode_uint(unsigned char *p, apr_uint64_t value) +encode_uint(unsigned char *p, + apr_uint64_t value) { unsigned char *start = p; while (value >= 0x80) @@ -720,7 +711,8 @@ encode_uint(unsigned char *p, apr_uint64_t value) * This maps signed ints onto unsigned ones. */ static apr_size_t -encode_int(unsigned char *p, apr_int64_t value) +encode_int(unsigned char *p, + apr_int64_t value) { return encode_uint(p, (apr_uint64_t)(value < 0 ? -1 - 2*value : 2*value)); } @@ -742,7 +734,9 @@ stream_write_encoded(svn_stream_t *stream, * Return the number of remaining entries in ARRAY after START. */ static int -rle_array(apr_array_header_t *array, int start, int end) +rle_array(apr_array_header_t *array, + int start, + int end) { int i; int target = start; @@ -969,8 +963,8 @@ svn_fs_x__l2p_index_append(svn_checksum_t **checksum, /* 1 page with up to L2P_PAGE_SIZE entries. * fsfs.conf settings validation guarantees this to fit into * our address space. */ - apr_size_t last_buffer_size - = (apr_size_t)svn_spillbuf__get_size(buffer); + apr_uint64_t last_buffer_size + = (apr_uint64_t)svn_spillbuf__get_size(buffer); svn_pool_clear(iterpool); @@ -1038,7 +1032,7 @@ svn_fs_x__l2p_index_append(svn_checksum_t **checksum, /* write header info */ - SVN_ERR(svn_stream_puts(stream, L2P_STREAM_PREFIX)); + SVN_ERR(svn_stream_puts(stream, SVN_FS_X__L2P_STREAM_PREFIX)); SVN_ERR(stream_write_encoded(stream, revision)); SVN_ERR(stream_write_encoded(stream, page_counts->nelts)); SVN_ERR(stream_write_encoded(stream, ffd->l2p_page_size)); @@ -1074,7 +1068,8 @@ svn_fs_x__l2p_index_append(svn_checksum_t **checksum, * REVISION in FS. */ static svn_revnum_t -base_revision(svn_fs_t *fs, svn_revnum_t revision) +base_revision(svn_fs_t *fs, + svn_revnum_t revision) { svn_fs_x__data_t *ffd = fs->fsap_data; return svn_fs_x__is_packed_rev(fs, revision) @@ -1231,32 +1226,6 @@ expand_rle(apr_array_header_t *values, return SVN_NO_ERROR; } -/* If REV_FILE->L2P_STREAM is NULL, create a new stream for the log-to-phys - * index for REVISION in FS and return it in REV_FILE. - */ -static svn_error_t * -auto_open_l2p_index(svn_fs_x__revision_file_t *rev_file, - svn_fs_t *fs, - svn_revnum_t revision) -{ - if (rev_file->l2p_stream == NULL) - { - svn_fs_x__data_t *ffd = fs->fsap_data; - - SVN_ERR(svn_fs_x__auto_read_footer(rev_file)); - SVN_ERR(packed_stream_open(&rev_file->l2p_stream, - rev_file->file, - rev_file->l2p_offset, - rev_file->p2l_offset, - L2P_STREAM_PREFIX, - (apr_size_t)ffd->block_size, - rev_file->pool, - rev_file->pool)); - } - - return SVN_NO_ERROR; -} - /* Read the header data structure of the log-to-phys index for REVISION * in FS and return it in *HEADER, allocated in RESULT_POOL. Use REV_FILE * to access on-disk data. Use SCRATCH_POOL for temporary allocations. @@ -1279,41 +1248,48 @@ get_l2p_header_body(l2p_header_t **header, svn_revnum_t next_rev; apr_array_header_t *expanded_values = apr_array_make(scratch_pool, 16, sizeof(apr_uint64_t)); + svn_fs_x__packed_number_stream_t *stream; + svn_fs_x__rev_file_info_t file_info; + svn_fs_x__index_info_t index_info; + /* What to look for. */ svn_fs_x__pair_cache_key_t key; - key.revision = rev_file->start_revision; - key.second = rev_file->is_packed; + SVN_ERR(svn_fs_x__rev_file_info(&file_info, rev_file)); + key.revision = file_info.start_revision; + key.second = file_info.is_packed; - SVN_ERR(auto_open_l2p_index(rev_file, fs, revision)); - packed_stream_seek(rev_file->l2p_stream, 0); + /* Access the L2P index stream. */ + SVN_ERR(svn_fs_x__rev_file_l2p_index(&stream, rev_file)); + SVN_ERR(svn_fs_x__rev_file_l2p_info(&index_info, rev_file)); + packed_stream_seek(stream, 0); /* Read the table sizes. Check the data for plausibility and * consistency with other bits. */ - SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream)); + SVN_ERR(packed_stream_get(&value, stream)); result->first_revision = (svn_revnum_t)value; - if (result->first_revision != rev_file->start_revision) + if (result->first_revision != file_info.start_revision) return svn_error_create(SVN_ERR_FS_INDEX_CORRUPTION, NULL, _("Index rev / pack file revision numbers do not match")); - SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream)); + SVN_ERR(packed_stream_get(&value, stream)); result->revision_count = (int)value; if ( result->revision_count != 1 && result->revision_count != (apr_uint64_t)ffd->max_files_per_dir) return svn_error_create(SVN_ERR_FS_INDEX_CORRUPTION, NULL, _("Invalid number of revisions in L2P index")); - SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream)); + SVN_ERR(packed_stream_get(&value, stream)); result->page_size = (apr_uint32_t)value; if (!result->page_size || (result->page_size & (result->page_size - 1))) return svn_error_create(SVN_ERR_FS_INDEX_CORRUPTION, NULL, _("L2P index page size is not a power of two")); - SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream)); + SVN_ERR(packed_stream_get(&value, stream)); page_count = (apr_size_t)value; if (page_count < result->revision_count) return svn_error_create(SVN_ERR_FS_INDEX_CORRUPTION, NULL, _("Fewer L2P index pages than revisions")); - if (page_count > (rev_file->p2l_offset - rev_file->l2p_offset) / 2) + if (page_count > (index_info.end - index_info.start) / 2) return svn_error_create(SVN_ERR_FS_INDEX_CORRUPTION, NULL, _("L2P index page count implausibly large")); @@ -1333,8 +1309,7 @@ get_l2p_header_body(l2p_header_t **header, /* read per-revision page table sizes (i.e. number of pages per rev) */ page_table_index = 0; result->page_table_index[0] = page_table_index; - SVN_ERR(expand_rle(expanded_values, rev_file->l2p_stream, - result->revision_count)); + SVN_ERR(expand_rle(expanded_values, stream, result->revision_count)); for (i = 0; i < result->revision_count; ++i) { value = (apr_size_t)APR_ARRAY_IDX(expanded_values, i, apr_uint64_t); @@ -1357,13 +1332,13 @@ get_l2p_header_body(l2p_header_t **header, /* read actual page tables */ for (page = 0; page < page_count; ++page) { - SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream)); + SVN_ERR(packed_stream_get(&value, stream)); if (value == 0) return svn_error_create(SVN_ERR_FS_INDEX_CORRUPTION, NULL, _("Empty L2P index page")); result->page_table[page].size = (apr_uint32_t)value; - SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream)); + SVN_ERR(packed_stream_get(&value, stream)); if (value > result->page_size) return svn_error_create(SVN_ERR_FS_INDEX_CORRUPTION, NULL, _("Page exceeds L2P index page size")); @@ -1372,7 +1347,7 @@ get_l2p_header_body(l2p_header_t **header, } /* correct the page description offsets */ - offset = packed_stream_offset(rev_file->l2p_stream); + offset = packed_stream_offset(stream); for (page = 0; page < page_count; ++page) { result->page_table[page].offset = offset; @@ -1437,11 +1412,13 @@ get_l2p_header(l2p_header_t **header, { svn_fs_x__data_t *ffd = fs->fsap_data; svn_boolean_t is_cached = FALSE; + svn_fs_x__rev_file_info_t file_info; /* first, try cache lookop */ svn_fs_x__pair_cache_key_t key; - key.revision = rev_file->start_revision; - key.second = rev_file->is_packed; + SVN_ERR(svn_fs_x__rev_file_info(&file_info, rev_file)); + key.revision = file_info.start_revision; + key.second = file_info.is_packed; SVN_ERR(svn_cache__get((void**)header, &is_cached, ffd->l2p_header_cache, &key, result_pool)); if (is_cached) @@ -1454,16 +1431,12 @@ get_l2p_header(l2p_header_t **header, return SVN_NO_ERROR; } -/* From the log-to-phys index file starting at START_REVISION in FS, read - * the mapping page identified by TABLE_ENTRY and return it in *PAGE. - * Use REV_FILE to access on-disk files. - * Use RESULT_POOL for allocations. +/* From the log-to-phys index in REV_FILE, read the mapping page identified + * by TABLE_ENTRY and return it in *PAGE, allocated in RESULT_POOL. */ static svn_error_t * get_l2p_page(l2p_page_t **page, svn_fs_x__revision_file_t *rev_file, - svn_fs_t *fs, - svn_revnum_t start_revision, l2p_page_table_entry_t *table_entry, apr_pool_t *result_pool) { @@ -1472,10 +1445,11 @@ get_l2p_page(l2p_page_t **page, l2p_page_t *result = apr_pcalloc(result_pool, sizeof(*result)); apr_uint64_t container_count; apr_off_t *container_offsets; + svn_fs_x__packed_number_stream_t *stream; /* open index file and select page */ - SVN_ERR(auto_open_l2p_index(rev_file, fs, start_revision)); - packed_stream_seek(rev_file->l2p_stream, table_entry->offset); + SVN_ERR(svn_fs_x__rev_file_l2p_index(&stream, rev_file)); + packed_stream_seek(stream, table_entry->offset); /* initialize the page content */ result->entry_count = table_entry->entry_count; @@ -1486,12 +1460,12 @@ get_l2p_page(l2p_page_t **page, /* container offsets array */ - SVN_ERR(packed_stream_get(&container_count, rev_file->l2p_stream)); + SVN_ERR(packed_stream_get(&container_count, stream)); container_offsets = apr_pcalloc(result_pool, container_count * sizeof(*result)); for (i = 0; i < container_count; ++i) { - SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream)); + SVN_ERR(packed_stream_get(&value, stream)); last_value += value; container_offsets[i] = (apr_off_t)last_value - 1; /* '-1' is represented as '0' in the index file */ @@ -1500,7 +1474,7 @@ get_l2p_page(l2p_page_t **page, /* read all page entries (offsets in rev file and container sub-items) */ for (i = 0; i < result->entry_count; ++i) { - SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream)); + SVN_ERR(packed_stream_get(&value, stream)); if (value == 0) { result->offsets[i] = -1; @@ -1509,7 +1483,7 @@ get_l2p_page(l2p_page_t **page, else if (value <= container_count) { result->offsets[i] = container_offsets[value - 1]; - SVN_ERR(packed_stream_get(&value, rev_file->l2p_stream)); + SVN_ERR(packed_stream_get(&value, stream)); result->sub_items[i] = (apr_uint32_t)value; } else @@ -1521,7 +1495,7 @@ get_l2p_page(l2p_page_t **page, /* After reading all page entries, the read cursor must have moved by * TABLE_ENTRY->SIZE bytes. */ - if ( packed_stream_offset(rev_file->l2p_stream) + if ( packed_stream_offset(stream) != table_entry->offset + table_entry->size) return svn_error_create(SVN_ERR_FS_INDEX_CORRUPTION, NULL, _("L2P actual page size does not match page table value.")); @@ -1690,9 +1664,8 @@ get_l2p_page_table(apr_array_header_t *pages, /* Utility function. Read the l2p index pages for REVISION in FS from * STREAM and put them into the cache. Skip page number EXLCUDED_PAGE_NO * (use -1 for 'skip none') and pages outside the MIN_OFFSET, MAX_OFFSET - * range in the l2p index file. The index is being identified by - * FIRST_REVISION. PAGES is a scratch container provided by the caller. - * SCRATCH_POOL is used for temporary allocations. + * range in the l2p index file. PAGES is a scratch container provided by + * the caller. SCRATCH_POOL is used for temporary allocations. * * This function may be a no-op if the header cache lookup fails / misses. */ @@ -1700,7 +1673,6 @@ static svn_error_t * prefetch_l2p_pages(svn_boolean_t *end, svn_fs_t *fs, svn_fs_x__revision_file_t *rev_file, - svn_revnum_t first_revision, svn_revnum_t revision, apr_array_header_t *pages, int exlcuded_page_no, @@ -1769,8 +1741,7 @@ prefetch_l2p_pages(svn_boolean_t *end, /* no in cache -> read from stream (data already buffered in APR) * and cache the result */ l2p_page_t *page = NULL; - SVN_ERR(get_l2p_page(&page, rev_file, fs, first_revision, - entry, iterpool)); + SVN_ERR(get_l2p_page(&page, rev_file, entry, iterpool)); SVN_ERR(svn_cache__set(ffd->l2p_page_cache, &key, page, iterpool)); @@ -1841,8 +1812,7 @@ l2p_index_lookup(apr_off_t *offset, apr_off_t min_offset = max_offset - ffd->block_size; /* read the relevant page */ - SVN_ERR(get_l2p_page(&page, rev_file, fs, info_baton.first_revision, - &info_baton.entry, scratch_pool)); + SVN_ERR(get_l2p_page(&page, rev_file, &info_baton.entry, scratch_pool)); /* cache the page and extract the result we need */ SVN_ERR(svn_cache__set(ffd->l2p_page_cache, &key, page, scratch_pool)); @@ -1863,7 +1833,6 @@ l2p_index_lookup(apr_off_t *offset, svn_pool_clear(iterpool); SVN_ERR(prefetch_l2p_pages(&end, fs, rev_file, - info_baton.first_revision, prefetch_revision, pages, excluded_page_no, min_offset, max_offset, iterpool)); @@ -1877,7 +1846,6 @@ l2p_index_lookup(apr_off_t *offset, svn_pool_clear(iterpool); SVN_ERR(prefetch_l2p_pages(&end, fs, rev_file, - info_baton.first_revision, prefetch_revision, pages, -1, min_offset, max_offset, iterpool)); } @@ -1950,8 +1918,7 @@ svn_fs_x__l2p_get_max_ids(apr_array_header_t **max_ids, apr_pool_t *header_pool = svn_pool_create(scratch_pool); /* read index master data structure for the index covering START_REV */ - SVN_ERR(svn_fs_x__open_pack_or_rev_file(&rev_file, fs, start_rev, - header_pool, header_pool)); + SVN_ERR(svn_fs_x__rev_file_init(&rev_file, fs, start_rev, header_pool)); SVN_ERR(get_l2p_header(&header, rev_file, fs, start_rev, header_pool, header_pool)); SVN_ERR(svn_fs_x__close_revision_file(rev_file)); @@ -1965,15 +1932,15 @@ svn_fs_x__l2p_get_max_ids(apr_array_header_t **max_ids, apr_uint64_t item_count; apr_size_t first_page_index, last_page_index; - if (revision >= header->first_revision + header->revision_count) + if (revision - header->first_revision >= header->revision_count) { /* need to read the next index. Clear up memory used for the * previous one. Note that intermittent pack runs do not change * the number of items in a revision, i.e. there is no consistency * issue here. */ svn_pool_clear(header_pool); - SVN_ERR(svn_fs_x__open_pack_or_rev_file(&rev_file, fs, revision, - header_pool, header_pool)); + SVN_ERR(svn_fs_x__rev_file_init(&rev_file, fs, revision, + header_pool)); SVN_ERR(get_l2p_header(&header, rev_file, fs, revision, header_pool, header_pool)); SVN_ERR(svn_fs_x__close_revision_file(rev_file)); @@ -2215,8 +2182,8 @@ svn_fs_x__p2l_index_append(svn_checksum_t **checksum, apr_uint64_t last_entry_end = 0; apr_uint64_t last_page_end = 0; - apr_size_t last_buffer_size = 0; /* byte offset in the spill buffer at - the begin of the current revision */ + apr_uint64_t last_buffer_size = 0; /* byte offset in the spill buffer at + the begin of the current revision */ apr_uint64_t file_size = 0; /* temporary data structures that collect the data which will be moved @@ -2315,7 +2282,8 @@ svn_fs_x__p2l_index_append(svn_checksum_t **checksum, encode_uint(encoded, entry.size), iterpool)); SVN_ERR(svn_spillbuf__write(buffer, (const char *)encoded, - encode_uint(encoded, entry.type + entry.item_count * 16), + encode_uint(encoded, entry.type + + entry.item_count * 16), iterpool)); SVN_ERR(svn_spillbuf__write(buffer, (const char *)encoded, encode_uint(encoded, entry.fnv1_checksum), @@ -2359,7 +2327,7 @@ svn_fs_x__p2l_index_append(svn_checksum_t **checksum, result_pool); /* write the start revision, file size and page size */ - SVN_ERR(svn_stream_puts(stream, P2L_STREAM_PREFIX)); + SVN_ERR(svn_stream_puts(stream, SVN_FS_X__P2L_STREAM_PREFIX)); SVN_ERR(stream_write_encoded(stream, revision)); SVN_ERR(stream_write_encoded(stream, file_size)); SVN_ERR(stream_write_encoded(stream, page_size)); @@ -2382,32 +2350,6 @@ svn_fs_x__p2l_index_append(svn_checksum_t **checksum, return SVN_NO_ERROR; } -/* If REV_FILE->P2L_STREAM is NULL, create a new stream for the phys-to-log - * index for REVISION in FS using the rev / pack file provided by REV_FILE. - */ -static svn_error_t * -auto_open_p2l_index(svn_fs_x__revision_file_t *rev_file, - svn_fs_t *fs, - svn_revnum_t revision) -{ - if (rev_file->p2l_stream == NULL) - { - svn_fs_x__data_t *ffd = fs->fsap_data; - - SVN_ERR(svn_fs_x__auto_read_footer(rev_file)); - SVN_ERR(packed_stream_open(&rev_file->p2l_stream, - rev_file->file, - rev_file->p2l_offset, - rev_file->footer_offset, - P2L_STREAM_PREFIX, - (apr_size_t)ffd->block_size, - rev_file->pool, - rev_file->pool)); - } - - return SVN_NO_ERROR; -} - /* Data structure that describes which p2l page info shall be extracted * from the cache and contains the fields that receive the result. */ @@ -2515,11 +2457,15 @@ get_p2l_header(p2l_header_t **header, apr_off_t offset; p2l_header_t *result; svn_boolean_t is_cached = FALSE; + svn_fs_x__packed_number_stream_t *stream; + svn_fs_x__rev_file_info_t file_info; + svn_fs_x__index_info_t l2p_index_info; /* look for the header data in our cache */ svn_fs_x__pair_cache_key_t key; - key.revision = rev_file->start_revision; - key.second = rev_file->is_packed; + SVN_ERR(svn_fs_x__rev_file_info(&file_info, rev_file)); + key.revision = file_info.start_revision; + key.second = file_info.is_packed; SVN_ERR(svn_cache__get((void**)header, &is_cached, ffd->p2l_header_cache, &key, result_pool)); @@ -2528,32 +2474,33 @@ get_p2l_header(p2l_header_t **header, /* not found -> must read it from disk. * Open index file or position read pointer to the begin of the file */ - SVN_ERR(auto_open_p2l_index(rev_file, fs, key.revision)); - packed_stream_seek(rev_file->p2l_stream, 0); + SVN_ERR(svn_fs_x__rev_file_p2l_index(&stream, rev_file)); + SVN_ERR(svn_fs_x__rev_file_l2p_info(&l2p_index_info, rev_file)); + packed_stream_seek(stream, 0); /* allocate result data structure */ result = apr_pcalloc(result_pool, sizeof(*result)); /* Read table sizes, check them for plausibility and allocate page array. */ - SVN_ERR(packed_stream_get(&value, rev_file->p2l_stream)); + SVN_ERR(packed_stream_get(&value, stream)); result->first_revision = (svn_revnum_t)value; - if (result->first_revision != rev_file->start_revision) + if (result->first_revision != file_info.start_revision) return svn_error_create(SVN_ERR_FS_INDEX_CORRUPTION, NULL, _("Index rev / pack file revision numbers do not match")); - SVN_ERR(packed_stream_get(&value, rev_file->p2l_stream)); + SVN_ERR(packed_stream_get(&value, stream)); result->file_size = value; - if (result->file_size != (apr_uint64_t)rev_file->l2p_offset) + if (result->file_size != (apr_uint64_t)l2p_index_info.start) return svn_error_create(SVN_ERR_FS_INDEX_CORRUPTION, NULL, _("Index offset and rev / pack file size do not match")); - SVN_ERR(packed_stream_get(&value, rev_file->p2l_stream)); + SVN_ERR(packed_stream_get(&value, stream)); result->page_size = value; if (!result->page_size || (result->page_size & (result->page_size - 1))) return svn_error_create(SVN_ERR_FS_INDEX_CORRUPTION, NULL, _("P2L index page size is not a power of two")); - SVN_ERR(packed_stream_get(&value, rev_file->p2l_stream)); + SVN_ERR(packed_stream_get(&value, stream)); result->page_count = (apr_size_t)value; if (result->page_count != (result->file_size - 1) / result->page_size + 1) return svn_error_create(SVN_ERR_FS_INDEX_CORRUPTION, NULL, @@ -2566,12 +2513,12 @@ get_p2l_header(p2l_header_t **header, result->offsets[0] = 0; for (i = 0; i < result->page_count; ++i) { - SVN_ERR(packed_stream_get(&value, rev_file->p2l_stream)); + SVN_ERR(packed_stream_get(&value, stream)); result->offsets[i+1] = result->offsets[i] + (apr_off_t)value; } /* correct the offset values */ - offset = packed_stream_offset(rev_file->p2l_stream); + offset = packed_stream_offset(stream); for (i = 0; i <= result->page_count; ++i) result->offsets[i] += offset; @@ -2703,6 +2650,13 @@ read_entry(svn_fs_x__packed_number_stream_t *stream, } } + /* Corrupted SIZE values might cause arithmetic overflow. + * The same can happen if you copy a repository from a system with 63 bit + * file lengths to one with 31 bit file lengths. */ + if ((apr_uint64_t)entry.offset + (apr_uint64_t)entry.size > off_t_max) + return svn_error_create(SVN_ERR_FS_INDEX_OVERFLOW , NULL, + _("P2L index entry size overflow.")); + APR_ARRAY_PUSH(result, svn_fs_x__p2l_entry_t) = entry; *item_offset += entry.size; @@ -2732,14 +2686,15 @@ get_p2l_page(apr_array_header_t **entries, = apr_array_make(result_pool, 16, sizeof(svn_fs_x__p2l_entry_t)); apr_off_t item_offset; apr_off_t offset; + svn_fs_x__packed_number_stream_t *stream; /* open index and navigate to page start */ - SVN_ERR(auto_open_p2l_index(rev_file, fs, start_revision)); - packed_stream_seek(rev_file->p2l_stream, start_offset); + SVN_ERR(svn_fs_x__rev_file_p2l_index(&stream, rev_file)); + packed_stream_seek(stream, start_offset); /* read rev file offset of the first page entry (all page entries will * only store their sizes). */ - SVN_ERR(packed_stream_get(&value, rev_file->p2l_stream)); + SVN_ERR(packed_stream_get(&value, stream)); item_offset = (apr_off_t)value; /* Special case: empty pages. */ @@ -2747,17 +2702,15 @@ get_p2l_page(apr_array_header_t **entries, { /* Empty page. This only happens if the first entry of the next page * also covers this page (and possibly more) completely. */ - SVN_ERR(read_entry(rev_file->p2l_stream, &item_offset, start_revision, - result)); + SVN_ERR(read_entry(stream, &item_offset, start_revision, result)); } else { /* Read non-empty page. */ do { - SVN_ERR(read_entry(rev_file->p2l_stream, &item_offset, - start_revision, result)); - offset = packed_stream_offset(rev_file->p2l_stream); + SVN_ERR(read_entry(stream, &item_offset, start_revision, result)); + offset = packed_stream_offset(stream); } while (offset < next_offset); @@ -2771,9 +2724,9 @@ get_p2l_page(apr_array_header_t **entries, * entry of the next page */ if (item_offset < page_start + page_size) { - SVN_ERR(packed_stream_get(&value, rev_file->p2l_stream)); + SVN_ERR(packed_stream_get(&value, stream)); item_offset = (apr_off_t)value; - SVN_ERR(read_entry(rev_file->p2l_stream, &item_offset, + SVN_ERR(read_entry(stream, &item_offset, start_revision, result)); } } @@ -3203,7 +3156,8 @@ svn_fs_x__p2l_index_lookup(apr_array_header_t **entries, * RHS. */ static int -compare_p2l_entry_offsets(const void *lhs, const void *rhs) +compare_p2l_entry_offsets(const void *lhs, + const void *rhs) { const svn_fs_x__p2l_entry_t *entry = (const svn_fs_x__p2l_entry_t *)lhs; apr_off_t offset = *(const apr_off_t *)rhs; @@ -3212,7 +3166,7 @@ compare_p2l_entry_offsets(const void *lhs, const void *rhs) } /* Cached data extraction utility. DATA is a P2L index page, e.g. an APR - * array of svn_fs_fs__p2l_entry_t elements. Return the entry for the item, + * array of svn_fs_x__p2l_entry_t elements. Return the entry for the item, * allocated in RESULT_POOL, starting at OFFSET or NULL if that's not an * the start offset of any item. Use SCRATCH_POOL for temporary allocations. */ @@ -3503,15 +3457,13 @@ calc_fnv1(svn_fs_x__p2l_entry_t *entry, } /* Read the block and feed it to the checksum calculator. */ - SVN_ERR(svn_io_file_seek(rev_file->file, APR_SET, &entry->offset, - scratch_pool)); + SVN_ERR(svn_fs_x__rev_file_seek(rev_file, NULL, entry->offset)); while (size > 0) { apr_size_t to_read = size > sizeof(buffer) ? sizeof(buffer) : (apr_size_t)size; - SVN_ERR(svn_io_file_read_full2(rev_file->file, buffer, to_read, NULL, - NULL, scratch_pool)); + SVN_ERR(svn_fs_x__rev_file_read(rev_file, buffer, to_read)); SVN_ERR(svn_checksum_update(context, buffer, to_read)); size -= to_read; } @@ -3795,7 +3747,7 @@ svn_error_t * svn_fs_x__deserialize_l2p_header(void **out, void *data, apr_size_t data_len, - apr_pool_t *pool) + apr_pool_t *result_pool) { l2p_header_t *header = (l2p_header_t *)data; @@ -3849,7 +3801,7 @@ svn_error_t * svn_fs_x__deserialize_l2p_page(void **out, void *data, apr_size_t data_len, - apr_pool_t *pool) + apr_pool_t *result_pool) { l2p_page_t *page = data; @@ -3898,7 +3850,7 @@ svn_error_t * svn_fs_x__deserialize_p2l_header(void **out, void *data, apr_size_t data_len, - apr_pool_t *pool) + apr_pool_t *result_pool) { p2l_header_t *header = data; @@ -3956,7 +3908,7 @@ svn_error_t * svn_fs_x__deserialize_p2l_page(void **out, void *data, apr_size_t data_len, - apr_pool_t *pool) + apr_pool_t *result_pool) { apr_array_header_t *page = (apr_array_header_t *)data; svn_fs_x__p2l_entry_t *entries; @@ -3971,7 +3923,7 @@ svn_fs_x__deserialize_p2l_page(void **out, svn_temp_deserializer__resolve(entries, (void**)&entries[i].items); /* patch up members */ - page->pool = pool; + page->pool = result_pool; page->nalloc = page->nelts; /* done */ diff --git a/subversion/libsvn_fs_x/index.h b/subversion/libsvn_fs_x/index.h index 4e0e1ddfcdf2..9a5454d01118 100644 --- a/subversion/libsvn_fs_x/index.h +++ b/subversion/libsvn_fs_x/index.h @@ -20,8 +20,8 @@ * ==================================================================== */ -#ifndef SVN_LIBSVN_FS__INDEX_H -#define SVN_LIBSVN_FS__INDEX_H +#ifndef SVN_LIBSVN_FS_X_INDEX_H +#define SVN_LIBSVN_FS_X_INDEX_H #include "fs.h" #include "rev_file.h" @@ -53,6 +53,28 @@ #define SVN_FS_X__ITEM_TYPE_REPS_CONT 10 /* item is a representations container */ +/* We put this string in front of the L2P index header. */ +#define SVN_FS_X__L2P_STREAM_PREFIX "L2P-INDEX\n" + +/* We put this string in front of the P2L index header. */ +#define SVN_FS_X__P2L_STREAM_PREFIX "P2L-INDEX\n" + + +/* Create and open a packed number stream reading from offsets START to + * END in FILE and return it in *STREAM. Access the file in chunks of + * BLOCK_SIZE bytes. Expect the stream to be prefixed by STREAM_PREFIX. + * Allocate *STREAM in RESULT_POOL and use SCRATCH_POOL for temporaries. + */ +svn_error_t * +svn_fs_x__packed_stream_open(svn_fs_x__packed_number_stream_t **stream, + apr_file_t *file, + apr_off_t start, + apr_off_t end, + const char *stream_prefix, + apr_size_t block_size, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + /* (user visible) entry in the phys-to-log index. It describes a section * of some packed / non-packed rev file as containing a specific item. * There must be no overlapping / conflicting entries. @@ -184,7 +206,7 @@ svn_fs_x__p2l_index_append(svn_checksum_t **checksum, /* Use the phys-to-log mapping files in FS to build a list of entries * that (at least partly) overlap with the range given by BLOCK_START * offset and BLOCK_SIZE in the rep / pack file containing REVISION. - * Return the array in *ENTRIES with svn_fs_fs__p2l_entry_t as elements, + * Return the array in *ENTRIES with svn_fs_x__p2l_entry_t as elements, * allocated in RESULT_POOL. REV_FILE determines whether to access single * rev or pack file data. If that is not available anymore (neither in * cache nor on disk), return an error. Use SCRATCH_POOL for temporary @@ -287,7 +309,7 @@ svn_fs_x__p2l_get_max_offset(apr_off_t *offset, /* For FS, create a new L2P auto-deleting proto index file in POOL and return * its name in *PROTONAME. All entries to write are given in ENTRIES and - * entries are of type svn_fs_fs__p2l_entry_t* (sic!). The ENTRIES array + * entries are of type svn_fs_x__p2l_entry_t* (sic!). The ENTRIES array * will be reordered. Give the proto index file the lifetime of RESULT_POOL * and use SCRATCH_POOL for temporary allocations. */ @@ -300,7 +322,7 @@ svn_fs_x__l2p_index_from_p2l_entries(const char **protoname, /* For FS, create a new P2L auto-deleting proto index file in POOL and return * its name in *PROTONAME. All entries to write are given in ENTRIES and - * of type svn_fs_fs__p2l_entry_t*. The FVN1 checksums are not taken from + * of type svn_fs_x__p2l_entry_t*. The FVN1 checksums are not taken from * ENTRIES but are begin calculated from the current contents of REV_FILE * as we go. Give the proto index file the lifetime of RESULT_POOL and use * SCRATCH_POOL for temporary allocations. @@ -350,7 +372,7 @@ svn_error_t * svn_fs_x__deserialize_l2p_header(void **out, void *data, apr_size_t data_len, - apr_pool_t *pool); + apr_pool_t *result_pool); /* * Implements svn_cache__serialize_func_t for l2p_page_t objects. @@ -368,7 +390,7 @@ svn_error_t * svn_fs_x__deserialize_l2p_page(void **out, void *data, apr_size_t data_len, - apr_pool_t *pool); + apr_pool_t *result_pool); /* * Implements svn_cache__serialize_func_t for p2l_header_t objects. @@ -386,7 +408,7 @@ svn_error_t * svn_fs_x__deserialize_p2l_header(void **out, void *data, apr_size_t data_len, - apr_pool_t *pool); + apr_pool_t *result_pool); /* * Implements svn_cache__serialize_func_t for apr_array_header_t objects @@ -406,6 +428,6 @@ svn_error_t * svn_fs_x__deserialize_p2l_page(void **out, void *data, apr_size_t data_len, - apr_pool_t *pool); + apr_pool_t *result_pool); #endif diff --git a/subversion/libsvn_fs_x/lock.c b/subversion/libsvn_fs_x/lock.c index 6819f630ef1a..d1db492c0f37 100644 --- a/subversion/libsvn_fs_x/lock.c +++ b/subversion/libsvn_fs_x/lock.c @@ -113,7 +113,8 @@ hash_fetch(apr_hash_t *hash, /* SVN_ERR_FS_CORRUPT: the lockfile for PATH in FS is corrupt. */ static svn_error_t * -err_corrupt_lockfile(const char *fs_path, const char *path) +err_corrupt_lockfile(const char *fs_path, + const char *path) { return svn_error_createf( @@ -234,7 +235,7 @@ write_digest_file(apr_hash_t *children, if ((err = svn_hash_write2(hash, stream, SVN_HASH_TERMINATOR, scratch_pool))) { - svn_error_clear(svn_stream_close(stream)); + err = svn_error_compose_create(err, svn_stream_close(stream)); return svn_error_createf(err->apr_err, err, _("Cannot write lock/entries hashfile '%s'"), @@ -243,7 +244,7 @@ write_digest_file(apr_hash_t *children, } SVN_ERR(svn_stream_close(stream)); - SVN_ERR(svn_io_file_rename(tmp_path, digest_path, scratch_pool)); + SVN_ERR(svn_io_file_rename2(tmp_path, digest_path, FALSE, scratch_pool)); SVN_ERR(svn_io_copy_perms(perms_reference, digest_path, scratch_pool)); return SVN_NO_ERROR; } @@ -286,7 +287,7 @@ read_digest_file(apr_hash_t **children_p, hash = apr_hash_make(pool); if ((err = svn_hash_read2(hash, stream, SVN_HASH_TERMINATOR, pool))) { - svn_error_clear(svn_stream_close(stream)); + err = svn_error_compose_create(err, svn_stream_close(stream)); return svn_error_createf(err->apr_err, err, _("Can't parse lock/entries hashfile '%s'"), @@ -470,6 +471,12 @@ unlock_single(svn_fs_t *fs, svn_lock_t *lock, apr_pool_t *pool); +/* Check if LOCK has been already expired. */ +static svn_boolean_t lock_expired(const svn_lock_t *lock) +{ + return lock->expiration_date && (apr_time_now() > lock->expiration_date); +} + /* Set *LOCK_P to the lock for PATH in FS. HAVE_WRITE_LOCK should be TRUE if the caller (or one of its callers) has taken out the repository-wide write lock, FALSE otherwise. If MUST_EXIST is @@ -499,7 +506,7 @@ get_lock(svn_lock_t **lock_p, return must_exist ? SVN_FS__ERR_NO_SUCH_LOCK(fs, path) : SVN_NO_ERROR; /* Don't return an expired lock. */ - if (lock->expiration_date && (apr_time_now() > lock->expiration_date)) + if (lock_expired(lock)) { /* Only remove the lock if we have the write lock. Read operations shouldn't change the filesystem. */ @@ -546,100 +553,6 @@ get_lock_helper(svn_fs_t *fs, } -/* Baton for locks_walker(). */ -typedef struct walk_locks_baton_t -{ - svn_fs_get_locks_callback_t get_locks_func; - void *get_locks_baton; - svn_fs_t *fs; -} walk_locks_baton_t; - -/* Implements walk_digests_callback_t. */ -static svn_error_t * -locks_walker(void *baton, - const char *fs_path, - const char *digest_path, - svn_lock_t *lock, - svn_boolean_t have_write_lock, - apr_pool_t *pool) -{ - walk_locks_baton_t *wlb = baton; - - if (lock) - { - /* Don't report an expired lock. */ - if (lock->expiration_date == 0 - || (apr_time_now() <= lock->expiration_date)) - { - if (wlb->get_locks_func) - SVN_ERR(wlb->get_locks_func(wlb->get_locks_baton, lock, pool)); - } - else - { - /* Only remove the lock if we have the write lock. - Read operations shouldn't change the filesystem. */ - if (have_write_lock) - SVN_ERR(unlock_single(wlb->fs, lock, pool)); - } - } - - return SVN_NO_ERROR; -} - -/* Callback type for walk_digest_files(). - * - * LOCK come from a read_digest_file(digest_path) call. - */ -typedef svn_error_t *(*walk_digests_callback_t)(void *baton, - const char *fs_path, - const char *digest_path, - svn_lock_t *lock, - svn_boolean_t have_write_lock, - apr_pool_t *pool); - -/* A function that calls WALK_DIGESTS_FUNC/WALK_DIGESTS_BATON for - all lock digest files in and under PATH in FS. - HAVE_WRITE_LOCK should be true if the caller (directly or indirectly) - has the FS write lock. */ -static svn_error_t * -walk_digest_files(const char *fs_path, - const char *digest_path, - walk_digests_callback_t walk_digests_func, - void *walk_digests_baton, - svn_boolean_t have_write_lock, - apr_pool_t *pool) -{ - apr_hash_index_t *hi; - apr_hash_t *children; - apr_pool_t *subpool; - svn_lock_t *lock; - - /* First, send up any locks in the current digest file. */ - SVN_ERR(read_digest_file(&children, &lock, fs_path, digest_path, pool)); - - SVN_ERR(walk_digests_func(walk_digests_baton, fs_path, digest_path, lock, - have_write_lock, pool)); - - /* Now, report all the child entries (if any; bail otherwise). */ - if (! apr_hash_count(children)) - return SVN_NO_ERROR; - subpool = svn_pool_create(pool); - for (hi = apr_hash_first(pool, children); hi; hi = apr_hash_next(hi)) - { - const char *digest = apr_hash_this_key(hi); - svn_pool_clear(subpool); - - SVN_ERR(read_digest_file - (NULL, &lock, fs_path, - digest_path_from_digest(fs_path, digest, subpool), subpool)); - - SVN_ERR(walk_digests_func(walk_digests_baton, fs_path, digest_path, lock, - have_write_lock, subpool)); - } - svn_pool_destroy(subpool); - return SVN_NO_ERROR; -} - /* A function that calls GET_LOCKS_FUNC/GET_LOCKS_BATON for all locks in and under PATH in FS. HAVE_WRITE_LOCK should be true if the caller (directly or indirectly) @@ -652,17 +565,55 @@ walk_locks(svn_fs_t *fs, svn_boolean_t have_write_lock, apr_pool_t *pool) { - walk_locks_baton_t wlb; + apr_hash_index_t *hi; + apr_hash_t *children; + apr_pool_t *subpool; + svn_lock_t *lock; - wlb.get_locks_func = get_locks_func; - wlb.get_locks_baton = get_locks_baton; - wlb.fs = fs; - SVN_ERR(walk_digest_files(fs->path, digest_path, locks_walker, &wlb, - have_write_lock, pool)); + /* First, send up any locks in the current digest file. */ + SVN_ERR(read_digest_file(&children, &lock, fs->path, digest_path, pool)); + + if (lock && lock_expired(lock)) + { + /* Only remove the lock if we have the write lock. + Read operations shouldn't change the filesystem. */ + if (have_write_lock) + SVN_ERR(unlock_single(fs, lock, pool)); + } + else if (lock) + { + SVN_ERR(get_locks_func(get_locks_baton, lock, pool)); + } + + /* Now, report all the child entries (if any; bail otherwise). */ + if (! apr_hash_count(children)) + return SVN_NO_ERROR; + subpool = svn_pool_create(pool); + for (hi = apr_hash_first(pool, children); hi; hi = apr_hash_next(hi)) + { + const char *digest = apr_hash_this_key(hi); + svn_pool_clear(subpool); + + SVN_ERR(read_digest_file + (NULL, &lock, fs->path, + digest_path_from_digest(fs->path, digest, subpool), subpool)); + + if (lock && lock_expired(lock)) + { + /* Only remove the lock if we have the write lock. + Read operations shouldn't change the filesystem. */ + if (have_write_lock) + SVN_ERR(unlock_single(fs, lock, pool)); + } + else if (lock) + { + SVN_ERR(get_locks_func(get_locks_baton, lock, pool)); + } + } + svn_pool_destroy(subpool); return SVN_NO_ERROR; } - /* Utility function: verify that a lock can be used. Interesting errors returned from this function: @@ -737,6 +688,35 @@ svn_fs_x__allow_locked_operation(const char *path, return SVN_NO_ERROR; } +/* Helper function called from the lock and unlock code. + UPDATES is a map from "const char *" parent paths to "apr_array_header_t *" + arrays of child paths. For all of the parent paths of PATH this function + adds PATH to the corresponding array of child paths. */ +static void +schedule_index_update(apr_hash_t *updates, + const char *path, + apr_pool_t *scratch_pool) +{ + apr_pool_t *hashpool = apr_hash_pool_get(updates); + const char *parent_path = path; + + while (! svn_fspath__is_root(parent_path, strlen(parent_path))) + { + apr_array_header_t *children; + + parent_path = svn_fspath__dirname(parent_path, scratch_pool); + children = svn_hash_gets(updates, parent_path); + + if (! children) + { + children = apr_array_make(hashpool, 8, sizeof(const char *)); + svn_hash_sets(updates, apr_pstrdup(hashpool, parent_path), children); + } + + APR_ARRAY_PUSH(children, const char *) = path; + } +} + /* The effective arguments for lock_body() below. */ typedef struct lock_baton_t { svn_fs_t *fs; @@ -859,7 +839,6 @@ check_lock(svn_error_t **fs_err, typedef struct lock_info_t { const char *path; - const char *component; svn_lock_t *lock; svn_error_t *fs_err; } lock_info_t; @@ -876,20 +855,20 @@ typedef struct lock_info_t { type, and assumes that the write lock is held. */ static svn_error_t * -lock_body(void *baton, apr_pool_t *pool) +lock_body(void *baton, + apr_pool_t *pool) { lock_baton_t *lb = baton; svn_fs_root_t *root; svn_revnum_t youngest; const char *rev_0_path; - int i, outstanding = 0; + int i; + apr_hash_t *index_updates = apr_hash_make(pool); + apr_hash_index_t *hi; apr_pool_t *iterpool = svn_pool_create(pool); - lb->infos = apr_array_make(lb->result_pool, lb->targets->nelts, - sizeof(lock_info_t)); - /* Until we implement directory locks someday, we only allow locks - on files or non-existent paths. */ + on files. */ /* Use fs->vtable->foo instead of svn_fs_foo to avoid circular library dependencies, which are not portable. */ SVN_ERR(lb->fs->vtable->youngest_rev(&youngest, lb->fs, pool)); @@ -899,35 +878,28 @@ lock_body(void *baton, apr_pool_t *pool) { const svn_sort__item_t *item = &APR_ARRAY_IDX(lb->targets, i, svn_sort__item_t); - const svn_fs_lock_target_t *target = item->value; lock_info_t info; svn_pool_clear(iterpool); info.path = item->key; - SVN_ERR(check_lock(&info.fs_err, info.path, target, lb, root, - youngest, iterpool)); info.lock = NULL; - info.component = NULL; - APR_ARRAY_PUSH(lb->infos, lock_info_t) = info; + info.fs_err = SVN_NO_ERROR; + + SVN_ERR(check_lock(&info.fs_err, info.path, item->value, lb, root, + youngest, iterpool)); + + /* If no error occurred while pre-checking, schedule the index updates for + this path. */ if (!info.fs_err) - ++outstanding; + schedule_index_update(index_updates, info.path, iterpool); + + APR_ARRAY_PUSH(lb->infos, lock_info_t) = info; } rev_0_path = svn_fs_x__path_rev_absolute(lb->fs, 0, pool); - /* Given the paths: - - /foo/bar/f - /foo/bar/g - /zig/x - - we loop through repeatedly. The first pass sees '/' on all paths - and writes the '/' index. The second pass sees '/foo' twice and - writes that index followed by '/zig' and that index. The third - pass sees '/foo/bar' twice and writes that index, and then writes - the lock for '/zig/x'. The fourth pass writes the locks for - '/foo/bar/f' and '/foo/bar/g'. + /* We apply the scheduled index updates before writing the actual locks. Writing indices before locks is correct: if interrupted it leaves indices without locks rather than locks without indices. An @@ -936,91 +908,50 @@ lock_body(void *baton, apr_pool_t *pool) index is inconsistent, svn_fs_x__allow_locked_operation will show locked on the file but unlocked on the parent. */ - - while (outstanding) + for (hi = apr_hash_first(pool, index_updates); hi; hi = apr_hash_next(hi)) { - const char *last_path = NULL; - apr_array_header_t *paths; + const char *path = apr_hash_this_key(hi); + apr_array_header_t *children = apr_hash_this_val(hi); svn_pool_clear(iterpool); - paths = apr_array_make(iterpool, 1, sizeof(const char *)); + SVN_ERR(add_to_digest(lb->fs->path, children, path, rev_0_path, + iterpool)); + } - for (i = 0; i < lb->infos->nelts; ++i) + for (i = 0; i < lb->infos->nelts; ++i) + { + struct lock_info_t *info = &APR_ARRAY_IDX(lb->infos, i, + struct lock_info_t); + svn_sort__item_t *item = &APR_ARRAY_IDX(lb->targets, i, svn_sort__item_t); + svn_fs_lock_target_t *target = item->value; + + svn_pool_clear(iterpool); + + if (! info->fs_err) { - lock_info_t *info = &APR_ARRAY_IDX(lb->infos, i, lock_info_t); - const svn_sort__item_t *item = &APR_ARRAY_IDX(lb->targets, i, - svn_sort__item_t); - const svn_fs_lock_target_t *target = item->value; + info->lock = svn_lock_create(lb->result_pool); + if (target->token) + info->lock->token = apr_pstrdup(lb->result_pool, target->token); + else + SVN_ERR(svn_fs_x__generate_lock_token(&(info->lock->token), lb->fs, + lb->result_pool)); - if (!info->fs_err && !info->lock) - { - if (!info->component) - { - info->component = info->path; - APR_ARRAY_PUSH(paths, const char *) = info->path; - last_path = "/"; - } - else - { - info->component = strchr(info->component + 1, '/'); - if (!info->component) - { - /* The component is a path to lock, this cannot - match a previous path that need to be indexed. */ - if (paths->nelts) - { - SVN_ERR(add_to_digest(lb->fs->path, paths, last_path, - rev_0_path, iterpool)); - apr_array_clear(paths); - last_path = NULL; - } + /* The INFO->PATH is already allocated in LB->RESULT_POOL as a result + of svn_fspath__canonicalize() (see svn_fs_x__lock()). */ + info->lock->path = info->path; + info->lock->owner = apr_pstrdup(lb->result_pool, + lb->fs->access_ctx->username); + info->lock->comment = apr_pstrdup(lb->result_pool, lb->comment); + info->lock->is_dav_comment = lb->is_dav_comment; + info->lock->creation_date = apr_time_now(); + info->lock->expiration_date = lb->expiration_date; - info->lock = svn_lock_create(lb->result_pool); - if (target->token) - info->lock->token = target->token; - else - SVN_ERR(svn_fs_x__generate_lock_token( - &(info->lock->token), lb->fs, - lb->result_pool)); - info->lock->path = info->path; - info->lock->owner = lb->fs->access_ctx->username; - info->lock->comment = lb->comment; - info->lock->is_dav_comment = lb->is_dav_comment; - info->lock->creation_date = apr_time_now(); - info->lock->expiration_date = lb->expiration_date; - - info->fs_err = set_lock(lb->fs->path, info->lock, - rev_0_path, iterpool); - --outstanding; - } - else - { - /* The component is a path to an index. */ - apr_size_t len = info->component - info->path; - - if (last_path - && (strncmp(last_path, info->path, len) - || strlen(last_path) != len)) - { - /* No match to the previous paths to index. */ - SVN_ERR(add_to_digest(lb->fs->path, paths, last_path, - rev_0_path, iterpool)); - apr_array_clear(paths); - last_path = NULL; - } - APR_ARRAY_PUSH(paths, const char *) = info->path; - if (!last_path) - last_path = apr_pstrndup(iterpool, info->path, len); - } - } - } - - if (last_path && i == lb->infos->nelts - 1) - SVN_ERR(add_to_digest(lb->fs->path, paths, last_path, - rev_0_path, iterpool)); + info->fs_err = set_lock(lb->fs->path, info->lock, rev_0_path, + iterpool); } } + svn_pool_destroy(iterpool); return SVN_NO_ERROR; } @@ -1061,10 +992,8 @@ check_unlock(svn_error_t **fs_err, typedef struct unlock_info_t { const char *path; - const char *component; svn_error_t *fs_err; svn_boolean_t done; - int components; } unlock_info_t; /* The body of svn_fs_x__unlock(), which see. @@ -1079,18 +1008,18 @@ typedef struct unlock_info_t { type, and assumes that the write lock is held. */ static svn_error_t * -unlock_body(void *baton, apr_pool_t *pool) +unlock_body(void *baton, + apr_pool_t *pool) { unlock_baton_t *ub = baton; svn_fs_root_t *root; svn_revnum_t youngest; const char *rev_0_path; - int i, max_components = 0, outstanding = 0; + int i; + apr_hash_t *indices_updates = apr_hash_make(pool); + apr_hash_index_t *hi; apr_pool_t *iterpool = svn_pool_create(pool); - ub->infos = apr_array_make(ub->result_pool, ub->targets->nelts, - sizeof( unlock_info_t)); - SVN_ERR(ub->fs->vtable->youngest_rev(&youngest, ub->fs, pool)); SVN_ERR(ub->fs->vtable->revision_root(&root, ub->fs, youngest, pool)); @@ -1099,95 +1028,56 @@ unlock_body(void *baton, apr_pool_t *pool) const svn_sort__item_t *item = &APR_ARRAY_IDX(ub->targets, i, svn_sort__item_t); const char *token = item->value; - unlock_info_t info = { 0 }; + unlock_info_t info; svn_pool_clear(iterpool); info.path = item->key; + info.fs_err = SVN_NO_ERROR; + info.done = FALSE; + if (!ub->skip_check) SVN_ERR(check_unlock(&info.fs_err, info.path, token, ub, root, iterpool)); + + /* If no error occurred while pre-checking, schedule the index updates for + this path. */ if (!info.fs_err) - { - const char *s; + schedule_index_update(indices_updates, info.path, iterpool); - info.components = 1; - info.component = info.path; - while((s = strchr(info.component + 1, '/'))) - { - info.component = s; - ++info.components; - } - - if (info.components > max_components) - max_components = info.components; - - ++outstanding; - } APR_ARRAY_PUSH(ub->infos, unlock_info_t) = info; } rev_0_path = svn_fs_x__path_rev_absolute(ub->fs, 0, pool); - for (i = max_components; i >= 0; --i) + /* Unlike the lock_body(), we need to delete locks *before* we start to + update indices. */ + + for (i = 0; i < ub->infos->nelts; ++i) { - const char *last_path = NULL; - apr_array_header_t *paths; - int j; + struct unlock_info_t *info = &APR_ARRAY_IDX(ub->infos, i, + struct unlock_info_t); svn_pool_clear(iterpool); - paths = apr_array_make(pool, 1, sizeof(const char *)); - for (j = 0; j < ub->infos->nelts; ++j) + if (! info->fs_err) { - unlock_info_t *info = &APR_ARRAY_IDX(ub->infos, j, unlock_info_t); - - if (!info->fs_err && info->path) - { - - if (info->components == i) - { - SVN_ERR(delete_lock(ub->fs->path, info->path, iterpool)); - info->done = TRUE; - } - else if (info->components > i) - { - apr_size_t len = info->component - info->path; - - if (last_path - && strcmp(last_path, "/") - && (strncmp(last_path, info->path, len) - || strlen(last_path) != len)) - { - SVN_ERR(delete_from_digest(ub->fs->path, paths, last_path, - rev_0_path, iterpool)); - apr_array_clear(paths); - last_path = NULL; - } - APR_ARRAY_PUSH(paths, const char *) = info->path; - if (!last_path) - { - if (info->component > info->path) - last_path = apr_pstrndup(pool, info->path, len); - else - last_path = "/"; - } - - if (info->component > info->path) - { - --info->component; - while(info->component[0] != '/') - --info->component; - } - } - } - - if (last_path && j == ub->infos->nelts - 1) - SVN_ERR(delete_from_digest(ub->fs->path, paths, last_path, - rev_0_path, iterpool)); + SVN_ERR(delete_lock(ub->fs->path, info->path, iterpool)); + info->done = TRUE; } } + for (hi = apr_hash_first(pool, indices_updates); hi; hi = apr_hash_next(hi)) + { + const char *path = apr_hash_this_key(hi); + apr_array_header_t *children = apr_hash_this_val(hi); + + svn_pool_clear(iterpool); + SVN_ERR(delete_from_digest(ub->fs->path, children, path, rev_0_path, + iterpool)); + } + + svn_pool_destroy(iterpool); return SVN_NO_ERROR; } @@ -1211,6 +1101,8 @@ unlock_single(svn_fs_t *fs, ub.fs = fs; ub.targets = targets; + ub.infos = apr_array_make(scratch_pool, targets->nelts, + sizeof(struct unlock_info_t)); ub.skip_check = TRUE; ub.result_pool = scratch_pool; @@ -1272,6 +1164,8 @@ svn_fs_x__lock(svn_fs_t *fs, lb.fs = fs; lb.targets = sorted_targets; + lb.infos = apr_array_make(result_pool, sorted_targets->nelts, + sizeof(struct lock_info_t)); lb.comment = comment; lb.is_dav_comment = is_dav_comment; lb.expiration_date = expiration_date; @@ -1366,6 +1260,8 @@ svn_fs_x__unlock(svn_fs_t *fs, ub.fs = fs; ub.targets = sorted_targets; + ub.infos = apr_array_make(result_pool, sorted_targets->nelts, + sizeof(struct unlock_info_t)); ub.skip_check = FALSE; ub.break_lock = break_lock; ub.result_pool = result_pool; diff --git a/subversion/libsvn_fs_x/lock.h b/subversion/libsvn_fs_x/lock.h index 1db5eb71677f..508c1ff0b001 100644 --- a/subversion/libsvn_fs_x/lock.h +++ b/subversion/libsvn_fs_x/lock.h @@ -20,8 +20,8 @@ * ==================================================================== */ -#ifndef SVN_LIBSVN_FS_LOCK_H -#define SVN_LIBSVN_FS_LOCK_H +#ifndef SVN_LIBSVN_FS_X_LOCK_H +#define SVN_LIBSVN_FS_X_LOCK_H #ifdef __cplusplus extern "C" { @@ -113,4 +113,4 @@ svn_fs_x__allow_locked_operation(const char *path, } #endif /* __cplusplus */ -#endif /* SVN_LIBSVN_FS_LOCK_H */ +#endif /* SVN_LIBSVN_FS_X_LOCK_H */ diff --git a/subversion/libsvn_fs_x/low_level.c b/subversion/libsvn_fs_x/low_level.c index 76f3fd2f3872..5c7e3ad26610 100644 --- a/subversion/libsvn_fs_x/low_level.c +++ b/subversion/libsvn_fs_x/low_level.c @@ -1,4 +1,4 @@ -/* low_level.c --- low level r/w access to fs_x file structures +/* low_level.c --- low level r/w access to FSX file structures * * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one @@ -56,7 +56,6 @@ #define ACTION_ADD "add" #define ACTION_DELETE "delete" #define ACTION_REPLACE "replace" -#define ACTION_RESET "reset" /* True and False flags. */ #define FLAG_TRUE "true" @@ -103,6 +102,19 @@ parse_revnum(svn_revnum_t *rev, return SVN_NO_ERROR; } +/* If ERR is not NULL, wrap it MESSAGE. The latter must have an %ld + * format parameter that will be filled with REV. */ +static svn_error_t * +wrap_footer_error(svn_error_t *err, + const char *message, + svn_revnum_t rev) +{ + if (err) + return svn_error_quick_wrapf(err, message, rev); + + return SVN_NO_ERROR; +} + svn_error_t * svn_fs_x__parse_footer(apr_off_t *l2p_offset, svn_checksum_t **l2p_checksum, @@ -110,6 +122,7 @@ svn_fs_x__parse_footer(apr_off_t *l2p_offset, svn_checksum_t **p2l_checksum, svn_stringbuf_t *footer, svn_revnum_t rev, + apr_off_t footer_offset, apr_pool_t *result_pool) { apr_int64_t val; @@ -118,17 +131,20 @@ svn_fs_x__parse_footer(apr_off_t *l2p_offset, /* Get the L2P offset. */ const char *str = svn_cstring_tokenize(" ", &last_str); if (str == NULL) - return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, - _("Invalid revision footer")); + return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, + "Invalid r%ld footer", rev); - SVN_ERR(svn_cstring_atoi64(&val, str)); + SVN_ERR(wrap_footer_error(svn_cstring_strtoi64(&val, str, 0, + footer_offset - 1, 10), + "Invalid L2P offset in r%ld footer", + rev)); *l2p_offset = (apr_off_t)val; /* Get the L2P checksum. */ str = svn_cstring_tokenize(" ", &last_str); if (str == NULL) - return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, - _("Invalid revision footer")); + return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, + "Invalid r%ld footer", rev); SVN_ERR(svn_checksum_parse_hex(l2p_checksum, svn_checksum_md5, str, result_pool)); @@ -136,17 +152,33 @@ svn_fs_x__parse_footer(apr_off_t *l2p_offset, /* Get the P2L offset. */ str = svn_cstring_tokenize(" ", &last_str); if (str == NULL) - return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, - _("Invalid revision footer")); + return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, + "Invalid r%ld footer", rev); - SVN_ERR(svn_cstring_atoi64(&val, str)); + SVN_ERR(wrap_footer_error(svn_cstring_strtoi64(&val, str, 0, + footer_offset - 1, 10), + "Invalid P2L offset in r%ld footer", + rev)); *p2l_offset = (apr_off_t)val; + /* The P2L indes follows the L2P index */ + if (*p2l_offset <= *l2p_offset) + return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, + "P2L offset %s must be larger than L2P offset %s" + " in r%ld footer", + apr_psprintf(result_pool, + "%" APR_UINT64_T_HEX_FMT, + (apr_uint64_t)*p2l_offset), + apr_psprintf(result_pool, + "%" APR_UINT64_T_HEX_FMT, + (apr_uint64_t)*l2p_offset), + rev); + /* Get the P2L checksum. */ str = svn_cstring_tokenize(" ", &last_str); if (str == NULL) - return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, - _("Invalid revision footer")); + return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, + "Invalid r%ld footer", rev); SVN_ERR(svn_checksum_parse_hex(p2l_checksum, svn_checksum_md5, str, result_pool)); @@ -797,14 +829,6 @@ read_change(svn_fs_x__change_t **change_p, change = apr_pcalloc(result_pool, sizeof(*change)); last_str = line->data; - /* Get the node-id of the change. */ - str = svn_cstring_tokenize(" ", &last_str); - if (str == NULL) - return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, - _("Invalid changes line in rev-file")); - - SVN_ERR(svn_fs_x__id_parse(&change->noderev_id, str)); - /* Get the change type. */ str = svn_cstring_tokenize(" ", &last_str); if (str == NULL) @@ -845,10 +869,6 @@ read_change(svn_fs_x__change_t **change_p, { change->change_kind = svn_fs_path_change_replace; } - else if (strcmp(str, ACTION_RESET) == 0) - { - change->change_kind = svn_fs_path_change_reset; - } else { return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, @@ -954,10 +974,10 @@ read_change(svn_fs_x__change_t **change_p, svn_error_t * svn_fs_x__read_changes(apr_array_header_t **changes, svn_stream_t *stream, + int max_count, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - svn_fs_x__change_t *change; apr_pool_t *iterpool; /* Pre-allocate enough room for most change lists. @@ -970,13 +990,16 @@ svn_fs_x__read_changes(apr_array_header_t **changes, */ *changes = apr_array_make(result_pool, 63, sizeof(svn_fs_x__change_t *)); - SVN_ERR(read_change(&change, stream, result_pool, scratch_pool)); iterpool = svn_pool_create(scratch_pool); - while (change) + for (; max_count > 0; --max_count) { - APR_ARRAY_PUSH(*changes, svn_fs_x__change_t*) = change; - SVN_ERR(read_change(&change, stream, result_pool, iterpool)); + svn_fs_x__change_t *change; svn_pool_clear(iterpool); + SVN_ERR(read_change(&change, stream, result_pool, iterpool)); + if (!change) + break; + + APR_ARRAY_PUSH(*changes, svn_fs_x__change_t*) = change; } svn_pool_destroy(iterpool); @@ -1016,7 +1039,6 @@ write_change_entry(svn_stream_t *stream, svn_fs_x__change_t *change, apr_pool_t *scratch_pool) { - const char *idstr; const char *change_string = NULL; const char *kind_string = ""; svn_stringbuf_t *buf; @@ -1036,17 +1058,12 @@ write_change_entry(svn_stream_t *stream, case svn_fs_path_change_replace: change_string = ACTION_REPLACE; break; - case svn_fs_path_change_reset: - change_string = ACTION_RESET; - break; default: return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, _("Invalid change type %d"), change->change_kind); } - idstr = svn_fs_x__id_unparse(&change->noderev_id, scratch_pool)->data; - SVN_ERR_ASSERT(change->node_kind == svn_node_dir || change->node_kind == svn_node_file); kind_string = apr_psprintf(scratch_pool, "-%s", @@ -1054,8 +1071,8 @@ write_change_entry(svn_stream_t *stream, ? SVN_FS_X__KIND_DIR : SVN_FS_X__KIND_FILE); - buf = svn_stringbuf_createf(scratch_pool, "%s %s%s %s %s %s %s\n", - idstr, change_string, kind_string, + buf = svn_stringbuf_createf(scratch_pool, "%s%s %s %s %s %s\n", + change_string, kind_string, change->text_mod ? FLAG_TRUE : FLAG_FALSE, change->prop_mod ? FLAG_TRUE : FLAG_FALSE, change->mergeinfo_mod == svn_tristate_true @@ -1121,3 +1138,107 @@ svn_fs_x__write_changes(svn_stream_t *stream, return SVN_NO_ERROR; } +svn_error_t * +svn_fs_x__parse_properties(apr_hash_t **properties, + const svn_string_t *content, + apr_pool_t *result_pool) +{ + const apr_byte_t *p = (const apr_byte_t *)content->data; + const apr_byte_t *end = p + content->len; + apr_uint64_t count; + + *properties = apr_hash_make(result_pool); + + /* Extract the number of properties we are expected to read. */ + p = svn__decode_uint(&count, p, end); + + /* Read all the properties we find. + Because prop-name and prop-value are nicely NUL-terminated + sub-strings of CONTENT, we can simply reference them there. + I.e. there is no need to copy them around. + */ + while (p < end) + { + apr_uint64_t value_len; + svn_string_t *value; + + const char *key = (const char *)p; + + /* Note that this may never overflow / segfault because + CONTENT itself is NUL-terminated. */ + apr_size_t key_len = strlen(key); + p += key_len + 1; + if (key[key_len]) + return svn_error_createf(SVN_ERR_FS_CORRUPT_PROPLIST, NULL, + "Property name not NUL terminated"); + + if (p >= end) + return svn_error_createf(SVN_ERR_FS_CORRUPT_PROPLIST, NULL, + "Property value missing"); + p = svn__decode_uint(&value_len, p, end); + if (value_len >= (end - p)) + return svn_error_createf(SVN_ERR_FS_CORRUPT_PROPLIST, NULL, + "Property value too long"); + + value = apr_pcalloc(result_pool, sizeof(*value)); + value->data = (const char *)p; + value->len = (apr_size_t)value_len; + if (p[value->len]) + return svn_error_createf(SVN_ERR_FS_CORRUPT_PROPLIST, NULL, + "Property value not NUL terminated"); + + p += value->len + 1; + + apr_hash_set(*properties, key, key_len, value); + } + + /* Check that we read the expected number of properties. */ + if ((apr_uint64_t)apr_hash_count(*properties) != count) + return svn_error_createf(SVN_ERR_FS_CORRUPT_PROPLIST, NULL, + "Property count mismatch"); + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_fs_x__write_properties(svn_stream_t *stream, + apr_hash_t *proplist, + apr_pool_t *scratch_pool) +{ + apr_byte_t buffer[SVN__MAX_ENCODED_UINT_LEN]; + apr_size_t len; + apr_hash_index_t *hi; + + /* Write the number of properties in this list. */ + len = svn__encode_uint(buffer, apr_hash_count(proplist)) - buffer; + SVN_ERR(svn_stream_write(stream, (const char *)buffer, &len)); + + /* Serialize each property as follows: + + + */ + for (hi = apr_hash_first(scratch_pool, proplist); + hi; + hi = apr_hash_next(hi)) + { + const char *key; + apr_size_t key_len; + svn_string_t *value; + apr_hash_this(hi, (const void **)&key, (apr_ssize_t *)&key_len, + (void **)&value); + + /* Include the terminating NUL. */ + ++key_len; + SVN_ERR(svn_stream_write(stream, key, &key_len)); + + len = svn__encode_uint(buffer, value->len) - buffer; + SVN_ERR(svn_stream_write(stream, (const char *)buffer, &len)); + SVN_ERR(svn_stream_write(stream, value->data, &value->len)); + + /* Terminate with NUL. */ + len = 1; + SVN_ERR(svn_stream_write(stream, "", &len)); + } + + return SVN_NO_ERROR; +} diff --git a/subversion/libsvn_fs_x/low_level.h b/subversion/libsvn_fs_x/low_level.h index e4fdf05a8d4b..d59618d1698b 100644 --- a/subversion/libsvn_fs_x/low_level.h +++ b/subversion/libsvn_fs_x/low_level.h @@ -1,4 +1,4 @@ -/* low_level.c --- low level r/w access to fs_x file structures +/* low_level.c --- low level r/w access to FSX file structures * * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one @@ -20,8 +20,8 @@ * ==================================================================== */ -#ifndef SVN_LIBSVN_FS__LOW_LEVEL_H -#define SVN_LIBSVN_FS__LOW_LEVEL_H +#ifndef SVN_LIBSVN_FS_X_LOW_LEVEL_H +#define SVN_LIBSVN_FS_X_LOW_LEVEL_H #include "svn_fs.h" @@ -50,6 +50,8 @@ extern "C" { * *P2L_OFFSET, respectively. Also, return the expected checksums in * in *L2P_CHECKSUM and *P2L_CHECKSUM. * + * FOOTER_OFFSET is used for validation. + * * Note that REV is only used to construct nicer error objects that * mention this revision. Allocate the checksums in RESULT_POOL. */ @@ -60,6 +62,7 @@ svn_fs_x__parse_footer(apr_off_t *l2p_offset, svn_checksum_t **p2l_checksum, svn_stringbuf_t *footer, svn_revnum_t rev, + apr_off_t footer_offset, apr_pool_t *result_pool); /* Given the offset of the L2P index data in L2P_OFFSET, the content @@ -167,15 +170,17 @@ svn_fs_x__write_rep_header(svn_fs_x__rep_header_t *header, svn_stream_t *stream, apr_pool_t *scratch_pool); -/* Read all the changes from STREAM and store them in *CHANGES, - allocated in RESULT_POOL. Do temporary allocations in SCRATCH_POOL. */ +/* Read up to MAX_COUNT of the changes from STREAM and store them in + *CHANGES, allocated in RESULT_POOL. Do temporary allocations in + SCRATCH_POOL. */ svn_error_t * svn_fs_x__read_changes(apr_array_header_t **changes, svn_stream_t *stream, + int max_count, apr_pool_t *result_pool, apr_pool_t *scratch_pool); -/* Callback function used by svn_fs_fs__read_changes_incrementally(), +/* Callback function used by svn_fs_x__read_changes_incrementally(), * asking the receiver to process to process CHANGE using BATON. CHANGE * and SCRATCH_POOL will not be valid beyond the current callback invocation. */ @@ -207,8 +212,25 @@ svn_fs_x__write_changes(svn_stream_t *stream, svn_boolean_t terminate_list, apr_pool_t *scratch_pool); +/* Parse the property list serialized in CONTENT and return it in + *PROPERTIES, allocated from RESULT_POOL. CONTENT must remain + valid at least until the next cleanup of RESULT_POOL. + */ +svn_error_t * +svn_fs_x__parse_properties(apr_hash_t **properties, + const svn_string_t *content, + apr_pool_t *result_pool); + +/* Write the property list PROPLIST to STREAM in serialized format. + Use SCRATCH_POOL for temporary allocations. + */ +svn_error_t * +svn_fs_x__write_properties(svn_stream_t *stream, + apr_hash_t *proplist, + apr_pool_t *scratch_pool); + #ifdef __cplusplus } #endif /* __cplusplus */ -#endif /* SVN_LIBSVN_FS__LOW_LEVEL_H */ +#endif /* SVN_LIBSVN_FS_X_LOW_LEVEL_H */ diff --git a/subversion/libsvn_fs_x/noderevs.c b/subversion/libsvn_fs_x/noderevs.c index 60c6029966ca..8e6cf7432268 100644 --- a/subversion/libsvn_fs_x/noderevs.c +++ b/subversion/libsvn_fs_x/noderevs.c @@ -361,7 +361,7 @@ svn_error_t * svn_fs_x__noderevs_get(svn_fs_x__noderev_t **noderev_p, const svn_fs_x__noderevs_t *container, apr_size_t idx, - apr_pool_t *pool) + apr_pool_t *result_pool) { svn_fs_x__noderev_t *noderev; binary_noderev_t *binary_noderev; @@ -373,14 +373,14 @@ svn_fs_x__noderevs_get(svn_fs_x__noderev_t **noderev_p, /* validate index */ if (idx >= (apr_size_t)container->noderevs->nelts) return svn_error_createf(SVN_ERR_FS_CONTAINER_INDEX, NULL, - apr_psprintf(pool, + apr_psprintf(result_pool, _("Node revision index %%%s" " exceeds container size %%d"), APR_SIZE_T_FMT), idx, container->noderevs->nelts); /* allocate result struct and fill it field by field */ - noderev = apr_pcalloc(pool, sizeof(*noderev)); + noderev = apr_pcalloc(result_pool, sizeof(*noderev)); binary_noderev = &APR_ARRAY_IDX(container->noderevs, idx, binary_noderev_t); noderev->kind = (svn_node_kind_t)(binary_noderev->flags & NODEREV_KIND_MASK); @@ -398,7 +398,7 @@ svn_fs_x__noderevs_get(svn_fs_x__noderev_t **noderev_p, = svn_fs_x__string_table_get(container->paths, binary_noderev->copyfrom_path, NULL, - pool); + result_pool); noderev->copyfrom_rev = binary_noderev->copyfrom_rev; } else @@ -413,7 +413,7 @@ svn_fs_x__noderevs_get(svn_fs_x__noderev_t **noderev_p, = svn_fs_x__string_table_get(container->paths, binary_noderev->copyroot_path, NULL, - pool); + result_pool); noderev->copyroot_rev = binary_noderev->copyroot_rev; } else @@ -425,16 +425,16 @@ svn_fs_x__noderevs_get(svn_fs_x__noderev_t **noderev_p, noderev->predecessor_count = binary_noderev->predecessor_count; SVN_ERR(get_representation(&noderev->prop_rep, container->reps, - binary_noderev->prop_rep, pool)); + binary_noderev->prop_rep, result_pool)); SVN_ERR(get_representation(&noderev->data_rep, container->reps, - binary_noderev->data_rep, pool)); + binary_noderev->data_rep, result_pool)); if (binary_noderev->flags & NODEREV_HAS_CPATH) noderev->created_path = svn_fs_x__string_table_get(container->paths, binary_noderev->created_path, NULL, - pool); + result_pool); noderev->mergeinfo_count = binary_noderev->mergeinfo_count; @@ -578,15 +578,15 @@ svn_fs_x__write_noderevs_container(svn_stream_t *stream, return SVN_NO_ERROR; } -/* Allocate a svn_fs_x__representation_t array in POOL and return it in - * REPS_P. Deserialize the data in REP_STREAM and DIGEST_STREAM and store +/* Allocate a svn_fs_x__representation_t array in RESULT_POOL and return it + * in REPS_P. Deserialize the data in REP_STREAM and DIGEST_STREAM and store * the resulting representations into the *REPS_P. */ static svn_error_t * read_reps(apr_array_header_t **reps_p, svn_packed__int_stream_t *rep_stream, svn_packed__byte_stream_t *digest_stream, - apr_pool_t *pool) + apr_pool_t *result_pool) { apr_size_t i; apr_size_t len; @@ -595,7 +595,8 @@ read_reps(apr_array_header_t **reps_p, apr_size_t count = svn_packed__int_count(svn_packed__first_int_substream(rep_stream)); apr_array_header_t *reps - = apr_array_make(pool, (int)count, sizeof(svn_fs_x__representation_t)); + = apr_array_make(result_pool, (int)count, + sizeof(svn_fs_x__representation_t)); for (i = 0; i < count; ++i) { @@ -613,7 +614,7 @@ read_reps(apr_array_header_t **reps_p, bytes = svn_packed__get_bytes(digest_stream, &len); if (len != sizeof(rep.md5_digest)) return svn_error_createf(SVN_ERR_FS_CONTAINER_INDEX, NULL, - apr_psprintf(pool, + apr_psprintf(result_pool, _("Unexpected MD5" " digest size %%%s"), APR_SIZE_T_FMT), @@ -625,7 +626,7 @@ read_reps(apr_array_header_t **reps_p, bytes = svn_packed__get_bytes(digest_stream, &len); if (len != sizeof(rep.sha1_digest)) return svn_error_createf(SVN_ERR_FS_CONTAINER_INDEX, NULL, - apr_psprintf(pool, + apr_psprintf(result_pool, _("Unexpected SHA1" " digest size %%%s"), APR_SIZE_T_FMT), @@ -766,15 +767,15 @@ svn_error_t * svn_fs_x__deserialize_noderevs_container(void **out, void *data, apr_size_t data_len, - apr_pool_t *pool) + apr_pool_t *result_pool) { svn_fs_x__noderevs_t *noderevs = (svn_fs_x__noderevs_t *)data; /* de-serialize sub-structures */ svn_fs_x__deserialize_string_table(noderevs, &noderevs->paths); - svn_fs_x__deserialize_apr_array(noderevs, &noderevs->ids, pool); - svn_fs_x__deserialize_apr_array(noderevs, &noderevs->reps, pool); - svn_fs_x__deserialize_apr_array(noderevs, &noderevs->noderevs, pool); + svn_fs_x__deserialize_apr_array(noderevs, &noderevs->ids, result_pool); + svn_fs_x__deserialize_apr_array(noderevs, &noderevs->reps, result_pool); + svn_fs_x__deserialize_apr_array(noderevs, &noderevs->noderevs, result_pool); /* done */ *out = noderevs; diff --git a/subversion/libsvn_fs_x/noderevs.h b/subversion/libsvn_fs_x/noderevs.h index f9b79dcf2be1..72b2ef84d239 100644 --- a/subversion/libsvn_fs_x/noderevs.h +++ b/subversion/libsvn_fs_x/noderevs.h @@ -20,8 +20,8 @@ * ==================================================================== */ -#ifndef SVN_LIBSVN_FS__NODEREVS_H -#define SVN_LIBSVN_FS__NODEREVS_H +#ifndef SVN_LIBSVN_FS_X_NODEREVS_H +#define SVN_LIBSVN_FS_X_NODEREVS_H #include "svn_io.h" #include "fs.h" @@ -76,7 +76,7 @@ svn_error_t * svn_fs_x__noderevs_get(svn_fs_x__noderev_t **noderev_p, const svn_fs_x__noderevs_t *container, apr_size_t idx, - apr_pool_t *pool); + apr_pool_t *result_pool); /* I/O interface. */ @@ -114,7 +114,7 @@ svn_error_t * svn_fs_x__deserialize_noderevs_container(void **out, void *data, apr_size_t data_len, - apr_pool_t *pool); + apr_pool_t *result_pool); /* Implements svn_cache__partial_getter_func_t for svn_fs_x__noderevs_t, * setting *OUT to the svn_fs_x__noderev_t selected by the apr_uint32_t index diff --git a/subversion/libsvn_fs_x/pack.c b/subversion/libsvn_fs_x/pack.c index cdbb98029322..095b04ec8297 100644 --- a/subversion/libsvn_fs_x/pack.c +++ b/subversion/libsvn_fs_x/pack.c @@ -106,9 +106,6 @@ typedef struct path_order_t /* when this change happened */ svn_revnum_t revision; - /* this is a directory node */ - svn_boolean_t is_dir; - /* length of the expanded representation content */ apr_int64_t expanded_size; @@ -219,7 +216,7 @@ typedef struct pack_context_t * to NULL that we already processed. */ apr_array_header_t *reps; - /* array of int, marking for each revision, the which offset their items + /* array of int, marking for each revision, at which offset their items * begin in REPS. Will be filled in phase 2 and be cleared after * each revision range. */ apr_array_header_t *rev_offsets; @@ -247,6 +244,7 @@ initialize_pack_context(pack_context_t *context, const char *shard_dir, svn_revnum_t shard_rev, int max_items, + svn_fs_x__batch_fsync_t *batch, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *pool) @@ -275,9 +273,9 @@ initialize_pack_context(pack_context_t *context, context->pack_file_dir = pack_file_dir; context->pack_file_path = svn_dirent_join(pack_file_dir, PATH_PACKED, pool); - SVN_ERR(svn_io_file_open(&context->pack_file, context->pack_file_path, - APR_WRITE | APR_BUFFERED | APR_BINARY | APR_EXCL - | APR_CREATE, APR_OS_DEFAULT, pool)); + + SVN_ERR(svn_fs_x__batch_fsync_open_file(&context->pack_file, batch, + context->pack_file_path, pool)); /* Proto index files */ SVN_ERR(svn_fs_x__l2p_proto_index_open( @@ -346,6 +344,7 @@ reset_pack_context(pack_context_t *context, SVN_ERR(svn_io_file_trunc(context->reps_file, 0, scratch_pool)); svn_pool_clear(context->info_pool); + context->paths = svn_prefix_tree__create(context->info_pool); return SVN_NO_ERROR; } @@ -382,8 +381,6 @@ close_pack_context(pack_context_t *context, SVN_ERR(svn_io_remove_file2(proto_l2p_index_path, FALSE, scratch_pool)); SVN_ERR(svn_io_remove_file2(proto_p2l_index_path, FALSE, scratch_pool)); - SVN_ERR(svn_io_file_close(context->pack_file, scratch_pool)); - return SVN_NO_ERROR; } @@ -395,7 +392,7 @@ static svn_error_t * copy_file_data(pack_context_t *context, apr_file_t *dest, apr_file_t *source, - apr_off_t size, + svn_filesize_t size, apr_pool_t *scratch_pool) { /* most non-representation items will be small. Minimize the buffer @@ -478,14 +475,16 @@ copy_item_to_temp(pack_context_t *context, svn_fs_x__p2l_entry_t *entry, apr_pool_t *scratch_pool) { + apr_file_t *file; svn_fs_x__p2l_entry_t *new_entry = svn_fs_x__p2l_entry_dup(entry, context->info_pool); - SVN_ERR(svn_fs_x__get_file_offset(&new_entry->offset, temp_file, - scratch_pool)); + SVN_ERR(svn_io_file_get_offset(&new_entry->offset, temp_file, + scratch_pool)); APR_ARRAY_PUSH(entries, svn_fs_x__p2l_entry_t *) = new_entry; - SVN_ERR(copy_file_data(context, temp_file, rev_file->file, entry->size, + SVN_ERR(svn_fs_x__rev_file_get(&file, rev_file)); + SVN_ERR(copy_file_data(context, temp_file, file, entry->size, scratch_pool)); return SVN_NO_ERROR; @@ -567,17 +566,20 @@ copy_rep_to_temp(pack_context_t *context, apr_pool_t *scratch_pool) { svn_fs_x__rep_header_t *rep_header; + svn_stream_t *stream; + apr_file_t *file; apr_off_t source_offset = entry->offset; /* create a copy of ENTRY, make it point to the copy destination and * store it in CONTEXT */ entry = svn_fs_x__p2l_entry_dup(entry, context->info_pool); - SVN_ERR(svn_fs_x__get_file_offset(&entry->offset, context->reps_file, - scratch_pool)); + SVN_ERR(svn_io_file_get_offset(&entry->offset, context->reps_file, + scratch_pool)); add_item_rep_mapping(context, entry); /* read & parse the representation header */ - SVN_ERR(svn_fs_x__read_rep_header(&rep_header, rev_file->stream, + SVN_ERR(svn_fs_x__rev_file_stream(&stream, rev_file)); + SVN_ERR(svn_fs_x__read_rep_header(&rep_header, stream, scratch_pool, scratch_pool)); /* if the representation is a delta against some other rep, link the two */ @@ -594,10 +596,10 @@ copy_rep_to_temp(pack_context_t *context, } /* copy the whole rep (including header!) to our temp file */ - SVN_ERR(svn_io_file_seek(rev_file->file, APR_SET, &source_offset, - scratch_pool)); - SVN_ERR(copy_file_data(context, context->reps_file, rev_file->file, - entry->size, scratch_pool)); + SVN_ERR(svn_fs_x__rev_file_seek(rev_file, NULL, source_offset)); + SVN_ERR(svn_fs_x__rev_file_get(&file, rev_file)); + SVN_ERR(copy_file_data(context, context->reps_file, file, entry->size, + scratch_pool)); return SVN_NO_ERROR; } @@ -616,9 +618,6 @@ compare_dir_entries(const svn_sort__item_t *a, const svn_fs_dirent_t *lhs = (const svn_fs_dirent_t *) a->value; const svn_fs_dirent_t *rhs = (const svn_fs_dirent_t *) b->value; - if (lhs->kind != rhs->kind) - return lhs->kind == svn_node_dir ? -1 : 1; - return strcmp(lhs->name, rhs->name); } @@ -642,7 +641,7 @@ svn_fs_x__order_dir_entries(svn_fs_t *fs, return result; } -/* Return a duplicate of the the ORIGINAL path and with special sub-strins +/* Return a duplicate of the ORIGINAL path and with special sub-strings * (e.g. "trunk") modified in such a way that have a lower lexicographic * value than any other "normal" file name. */ @@ -687,25 +686,28 @@ copy_node_to_temp(pack_context_t *context, path_order_t *path_order = apr_pcalloc(context->info_pool, sizeof(*path_order)); svn_fs_x__noderev_t *noderev; + svn_stream_t *stream; + apr_file_t *file; const char *sort_path; apr_off_t source_offset = entry->offset; /* read & parse noderev */ - SVN_ERR(svn_fs_x__read_noderev(&noderev, rev_file->stream, scratch_pool, + SVN_ERR(svn_fs_x__rev_file_stream(&stream, rev_file)); + SVN_ERR(svn_fs_x__read_noderev(&noderev, stream, scratch_pool, scratch_pool)); /* create a copy of ENTRY, make it point to the copy destination and * store it in CONTEXT */ entry = svn_fs_x__p2l_entry_dup(entry, context->info_pool); - SVN_ERR(svn_fs_x__get_file_offset(&entry->offset, context->reps_file, - scratch_pool)); + SVN_ERR(svn_io_file_get_offset(&entry->offset, context->reps_file, + scratch_pool)); add_item_rep_mapping(context, entry); /* copy the noderev to our temp file */ - SVN_ERR(svn_io_file_seek(rev_file->file, APR_SET, &source_offset, - scratch_pool)); - SVN_ERR(copy_file_data(context, context->reps_file, rev_file->file, - entry->size, scratch_pool)); + SVN_ERR(svn_fs_x__rev_file_seek(rev_file, NULL, source_offset)); + SVN_ERR(svn_fs_x__rev_file_get(&file, rev_file)); + SVN_ERR(copy_file_data(context, context->reps_file, file, entry->size, + scratch_pool)); /* if the node has a data representation, make that the node's "base". * This will (often) cause the noderev to be placed right in front of @@ -732,7 +734,6 @@ copy_node_to_temp(pack_context_t *context, path_order->path = svn_prefix_string__create(context->paths, sort_path); path_order->node_id = noderev->node_id; path_order->revision = svn_fs_x__get_revnum(noderev->noderev_id.change_set); - path_order->is_dir = noderev->kind == svn_node_dir; path_order->noderev_id = noderev->noderev_id; APR_ARRAY_PUSH(context->path_order, path_order_t *) = path_order; @@ -776,13 +777,8 @@ compare_path_order(const path_order_t * const * lhs_p, const path_order_t * lhs = *lhs_p; const path_order_t * rhs = *rhs_p; - /* cluster all directories */ - int diff = rhs->is_dir - lhs->is_dir; - if (diff) - return diff; - /* lexicographic order on path and node (i.e. latest first) */ - diff = svn_prefix_string__compare(lhs->path, rhs->path); + int diff = svn_prefix_string__compare(lhs->path, rhs->path); if (diff) return diff; @@ -826,7 +822,7 @@ sort_reps(pack_context_t *context) /* Return the remaining unused bytes in the current block in CONTEXT's * pack file. */ -static apr_ssize_t +static apr_off_t get_block_left(pack_context_t *context) { svn_fs_x__data_t *ffd = context->fs->fsap_data; @@ -1234,7 +1230,7 @@ write_reps_containers(pack_context_t *context, = apr_array_make(scratch_pool, 64, sizeof(svn_fs_x__id_t)); svn_fs_x__revision_file_t *file; - SVN_ERR(svn_fs_x__wrap_temp_rev_file(&file, context->fs, temp_file, + SVN_ERR(svn_fs_x__rev_file_wrap_temp(&file, context->fs, temp_file, scratch_pool)); /* copy all items in strict order */ @@ -1608,8 +1604,8 @@ write_changes_containers(pack_context_t *context, * the container */ SVN_ERR(svn_io_file_seek(temp_file, APR_SET, &entry->offset, iterpool)); - SVN_ERR(svn_fs_x__read_changes(&changes, temp_stream, scratch_pool, - iterpool)); + SVN_ERR(svn_fs_x__read_changes(&changes, temp_stream, INT_MAX, + scratch_pool, iterpool)); SVN_ERR(svn_fs_x__changes_append_list(&list_index, container, changes)); SVN_ERR_ASSERT(list_index == sub_items->nelts); block_left -= estimated_size; @@ -1723,18 +1719,19 @@ pack_range(pack_context_t *context, { apr_off_t offset = 0; svn_fs_x__revision_file_t *rev_file; + svn_fs_x__index_info_t l2p_index_info; /* Get the rev file dimensions (mainly index locations). */ - SVN_ERR(svn_fs_x__open_pack_or_rev_file(&rev_file, context->fs, - revision, revpool, iterpool)); - SVN_ERR(svn_fs_x__auto_read_footer(rev_file)); + SVN_ERR(svn_fs_x__rev_file_init(&rev_file, context->fs, revision, + revpool)); + SVN_ERR(svn_fs_x__rev_file_l2p_info(&l2p_index_info, rev_file)); /* store the indirect array index */ APR_ARRAY_PUSH(context->rev_offsets, int) = context->reps->nelts; /* read the phys-to-log index file until we covered the whole rev file. * That index contains enough info to build both target indexes from it. */ - while (offset < rev_file->l2p_offset) + while (offset < l2p_index_info.start) { /* read one cluster */ int i; @@ -1758,10 +1755,9 @@ pack_range(pack_context_t *context, /* process entry while inside the rev file */ offset = entry->offset; - if (offset < rev_file->l2p_offset) + if (offset < l2p_index_info.start) { - SVN_ERR(svn_io_file_seek(rev_file->file, APR_SET, &offset, - iterpool)); + SVN_ERR(svn_fs_x__rev_file_seek(rev_file, NULL, offset)); if (entry->type == SVN_FS_X__ITEM_TYPE_CHANGES) SVN_ERR(copy_item_to_temp(context, @@ -1843,21 +1839,19 @@ append_revision(pack_context_t *context, apr_off_t offset = 0; apr_pool_t *iterpool = svn_pool_create(scratch_pool); svn_fs_x__revision_file_t *rev_file; - apr_finfo_t finfo; + apr_file_t *file; + svn_filesize_t revdata_size; - /* Get the size of the file. */ - const char *path = svn_dirent_join(context->shard_dir, - apr_psprintf(iterpool, "%ld", - context->start_rev), - scratch_pool); - SVN_ERR(svn_io_stat(&finfo, path, APR_FINFO_SIZE, scratch_pool)); + /* Copy all non-index contents the rev file to the end of the pack file. */ + SVN_ERR(svn_fs_x__rev_file_init(&rev_file, context->fs, context->start_rev, + scratch_pool)); + SVN_ERR(svn_fs_x__rev_file_data_size(&revdata_size, rev_file)); - /* Copy all the bits from the rev file to the end of the pack file. */ - SVN_ERR(svn_fs_x__open_pack_or_rev_file(&rev_file, context->fs, - context->start_rev, scratch_pool, - iterpool)); - SVN_ERR(copy_file_data(context, context->pack_file, rev_file->file, - finfo.size, iterpool)); + SVN_ERR(svn_fs_x__rev_file_get(&file, rev_file)); + SVN_ERR(svn_io_file_aligned_seek(file, ffd->block_size, NULL, 0, + iterpool)); + SVN_ERR(copy_file_data(context, context->pack_file, file, revdata_size, + iterpool)); /* mark the start of a new revision */ SVN_ERR(svn_fs_x__l2p_proto_index_add_revision(context->proto_l2p_index, @@ -1865,7 +1859,7 @@ append_revision(pack_context_t *context, /* read the phys-to-log index file until we covered the whole rev file. * That index contains enough info to build both target indexes from it. */ - while (offset < finfo.size) + while (offset < revdata_size) { /* read one cluster */ int i; @@ -1887,7 +1881,7 @@ append_revision(pack_context_t *context, /* process entry while inside the rev file */ offset = entry->offset; - if (offset < finfo.size) + if (offset < revdata_size) { /* there should be true containers */ SVN_ERR_ASSERT(entry->item_count == 1); @@ -1906,7 +1900,7 @@ append_revision(pack_context_t *context, } svn_pool_destroy(iterpool); - context->pack_offset += finfo.size; + context->pack_offset += revdata_size; return SVN_NO_ERROR; } @@ -1917,6 +1911,7 @@ append_revision(pack_context_t *context, * SHARD_DIR into the PACK_FILE_DIR, using SCRATCH_POOL for temporary * allocations. Limit the extra memory consumption to MAX_MEM bytes. * CANCEL_FUNC and CANCEL_BATON are what you think they are. + * Schedule necessary fsync calls in BATCH. */ static svn_error_t * pack_log_addressed(svn_fs_t *fs, @@ -1924,6 +1919,7 @@ pack_log_addressed(svn_fs_t *fs, const char *shard_dir, svn_revnum_t shard_rev, apr_size_t max_mem, + svn_fs_x__batch_fsync_t *batch, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *scratch_pool) @@ -1950,7 +1946,7 @@ pack_log_addressed(svn_fs_t *fs, /* set up a pack context */ SVN_ERR(initialize_pack_context(&context, fs, pack_file_dir, shard_dir, - shard_rev, max_items, cancel_func, + shard_rev, max_items, batch, cancel_func, cancel_baton, scratch_pool)); /* phase 1: determine the size of the revisions to pack */ @@ -1960,8 +1956,10 @@ pack_log_addressed(svn_fs_t *fs, /* pack revisions in ranges that don't exceed MAX_MEM */ for (i = 0; i < max_ids->nelts; ++i) - if (APR_ARRAY_IDX(max_ids, i, apr_uint64_t) + item_count <= max_items) + if ( APR_ARRAY_IDX(max_ids, i, apr_uint64_t) + <= (apr_uint64_t)max_items - item_count) { + item_count += APR_ARRAY_IDX(max_ids, i, apr_uint64_t); context.end_rev++; } else @@ -2003,77 +2001,11 @@ pack_log_addressed(svn_fs_t *fs, return SVN_NO_ERROR; } -/* Given REV in FS, set *REV_OFFSET to REV's offset in the packed file. - Use SCRATCH_POOL for temporary allocations. */ -svn_error_t * -svn_fs_x__get_packed_offset(apr_off_t *rev_offset, - svn_fs_t *fs, - svn_revnum_t rev, - apr_pool_t *scratch_pool) -{ - svn_fs_x__data_t *ffd = fs->fsap_data; - svn_stream_t *manifest_stream; - svn_boolean_t is_cached; - svn_revnum_t shard; - apr_int64_t shard_pos; - apr_array_header_t *manifest; - apr_pool_t *iterpool; - - shard = rev / ffd->max_files_per_dir; - - /* position of the shard within the manifest */ - shard_pos = rev % ffd->max_files_per_dir; - - /* fetch exactly that element into *rev_offset, if the manifest is found - in the cache */ - SVN_ERR(svn_cache__get_partial((void **) rev_offset, &is_cached, - ffd->packed_offset_cache, &shard, - svn_fs_x__get_sharded_offset, &shard_pos, - scratch_pool)); - - if (is_cached) - return SVN_NO_ERROR; - - /* Open the manifest file. */ - SVN_ERR(svn_stream_open_readonly(&manifest_stream, - svn_fs_x__path_rev_packed(fs, rev, PATH_MANIFEST, - scratch_pool), - scratch_pool, scratch_pool)); - - /* While we're here, let's just read the entire manifest file into an array, - so we can cache the entire thing. */ - iterpool = svn_pool_create(scratch_pool); - manifest = apr_array_make(scratch_pool, ffd->max_files_per_dir, - sizeof(apr_off_t)); - while (1) - { - svn_boolean_t eof; - apr_int64_t val; - - svn_pool_clear(iterpool); - SVN_ERR(svn_fs_x__read_number_from_stream(&val, &eof, manifest_stream, - iterpool)); - if (eof) - break; - - APR_ARRAY_PUSH(manifest, apr_off_t) = (apr_off_t)val; - } - svn_pool_destroy(iterpool); - - *rev_offset = APR_ARRAY_IDX(manifest, rev % ffd->max_files_per_dir, - apr_off_t); - - /* Close up shop and cache the array. */ - SVN_ERR(svn_stream_close(manifest_stream)); - return svn_cache__set(ffd->packed_offset_cache, &shard, manifest, - scratch_pool); -} - /* In filesystem FS, pack the revision SHARD containing exactly * MAX_FILES_PER_DIR revisions from SHARD_PATH into the PACK_FILE_DIR, * using SCRATCH_POOL for temporary allocations. Try to limit the amount of * temporary memory needed to MAX_MEM bytes. CANCEL_FUNC and CANCEL_BATON - * are what you think they are. + * are what you think they are. Schedule necessary fsync calls in BATCH. * * If for some reason we detect a partial packing already performed, we * remove the pack file and start again. @@ -2087,6 +2019,7 @@ pack_rev_shard(svn_fs_t *fs, apr_int64_t shard, int max_files_per_dir, apr_size_t max_mem, + svn_fs_x__batch_fsync_t *batch, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *scratch_pool) @@ -2103,10 +2036,11 @@ pack_rev_shard(svn_fs_t *fs, /* Create the new directory and pack file. */ SVN_ERR(svn_io_dir_make(pack_file_dir, APR_OS_DEFAULT, scratch_pool)); + SVN_ERR(svn_fs_x__batch_fsync_new_path(batch, pack_file_dir, scratch_pool)); /* Index information files */ SVN_ERR(pack_log_addressed(fs, pack_file_dir, shard_path, shard_rev, - max_mem, cancel_func, cancel_baton, + max_mem, batch, cancel_func, cancel_baton, scratch_pool)); SVN_ERR(svn_io_copy_perms(shard_path, pack_file_dir, scratch_pool)); @@ -2115,11 +2049,10 @@ pack_rev_shard(svn_fs_t *fs, return SVN_NO_ERROR; } -/* In the file system at FS_PATH, pack the SHARD in REVS_DIR and - * REVPROPS_DIR containing exactly MAX_FILES_PER_DIR revisions, using - * SCRATCH_POOL temporary for allocations. REVPROPS_DIR will be NULL if - * revprop packing is not supported. COMPRESSION_LEVEL and MAX_PACK_SIZE - * will be ignored in that case. +/* In the file system at FS_PATH, pack the SHARD in DIR containing exactly + * MAX_FILES_PER_DIR revisions, using SCRATCH_POOL temporary for allocations. + * COMPRESSION_LEVEL and MAX_PACK_SIZE will be ignored in that case. + * An attempt will be made to keep memory usage below MAX_MEM. * * CANCEL_FUNC and CANCEL_BATON are what you think they are; similarly * NOTIFY_FUNC and NOTIFY_BATON. @@ -2128,13 +2061,13 @@ pack_rev_shard(svn_fs_t *fs, * remove the pack file and start again. */ static svn_error_t * -pack_shard(const char *revs_dir, - const char *revsprops_dir, +pack_shard(const char *dir, svn_fs_t *fs, apr_int64_t shard, int max_files_per_dir, apr_off_t max_pack_size, int compression_level, + apr_size_t max_mem, svn_fs_pack_notify_t notify_func, void *notify_baton, svn_cancel_func_t cancel_func, @@ -2142,49 +2075,42 @@ pack_shard(const char *revs_dir, apr_pool_t *scratch_pool) { svn_fs_x__data_t *ffd = fs->fsap_data; - const char *rev_shard_path, *rev_pack_file_dir; - const char *revprops_shard_path, *revprops_pack_file_dir; + const char *shard_path, *pack_file_dir; + svn_fs_x__batch_fsync_t *batch; /* Notify caller we're starting to pack this shard. */ if (notify_func) SVN_ERR(notify_func(notify_baton, shard, svn_fs_pack_notify_start, scratch_pool)); + /* Perform all fsyncs through this instance. */ + SVN_ERR(svn_fs_x__batch_fsync_create(&batch, ffd->flush_to_disk, + scratch_pool)); + /* Some useful paths. */ - rev_pack_file_dir = svn_dirent_join(revs_dir, + pack_file_dir = svn_dirent_join(dir, apr_psprintf(scratch_pool, "%" APR_INT64_T_FMT PATH_EXT_PACKED_SHARD, shard), scratch_pool); - rev_shard_path = svn_dirent_join(revs_dir, + shard_path = svn_dirent_join(dir, apr_psprintf(scratch_pool, "%" APR_INT64_T_FMT, shard), scratch_pool); /* pack the revision content */ - SVN_ERR(pack_rev_shard(fs, rev_pack_file_dir, rev_shard_path, - shard, max_files_per_dir, DEFAULT_MAX_MEM, + SVN_ERR(pack_rev_shard(fs, pack_file_dir, shard_path, + shard, max_files_per_dir, max_mem, batch, cancel_func, cancel_baton, scratch_pool)); - /* if enabled, pack the revprops in an equivalent way */ - if (revsprops_dir) - { - revprops_pack_file_dir = svn_dirent_join(revsprops_dir, - apr_psprintf(scratch_pool, - "%" APR_INT64_T_FMT PATH_EXT_PACKED_SHARD, - shard), - scratch_pool); - revprops_shard_path = svn_dirent_join(revsprops_dir, - apr_psprintf(scratch_pool, "%" APR_INT64_T_FMT, shard), - scratch_pool); - - SVN_ERR(svn_fs_x__pack_revprops_shard(revprops_pack_file_dir, - revprops_shard_path, - shard, max_files_per_dir, - (int)(0.9 * max_pack_size), - compression_level, - cancel_func, cancel_baton, - scratch_pool)); - } + /* pack the revprops in an equivalent way */ + SVN_ERR(svn_fs_x__pack_revprops_shard(fs, + pack_file_dir, + shard_path, + shard, max_files_per_dir, + (int)(0.9 * max_pack_size), + compression_level, batch, + cancel_func, cancel_baton, + scratch_pool)); /* Update the min-unpacked-rev file to reflect our newly packed shard. */ SVN_ERR(svn_fs_x__write_min_unpacked_rev(fs, @@ -2192,35 +2118,12 @@ pack_shard(const char *revs_dir, scratch_pool)); ffd->min_unpacked_rev = (svn_revnum_t)((shard + 1) * max_files_per_dir); - /* Finally, remove the existing shard directories. - * For revprops, clean up older obsolete shards as well as they might - * have been left over from an interrupted FS upgrade. */ - SVN_ERR(svn_io_remove_dir2(rev_shard_path, TRUE, - cancel_func, cancel_baton, scratch_pool)); - if (revsprops_dir) - { - svn_node_kind_t kind = svn_node_dir; - apr_int64_t to_cleanup = shard; - do - { - SVN_ERR(svn_fs_x__delete_revprops_shard(revprops_shard_path, - to_cleanup, - max_files_per_dir, - cancel_func, cancel_baton, - scratch_pool)); + /* Ensure that packed file is written to disk.*/ + SVN_ERR(svn_fs_x__batch_fsync_run(batch, scratch_pool)); - /* If the previous shard exists, clean it up as well. - Don't try to clean up shard 0 as it we can't tell quickly - whether it actually needs cleaning up. */ - revprops_shard_path = svn_dirent_join(revsprops_dir, - apr_psprintf(scratch_pool, - "%" APR_INT64_T_FMT, - --to_cleanup), - scratch_pool); - SVN_ERR(svn_io_check_path(revprops_shard_path, &kind, scratch_pool)); - } - while (kind == svn_node_dir && to_cleanup > 0); - } + /* Finally, remove the existing shard directories. */ + SVN_ERR(svn_io_remove_dir2(shard_path, TRUE, + cancel_func, cancel_baton, scratch_pool)); /* Notify caller we're starting to pack this shard. */ if (notify_func) @@ -2230,9 +2133,38 @@ pack_shard(const char *revs_dir, return SVN_NO_ERROR; } +/* Read the youngest rev and the first non-packed rev info for FS from disk. + Set *FULLY_PACKED when there is no completed unpacked shard. + Use SCRATCH_POOL for temporary allocations. + */ +static svn_error_t * +get_pack_status(svn_boolean_t *fully_packed, + svn_fs_t *fs, + apr_pool_t *scratch_pool) +{ + svn_fs_x__data_t *ffd = fs->fsap_data; + apr_int64_t completed_shards; + svn_revnum_t youngest; + + SVN_ERR(svn_fs_x__read_min_unpacked_rev(&ffd->min_unpacked_rev, fs, + scratch_pool)); + + SVN_ERR(svn_fs_x__youngest_rev(&youngest, fs, scratch_pool)); + completed_shards = (youngest + 1) / ffd->max_files_per_dir; + + /* See if we've already completed all possible shards thus far. */ + if (ffd->min_unpacked_rev == (completed_shards * ffd->max_files_per_dir)) + *fully_packed = TRUE; + else + *fully_packed = FALSE; + + return SVN_NO_ERROR; +} + typedef struct pack_baton_t { svn_fs_t *fs; + apr_size_t max_mem; svn_fs_pack_notify_t notify_func; void *notify_baton; svn_cancel_func_t cancel_func; @@ -2262,25 +2194,25 @@ pack_body(void *baton, svn_fs_x__data_t *ffd = pb->fs->fsap_data; apr_int64_t completed_shards; apr_int64_t i; - svn_revnum_t youngest; apr_pool_t *iterpool; - const char *rev_data_path; - const char *revprops_data_path = NULL; + const char *data_path; + svn_boolean_t fully_packed; - /* If we aren't using sharding, we can't do any packing, so quit. */ - SVN_ERR(svn_fs_x__read_min_unpacked_rev(&ffd->min_unpacked_rev, pb->fs, - scratch_pool)); + /* Since another process might have already packed the repo, + we need to re-read the pack status. */ + SVN_ERR(get_pack_status(&fully_packed, pb->fs, scratch_pool)); + if (fully_packed) + { + if (pb->notify_func) + (*pb->notify_func)(pb->notify_baton, + ffd->min_unpacked_rev / ffd->max_files_per_dir, + svn_fs_pack_notify_noop, scratch_pool); - SVN_ERR(svn_fs_x__youngest_rev(&youngest, pb->fs, scratch_pool)); - completed_shards = (youngest + 1) / ffd->max_files_per_dir; + return SVN_NO_ERROR; + } - /* See if we've already completed all possible shards thus far. */ - if (ffd->min_unpacked_rev == (completed_shards * ffd->max_files_per_dir)) - return SVN_NO_ERROR; - - rev_data_path = svn_dirent_join(pb->fs->path, PATH_REVS_DIR, scratch_pool); - revprops_data_path = svn_dirent_join(pb->fs->path, PATH_REVPROPS_DIR, - scratch_pool); + completed_shards = (ffd->youngest_rev_cache + 1) / ffd->max_files_per_dir; + data_path = svn_dirent_join(pb->fs->path, PATH_REVS_DIR, scratch_pool); iterpool = svn_pool_create(scratch_pool); for (i = ffd->min_unpacked_rev / ffd->max_files_per_dir; @@ -2292,12 +2224,13 @@ pack_body(void *baton, if (pb->cancel_func) SVN_ERR(pb->cancel_func(pb->cancel_baton)); - SVN_ERR(pack_shard(rev_data_path, revprops_data_path, + SVN_ERR(pack_shard(data_path, pb->fs, i, ffd->max_files_per_dir, ffd->revprop_pack_size, ffd->compress_packed_revprops ? SVN__COMPRESSION_ZLIB_DEFAULT : SVN__COMPRESSION_NONE, + pb->max_mem, pb->notify_func, pb->notify_baton, pb->cancel_func, pb->cancel_baton, iterpool)); } @@ -2308,6 +2241,7 @@ pack_body(void *baton, svn_error_t * svn_fs_x__pack(svn_fs_t *fs, + apr_size_t max_mem, svn_fs_pack_notify_t notify_func, void *notify_baton, svn_cancel_func_t cancel_func, @@ -2315,10 +2249,29 @@ svn_fs_x__pack(svn_fs_t *fs, apr_pool_t *scratch_pool) { pack_baton_t pb = { 0 }; + svn_boolean_t fully_packed; + + /* Is there we even anything to do?. */ + SVN_ERR(get_pack_status(&fully_packed, fs, scratch_pool)); + if (fully_packed) + { + svn_fs_x__data_t *ffd = fs->fsap_data; + + if (notify_func) + (*notify_func)(notify_baton, + ffd->min_unpacked_rev / ffd->max_files_per_dir, + svn_fs_pack_notify_noop, scratch_pool); + + return SVN_NO_ERROR; + } + + /* Lock the repo and start the pack process. */ pb.fs = fs; pb.notify_func = notify_func; pb.notify_baton = notify_baton; pb.cancel_func = cancel_func; pb.cancel_baton = cancel_baton; + pb.max_mem = max_mem ? max_mem : DEFAULT_MAX_MEM; + return svn_fs_x__with_pack_lock(fs, pack_body, &pb, scratch_pool); } diff --git a/subversion/libsvn_fs_x/pack.h b/subversion/libsvn_fs_x/pack.h index 55416190f550..9677946c60f4 100644 --- a/subversion/libsvn_fs_x/pack.h +++ b/subversion/libsvn_fs_x/pack.h @@ -20,36 +20,31 @@ * ==================================================================== */ -#ifndef SVN_LIBSVN_FS__PACK_H -#define SVN_LIBSVN_FS__PACK_H +#ifndef SVN_LIBSVN_FS_X_PACK_H +#define SVN_LIBSVN_FS_X_PACK_H #include "fs.h" /* Possibly pack the repository at PATH. This just take full shards, and - combines all the revision files into a single one, with a manifest header. + combines all the revision files into a single one, with a manifest header + when required by the repository format. + + MAX_MEM limits the size of in-memory data structures needed for reordering + items. 0 means use the built-in default. + Use optional CANCEL_FUNC/CANCEL_BATON for cancellation support. Use SCRATCH_POOL for temporary allocations. Existing filesystem references need not change. */ svn_error_t * svn_fs_x__pack(svn_fs_t *fs, + apr_size_t max_mem, svn_fs_pack_notify_t notify_func, void *notify_baton, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *scratch_pool); -/** - * For the packed revision REV in FS, determine the offset within the - * revision pack file and return it in REV_OFFSET. - * Use SCRATCH_POOL for temporary allocations. - */ -svn_error_t * -svn_fs_x__get_packed_offset(apr_off_t *rev_offset, - svn_fs_t *fs, - svn_revnum_t rev, - apr_pool_t *scratch_pool); - /* Return the svn_dir_entry_t* objects of DIRECTORY in an APR array * allocated in RESULT_POOL with entries added in storage (on-disk) order. * FS' format will be used to pick the optimal ordering strategy. Use diff --git a/subversion/libsvn_fs_x/recovery.c b/subversion/libsvn_fs_x/recovery.c index 984b74023130..f49f6a645148 100644 --- a/subversion/libsvn_fs_x/recovery.c +++ b/subversion/libsvn_fs_x/recovery.c @@ -22,6 +22,7 @@ #include "recovery.h" +#include "svn_dirent_uri.h" #include "svn_hash.h" #include "svn_pools.h" #include "private/svn_string_private.h" @@ -38,6 +39,22 @@ #include "svn_private_config.h" +/* Set *EXISTS to TRUE, if the revision / pack file for REV exists in FS. + Use SCRATCH_POOL for temporary allocations. */ +static svn_error_t * +revision_file_exists(svn_boolean_t *exists, + svn_fs_t *fs, + svn_revnum_t rev, + apr_pool_t *scratch_pool) +{ + svn_node_kind_t kind; + const char *path = svn_fs_x__path_rev_absolute(fs, rev, scratch_pool); + SVN_ERR(svn_io_check_path(path, &kind, scratch_pool)); + + *exists = kind == svn_node_file; + return SVN_NO_ERROR; +} + /* Part of the recovery procedure. Return the largest revision *REV in filesystem FS. Use SCRATCH_POOL for temporary allocation. */ static svn_error_t * @@ -56,19 +73,12 @@ recover_get_largest_revision(svn_fs_t *fs, /* Keep doubling right, until we find a revision that doesn't exist. */ while (1) { - svn_error_t *err; - svn_fs_x__revision_file_t *file; + svn_boolean_t exists; svn_pool_clear(iterpool); - err = svn_fs_x__open_pack_or_rev_file(&file, fs, right, iterpool, - iterpool); - if (err && err->apr_err == SVN_ERR_FS_NO_SUCH_REVISION) - { - svn_error_clear(err); - break; - } - else - SVN_ERR(err); + SVN_ERR(revision_file_exists(&exists, fs, right, iterpool)); + if (!exists) + break; right <<= 1; } @@ -80,22 +90,14 @@ recover_get_largest_revision(svn_fs_t *fs, while (left + 1 < right) { svn_revnum_t probe = left + ((right - left) / 2); - svn_error_t *err; - svn_fs_x__revision_file_t *file; + svn_boolean_t exists; svn_pool_clear(iterpool); - err = svn_fs_x__open_pack_or_rev_file(&file, fs, probe, iterpool, - iterpool); - if (err && err->apr_err == SVN_ERR_FS_NO_SUCH_REVISION) - { - svn_error_clear(err); - right = probe; - } + SVN_ERR(revision_file_exists(&exists, fs, probe, iterpool)); + if (exists) + left = probe; else - { - SVN_ERR(err); - left = probe; - } + right = probe; } svn_pool_destroy(iterpool); @@ -105,6 +107,86 @@ recover_get_largest_revision(svn_fs_t *fs, return SVN_NO_ERROR; } +/* Delete all files and sub-directories (recursively) of DIR_PATH but + leave DIR_PATH itself in place. Use SCRATCH_POOL for temporaries. */ +static svn_error_t * +clear_directory(const char *dir_path, + apr_pool_t *scratch_pool) +{ + apr_hash_t *dirents; + apr_hash_index_t *hi; + apr_pool_t *iterpool = svn_pool_create(scratch_pool); + + SVN_ERR(svn_io_get_dirents3(&dirents, dir_path, TRUE, scratch_pool, + scratch_pool)); + + for (hi = apr_hash_first(scratch_pool, dirents); + hi; + hi = apr_hash_next(hi)) + { + const char *path; + const char *name; + svn_dirent_t *dirent; + + svn_pool_clear(iterpool); + apr_hash_this(hi, (const void **)&name, NULL, (void **)&dirent); + + path = svn_dirent_join(dir_path, name, iterpool); + if (dirent->kind == svn_node_dir) + SVN_ERR(svn_io_remove_dir2(path, TRUE, NULL, NULL, iterpool)); + else + SVN_ERR(svn_io_remove_file2(path, TRUE, iterpool)); + } + + svn_pool_destroy(iterpool); + + return SVN_NO_ERROR; +} + +/* Delete all uncommitted transaction data from FS. + Use SCRATCH_POOL for temporaries. */ +static svn_error_t * +discard_transactions(svn_fs_t *fs, + apr_pool_t *scratch_pool) +{ + svn_fs_x__data_t *ffd = fs->fsap_data; + svn_fs_x__shared_data_t *ffsd = ffd->shared; + + /* In case this FS has been opened more than once in this process, + we should purge their shared transaction data as well. We do the + same as abort_txn would, except that we don't expect all txn files + to be complete on disk. */ + while (ffsd->txns) + { + svn_fs_x__shared_txn_data_t *txn = ffsd->txns; + ffsd->txns = txn->next; + + svn_pool_destroy(txn->pool); + } + + /* Remove anything from the transaction folders. */ + SVN_ERR(clear_directory(svn_fs_x__path_txns_dir(fs, scratch_pool), + scratch_pool)); + SVN_ERR(clear_directory(svn_fs_x__path_txn_proto_revs(fs, scratch_pool), + scratch_pool)); + + return SVN_NO_ERROR; +} + +/* Reset txn-current in FS. Use SCRATCH_POOL for temporaries. */ +static svn_error_t * +reset_txn_number(svn_fs_t *fs, + apr_pool_t *scratch_pool) +{ + const char *initial_txn = "0\n"; + SVN_ERR(svn_io_write_atomic2(svn_fs_x__path_txn_current(fs, scratch_pool), + initial_txn, strlen(initial_txn), + svn_fs_x__path_uuid(fs, scratch_pool), + FALSE, scratch_pool)); + + return SVN_NO_ERROR; +} + /* Baton used for recover_body below. */ typedef struct recover_baton_t { svn_fs_t *fs; @@ -133,7 +215,13 @@ recover_body(void *baton, /* The admin may have created a plain copy of this repo before attempting to recover it (hotcopy may or may not work with corrupted repos). Bump the instance ID. */ - SVN_ERR(svn_fs_x__set_uuid(fs, fs->uuid, NULL, scratch_pool)); + SVN_ERR(svn_fs_x__set_uuid(fs, fs->uuid, NULL, TRUE, scratch_pool)); + + /* Because transactions are not resilient against system crashes, + any existing transaction is suspect (and would probably not be + reopened anyway). Get rid of those. */ + SVN_ERR(discard_transactions(fs, scratch_pool)); + SVN_ERR(reset_txn_number(fs, scratch_pool)); /* We need to know the largest revision in the filesystem. */ SVN_ERR(recover_get_largest_revision(fs, &max_rev, scratch_pool)); diff --git a/subversion/libsvn_fs_x/recovery.h b/subversion/libsvn_fs_x/recovery.h index 4fe0a072adcb..ffb064673e85 100644 --- a/subversion/libsvn_fs_x/recovery.h +++ b/subversion/libsvn_fs_x/recovery.h @@ -20,8 +20,8 @@ * ==================================================================== */ -#ifndef SVN_LIBSVN_FS__RECOVERY_H -#define SVN_LIBSVN_FS__RECOVERY_H +#ifndef SVN_LIBSVN_FS_X_RECOVERY_H +#define SVN_LIBSVN_FS_X_RECOVERY_H #include "fs.h" diff --git a/subversion/libsvn_fs_x/rep-cache-db.h b/subversion/libsvn_fs_x/rep-cache-db.h index 918955f51d9f..c212760651d5 100644 --- a/subversion/libsvn_fs_x/rep-cache-db.h +++ b/subversion/libsvn_fs_x/rep-cache-db.h @@ -1,4 +1,4 @@ -/* This file is automatically generated from rep-cache-db.sql and .dist_sandbox/subversion-1.9.7/subversion/libsvn_fs_x/token-map.h. +/* This file is automatically generated from rep-cache-db.sql and subversion/libsvn_fs_x/token-map.h. * Do not edit this file -- edit the source and rerun gen-make.py */ #define STMT_CREATE_SCHEMA 0 diff --git a/subversion/libsvn_fs_x/rep-cache.c b/subversion/libsvn_fs_x/rep-cache.c index 85e62a46f376..639762182582 100644 --- a/subversion/libsvn_fs_x/rep-cache.c +++ b/subversion/libsvn_fs_x/rep-cache.c @@ -100,12 +100,16 @@ open_rep_cache(void *baton, 0, NULL, 0, fs->pool, scratch_pool)); - SVN_ERR(svn_sqlite__read_schema_version(&version, sdb, scratch_pool)); + SVN_SQLITE__ERR_CLOSE(svn_sqlite__read_schema_version(&version, sdb, + scratch_pool), + sdb); if (version < REP_CACHE_SCHEMA_FORMAT) { /* Must be 0 -- an uninitialized (no schema) database. Create the schema. Results in schema version of 1. */ - SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_CREATE_SCHEMA)); + SVN_SQLITE__ERR_CLOSE(svn_sqlite__exec_statements(sdb, + STMT_CREATE_SCHEMA), + sdb); } /* This is used as a flag that the database is available so don't @@ -122,7 +126,26 @@ svn_fs_x__open_rep_cache(svn_fs_t *fs, svn_fs_x__data_t *ffd = fs->fsap_data; svn_error_t *err = svn_atomic__init_once(&ffd->rep_cache_db_opened, open_rep_cache, fs, scratch_pool); - return svn_error_quick_wrap(err, _("Couldn't open rep-cache database")); + return svn_error_quick_wrapf(err, + _("Couldn't open rep-cache database '%s'"), + svn_dirent_local_style( + path_rep_cache_db(fs->path, scratch_pool), + scratch_pool)); +} + +svn_error_t * +svn_fs_x__close_rep_cache(svn_fs_t *fs) +{ + svn_fs_x__data_t *ffd = fs->fsap_data; + + if (ffd->rep_cache_db) + { + SVN_ERR(svn_sqlite__close(ffd->rep_cache_db)); + ffd->rep_cache_db = NULL; + ffd->rep_cache_db_opened = 0; + } + + return SVN_NO_ERROR; } svn_error_t * @@ -236,7 +259,7 @@ svn_fs_x__walk_rep_reference(svn_fs_t *fs, If you extend this function, check the callsite to see if you have to make it not-ignore additional error codes. */ svn_error_t * -svn_fs_x__get_rep_reference(svn_fs_x__representation_t **rep, +svn_fs_x__get_rep_reference(svn_fs_x__representation_t **rep_p, svn_fs_t *fs, svn_checksum_t *checksum, apr_pool_t *result_pool, @@ -245,6 +268,7 @@ svn_fs_x__get_rep_reference(svn_fs_x__representation_t **rep, svn_fs_x__data_t *ffd = fs->fsap_data; svn_sqlite__stmt_t *stmt; svn_boolean_t have_row; + svn_fs_x__representation_t *rep; SVN_ERR_ASSERT(ffd->rep_sharing_allowed); if (! ffd->rep_cache_db) @@ -263,24 +287,23 @@ svn_fs_x__get_rep_reference(svn_fs_x__representation_t **rep, SVN_ERR(svn_sqlite__step(&have_row, stmt)); if (have_row) { - *rep = apr_pcalloc(result_pool, sizeof(**rep)); - memcpy((*rep)->sha1_digest, checksum->digest, - sizeof((*rep)->sha1_digest)); - (*rep)->has_sha1 = TRUE; - (*rep)->id.change_set = svn_sqlite__column_revnum(stmt, 0); - (*rep)->id.number = svn_sqlite__column_int64(stmt, 1); - (*rep)->size = svn_sqlite__column_int64(stmt, 2); - (*rep)->expanded_size = svn_sqlite__column_int64(stmt, 3); + rep = apr_pcalloc(result_pool, sizeof(*rep)); + memcpy(rep->sha1_digest, checksum->digest, sizeof(rep->sha1_digest)); + rep->has_sha1 = TRUE; + rep->id.change_set = svn_sqlite__column_revnum(stmt, 0); + rep->id.number = svn_sqlite__column_int64(stmt, 1); + rep->size = svn_sqlite__column_int64(stmt, 2); + rep->expanded_size = svn_sqlite__column_int64(stmt, 3); } else - *rep = NULL; + rep = NULL; SVN_ERR(svn_sqlite__reset(stmt)); - if (*rep) + if (rep) { /* Check that REP refers to a revision that exists in FS. */ - svn_revnum_t revision = svn_fs_x__get_revnum((*rep)->id.change_set); + svn_revnum_t revision = svn_fs_x__get_revnum(rep->id.change_set); svn_error_t *err = svn_fs_x__ensure_revision_exists(revision, fs, scratch_pool); if (err) @@ -289,6 +312,7 @@ svn_fs_x__get_rep_reference(svn_fs_x__representation_t **rep, svn_checksum_to_cstring_display(checksum, scratch_pool)); } + *rep_p = rep; return SVN_NO_ERROR; } diff --git a/subversion/libsvn_fs_x/rep-cache.h b/subversion/libsvn_fs_x/rep-cache.h index 1fe26da9b810..5c355cbbe03e 100644 --- a/subversion/libsvn_fs_x/rep-cache.h +++ b/subversion/libsvn_fs_x/rep-cache.h @@ -40,6 +40,10 @@ svn_error_t * svn_fs_x__open_rep_cache(svn_fs_t *fs, apr_pool_t *scratch_pool); +/* Close the rep cache database associated with FS. */ +svn_error_t * +svn_fs_x__close_rep_cache(svn_fs_t *fs); + /* Set *EXISTS to TRUE iff the rep-cache DB file exists. */ svn_error_t * svn_fs_x__exists_rep_cache(svn_boolean_t *exists, @@ -61,11 +65,12 @@ svn_fs_x__walk_rep_reference(svn_fs_t *fs, apr_pool_t *scratch_pool); /* Return the representation REP in FS which has fulltext CHECKSUM. - REP is allocated in RESULT_POOL. If the rep cache database has not been - opened, just set *REP to NULL. Returns SVN_ERR_FS_CORRUPT if a reference - beyond HEAD is detected. Uses SCRATCH_POOL for temporary allocations. */ + *REP_P is allocated in RESULT_POOL. If the rep cache database has not + been opened, just set *REP_P to NULL. Returns SVN_ERR_FS_CORRUPT if + a reference beyond HEAD is detected. Uses SCRATCH_POOL for temporary + allocations.*/ svn_error_t * -svn_fs_x__get_rep_reference(svn_fs_x__representation_t **rep, +svn_fs_x__get_rep_reference(svn_fs_x__representation_t **rep_p, svn_fs_t *fs, svn_checksum_t *checksum, apr_pool_t *result_pool, diff --git a/subversion/libsvn_fs_x/reps.c b/subversion/libsvn_fs_x/reps.c index 85a5269a7fc3..0bfc2412237c 100644 --- a/subversion/libsvn_fs_x/reps.c +++ b/subversion/libsvn_fs_x/reps.c @@ -417,8 +417,8 @@ svn_fs_x__reps_add_base(svn_fs_x__reps_builder_t *builder, apr_size_t idx; SVN_ERR(svn_fs_x__get_contents(&stream, builder->fs, rep, FALSE, scratch_pool)); - SVN_ERR(svn_string_from_stream(&contents, stream, scratch_pool, - scratch_pool)); + SVN_ERR(svn_string_from_stream2(&contents, stream, SVN__STREAM_CHUNK_SIZE, + scratch_pool)); SVN_ERR(svn_fs_x__reps_add(&idx, builder, contents)); base.revision = svn_fs_x__get_revnum(rep->id.change_set); @@ -641,16 +641,17 @@ svn_fs_x__reps_get(svn_fs_x__rep_extractor_t **extractor, svn_fs_t *fs, const svn_fs_x__reps_t *container, apr_size_t idx, - apr_pool_t *pool) + apr_pool_t *result_pool) { apr_uint32_t first = container->first_instructions[idx]; apr_uint32_t last = container->first_instructions[idx + 1]; /* create the extractor object */ - svn_fs_x__rep_extractor_t *result = apr_pcalloc(pool, sizeof(*result)); + svn_fs_x__rep_extractor_t *result = apr_pcalloc(result_pool, + sizeof(*result)); result->fs = fs; - result->result = svn_stringbuf_create_empty(pool); - result->pool = pool; + result->result = svn_stringbuf_create_empty(result_pool); + result->pool = result_pool; /* fill all the bits of the result that we can, i.e. all but bits coming * from base representations */ @@ -900,7 +901,7 @@ svn_error_t * svn_fs_x__deserialize_reps_container(void **out, void *data, apr_size_t data_len, - apr_pool_t *pool) + apr_pool_t *result_pool) { svn_fs_x__reps_t *reps = (svn_fs_x__reps_t *)data; diff --git a/subversion/libsvn_fs_x/reps.h b/subversion/libsvn_fs_x/reps.h index 720bfbfb4290..8edd21361d44 100644 --- a/subversion/libsvn_fs_x/reps.h +++ b/subversion/libsvn_fs_x/reps.h @@ -20,8 +20,8 @@ * ==================================================================== */ -#ifndef SVN_LIBSVN_FS__REPS_H -#define SVN_LIBSVN_FS__REPS_H +#ifndef SVN_LIBSVN_FS_X_REPS_H +#define SVN_LIBSVN_FS_X_REPS_H #include "svn_io.h" #include "fs.h" @@ -112,14 +112,14 @@ svn_fs_x__reps_estimate_size(const svn_fs_x__reps_builder_t *builder); /* Read from representation containers. */ /* For fulltext IDX in CONTAINER in filesystem FS, create an extract object - * allocated in POOL and return it in *EXTRACTOR. + * allocated in RESULT_POOL and return it in *EXTRACTOR. */ svn_error_t * svn_fs_x__reps_get(svn_fs_x__rep_extractor_t **extractor, svn_fs_t *fs, const svn_fs_x__reps_t *container, apr_size_t idx, - apr_pool_t *pool); + apr_pool_t *result_pool); /* Let the EXTRACTOR object fetch all parts of the desired fulltext and * return the latter in *CONTENTS. If SIZE is not 0, return SIZE bytes @@ -172,7 +172,7 @@ svn_error_t * svn_fs_x__deserialize_reps_container(void **out, void *data, apr_size_t data_len, - apr_pool_t *pool); + apr_pool_t *result_pool); /* Implements svn_cache__partial_getter_func_t for svn_fs_x__reps_t, * setting *OUT to an svn_fs_x__rep_extractor_t object defined by the diff --git a/subversion/libsvn_fs_x/rev_file.c b/subversion/libsvn_fs_x/rev_file.c index 445d45b55b43..2a362337a93c 100644 --- a/subversion/libsvn_fs_x/rev_file.c +++ b/subversion/libsvn_fs_x/rev_file.c @@ -20,6 +20,8 @@ * ==================================================================== */ +#include "svn_pools.h" + #include "rev_file.h" #include "fs_x.h" #include "index.h" @@ -31,6 +33,46 @@ #include "private/svn_io_private.h" #include "svn_private_config.h" +struct svn_fs_x__revision_file_t +{ + /* the filesystem that this revision file belongs to */ + svn_fs_t *fs; + + /* Meta-data to FILE. */ + svn_fs_x__rev_file_info_t file_info; + + /* rev / pack file */ + apr_file_t *file; + + /* stream based on FILE and not NULL exactly when FILE is not NULL */ + svn_stream_t *stream; + + /* the opened P2L index stream or NULL. Always NULL for txns. */ + svn_fs_x__packed_number_stream_t *p2l_stream; + + /* the opened L2P index stream or NULL. Always NULL for txns. */ + svn_fs_x__packed_number_stream_t *l2p_stream; + + /* Copied from FS->FFD->BLOCK_SIZE upon creation. It allows us to + * use aligned seek() without having the FS handy. */ + apr_off_t block_size; + + /* Info on the L2P index within FILE. + * Elements are -1 / NULL until svn_fs_x__auto_read_footer gets called. */ + svn_fs_x__index_info_t l2p_info; + + /* Info on the P2L index within FILE. + * Elements are -1 / NULL until svn_fs_x__auto_read_footer gets called. */ + svn_fs_x__index_info_t p2l_info; + + /* Pool used for all sub-structure allocations (file, streams etc.). + A sub-pool of OWNER. NULL until the lazily initilized. */ + apr_pool_t *pool; + + /* Pool that this structure got allocated in. */ + apr_pool_t *owner; +}; + /* Return a new revision file instance, allocated in RESULT_POOL, for * filesystem FS. Set its pool member to the provided RESULT_POOL. */ static svn_fs_x__revision_file_t * @@ -38,22 +80,24 @@ create_revision_file(svn_fs_t *fs, apr_pool_t *result_pool) { svn_fs_x__data_t *ffd = fs->fsap_data; + svn_fs_x__revision_file_t *file = apr_palloc(result_pool, sizeof(*file)); - - file->is_packed = FALSE; - file->start_revision = SVN_INVALID_REVNUM; - + file->fs = fs; + file->file_info.is_packed = FALSE; + file->file_info.start_revision = SVN_INVALID_REVNUM; file->file = NULL; file->stream = NULL; file->p2l_stream = NULL; file->l2p_stream = NULL; file->block_size = ffd->block_size; - file->l2p_offset = -1; - file->l2p_checksum = NULL; - file->p2l_offset = -1; - file->p2l_checksum = NULL; - file->footer_offset = -1; - file->pool = result_pool; + file->l2p_info.start = -1; + file->l2p_info.end = -1; + file->l2p_info.checksum = NULL; + file->p2l_info.start = -1; + file->p2l_info.end = -1; + file->p2l_info.checksum = NULL; + file->pool = NULL; + file->owner = result_pool; return file; } @@ -68,8 +112,8 @@ init_revision_file(svn_fs_t *fs, { svn_fs_x__revision_file_t *file = create_revision_file(fs, result_pool); - file->is_packed = svn_fs_x__is_packed_rev(fs, revision); - file->start_revision = svn_fs_x__packed_base_rev(fs, revision); + file->file_info.is_packed = svn_fs_x__is_packed_rev(fs, revision); + file->file_info.start_revision = svn_fs_x__packed_base_rev(fs, revision); return file; } @@ -137,20 +181,31 @@ auto_make_writable(const char *path, return SVN_NO_ERROR; } -/* Core implementation of svn_fs_fs__open_pack_or_rev_file working on an +/* Return the pool to be used for allocations with FILE. + Lazily created that pool upon the first call. */ +static apr_pool_t * +get_file_pool(svn_fs_x__revision_file_t *file) +{ + if (file->pool == NULL) + file->pool = svn_pool_create(file->owner); + + return file->pool; +} + +/* Core implementation of svn_fs_x__open_pack_or_rev_file working on an * existing, initialized FILE structure. If WRITABLE is TRUE, give write * access to the file - temporarily resetting the r/o state if necessary. */ static svn_error_t * open_pack_or_rev_file(svn_fs_x__revision_file_t *file, - svn_fs_t *fs, - svn_revnum_t rev, svn_boolean_t writable, - apr_pool_t *result_pool, apr_pool_t *scratch_pool) { svn_error_t *err; svn_boolean_t retry = FALSE; + svn_fs_t *fs = file->fs; + svn_revnum_t rev = file->file_info.start_revision; + apr_pool_t *file_pool = get_file_pool(file); do { @@ -161,19 +216,19 @@ open_pack_or_rev_file(svn_fs_x__revision_file_t *file, : APR_READ | APR_BUFFERED; /* We may have to *temporarily* enable write access. */ - err = writable ? auto_make_writable(path, result_pool, scratch_pool) + err = writable ? auto_make_writable(path, file_pool, scratch_pool) : SVN_NO_ERROR; /* open the revision file in buffered r/o or r/w mode */ if (!err) err = svn_io_file_open(&apr_file, path, flags, APR_OS_DEFAULT, - result_pool); + file_pool); if (!err) { file->file = apr_file; file->stream = svn_stream_from_aprfile2(apr_file, TRUE, - result_pool); + file_pool); return SVN_NO_ERROR; } @@ -191,7 +246,7 @@ open_pack_or_rev_file(svn_fs_x__revision_file_t *file, /* We failed for the first time. Refresh cache & retry. */ SVN_ERR(svn_fs_x__update_min_unpacked_rev(fs, scratch_pool)); - file->start_revision = svn_fs_x__packed_base_rev(fs, rev); + file->file_info.start_revision = svn_fs_x__packed_base_rev(fs, rev); retry = TRUE; } @@ -206,39 +261,52 @@ open_pack_or_rev_file(svn_fs_x__revision_file_t *file, } svn_error_t * -svn_fs_x__open_pack_or_rev_file(svn_fs_x__revision_file_t **file, - svn_fs_t *fs, +svn_fs_x__rev_file_init(svn_fs_x__revision_file_t **file, + svn_fs_t *fs, + svn_revnum_t rev, + apr_pool_t *result_pool) +{ + *file = init_revision_file(fs, rev, result_pool); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_fs_x__rev_file_open_writable(svn_fs_x__revision_file_t** file, + svn_fs_t* fs, svn_revnum_t rev, - apr_pool_t *result_pool, + apr_pool_t* result_pool, apr_pool_t *scratch_pool) { *file = init_revision_file(fs, rev, result_pool); - return svn_error_trace(open_pack_or_rev_file(*file, fs, rev, FALSE, - result_pool, scratch_pool)); + return svn_error_trace(open_pack_or_rev_file(*file, TRUE, scratch_pool)); } -svn_error_t * -svn_fs_x__open_pack_or_rev_file_writable(svn_fs_x__revision_file_t** file, - svn_fs_t* fs, - svn_revnum_t rev, - apr_pool_t* result_pool, - apr_pool_t *scratch_pool) +/* If the revision file in FILE has not been opened, yet, do it now. */ +static svn_error_t * +auto_open(svn_fs_x__revision_file_t *file) { - *file = init_revision_file(fs, rev, result_pool); - return svn_error_trace(open_pack_or_rev_file(*file, fs, rev, TRUE, - result_pool, scratch_pool)); + if (file->file == NULL) + SVN_ERR(open_pack_or_rev_file(file, FALSE, get_file_pool(file))); + + return SVN_NO_ERROR; } -svn_error_t * -svn_fs_x__auto_read_footer(svn_fs_x__revision_file_t *file) +/* If the footer data in FILE has not been read, yet, do so now. + * Index locations will only be read upon request as we assume they get + * cached and the FILE is usually used for REP data access only. + * Hence, the separate step. + */ +static svn_error_t * +auto_read_footer(svn_fs_x__revision_file_t *file) { - if (file->l2p_offset == -1) + if (file->l2p_info.start == -1) { apr_off_t filesize = 0; unsigned char footer_length; svn_stringbuf_t *footer; /* Determine file size. */ + SVN_ERR(auto_open(file)); SVN_ERR(svn_io_file_seek(file->file, APR_END, &filesize, file->pool)); /* Read last byte (containing the length of the footer). */ @@ -258,22 +326,25 @@ svn_fs_x__auto_read_footer(svn_fs_x__revision_file_t *file) footer->data[footer->len] = '\0'; /* Extract index locations. */ - SVN_ERR(svn_fs_x__parse_footer(&file->l2p_offset, &file->l2p_checksum, - &file->p2l_offset, &file->p2l_checksum, - footer, file->start_revision, - file->pool)); - file->footer_offset = filesize - footer_length - 1; + SVN_ERR(svn_fs_x__parse_footer(&file->l2p_info.start, + &file->l2p_info.checksum, + &file->p2l_info.start, + &file->p2l_info.checksum, + footer, file->file_info.start_revision, + filesize - footer_length - 1, file->pool)); + file->l2p_info.end = file->p2l_info.start; + file->p2l_info.end = filesize - footer_length - 1; } return SVN_NO_ERROR; } svn_error_t * -svn_fs_x__open_proto_rev_file(svn_fs_x__revision_file_t **file, - svn_fs_t *fs, - svn_fs_x__txn_id_t txn_id, - apr_pool_t* result_pool, - apr_pool_t *scratch_pool) +svn_fs_x__rev_file_open_proto_rev(svn_fs_x__revision_file_t **file, + svn_fs_t *fs, + svn_fs_x__txn_id_t txn_id, + apr_pool_t* result_pool, + apr_pool_t *scratch_pool) { apr_file_t *apr_file; SVN_ERR(svn_io_file_open(&apr_file, @@ -282,12 +353,12 @@ svn_fs_x__open_proto_rev_file(svn_fs_x__revision_file_t **file, APR_READ | APR_BUFFERED, APR_OS_DEFAULT, result_pool)); - return svn_error_trace(svn_fs_x__wrap_temp_rev_file(file, fs, apr_file, + return svn_error_trace(svn_fs_x__rev_file_wrap_temp(file, fs, apr_file, result_pool)); } svn_error_t * -svn_fs_x__wrap_temp_rev_file(svn_fs_x__revision_file_t **file, +svn_fs_x__rev_file_wrap_temp(svn_fs_x__revision_file_t **file, svn_fs_t *fs, apr_file_t *temp_file, apr_pool_t *result_pool) @@ -299,18 +370,170 @@ svn_fs_x__wrap_temp_rev_file(svn_fs_x__revision_file_t **file, return SVN_NO_ERROR; } +svn_error_t * +svn_fs_x__rev_file_info(svn_fs_x__rev_file_info_t *info, + svn_fs_x__revision_file_t *file) +{ + SVN_ERR(auto_open(file)); + + *info = file->file_info; + return SVN_NO_ERROR; +} + +svn_error_t * +svn_fs_x__rev_file_name(const char **filename, + svn_fs_x__revision_file_t *file, + apr_pool_t *result_pool) +{ + SVN_ERR(auto_open(file)); + + return svn_error_trace(svn_io_file_name_get(filename, file->file, + result_pool)); +} + +svn_error_t * +svn_fs_x__rev_file_stream(svn_stream_t **stream, + svn_fs_x__revision_file_t *file) +{ + SVN_ERR(auto_open(file)); + + *stream = file->stream; + return SVN_NO_ERROR; +} + +svn_error_t * +svn_fs_x__rev_file_get(apr_file_t **apr_file, + svn_fs_x__revision_file_t *file) +{ + SVN_ERR(auto_open(file)); + + *apr_file = file->file; + return SVN_NO_ERROR; +} + +svn_error_t * +svn_fs_x__rev_file_l2p_index(svn_fs_x__packed_number_stream_t **stream, + svn_fs_x__revision_file_t *file) +{ + if (file->l2p_stream == NULL) + { + SVN_ERR(auto_read_footer(file)); + SVN_ERR(svn_fs_x__packed_stream_open(&file->l2p_stream, + file->file, + file->l2p_info.start, + file->l2p_info.end, + SVN_FS_X__L2P_STREAM_PREFIX, + (apr_size_t)file->block_size, + file->pool, + file->pool)); + } + + *stream = file->l2p_stream; + return SVN_NO_ERROR; +} + +svn_error_t * +svn_fs_x__rev_file_p2l_index(svn_fs_x__packed_number_stream_t **stream, + svn_fs_x__revision_file_t *file) +{ + if (file->p2l_stream== NULL) + { + SVN_ERR(auto_read_footer(file)); + SVN_ERR(svn_fs_x__packed_stream_open(&file->p2l_stream, + file->file, + file->p2l_info.start, + file->p2l_info.end, + SVN_FS_X__P2L_STREAM_PREFIX, + (apr_size_t)file->block_size, + file->pool, + file->pool)); + } + + *stream = file->p2l_stream; + return SVN_NO_ERROR; +} + +svn_error_t * +svn_fs_x__rev_file_l2p_info(svn_fs_x__index_info_t *info, + svn_fs_x__revision_file_t *file) +{ + SVN_ERR(auto_read_footer(file)); + *info = file->l2p_info; + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_fs_x__rev_file_p2l_info(svn_fs_x__index_info_t *info, + svn_fs_x__revision_file_t *file) +{ + SVN_ERR(auto_read_footer(file)); + *info = file->p2l_info; + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_fs_x__rev_file_data_size(svn_filesize_t *size, + svn_fs_x__revision_file_t *file) +{ + SVN_ERR(auto_read_footer(file)); + *size = file->l2p_info.start; + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_fs_x__rev_file_seek(svn_fs_x__revision_file_t *file, + apr_off_t *buffer_start, + apr_off_t offset) +{ + SVN_ERR(auto_open(file)); + return svn_error_trace(svn_io_file_aligned_seek(file->file, + file->block_size, + buffer_start, offset, + file->pool)); +} + +svn_error_t * +svn_fs_x__rev_file_offset(apr_off_t *offset, + svn_fs_x__revision_file_t *file) +{ + SVN_ERR(auto_open(file)); + return svn_error_trace(svn_io_file_get_offset(offset, file->file, + file->pool)); +} + +svn_error_t * +svn_fs_x__rev_file_read(svn_fs_x__revision_file_t *file, + void *buf, + apr_size_t nbytes) +{ + SVN_ERR(auto_open(file)); + return svn_error_trace(svn_io_file_read_full2(file->file, buf, nbytes, + NULL, NULL, file->pool)); +} + svn_error_t * svn_fs_x__close_revision_file(svn_fs_x__revision_file_t *file) { + /* Close sub-objects properly */ if (file->stream) SVN_ERR(svn_stream_close(file->stream)); if (file->file) SVN_ERR(svn_io_file_close(file->file, file->pool)); + /* Release the memory. */ + if (file->pool) + svn_pool_clear(file->pool); + + /* Reset pointers to objects previously allocated from FILE->POOL. */ file->file = NULL; file->stream = NULL; file->l2p_stream = NULL; file->p2l_stream = NULL; + /* Cause any index data getters to re-read the footer. */ + file->l2p_info.start = -1; return SVN_NO_ERROR; } diff --git a/subversion/libsvn_fs_x/rev_file.h b/subversion/libsvn_fs_x/rev_file.h index b96d0351883d..8fa791ab7ea8 100644 --- a/subversion/libsvn_fs_x/rev_file.h +++ b/subversion/libsvn_fs_x/rev_file.h @@ -26,11 +26,14 @@ #include "svn_fs.h" #include "id.h" -/* In format 7, index files must be read in sync with the respective - * revision / pack file. I.e. we must use packed index files for packed - * rev files and unpacked ones for non-packed rev files. So, the whole - * point is to open them with matching "is packed" setting in case some - * background pack process was run. +/* In FSX, index data must be read in sync with the respective revision / + * pack file. I.e. we must use packed index files for packed rev files and + * unpacked ones for non-packed rev files. So, the whole point is to open + * them with matching "is packed" setting in case some background pack + * process was run. + * + * Another thing that this allows us is to lazily open the file, i.e. open + * it upon first access. */ /* Opaque index stream type. @@ -38,11 +41,22 @@ typedef struct svn_fs_x__packed_number_stream_t svn_fs_x__packed_number_stream_t; -/* Data file, including indexes data, and associated properties for - * START_REVISION. As the FILE is kept open, background pack operations - * will not cause access to this file to fail. - */ -typedef struct svn_fs_x__revision_file_t +/* Location and content meta data for an index. */ +typedef struct svn_fs_x__index_info_t +{ + /* Offset within the pack / rev file at which the index data starts. */ + apr_off_t start; + + /* First offset behind the index data. */ + apr_off_t end; + + /* MD5 checksum on the whole on-disk representation of the index. */ + svn_checksum_t *checksum; + +} svn_fs_x__index_info_t; + +/* Location and content meta data for a revision / pack file. */ +typedef struct svn_fs_x__rev_file_info_t { /* first (potentially only) revision in the rev / pack file. * SVN_INVALID_REVNUM for txn proto-rev files. */ @@ -51,60 +65,24 @@ typedef struct svn_fs_x__revision_file_t /* the revision was packed when the first file / stream got opened */ svn_boolean_t is_packed; - /* rev / pack file */ - apr_file_t *file; +} svn_fs_x__rev_file_info_t; - /* stream based on FILE and not NULL exactly when FILE is not NULL */ - svn_stream_t *stream; +/* Data file, including indexes data, and associated properties for + * START_REVISION. As the FILE is kept open, background pack operations + * will not cause access to this file to fail. + */ +typedef struct svn_fs_x__revision_file_t svn_fs_x__revision_file_t; - /* the opened P2L index stream or NULL. Always NULL for txns. */ - svn_fs_x__packed_number_stream_t *p2l_stream; - - /* the opened L2P index stream or NULL. Always NULL for txns. */ - svn_fs_x__packed_number_stream_t *l2p_stream; - - /* Copied from FS->FFD->BLOCK_SIZE upon creation. It allows us to - * use aligned seek() without having the FS handy. */ - apr_off_t block_size; - - /* Offset within FILE at which the rev data ends and the L2P index - * data starts. Less than P2L_OFFSET. -1 if svn_fs_fs__auto_read_footer - * has not been called, yet. */ - apr_off_t l2p_offset; - - /* MD5 checksum on the whole on-disk representation of the L2P index. - * NULL if svn_fs_fs__auto_read_footer has not been called, yet. */ - svn_checksum_t *l2p_checksum; - - /* Offset within FILE at which the L2P index ends and the P2L index - * data starts. Greater than L2P_OFFSET. -1 if svn_fs_fs__auto_read_footer - * has not been called, yet. */ - apr_off_t p2l_offset; - - /* MD5 checksum on the whole on-disk representation of the P2L index. - * NULL if svn_fs_fs__auto_read_footer has not been called, yet. */ - svn_checksum_t *p2l_checksum; - - /* Offset within FILE at which the P2L index ends and the footer starts. - * Greater than P2L_OFFSET. -1 if svn_fs_fs__auto_read_footer has not - * been called, yet. */ - apr_off_t footer_offset; - - /* pool containing this object */ - apr_pool_t *pool; -} svn_fs_x__revision_file_t; - -/* Open the correct revision file for REV. If the filesystem FS has - * been packed, *FILE will be set to the packed file; otherwise, set *FILE - * to the revision file for REV. Return SVN_ERR_FS_NO_SUCH_REVISION if the - * file doesn't exist. Allocate *FILE in RESULT_POOL and use SCRATCH_POOL - * for temporaries. */ +/* Initialize the revision / pack file access structure in *FILE for reading + * revision REV from filesystem FS. The file will not be opened until the + * first call to any of the access functions. + * + * Allocate *FILE in RESULT_POOL. */ svn_error_t * -svn_fs_x__open_pack_or_rev_file(svn_fs_x__revision_file_t **file, - svn_fs_t *fs, - svn_revnum_t rev, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool); +svn_fs_x__rev_file_init(svn_fs_x__revision_file_t **file, + svn_fs_t *fs, + svn_revnum_t rev, + apr_pool_t *result_pool); /* Open the correct revision file for REV with read and write access. * If necessary, temporarily reset the file's read-only state. If the @@ -114,39 +92,107 @@ svn_fs_x__open_pack_or_rev_file(svn_fs_x__revision_file_t **file, * Return SVN_ERR_FS_NO_SUCH_REVISION if the file doesn't exist. * Allocate *FILE in RESULT_POOL and use SCRATCH_POOLfor temporaries. */ svn_error_t * -svn_fs_x__open_pack_or_rev_file_writable(svn_fs_x__revision_file_t **file, - svn_fs_t *fs, - svn_revnum_t rev, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool); - -/* If the footer data in FILE has not been read, yet, do so now. - * Index locations will only be read upon request as we assume they get - * cached and the FILE is usually used for REP data access only. - * Hence, the separate step. - */ -svn_error_t * -svn_fs_x__auto_read_footer(svn_fs_x__revision_file_t *file); +svn_fs_x__rev_file_open_writable(svn_fs_x__revision_file_t **file, + svn_fs_t *fs, + svn_revnum_t rev, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); /* Open the proto-rev file of transaction TXN_ID in FS and return it in *FILE. * Allocate *FILE in RESULT_POOL use and SCRATCH_POOL for temporaries.. */ svn_error_t * -svn_fs_x__open_proto_rev_file(svn_fs_x__revision_file_t **file, - svn_fs_t *fs, - svn_fs_x__txn_id_t txn_id, - apr_pool_t* result_pool, - apr_pool_t *scratch_pool); +svn_fs_x__rev_file_open_proto_rev(svn_fs_x__revision_file_t **file, + svn_fs_t *fs, + svn_fs_x__txn_id_t txn_id, + apr_pool_t* result_pool, + apr_pool_t *scratch_pool); /* Wrap the TEMP_FILE, used in the context of FS, into a revision file * struct, allocated in RESULT_POOL, and return it in *FILE. */ svn_error_t * -svn_fs_x__wrap_temp_rev_file(svn_fs_x__revision_file_t **file, +svn_fs_x__rev_file_wrap_temp(svn_fs_x__revision_file_t **file, svn_fs_t *fs, apr_file_t *temp_file, apr_pool_t *result_pool); -/* Close all files and streams in FILE. +/* Access functions */ + +/* Copy the L2P index info for FILE into *INFO. + */ +svn_error_t * +svn_fs_x__rev_file_info(svn_fs_x__rev_file_info_t *info, + svn_fs_x__revision_file_t *file); + +/* Convenience wrapper around svn_io_file_name_get. */ +svn_error_t * +svn_fs_x__rev_file_name(const char **filename, + svn_fs_x__revision_file_t *file, + apr_pool_t *result_pool); + +/* Set *STREAM to the shared stream object of FILE. + */ +svn_error_t * +svn_fs_x__rev_file_stream(svn_stream_t **stream, + svn_fs_x__revision_file_t *file); + +/* Set *APR_FILE to the shared file object of FILE. + */ +svn_error_t * +svn_fs_x__rev_file_get(apr_file_t **apr_file, + svn_fs_x__revision_file_t *file); + +/* Set *STREAM to the shared L2P data stream of FILE. + */ +svn_error_t * +svn_fs_x__rev_file_l2p_index(svn_fs_x__packed_number_stream_t **stream, + svn_fs_x__revision_file_t *file); + +/* Set *STREAM to the shared P2L data stream of FILE. + */ +svn_error_t * +svn_fs_x__rev_file_p2l_index(svn_fs_x__packed_number_stream_t **stream, + svn_fs_x__revision_file_t *file); + +/* Copy the L2P index info for FILE into *INFO. + */ +svn_error_t * +svn_fs_x__rev_file_l2p_info(svn_fs_x__index_info_t *info, + svn_fs_x__revision_file_t *file); + +/* Copy the P2L index info for FILE into *INFO. + */ +svn_error_t * +svn_fs_x__rev_file_p2l_info(svn_fs_x__index_info_t *info, + svn_fs_x__revision_file_t *file); + +/* Set *SIZE to the length of the revision data in FILE. + */ +svn_error_t * +svn_fs_x__rev_file_data_size(svn_filesize_t *size, + svn_fs_x__revision_file_t *file); + +/* File manipulation. */ + +/* Convenience wrapper around svn_io_file_aligned_seek. */ +svn_error_t * +svn_fs_x__rev_file_seek(svn_fs_x__revision_file_t *file, + apr_off_t *buffer_start, + apr_off_t offset); + +/* Convenience wrapper around svn_fs_x__get_file_offset. */ +svn_error_t * +svn_fs_x__rev_file_offset(apr_off_t *offset, + svn_fs_x__revision_file_t *file); + +/* Convenience wrapper around svn_io_file_read_full2. */ +svn_error_t * +svn_fs_x__rev_file_read(svn_fs_x__revision_file_t *file, + void *buf, + apr_size_t nbytes); + +/* Close all files and streams in FILE. They will be reopened automatically + * by any of the above access functions. */ svn_error_t * svn_fs_x__close_revision_file(svn_fs_x__revision_file_t *file); diff --git a/subversion/libsvn_fs_x/revprops.c b/subversion/libsvn_fs_x/revprops.c index 5bc62ccc1721..f98c04478f24 100644 --- a/subversion/libsvn_fs_x/revprops.c +++ b/subversion/libsvn_fs_x/revprops.c @@ -26,12 +26,16 @@ #include "svn_pools.h" #include "svn_hash.h" #include "svn_dirent_uri.h" +#include "svn_sorts.h" #include "fs_x.h" +#include "low_level.h" #include "revprops.h" #include "util.h" #include "transaction.h" +#include "private/svn_packed_data.h" +#include "private/svn_sorts_private.h" #include "private/svn_subr_private.h" #include "private/svn_string_private.h" #include "../libsvn_fs/fs-loader.h" @@ -48,102 +52,6 @@ giving up. */ #define GENERATION_READ_RETRY_COUNT 100 -/* Maximum size of the generation number file contents (including NUL). */ -#define CHECKSUMMED_NUMBER_BUFFER_LEN \ - (SVN_INT64_BUFFER_SIZE + 3 + APR_MD5_DIGESTSIZE * 2) - - -svn_error_t * -svn_fs_x__upgrade_pack_revprops(svn_fs_t *fs, - svn_fs_upgrade_notify_t notify_func, - void *notify_baton, - svn_cancel_func_t cancel_func, - void *cancel_baton, - apr_pool_t *scratch_pool) -{ - svn_fs_x__data_t *ffd = fs->fsap_data; - const char *revprops_shard_path; - const char *revprops_pack_file_dir; - apr_int64_t shard; - apr_int64_t first_unpacked_shard - = ffd->min_unpacked_rev / ffd->max_files_per_dir; - - apr_pool_t *iterpool = svn_pool_create(scratch_pool); - const char *revsprops_dir = svn_dirent_join(fs->path, PATH_REVPROPS_DIR, - scratch_pool); - int compression_level = ffd->compress_packed_revprops - ? SVN_DELTA_COMPRESSION_LEVEL_DEFAULT - : SVN_DELTA_COMPRESSION_LEVEL_NONE; - - /* first, pack all revprops shards to match the packed revision shards */ - for (shard = 0; shard < first_unpacked_shard; ++shard) - { - svn_pool_clear(iterpool); - - revprops_pack_file_dir = svn_dirent_join(revsprops_dir, - apr_psprintf(iterpool, - "%" APR_INT64_T_FMT PATH_EXT_PACKED_SHARD, - shard), - iterpool); - revprops_shard_path = svn_dirent_join(revsprops_dir, - apr_psprintf(iterpool, "%" APR_INT64_T_FMT, shard), - iterpool); - - SVN_ERR(svn_fs_x__pack_revprops_shard(revprops_pack_file_dir, - revprops_shard_path, - shard, ffd->max_files_per_dir, - (int)(0.9 * ffd->revprop_pack_size), - compression_level, - cancel_func, cancel_baton, iterpool)); - if (notify_func) - SVN_ERR(notify_func(notify_baton, shard, - svn_fs_upgrade_pack_revprops, iterpool)); - } - - svn_pool_destroy(iterpool); - - return SVN_NO_ERROR; -} - -svn_error_t * -svn_fs_x__upgrade_cleanup_pack_revprops(svn_fs_t *fs, - svn_fs_upgrade_notify_t notify_func, - void *notify_baton, - svn_cancel_func_t cancel_func, - void *cancel_baton, - apr_pool_t *scratch_pool) -{ - svn_fs_x__data_t *ffd = fs->fsap_data; - const char *revprops_shard_path; - apr_int64_t shard; - apr_int64_t first_unpacked_shard - = ffd->min_unpacked_rev / ffd->max_files_per_dir; - - apr_pool_t *iterpool = svn_pool_create(scratch_pool); - const char *revsprops_dir = svn_dirent_join(fs->path, PATH_REVPROPS_DIR, - scratch_pool); - - /* delete the non-packed revprops shards afterwards */ - for (shard = 0; shard < first_unpacked_shard; ++shard) - { - svn_pool_clear(iterpool); - - revprops_shard_path = svn_dirent_join(revsprops_dir, - apr_psprintf(iterpool, "%" APR_INT64_T_FMT, shard), - iterpool); - SVN_ERR(svn_fs_x__delete_revprops_shard(revprops_shard_path, - shard, ffd->max_files_per_dir, - cancel_func, cancel_baton, - iterpool)); - if (notify_func) - SVN_ERR(notify_func(notify_baton, shard, - svn_fs_upgrade_cleanup_revprops, iterpool)); - } - - svn_pool_destroy(iterpool); - - return SVN_NO_ERROR; -} /* Revprop caching management. * @@ -159,16 +67,7 @@ svn_fs_x__upgrade_cleanup_pack_revprops(svn_fs_t *fs, * as keys with the generation being incremented upon every revprop change. * Since the cache is process-local, the generation needs to be tracked * for at least as long as the process lives but may be reset afterwards. - * - * We track the revprop generation in a persistent, unbuffered file that - * we may keep open for the lifetime of the svn_fs_t. It is the OS' - * responsibility to provide us with the latest contents upon read. To - * detect incomplete updates due to non-atomic reads, we put a MD5 checksum - * next to the actual generation number and verify that it matches. - * - * Since we cannot guarantee that the OS will provide us with up-to-date - * data buffers for open files, we re-open and re-read the file before - * modifying it. This will prevent lost updates. + * We track the revprop generation in a file that. * * A race condition exists between switching to the modified revprop data * and bumping the generation number. In particular, the process may crash @@ -187,110 +86,6 @@ svn_fs_x__upgrade_cleanup_pack_revprops(svn_fs_t *fs, * after the crash, reader caches may be stale. */ -/* If the revprop generation file in FS is open, close it. This is a no-op - * if the file is not open. - */ -static svn_error_t * -close_revprop_generation_file(svn_fs_t *fs, - apr_pool_t *scratch_pool) -{ - svn_fs_x__data_t *ffd = fs->fsap_data; - if (ffd->revprop_generation_file) - { - SVN_ERR(svn_io_file_close(ffd->revprop_generation_file, scratch_pool)); - ffd->revprop_generation_file = NULL; - } - - return SVN_NO_ERROR; -} - -/* Make sure the revprop_generation member in FS is set. If READ_ONLY is - * set, open the file w/o write permission if the file is not open yet. - * The file is kept open if it has sufficient rights (or more) but will be - * closed and re-opened if it provided insufficient access rights. - * - * Call only for repos that support revprop caching. - */ -static svn_error_t * -open_revprop_generation_file(svn_fs_t *fs, - svn_boolean_t read_only, - apr_pool_t *scratch_pool) -{ - svn_fs_x__data_t *ffd = fs->fsap_data; - apr_int32_t flags = read_only ? APR_READ : (APR_READ | APR_WRITE); - - /* Close the current file handle if it has insufficient rights. */ - if ( ffd->revprop_generation_file - && (apr_file_flags_get(ffd->revprop_generation_file) & flags) != flags) - SVN_ERR(close_revprop_generation_file(fs, scratch_pool)); - - /* If not open already, open with sufficient rights. */ - if (ffd->revprop_generation_file == NULL) - { - const char *path = svn_fs_x__path_revprop_generation(fs, scratch_pool); - SVN_ERR(svn_io_file_open(&ffd->revprop_generation_file, path, - flags, APR_OS_DEFAULT, fs->pool)); - } - - return SVN_NO_ERROR; -} - -/* Return the textual representation of NUMBER and its checksum in *BUFFER. - */ -static svn_error_t * -checkedsummed_number(svn_stringbuf_t **buffer, - apr_int64_t number, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) -{ - svn_checksum_t *checksum; - const char *digest; - - char str[SVN_INT64_BUFFER_SIZE]; - apr_size_t len = svn__i64toa(str, number); - str[len] = 0; - - SVN_ERR(svn_checksum(&checksum, svn_checksum_md5, str, len, scratch_pool)); - digest = svn_checksum_to_cstring_display(checksum, scratch_pool); - - *buffer = svn_stringbuf_createf(result_pool, "%s %s\n", digest, str); - - return SVN_NO_ERROR; -} - -/* Extract the generation number from the text BUFFER of LEN bytes and - * verify it against the checksum in the same BUFFER. If they match, return - * the generation in *NUMBER. Otherwise, return an error. - * BUFFER does not need to be NUL-terminated. - */ -static svn_error_t * -verify_extract_number(apr_int64_t *number, - const char *buffer, - apr_size_t len, - apr_pool_t *scratch_pool) -{ - const char *digest_end = strchr(buffer, ' '); - - /* Does the buffer even contain checksum _and_ number? */ - if (digest_end != NULL) - { - svn_checksum_t *expected; - svn_checksum_t *actual; - - SVN_ERR(svn_checksum_parse_hex(&expected, svn_checksum_md5, buffer, - scratch_pool)); - SVN_ERR(svn_checksum(&actual, svn_checksum_md5, digest_end + 1, - (buffer + len) - (digest_end + 1), scratch_pool)); - - if (svn_checksum_match(expected, actual)) - return svn_error_trace(svn_cstring_atoi64(number, digest_end + 1)); - } - - /* Incomplete buffer or not a match. */ - return svn_error_create(SVN_ERR_FS_INVALID_GENERATION, NULL, - _("Invalid generation number data.")); -} - /* Read revprop generation as stored on disk for repository FS. The result is * returned in *CURRENT. Call only for repos that support revprop caching. */ @@ -299,40 +94,32 @@ read_revprop_generation_file(apr_int64_t *current, svn_fs_t *fs, apr_pool_t *scratch_pool) { - svn_fs_x__data_t *ffd = fs->fsap_data; apr_pool_t *iterpool = svn_pool_create(scratch_pool); - char buf[CHECKSUMMED_NUMBER_BUFFER_LEN]; - apr_size_t len; - apr_off_t offset = 0; int i; svn_error_t *err = SVN_NO_ERROR; + const char *path = svn_fs_x__path_revprop_generation(fs, scratch_pool); /* Retry in case of incomplete file buffer updates. */ for (i = 0; i < GENERATION_READ_RETRY_COUNT; ++i) { + svn_stringbuf_t *buf; + svn_error_clear(err); svn_pool_clear(iterpool); - /* If we can't even access the data, things are very wrong. - * Don't retry in that case. - */ - SVN_ERR(open_revprop_generation_file(fs, TRUE, iterpool)); - SVN_ERR(svn_io_file_seek(ffd->revprop_generation_file, APR_SET, &offset, - iterpool)); + /* Read the generation file. */ + err = svn_stringbuf_from_file2(&buf, path, iterpool); - len = sizeof(buf); - SVN_ERR(svn_io_read_length_line(ffd->revprop_generation_file, buf, &len, - iterpool)); - - /* Some data has been read. It will most likely be complete and - * consistent. Extract and verify anyway. */ - err = verify_extract_number(current, buf, len, iterpool); + /* If we could read the file, it should be complete due to our atomic + * file replacement scheme. */ if (!err) - break; - - /* Got unlucky and data was invalid. Retry. */ - SVN_ERR(close_revprop_generation_file(fs, iterpool)); + { + svn_stringbuf_strip_whitespace(buf); + SVN_ERR(svn_cstring_atoi64(current, buf->data)); + break; + } + /* Got unlucky the file was not available. Retry. */ #if APR_HAS_THREADS apr_thread_yield(); #else @@ -356,17 +143,21 @@ write_revprop_generation_file(svn_fs_t *fs, { svn_fs_x__data_t *ffd = fs->fsap_data; svn_stringbuf_t *buffer; - apr_off_t offset = 0; + const char *path = svn_fs_x__path_revprop_generation(fs, scratch_pool); - SVN_ERR(checkedsummed_number(&buffer, current, scratch_pool, scratch_pool)); + /* Invalidate our cached revprop generation in case the file operations + * below fail. */ + ffd->revprop_generation = -1; - SVN_ERR(open_revprop_generation_file(fs, FALSE, scratch_pool)); - SVN_ERR(svn_io_file_seek(ffd->revprop_generation_file, APR_SET, &offset, - scratch_pool)); - SVN_ERR(svn_io_file_write_full(ffd->revprop_generation_file, buffer->data, - buffer->len, NULL, scratch_pool)); - SVN_ERR(svn_io_file_flush_to_disk(ffd->revprop_generation_file, - scratch_pool)); + /* Write the new number. */ + buffer = svn_stringbuf_createf(scratch_pool, "%" APR_INT64_T_FMT "\n", + current); + SVN_ERR(svn_io_write_atomic2(path, buffer->data, buffer->len, + path /* copy_perms */, FALSE, + scratch_pool)); + + /* Remember it to spare us the re-read. */ + ffd->revprop_generation = current; return SVN_NO_ERROR; } @@ -375,49 +166,12 @@ svn_error_t * svn_fs_x__reset_revprop_generation_file(svn_fs_t *fs, apr_pool_t *scratch_pool) { - const char *path = svn_fs_x__path_revprop_generation(fs, scratch_pool); - svn_stringbuf_t *buffer; - - /* Unconditionally close the revprop generation file. - * Don't care about FS formats. This ensures consistent internal state. */ - SVN_ERR(close_revprop_generation_file(fs, scratch_pool)); - - /* Unconditionally remove any old revprop generation file. - * Don't care about FS formats. This ensures consistent on-disk state - * for old format repositories. */ - SVN_ERR(svn_io_remove_file2(path, TRUE, scratch_pool)); - - /* Write the initial revprop generation file contents, if supported by - * the current format. This ensures consistent on-disk state for new - * format repositories. */ - SVN_ERR(checkedsummed_number(&buffer, 0, scratch_pool, scratch_pool)); - SVN_ERR(svn_io_write_atomic(path, buffer->data, buffer->len, NULL, - scratch_pool)); - - /* ffd->revprop_generation_file will be re-opened on demand. */ + /* Write the initial revprop generation file contents. */ + SVN_ERR(write_revprop_generation_file(fs, 0, scratch_pool)); return SVN_NO_ERROR; } -/* Create an error object with the given MESSAGE and pass it to the - WARNING member of FS. Clears UNDERLYING_ERR. */ -static void -log_revprop_cache_init_warning(svn_fs_t *fs, - svn_error_t *underlying_err, - const char *message, - apr_pool_t *scratch_pool) -{ - svn_error_t *err = svn_error_createf( - SVN_ERR_FS_REVPROP_CACHE_INIT_FAILURE, - underlying_err, message, - svn_dirent_local_style(fs->path, scratch_pool)); - - if (fs->warning) - (fs->warning)(fs->warning_baton, err); - - svn_error_clear(err); -} - /* Test whether revprop cache and necessary infrastructure are available in FS. */ static svn_boolean_t @@ -425,29 +179,9 @@ has_revprop_cache(svn_fs_t *fs, apr_pool_t *scratch_pool) { svn_fs_x__data_t *ffd = fs->fsap_data; - svn_error_t *error; - /* is the cache (still) enabled? */ - if (ffd->revprop_cache == NULL) - return FALSE; - - /* try initialize our file-backed infrastructure */ - error = open_revprop_generation_file(fs, TRUE, scratch_pool); - if (error) - { - /* failure -> disable revprop cache for good */ - - ffd->revprop_cache = NULL; - log_revprop_cache_init_warning(fs, error, - "Revprop caching for '%s' disabled " - "because infrastructure for revprop " - "caching failed to initialize.", - scratch_pool); - - return FALSE; - } - - return TRUE; + /* is the cache enabled? */ + return ffd->revprop_cache != NULL; } /* Baton structure for revprop_generation_fixup. */ @@ -475,9 +209,6 @@ revprop_generation_fixup(void *void_baton, svn_fs_x__data_t *ffd = baton->fs->fsap_data; assert(ffd->has_write_lock); - /* Make sure we don't operate on stale OS buffers. */ - SVN_ERR(close_revprop_generation_file(baton->fs, scratch_pool)); - /* Maybe, either the original revprop writer or some other reader has already corrected / bumped the revprop generation. Thus, we need to read it again. However, we will now be the only ones changing @@ -498,12 +229,10 @@ revprop_generation_fixup(void *void_baton, return SVN_NO_ERROR; } -/* Read the current revprop generation and return it in *GENERATION. - Also, detect aborted / crashed writers and recover from that. - Use the access object in FS to set the shared mem values. */ +/* Read the current revprop generation of FS and its value in FS->FSAP_DATA. + Also, detect aborted / crashed writers and recover from that. */ static svn_error_t * -read_revprop_generation(apr_int64_t *generation, - svn_fs_t *fs, +read_revprop_generation(svn_fs_t *fs, apr_pool_t *scratch_pool) { apr_int64_t current = 0; @@ -548,60 +277,84 @@ read_revprop_generation(apr_int64_t *generation, } /* return the value we just got */ - *generation = current; + ffd->revprop_generation = current; return SVN_NO_ERROR; } +void +svn_fs_x__invalidate_revprop_generation(svn_fs_t *fs) +{ + svn_fs_x__data_t *ffd = fs->fsap_data; + ffd->revprop_generation = -1; +} + +/* Return TRUE if the revprop generation value in FS->FSAP_DATA is valid. */ +static svn_boolean_t +is_generation_valid(svn_fs_t *fs) +{ + svn_fs_x__data_t *ffd = fs->fsap_data; + return ffd->revprop_generation >= 0; +} + /* Set the revprop generation in FS to the next odd number to indicate - that there is a revprop write process under way. Return that value - in *GENERATION. If the change times out, readers shall recover from - that state & re-read revprops. + that there is a revprop write process under way. Update the value + in FS->FSAP_DATA accordingly. If the change times out, readers shall + recover from that state & re-read revprops. This is a no-op for repo formats that don't support revprop caching. */ static svn_error_t * -begin_revprop_change(apr_int64_t *generation, - svn_fs_t *fs, +begin_revprop_change(svn_fs_t *fs, apr_pool_t *scratch_pool) { svn_fs_x__data_t *ffd = fs->fsap_data; SVN_ERR_ASSERT(ffd->has_write_lock); - /* Close and re-open to make sure we read the latest data. */ - SVN_ERR(close_revprop_generation_file(fs, scratch_pool)); - SVN_ERR(open_revprop_generation_file(fs, FALSE, scratch_pool)); - /* Set the revprop generation to an odd value to indicate * that a write is in progress. */ - SVN_ERR(read_revprop_generation(generation, fs, scratch_pool)); - ++*generation; - SVN_ERR(write_revprop_generation_file(fs, *generation, scratch_pool)); + SVN_ERR(read_revprop_generation(fs, scratch_pool)); + ++ffd->revprop_generation; + SVN_ERR_ASSERT(ffd->revprop_generation % 2); + SVN_ERR(write_revprop_generation_file(fs, ffd->revprop_generation, + scratch_pool)); return SVN_NO_ERROR; } /* Set the revprop generation in FS to the next even generation after - the odd value in GENERATION to indicate that + the odd value in FS->FSAP_DATA to indicate that a) readers shall re-read revprops, and b) the write process has been completed (no recovery required). This is a no-op for repo formats that don't support revprop caching. */ static svn_error_t * end_revprop_change(svn_fs_t *fs, - apr_int64_t generation, apr_pool_t *scratch_pool) { svn_fs_x__data_t *ffd = fs->fsap_data; SVN_ERR_ASSERT(ffd->has_write_lock); - SVN_ERR_ASSERT(generation % 2); + SVN_ERR_ASSERT(ffd->revprop_generation % 2); /* Set the revprop generation to an even value to indicate * that a write has been completed. Since we held the write * lock, nobody else could have updated the file contents. */ - SVN_ERR(write_revprop_generation_file(fs, generation + 1, scratch_pool)); + SVN_ERR(write_revprop_generation_file(fs, ffd->revprop_generation + 1, + scratch_pool)); return SVN_NO_ERROR; } +/* Represents an entry in the packed revprop manifest. + * There is one such entry per pack file. */ +typedef struct manifest_entry_t +{ + /* First revision in the pack file. */ + svn_revnum_t start_rev; + + /* Tag (a counter) appended to the file name to distinguish it from + outdated ones. */ + apr_uint64_t tag; +} manifest_entry_t; + /* Container for all data required to access the packed revprop file * for a given REVISION. This structure will be filled incrementally * by read_pack_revprops() its sub-routines. @@ -611,9 +364,6 @@ typedef struct packed_revprops_t /* revision number to read (not necessarily the first in the pack) */ svn_revnum_t revision; - /* current revprop generation. Used when populating the revprop cache */ - apr_int64_t generation; - /* the actual revision properties */ apr_hash_t *properties; @@ -622,8 +372,8 @@ typedef struct packed_revprops_t apr_size_t serialized_size; - /* name of the pack file (without folder path) */ - const char *filename; + /* manifest entry describing the pack file */ + manifest_entry_t entry; /* packed shard folder path */ const char *folder; @@ -631,34 +381,19 @@ typedef struct packed_revprops_t /* sum of values in SIZES */ apr_size_t total_size; - /* first revision in the pack (>= MANIFEST_START) */ - svn_revnum_t start_revision; - - /* size of the revprops in PACKED_REVPROPS */ - apr_array_header_t *sizes; - - /* offset of the revprops in PACKED_REVPROPS */ - apr_array_header_t *offsets; - - - /* concatenation of the serialized representation of all revprops - * in the pack, i.e. the pack content without header and compression */ - svn_stringbuf_t *packed_revprops; - - /* First revision covered by MANIFEST. - * Will equal the shard start revision or 1, for the 1st shard. */ - svn_revnum_t manifest_start; + /* Array of svn_string_t, containing the serialized revprops for + * REVISION * I. */ + apr_array_header_t *revprops; /* content of the manifest. - * Maps long(rev - MANIFEST_START) to const char* pack file name */ + * Sorted list of manifest_entry_t. */ apr_array_header_t *manifest; } packed_revprops_t; /* Parse the serialized revprops in CONTENT and return them in *PROPERTIES. * Also, put them into the revprop cache, if activated, for future use. * Three more parameters are being used to update the revprop cache: FS is - * our file system, the revprops belong to REVISION and the global revprop - * GENERATION is used as well. + * our file system, the revprops belong to REVISION. * * The returned hash will be allocated in RESULT_POOL, SCRATCH_POOL is * being used for temporary allocations. @@ -667,23 +402,23 @@ static svn_error_t * parse_revprop(apr_hash_t **properties, svn_fs_t *fs, svn_revnum_t revision, - apr_int64_t generation, - svn_string_t *content, + const svn_string_t *content, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - svn_stream_t *stream = svn_stream_from_string(content, scratch_pool); - *properties = apr_hash_make(result_pool); + SVN_ERR_W(svn_fs_x__parse_properties(properties, content, result_pool), + apr_psprintf(scratch_pool, "Failed to parse revprops for r%ld.", + revision)); - SVN_ERR(svn_hash_read2(*properties, stream, SVN_HASH_TERMINATOR, - result_pool)); if (has_revprop_cache(fs, scratch_pool)) { svn_fs_x__data_t *ffd = fs->fsap_data; svn_fs_x__pair_cache_key_t key = { 0 }; + SVN_ERR_ASSERT(is_generation_valid(fs)); + key.revision = revision; - key.second = generation; + key.second = ffd->revprop_generation; SVN_ERR(svn_cache__set(ffd->revprop_cache, &key, *properties, scratch_pool)); } @@ -691,9 +426,37 @@ parse_revprop(apr_hash_t **properties, return SVN_NO_ERROR; } +/* Verify the checksum attached to CONTENT and remove it. + * Use SCRATCH_POOL for temporary allocations. + */ +static svn_error_t * +verify_checksum(svn_stringbuf_t *content, + apr_pool_t *scratch_pool) +{ + const apr_byte_t *digest; + svn_checksum_t *actual, *expected; + + /* Verify the checksum. */ + if (content->len < sizeof(apr_uint32_t)) + return svn_error_create(SVN_ERR_CORRUPT_PACKED_DATA, NULL, + "File too short"); + + content->len -= sizeof(apr_uint32_t); + digest = (apr_byte_t *)content->data + content->len; + + expected = svn_checksum__from_digest_fnv1a_32x4(digest, scratch_pool); + SVN_ERR(svn_checksum(&actual, svn_checksum_fnv1a_32x4, content->data, + content->len, scratch_pool)); + + if (!svn_checksum_match(actual, expected)) + SVN_ERR(svn_checksum_mismatch_err(expected, actual, scratch_pool, + "checksum mismatch")); + + return SVN_NO_ERROR; +} + /* Read the non-packed revprops for revision REV in FS, put them into the - * revprop cache if activated and return them in *PROPERTIES. GENERATION - * is the current revprop generation. + * revprop cache if activated and return them in *PROPERTIES. * * If the data could not be read due to an otherwise recoverable error, * leave *PROPERTIES unchanged. No error will be returned in that case. @@ -704,7 +467,6 @@ static svn_error_t * read_non_packed_revprop(apr_hash_t **properties, svn_fs_t *fs, svn_revnum_t rev, - apr_int64_t generation, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { @@ -726,26 +488,193 @@ read_non_packed_revprop(apr_hash_t **properties, } if (content) - SVN_ERR(parse_revprop(properties, fs, rev, generation, - svn_stringbuf__morph_into_string(content), - result_pool, iterpool)); + { + svn_string_t *as_string; + + /* Consistency check. */ + SVN_ERR_W(verify_checksum(content, scratch_pool), + apr_psprintf(scratch_pool, + "Revprop file for r%ld is corrupt", + rev)); + + /* The contents string becomes part of the *PROPERTIES structure, i.e. + * we must make sure it lives at least as long as the latter. */ + as_string = svn_string_create_from_buf(content, result_pool); + SVN_ERR(parse_revprop(properties, fs, rev, as_string, + result_pool, iterpool)); + } svn_pool_clear(iterpool); return SVN_NO_ERROR; } -/* Return the minimum length of any packed revprop file name in REVPROPS. */ -static apr_size_t -get_min_filename_len(packed_revprops_t *revprops) +/* Serialize ROOT into FILE and append a checksum to it. + * Use SCRATCH_POOL for temporary allocations. + */ +static svn_error_t * +write_packed_data_checksummed(svn_packed__data_root_t *root, + apr_file_t *file, + apr_pool_t *scratch_pool) { - char number_buffer[SVN_INT64_BUFFER_SIZE]; + svn_checksum_t *checksum; + svn_stream_t *stream; - /* The revprop filenames have the format . - with being - * at least the first rev in the shard and having at least one - * digit. Thus, the minimum is 2 + #decimal places in the start rev. - */ - return svn__i64toa(number_buffer, revprops->manifest_start) + 2; + stream = svn_stream_from_aprfile2(file, TRUE, scratch_pool); + stream = svn_checksum__wrap_write_stream(&checksum, stream, + svn_checksum_fnv1a_32x4, + scratch_pool); + SVN_ERR(svn_packed__data_write(stream, root, scratch_pool)); + SVN_ERR(svn_stream_close(stream)); + + /* Append the checksum */ + SVN_ERR(svn_io_file_write_full(file, checksum->digest, + svn_checksum_size(checksum), NULL, + scratch_pool)); + + return SVN_NO_ERROR; +} + +/* Serialize the packed revprops MANIFEST into FILE. + * Use SCRATCH_POOL for temporary allocations. + */ +static svn_error_t * +write_manifest(apr_file_t *file, + const apr_array_header_t *manifest, + apr_pool_t *scratch_pool) +{ + int i; + svn_packed__data_root_t *root = svn_packed__data_create_root(scratch_pool); + + /* one top-level stream per struct element */ + svn_packed__int_stream_t *start_rev_stream + = svn_packed__create_int_stream(root, TRUE, FALSE); + svn_packed__int_stream_t *tag_stream + = svn_packed__create_int_stream(root, FALSE, FALSE); + + /* serialize ENTRIES */ + for (i = 0; i < manifest->nelts; ++i) + { + manifest_entry_t *entry = &APR_ARRAY_IDX(manifest, i, manifest_entry_t); + svn_packed__add_uint(start_rev_stream, entry->start_rev); + svn_packed__add_uint(tag_stream, entry->tag); + } + + /* Write to file and calculate the checksum. */ + SVN_ERR(write_packed_data_checksummed(root, file, scratch_pool)); + + return SVN_NO_ERROR; +} + +/* Read *ROOT from CONTENT and verify its checksum. Allocate *ROOT in + * RESULT_POOL and use SCRATCH_POOL for temporary allocations. + */ +static svn_error_t * +read_packed_data_checksummed(svn_packed__data_root_t **root, + svn_stringbuf_t *content, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_stream_t *stream; + + SVN_ERR(verify_checksum(content, scratch_pool)); + + stream = svn_stream_from_stringbuf(content, scratch_pool); + SVN_ERR(svn_packed__data_read(root, stream, result_pool, scratch_pool)); + + return SVN_NO_ERROR; +} + +/* Read the packed revprops manifest from the CONTENT buffer and return it + * in *MANIFEST, allocated in RESULT_POOL. REVISION is the revision number + * to put into error messages. Use SCRATCH_POOL for temporary allocations. + */ +static svn_error_t * +read_manifest(apr_array_header_t **manifest, + svn_stringbuf_t *content, + svn_revnum_t revision, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + apr_size_t i; + apr_size_t count; + + svn_packed__data_root_t *root; + svn_packed__int_stream_t *start_rev_stream; + svn_packed__int_stream_t *tag_stream; + + /* Verify the checksum and decode packed data. */ + SVN_ERR_W(read_packed_data_checksummed(&root, content, result_pool, + scratch_pool), + apr_psprintf(scratch_pool, + "Revprop manifest file for r%ld is corrupt", + revision)); + + /* get streams */ + start_rev_stream = svn_packed__first_int_stream(root); + tag_stream = svn_packed__next_int_stream(start_rev_stream); + + /* read ids array */ + count = svn_packed__int_count(start_rev_stream); + *manifest = apr_array_make(result_pool, (int)count, + sizeof(manifest_entry_t)); + + for (i = 0; i < count; ++i) + { + manifest_entry_t *entry = apr_array_push(*manifest); + entry->start_rev = (svn_revnum_t)svn_packed__get_int(start_rev_stream); + entry->tag = svn_packed__get_uint(tag_stream); + } + + return SVN_NO_ERROR; +} + +/* Implements the standard comparison function signature comparing the + * manifest_entry_t(lhs).start_rev to svn_revnum_t(rhs). */ +static int +compare_entry_revision(const void *lhs, + const void *rhs) +{ + const manifest_entry_t *entry = lhs; + const svn_revnum_t *revision = rhs; + + if (entry->start_rev < *revision) + return -1; + + return entry->start_rev == *revision ? 0 : 1; +} + +/* Return the index in MANIFEST that has the info for the pack file + * containing REVISION. */ +static int +get_entry(apr_array_header_t *manifest, + svn_revnum_t revision) +{ + manifest_entry_t *entry; + int idx = svn_sort__bsearch_lower_bound(manifest, &revision, + compare_entry_revision); + + assert(manifest->nelts > 0); + if (idx >= manifest->nelts) + return idx - 1; + + entry = &APR_ARRAY_IDX(manifest, idx, manifest_entry_t); + if (entry->start_rev > revision && idx > 0) + return idx - 1; + + return idx; +} + +/* Return the full path of the revprop pack file given by ENTRY within + * REVPROPS. Allocate the result in RESULT_POOL. */ +static const char * +get_revprop_pack_filepath(packed_revprops_t *revprops, + manifest_entry_t *entry, + apr_pool_t *result_pool) +{ + const char *filename = apr_psprintf(result_pool, "%ld.%" APR_UINT64_T_FMT, + entry->start_rev, entry->tag); + return svn_dirent_join(revprops->folder, filename, result_pool); } /* Given FS and REVPROPS->REVISION, fill the FILENAME, FOLDER and MANIFEST @@ -761,98 +690,59 @@ get_revprop_packname(svn_fs_t *fs, svn_fs_x__data_t *ffd = fs->fsap_data; svn_stringbuf_t *content = NULL; const char *manifest_file_path; - int idx, rev_count; - char *buffer, *buffer_end; - const char **filenames, **filenames_end; - apr_size_t min_filename_len; + int idx; + svn_revnum_t previous_start_rev; + int i; /* Determine the dimensions. Rev 0 is excluded from the first shard. */ - rev_count = ffd->max_files_per_dir; - revprops->manifest_start + int rev_count = ffd->max_files_per_dir; + svn_revnum_t manifest_start = revprops->revision - (revprops->revision % rev_count); - if (revprops->manifest_start == 0) + if (manifest_start == 0) { - ++revprops->manifest_start; + ++manifest_start; --rev_count; } - revprops->manifest = apr_array_make(result_pool, rev_count, - sizeof(const char*)); - - /* No line in the file can be less than this number of chars long. */ - min_filename_len = get_min_filename_len(revprops); - /* Read the content of the manifest file */ - revprops->folder - = svn_fs_x__path_revprops_pack_shard(fs, revprops->revision, result_pool); + revprops->folder = svn_fs_x__path_pack_shard(fs, revprops->revision, + result_pool); manifest_file_path = svn_dirent_join(revprops->folder, PATH_MANIFEST, result_pool); - SVN_ERR(svn_fs_x__read_content(&content, manifest_file_path, result_pool)); + SVN_ERR(read_manifest(&revprops->manifest, content, revprops->revision, + result_pool, scratch_pool)); - /* There CONTENT must have a certain minimal size and there no - * unterminated lines at the end of the file. Both guarantees also - * simplify the parser loop below. - */ - if ( content->len < rev_count * (min_filename_len + 1) - || content->data[content->len - 1] != '\n') - return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, - _("Packed revprop manifest for r%ld not " - "properly terminated"), revprops->revision); + /* Verify the manifest data. */ + if (revprops->manifest->nelts == 0) + return svn_error_createf(SVN_ERR_FS_CORRUPT_REVPROP_MANIFEST, NULL, + "Revprop manifest for r%ld is empty", + revprops->revision); - /* Chop (parse) the manifest CONTENT into filenames, one per line. - * We only have to replace all newlines with NUL and add all line - * starts to REVPROPS->MANIFEST. - * - * There must be exactly REV_COUNT lines and that is the number of - * lines we parse from BUFFER to FILENAMES. Set the end pointer for - * the source BUFFER such that BUFFER+MIN_FILENAME_LEN is still valid - * BUFFER_END is always valid due to CONTENT->LEN > MIN_FILENAME_LEN. - * - * Please note that this loop is performance critical for e.g. 'svn log'. - * It is run 1000x per revprop access, i.e. per revision and about - * 50 million times per sec (and CPU core). - */ - for (filenames = (const char **)revprops->manifest->elts, - filenames_end = filenames + rev_count, - buffer = content->data, - buffer_end = buffer + content->len - min_filename_len; - (filenames < filenames_end) && (buffer < buffer_end); - ++filenames) + previous_start_rev = 0; + for (i = 0; i < revprops->manifest->nelts; ++i) { - /* BUFFER always points to the start of the next line / filename. */ - *filenames = buffer; + svn_revnum_t start_rev = APR_ARRAY_IDX(revprops->manifest, i, + manifest_entry_t).start_rev; + if ( start_rev < manifest_start + || start_rev >= manifest_start + rev_count) + return svn_error_createf(SVN_ERR_FS_CORRUPT_REVPROP_MANIFEST, NULL, + "Revprop manifest for r%ld contains " + "out-of-range revision r%ld", + revprops->revision, start_rev); - /* Find the next EOL. This is guaranteed to stay within the CONTENT - * buffer because we left enough room after BUFFER_END and we know - * we will always see a newline as the last non-NUL char. */ - buffer += min_filename_len; - while (*buffer != '\n') - ++buffer; + if (start_rev < previous_start_rev) + return svn_error_createf(SVN_ERR_FS_CORRUPT_REVPROP_MANIFEST, NULL, + "Entries in revprop manifest for r%ld " + "are not ordered", revprops->revision); - /* Found EOL. Turn it into the filename terminator and move BUFFER - * to the start of the next line or CONTENT buffer end. */ - *buffer = '\0'; - ++buffer; + previous_start_rev = start_rev; } - /* We must have reached the end of both buffers. */ - if (buffer < content->data + content->len) - return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, - _("Packed revprop manifest for r%ld " - "has too many entries"), revprops->revision); - - if (filenames < filenames_end) - return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, - _("Packed revprop manifest for r%ld " - "has too few entries"), revprops->revision); - - /* The target array has now exactly one entry per revision. */ - revprops->manifest->nelts = rev_count; - - /* Now get the file name */ - idx = (int)(revprops->revision - revprops->manifest_start); - revprops->filename = APR_ARRAY_IDX(revprops->manifest, idx, const char*); + /* Now get the pack file description */ + idx = get_entry(revprops->manifest, revprops->revision); + revprops->entry = APR_ARRAY_IDX(revprops->manifest, idx, + manifest_entry_t); return SVN_NO_ERROR; } @@ -868,10 +758,9 @@ same_shard(svn_fs_t *fs, return (r1 / ffd->max_files_per_dir) == (r2 / ffd->max_files_per_dir); } -/* Given FS and the full packed file content in REVPROPS->PACKED_REVPROPS, - * fill the START_REVISION member, and make PACKED_REVPROPS point to the - * first serialized revprop. If READ_ALL is set, initialize the SIZES - * and OFFSETS members as well. +/* Given FS and the full packed file content in CONTENT and make + * PACKED_REVPROPS point to the first serialized revprop. If READ_ALL + * is set, initialize the SIZES and OFFSETS members as well. * * Parse the revprops for REVPROPS->REVISION and set the PROPERTIES as * well as the SERIALIZED_SIZE member. If revprop caching has been @@ -880,33 +769,31 @@ same_shard(svn_fs_t *fs, static svn_error_t * parse_packed_revprops(svn_fs_t *fs, packed_revprops_t *revprops, + svn_stringbuf_t *content, svn_boolean_t read_all, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - svn_stream_t *stream; - apr_int64_t first_rev, count, i; - apr_off_t offset; - const char *header_end; + apr_size_t count, i; apr_pool_t *iterpool = svn_pool_create(scratch_pool); svn_boolean_t cache_all = has_revprop_cache(fs, scratch_pool); + svn_packed__data_root_t *root; + svn_packed__byte_stream_t *revprops_stream; + svn_revnum_t first_rev = revprops->entry.start_rev; - /* decompress (even if the data is only "stored", there is still a - * length header to remove) */ - svn_stringbuf_t *compressed = revprops->packed_revprops; - svn_stringbuf_t *uncompressed = svn_stringbuf_create_empty(result_pool); - SVN_ERR(svn__decompress(compressed, uncompressed, APR_SIZE_MAX)); + /* Verify the checksum and decode packed data. */ + SVN_ERR_W(read_packed_data_checksummed(&root, content, result_pool, + scratch_pool), + apr_psprintf(scratch_pool, + "Revprop pack file for r%ld is corrupt", + first_rev)); - /* read first revision number and number of revisions in the pack */ - stream = svn_stream_from_stringbuf(uncompressed, scratch_pool); - SVN_ERR(svn_fs_x__read_number_from_stream(&first_rev, NULL, stream, - iterpool)); - SVN_ERR(svn_fs_x__read_number_from_stream(&count, NULL, stream, iterpool)); + /* get streams */ + revprops_stream = svn_packed__first_byte_stream(root); + count = svn_packed__byte_block_count(revprops_stream); /* Check revision range for validity. */ - if ( !same_shard(fs, revprops->revision, first_rev) - || !same_shard(fs, revprops->revision, first_rev + count - 1) - || count < 1) + if (!same_shard(fs, first_rev, first_rev + count - 1) || count < 1) return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, _("Revprop pack for revision r%ld" " contains revprops for r%ld .. r%ld"), @@ -923,58 +810,35 @@ parse_packed_revprops(svn_fs_t *fs, " starts at non-packed revisions r%ld"), revprops->revision, (svn_revnum_t)first_rev); - /* make PACKED_REVPROPS point to the first char after the header. - * This is where the serialized revprops are. */ - header_end = strstr(uncompressed->data, "\n\n"); - if (header_end == NULL) - return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, - _("Header end not found")); - - offset = header_end - uncompressed->data + 2; - - revprops->packed_revprops = svn_stringbuf_create_empty(result_pool); - revprops->packed_revprops->data = uncompressed->data + offset; - revprops->packed_revprops->len = (apr_size_t)(uncompressed->len - offset); - revprops->packed_revprops->blocksize = (apr_size_t)(uncompressed->blocksize - offset); - - /* STREAM still points to the first entry in the sizes list. */ - revprops->start_revision = (svn_revnum_t)first_rev; - if (read_all) + /* Request all data (just references to data already expanded in ROOT) */ + revprops->revprops = apr_array_make(result_pool, (int)count, + sizeof(svn_string_t)); + for (i = 0, revprops->total_size = 0; i < count; ++i) { - /* Init / construct REVPROPS members. */ - revprops->sizes = apr_array_make(result_pool, (int)count, - sizeof(offset)); - revprops->offsets = apr_array_make(result_pool, (int)count, - sizeof(offset)); + svn_string_t *props = apr_array_push(revprops->revprops); + props->data = svn_packed__get_bytes(revprops_stream, &props->len); + + revprops->total_size += props->len; } - /* Now parse, revision by revision, the size and content of each - * revisions' revprops. */ - for (i = 0, offset = 0, revprops->total_size = 0; i < count; ++i) + /* Now parse the serialized revprops. */ + for (i = 0; i < count; ++i) { - apr_int64_t size; - svn_string_t serialized; - svn_revnum_t revision = (svn_revnum_t)(first_rev + i); + const svn_string_t *serialized; + svn_revnum_t revision; + svn_pool_clear(iterpool); - /* read & check the serialized size */ - SVN_ERR(svn_fs_x__read_number_from_stream(&size, NULL, stream, - iterpool)); - if (size + offset > (apr_int64_t)revprops->packed_revprops->len) - return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, - _("Packed revprop size exceeds pack file size")); + serialized = &APR_ARRAY_IDX(revprops->revprops, (int)i, svn_string_t); + revision = first_rev + (long)i; /* Parse this revprops list, if necessary */ - serialized.data = revprops->packed_revprops->data + offset; - serialized.len = (apr_size_t)size; - if (revision == revprops->revision) { /* Parse (and possibly cache) the one revprop list we care about. */ SVN_ERR(parse_revprop(&revprops->properties, fs, revision, - revprops->generation, &serialized, - result_pool, iterpool)); - revprops->serialized_size = serialized.len; + serialized, result_pool, iterpool)); + revprops->serialized_size = serialized->len; /* If we only wanted the revprops for REVISION then we are done. */ if (!read_all && !cache_all) @@ -984,29 +848,20 @@ parse_packed_revprops(svn_fs_t *fs, { /* Parse and cache all other revprop lists. */ apr_hash_t *properties; - SVN_ERR(parse_revprop(&properties, fs, revision, - revprops->generation, &serialized, + SVN_ERR(parse_revprop(&properties, fs, revision, serialized, iterpool, iterpool)); } - - if (read_all) - { - /* fill REVPROPS data structures */ - APR_ARRAY_PUSH(revprops->sizes, apr_off_t) = serialized.len; - APR_ARRAY_PUSH(revprops->offsets, apr_off_t) = offset; - } - revprops->total_size += serialized.len; - - offset += serialized.len; } + svn_pool_destroy(iterpool); + return SVN_NO_ERROR; } /* In filesystem FS, read the packed revprops for revision REV into - * *REVPROPS. Use GENERATION to populate the revprop cache, if enabled. - * If you want to modify revprop contents / update REVPROPS, READ_ALL - * must be set. Otherwise, only the properties of REV are being provided. + * *REVPROPS. Populate the revprop cache, if enabled. If you want to + * modify revprop contents / update REVPROPS, READ_ALL must be set. + * Otherwise, only the properties of REV are being provided. * * Allocate *PROPERTIES in RESULT_POOL and temporaries in SCRATCH_POOL. */ @@ -1014,14 +869,12 @@ static svn_error_t * read_pack_revprop(packed_revprops_t **revprops, svn_fs_t *fs, svn_revnum_t rev, - apr_int64_t generation, svn_boolean_t read_all, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { apr_pool_t *iterpool = svn_pool_create(scratch_pool); svn_boolean_t missing = FALSE; - svn_error_t *err; packed_revprops_t *result; int i; @@ -1036,29 +889,37 @@ read_pack_revprop(packed_revprops_t **revprops, /* initialize the result data structure */ result = apr_pcalloc(result_pool, sizeof(*result)); result->revision = rev; - result->generation = generation; /* try to read the packed revprops. This may require retries if we have * concurrent writers. */ - for (i = 0; - i < SVN_FS_X__RECOVERABLE_RETRY_COUNT && !result->packed_revprops; - ++i) + for (i = 0; i < SVN_FS_X__RECOVERABLE_RETRY_COUNT; ++i) { const char *file_path; + svn_stringbuf_t *contents = NULL; + svn_pool_clear(iterpool); /* there might have been concurrent writes. * Re-read the manifest and the pack file. */ SVN_ERR(get_revprop_packname(fs, result, result_pool, iterpool)); - file_path = svn_dirent_join(result->folder, - result->filename, - iterpool); - SVN_ERR(svn_fs_x__try_stringbuf_from_file(&result->packed_revprops, + file_path = get_revprop_pack_filepath(result, &result->entry, + iterpool); + SVN_ERR(svn_fs_x__try_stringbuf_from_file(&contents, &missing, file_path, i + 1 < SVN_FS_X__RECOVERABLE_RETRY_COUNT, - result_pool)); + iterpool)); + + if (contents) + { + SVN_ERR_W(parse_packed_revprops(fs, result, contents, read_all, + result_pool, iterpool), + apr_psprintf(iterpool, + "Revprop pack file for r%ld is corrupt", + rev)); + break; + } /* If we could not find the file, there was a write. * So, we should refresh our revprop generation info as well such @@ -1066,40 +927,29 @@ read_pack_revprop(packed_revprops_t **revprops, * consider it outdated, otherwise. */ if (missing && has_revprop_cache(fs, iterpool)) - SVN_ERR(read_revprop_generation(&result->generation, fs, iterpool)); + SVN_ERR(read_revprop_generation(fs, iterpool)); } /* the file content should be available now */ - if (!result->packed_revprops) + if (!result->revprops) return svn_error_createf(SVN_ERR_FS_PACKED_REVPROP_READ_FAILURE, NULL, _("Failed to read revprop pack file for r%ld"), rev); - /* parse it. RESULT will be complete afterwards. */ - err = parse_packed_revprops(fs, result, read_all, result_pool, iterpool); - svn_pool_destroy(iterpool); - if (err) - return svn_error_createf(SVN_ERR_FS_CORRUPT, err, - _("Revprop pack file for r%ld is corrupt"), rev); - *revprops = result; return SVN_NO_ERROR; } -/* Read the revprops for revision REV in FS and return them in *PROPERTIES_P. - * - * Allocations will be done in POOL. - */ svn_error_t * svn_fs_x__get_revision_proplist(apr_hash_t **proplist_p, svn_fs_t *fs, svn_revnum_t rev, svn_boolean_t bypass_cache, + svn_boolean_t refresh, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { svn_fs_x__data_t *ffd = fs->fsap_data; - apr_int64_t generation = 0; /* not found, yet */ *proplist_p = NULL; @@ -1107,16 +957,18 @@ svn_fs_x__get_revision_proplist(apr_hash_t **proplist_p, /* should they be available at all? */ SVN_ERR(svn_fs_x__ensure_revision_exists(rev, fs, scratch_pool)); + /* Ensure that the revprop generation info is valid. */ + if (refresh || !is_generation_valid(fs)) + SVN_ERR(read_revprop_generation(fs, scratch_pool)); + /* Try cache lookup first. */ if (!bypass_cache && has_revprop_cache(fs, scratch_pool)) { svn_boolean_t is_cached; svn_fs_x__pair_cache_key_t key = { 0 }; - SVN_ERR(read_revprop_generation(&generation, fs, scratch_pool)); - key.revision = rev; - key.second = generation; + key.second = ffd->revprop_generation; SVN_ERR(svn_cache__get((void **) proplist_p, &is_cached, ffd->revprop_cache, &key, result_pool)); if (is_cached) @@ -1129,8 +981,7 @@ svn_fs_x__get_revision_proplist(apr_hash_t **proplist_p, if (!svn_fs_x__is_packed_revprop(fs, rev)) { svn_error_t *err = read_non_packed_revprop(proplist_p, fs, rev, - generation, result_pool, - scratch_pool); + result_pool, scratch_pool); if (err) { if (!APR_STATUS_IS_ENOENT(err->apr_err)) @@ -1147,7 +998,7 @@ svn_fs_x__get_revision_proplist(apr_hash_t **proplist_p, if (!*proplist_p) { packed_revprops_t *revprops; - SVN_ERR(read_pack_revprop(&revprops, fs, rev, generation, FALSE, + SVN_ERR(read_pack_revprop(&revprops, fs, rev, FALSE, result_pool, scratch_pool)); *proplist_p = revprops->properties; } @@ -1161,10 +1012,33 @@ svn_fs_x__get_revision_proplist(apr_hash_t **proplist_p, return SVN_NO_ERROR; } +svn_error_t * +svn_fs_x__write_non_packed_revprops(apr_file_t *file, + apr_hash_t *proplist, + apr_pool_t *scratch_pool) +{ + svn_stream_t *stream; + svn_checksum_t *checksum; + + stream = svn_stream_from_aprfile2(file, TRUE, scratch_pool); + stream = svn_checksum__wrap_write_stream(&checksum, stream, + svn_checksum_fnv1a_32x4, + scratch_pool); + SVN_ERR(svn_fs_x__write_properties(stream, proplist, scratch_pool)); + SVN_ERR(svn_stream_close(stream)); + + /* Append the checksum */ + SVN_ERR(svn_io_file_write_full(file, checksum->digest, + svn_checksum_size(checksum), NULL, + scratch_pool)); + + return SVN_NO_ERROR; +} + /* Serialize the revision property list PROPLIST of revision REV in * filesystem FS to a non-packed file. Return the name of that temporary * file in *TMP_PATH and the file path that it must be moved to in - * *FINAL_PATH. + * *FINAL_PATH. Schedule necessary fsync calls in BATCH. * * Allocate *FINAL_PATH and *TMP_PATH in RESULT_POOL. Use SCRATCH_POOL * for temporary allocations. @@ -1175,29 +1049,25 @@ write_non_packed_revprop(const char **final_path, svn_fs_t *fs, svn_revnum_t rev, apr_hash_t *proplist, + svn_fs_x__batch_fsync_t *batch, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - svn_stream_t *stream; + apr_file_t *file; *final_path = svn_fs_x__path_revprops(fs, rev, result_pool); - /* ### do we have a directory sitting around already? we really shouldn't - ### have to get the dirname here. */ - SVN_ERR(svn_stream_open_unique(&stream, tmp_path, - svn_dirent_dirname(*final_path, - scratch_pool), - svn_io_file_del_none, - result_pool, scratch_pool)); - SVN_ERR(svn_hash_write2(proplist, stream, SVN_HASH_TERMINATOR, - scratch_pool)); - SVN_ERR(svn_stream_close(stream)); + *tmp_path = apr_pstrcat(result_pool, *final_path, ".tmp", SVN_VA_NULL); + SVN_ERR(svn_fs_x__batch_fsync_open_file(&file, batch, *tmp_path, + scratch_pool)); + + SVN_ERR(svn_fs_x__write_non_packed_revprops(file, proplist, scratch_pool)); return SVN_NO_ERROR; } /* After writing the new revprop file(s), call this function to move the * file at TMP_PATH to FINAL_PATH and give it the permissions from - * PERMS_REFERENCE. + * PERMS_REFERENCE. Schedule necessary fsync calls in BATCH. * * If indicated in BUMP_GENERATION, increase FS' revprop generation. * Finally, delete all the temporary files given in FILES_TO_DELETE. @@ -1212,21 +1082,26 @@ switch_to_new_revprop(svn_fs_t *fs, const char *perms_reference, apr_array_header_t *files_to_delete, svn_boolean_t bump_generation, + svn_fs_x__batch_fsync_t *batch, apr_pool_t *scratch_pool) { - apr_int64_t generation; - /* Now, we may actually be replacing revprops. Make sure that all other threads and processes will know about this. */ if (bump_generation) - SVN_ERR(begin_revprop_change(&generation, fs, scratch_pool)); + SVN_ERR(begin_revprop_change(fs, scratch_pool)); + /* Ensure the new file contents makes it to disk before switching over to + * it. */ + SVN_ERR(svn_fs_x__batch_fsync_run(batch, scratch_pool)); + + /* Make the revision visible to all processes and threads. */ SVN_ERR(svn_fs_x__move_into_place(tmp_path, final_path, perms_reference, - scratch_pool)); + batch, scratch_pool)); + SVN_ERR(svn_fs_x__batch_fsync_run(batch, scratch_pool)); /* Indicate that the update (if relevant) has been completed. */ if (bump_generation) - SVN_ERR(end_revprop_change(fs, generation, scratch_pool)); + SVN_ERR(end_revprop_change(fs, scratch_pool)); /* Clean up temporary files, if necessary. */ if (files_to_delete) @@ -1247,52 +1122,8 @@ switch_to_new_revprop(svn_fs_t *fs, return SVN_NO_ERROR; } -/* Write a pack file header to STREAM that starts at revision START_REVISION - * and contains the indexes [START,END) of SIZES. - */ -static svn_error_t * -serialize_revprops_header(svn_stream_t *stream, - svn_revnum_t start_revision, - apr_array_header_t *sizes, - int start, - int end, - apr_pool_t *scratch_pool) -{ - apr_pool_t *iterpool = svn_pool_create(scratch_pool); - int i; - - SVN_ERR_ASSERT(start < end); - - /* start revision and entry count */ - SVN_ERR(svn_stream_printf(stream, scratch_pool, "%ld\n", start_revision)); - SVN_ERR(svn_stream_printf(stream, scratch_pool, "%d\n", end - start)); - - /* the sizes array */ - for (i = start; i < end; ++i) - { - /* Non-standard pool usage. - * - * We only allocate a few bytes each iteration -- even with a - * million iterations we would still be in good shape memory-wise. - */ - apr_off_t size = APR_ARRAY_IDX(sizes, i, apr_off_t); - SVN_ERR(svn_stream_printf(stream, iterpool, "%" APR_OFF_T_FMT "\n", - size)); - } - - /* the double newline char indicates the end of the header */ - SVN_ERR(svn_stream_printf(stream, iterpool, "\n")); - - svn_pool_destroy(iterpool); - return SVN_NO_ERROR; -} - -/* Writes the a pack file to FILE_STREAM. It copies the serialized data - * from REVPROPS for the indexes [START,END) except for index CHANGED_INDEX. - * - * The data for the latter is taken from NEW_SERIALIZED. Note, that - * CHANGED_INDEX may be outside the [START,END) range, i.e. no new data is - * taken in that case but only a subset of the old data will be copied. +/* Writes the a pack file to FILE. It copies the serialized data + * from REVPROPS for the indexes [START,END). * * NEW_TOTAL_SIZE is a hint for pre-allocating buffers of appropriate size. * SCRATCH_POOL is used for temporary allocations. @@ -1302,137 +1133,99 @@ repack_revprops(svn_fs_t *fs, packed_revprops_t *revprops, int start, int end, - int changed_index, - svn_stringbuf_t *new_serialized, - apr_off_t new_total_size, - svn_stream_t *file_stream, + apr_size_t new_total_size, + apr_file_t *file, apr_pool_t *scratch_pool) { - svn_fs_x__data_t *ffd = fs->fsap_data; - svn_stream_t *stream; int i; - /* create data empty buffers and the stream object */ - svn_stringbuf_t *uncompressed - = svn_stringbuf_create_ensure((apr_size_t)new_total_size, scratch_pool); - svn_stringbuf_t *compressed - = svn_stringbuf_create_empty(scratch_pool); - stream = svn_stream_from_stringbuf(uncompressed, scratch_pool); - - /* write the header*/ - SVN_ERR(serialize_revprops_header(stream, revprops->start_revision + start, - revprops->sizes, start, end, - scratch_pool)); + svn_packed__data_root_t *root = svn_packed__data_create_root(scratch_pool); + svn_packed__byte_stream_t *revprops_stream + = svn_packed__create_bytes_stream(root); /* append the serialized revprops */ for (i = start; i < end; ++i) - if (i == changed_index) - { - SVN_ERR(svn_stream_write(stream, - new_serialized->data, - &new_serialized->len)); - } - else - { - apr_size_t size - = (apr_size_t)APR_ARRAY_IDX(revprops->sizes, i, apr_off_t); - apr_size_t offset - = (apr_size_t)APR_ARRAY_IDX(revprops->offsets, i, apr_off_t); + { + const svn_string_t *props + = &APR_ARRAY_IDX(revprops->revprops, i, svn_string_t); - SVN_ERR(svn_stream_write(stream, - revprops->packed_revprops->data + offset, - &size)); - } + svn_packed__add_bytes(revprops_stream, props->data, props->len); + } - /* flush the stream buffer (if any) to our underlying data buffer */ - SVN_ERR(svn_stream_close(stream)); - - /* compress / store the data */ - SVN_ERR(svn__compress(uncompressed, - compressed, - ffd->compress_packed_revprops - ? SVN_DELTA_COMPRESSION_LEVEL_DEFAULT - : SVN_DELTA_COMPRESSION_LEVEL_NONE)); - - /* finally, write the content to the target stream and close it */ - SVN_ERR(svn_stream_write(file_stream, compressed->data, &compressed->len)); - SVN_ERR(svn_stream_close(file_stream)); + /* Write to file. */ + SVN_ERR(write_packed_data_checksummed(root, file, scratch_pool)); return SVN_NO_ERROR; } -/* Allocate a new pack file name for revisions - * [REVPROPS->START_REVISION + START, REVPROPS->START_REVISION + END - 1] - * of REVPROPS->MANIFEST. Add the name of old file to FILES_TO_DELETE, - * auto-create that array if necessary. Return an open file stream to - * the new file in *STREAM allocated in RESULT_POOL. Allocate the paths - * in *FILES_TO_DELETE from the same pool that contains the array itself. +/* Allocate a new pack file name for revisions starting at START_REV in + * REVPROPS->MANIFEST. Add the name of old file to FILES_TO_DELETE, + * auto-create that array if necessary. Return an open file *FILE that is + * allocated in RESULT_POOL. Allocate the paths in *FILES_TO_DELETE from + * the same pool that contains the array itself. Schedule necessary fsync + * calls in BATCH. * * Use SCRATCH_POOL for temporary allocations. */ static svn_error_t * -repack_stream_open(svn_stream_t **stream, - svn_fs_t *fs, - packed_revprops_t *revprops, - int start, - int end, - apr_array_header_t **files_to_delete, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) +repack_file_open(apr_file_t **file, + svn_fs_t *fs, + packed_revprops_t *revprops, + svn_revnum_t start_rev, + apr_array_header_t **files_to_delete, + svn_fs_x__batch_fsync_t *batch, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { - apr_int64_t tag; - const char *tag_string; - svn_string_t *new_filename; - int i; - apr_file_t *file; - int manifest_offset - = (int)(revprops->start_revision - revprops->manifest_start); + manifest_entry_t new_entry; + const char *new_path; + int idx; - /* get the old (= current) file name and enlist it for later deletion */ - const char *old_filename = APR_ARRAY_IDX(revprops->manifest, - start + manifest_offset, - const char*); + /* We always replace whole pack files - possibly by more than one new file. + * When we create the file for the first part of the pack, enlist the old + * one for later deletion */ + SVN_ERR_ASSERT(start_rev >= revprops->entry.start_rev); if (*files_to_delete == NULL) *files_to_delete = apr_array_make(result_pool, 3, sizeof(const char*)); - APR_ARRAY_PUSH(*files_to_delete, const char*) - = svn_dirent_join(revprops->folder, old_filename, - (*files_to_delete)->pool); + if (revprops->entry.start_rev == start_rev) + APR_ARRAY_PUSH(*files_to_delete, const char*) + = get_revprop_pack_filepath(revprops, &revprops->entry, + (*files_to_delete)->pool); - /* increase the tag part, i.e. the counter after the dot */ - tag_string = strchr(old_filename, '.'); - if (tag_string == NULL) - return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, - _("Packed file '%s' misses a tag"), - old_filename); - - SVN_ERR(svn_cstring_atoi64(&tag, tag_string + 1)); - new_filename = svn_string_createf((*files_to_delete)->pool, - "%ld.%" APR_INT64_T_FMT, - revprops->start_revision + start, - ++tag); + /* Initialize the new manifest entry. Bump the tag part. */ + new_entry.start_rev = start_rev; + new_entry.tag = revprops->entry.tag + 1; /* update the manifest to point to the new file */ - for (i = start; i < end; ++i) - APR_ARRAY_IDX(revprops->manifest, i + manifest_offset, const char*) - = new_filename->data; + idx = get_entry(revprops->manifest, start_rev); + if (revprops->entry.start_rev == start_rev) + APR_ARRAY_IDX(revprops->manifest, idx, manifest_entry_t) = new_entry; + else + svn_sort__array_insert(revprops->manifest, &new_path, idx + 1); - /* create a file stream for the new file */ - SVN_ERR(svn_io_file_open(&file, svn_dirent_join(revprops->folder, - new_filename->data, - scratch_pool), - APR_WRITE | APR_CREATE, APR_OS_DEFAULT, - result_pool)); - *stream = svn_stream_from_aprfile2(file, FALSE, result_pool); + /* open the file */ + new_path = get_revprop_pack_filepath(revprops, &new_entry, scratch_pool); + SVN_ERR(svn_fs_x__batch_fsync_open_file(file, batch, new_path, + scratch_pool)); return SVN_NO_ERROR; } +/* Return the length of the serialized reprop list of index I in REVPROPS. */ +static apr_size_t +props_len(packed_revprops_t *revprops, + int i) +{ + return APR_ARRAY_IDX(revprops->revprops, i, svn_string_t).len; +} + /* For revision REV in filesystem FS, set the revision properties to * PROPLIST. Return a new file in *TMP_PATH that the caller shall move * to *FINAL_PATH to make the change visible. Files to be deleted will * be listed in *FILES_TO_DELETE which may remain unchanged / unallocated. + * Schedule necessary fsync calls in BATCH. * * Allocate output values in RESULT_POOL and temporaries from SCRATCH_POOL. */ @@ -1443,88 +1236,87 @@ write_packed_revprop(const char **final_path, svn_fs_t *fs, svn_revnum_t rev, apr_hash_t *proplist, + svn_fs_x__batch_fsync_t *batch, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { svn_fs_x__data_t *ffd = fs->fsap_data; packed_revprops_t *revprops; - apr_int64_t generation = 0; svn_stream_t *stream; + apr_file_t *file; svn_stringbuf_t *serialized; - apr_off_t new_total_size; + apr_size_t new_total_size; int changed_index; + int count; /* read the current revprop generation. This value will not change * while we hold the global write lock to this FS. */ if (has_revprop_cache(fs, scratch_pool)) - SVN_ERR(read_revprop_generation(&generation, fs, scratch_pool)); + SVN_ERR(read_revprop_generation(fs, scratch_pool)); /* read contents of the current pack file */ - SVN_ERR(read_pack_revprop(&revprops, fs, rev, generation, TRUE, + SVN_ERR(read_pack_revprop(&revprops, fs, rev, TRUE, scratch_pool, scratch_pool)); /* serialize the new revprops */ serialized = svn_stringbuf_create_empty(scratch_pool); stream = svn_stream_from_stringbuf(serialized, scratch_pool); - SVN_ERR(svn_hash_write2(proplist, stream, SVN_HASH_TERMINATOR, - scratch_pool)); + SVN_ERR(svn_fs_x__write_properties(stream, proplist, scratch_pool)); SVN_ERR(svn_stream_close(stream)); - /* calculate the size of the new data */ - changed_index = (int)(rev - revprops->start_revision); + /* estimate the size of the new data */ + count = revprops->revprops->nelts; + changed_index = (int)(rev - revprops->entry.start_rev); new_total_size = revprops->total_size - revprops->serialized_size + serialized->len - + (revprops->offsets->nelts + 2) * SVN_INT64_BUFFER_SIZE; + + (count + 2) * SVN_INT64_BUFFER_SIZE; - APR_ARRAY_IDX(revprops->sizes, changed_index, apr_off_t) = serialized->len; + APR_ARRAY_IDX(revprops->revprops, changed_index, svn_string_t) + = *svn_stringbuf__morph_into_string(serialized); /* can we put the new data into the same pack as the before? */ - if ( new_total_size < ffd->revprop_pack_size - || revprops->sizes->nelts == 1) + if (new_total_size < ffd->revprop_pack_size || count == 1) { /* simply replace the old pack file with new content as we do it * in the non-packed case */ - *final_path = svn_dirent_join(revprops->folder, revprops->filename, - result_pool); - SVN_ERR(svn_stream_open_unique(&stream, tmp_path, revprops->folder, - svn_io_file_del_none, result_pool, - scratch_pool)); - SVN_ERR(repack_revprops(fs, revprops, 0, revprops->sizes->nelts, - changed_index, serialized, new_total_size, - stream, scratch_pool)); + *final_path = get_revprop_pack_filepath(revprops, &revprops->entry, + result_pool); + *tmp_path = apr_pstrcat(result_pool, *final_path, ".tmp", SVN_VA_NULL); + SVN_ERR(svn_fs_x__batch_fsync_open_file(&file, batch, *tmp_path, + scratch_pool)); + SVN_ERR(repack_revprops(fs, revprops, 0, count, + new_total_size, file, scratch_pool)); } else { /* split the pack file into two of roughly equal size */ - int right_count, left_count, i; + int right_count, left_count; int left = 0; - int right = revprops->sizes->nelts - 1; - apr_off_t left_size = 2 * SVN_INT64_BUFFER_SIZE; - apr_off_t right_size = 2 * SVN_INT64_BUFFER_SIZE; + int right = count - 1; + apr_size_t left_size = 2 * SVN_INT64_BUFFER_SIZE; + apr_size_t right_size = 2 * SVN_INT64_BUFFER_SIZE; /* let left and right side grow such that their size difference * is minimal after each step. */ while (left <= right) - if ( left_size + APR_ARRAY_IDX(revprops->sizes, left, apr_off_t) - < right_size + APR_ARRAY_IDX(revprops->sizes, right, apr_off_t)) + if ( left_size + props_len(revprops, left) + < right_size + props_len(revprops, right)) { - left_size += APR_ARRAY_IDX(revprops->sizes, left, apr_off_t) - + SVN_INT64_BUFFER_SIZE; + left_size += props_len(revprops, left) + SVN_INT64_BUFFER_SIZE; ++left; } else { - right_size += APR_ARRAY_IDX(revprops->sizes, right, apr_off_t) - + SVN_INT64_BUFFER_SIZE; + right_size += props_len(revprops, right) + SVN_INT64_BUFFER_SIZE; --right; } /* since the items need much less than SVN_INT64_BUFFER_SIZE * bytes to represent their length, the split may not be optimal */ left_count = left; - right_count = revprops->sizes->nelts - left; + right_count = count - left; /* if new_size is large, one side may exceed the pack size limit. * In that case, split before and after the modified revprop.*/ @@ -1532,7 +1324,7 @@ write_packed_revprop(const char **final_path, || right_size > ffd->revprop_pack_size) { left_count = changed_index; - right_count = revprops->sizes->nelts - left_count - 1; + right_count = count - left_count - 1; } /* Allocate this here such that we can call the repack functions with @@ -1544,54 +1336,40 @@ write_packed_revprop(const char **final_path, /* write the new, split files */ if (left_count) { - SVN_ERR(repack_stream_open(&stream, fs, revprops, 0, - left_count, files_to_delete, - scratch_pool, scratch_pool)); + SVN_ERR(repack_file_open(&file, fs, revprops, + revprops->entry.start_rev, + files_to_delete, batch, + scratch_pool, scratch_pool)); SVN_ERR(repack_revprops(fs, revprops, 0, left_count, - changed_index, serialized, new_total_size, - stream, scratch_pool)); + new_total_size, file, scratch_pool)); } - if (left_count + right_count < revprops->sizes->nelts) + if (left_count + right_count < count) { - SVN_ERR(repack_stream_open(&stream, fs, revprops, changed_index, - changed_index + 1, files_to_delete, - scratch_pool, scratch_pool)); + SVN_ERR(repack_file_open(&file, fs, revprops, rev, + files_to_delete, batch, + scratch_pool, scratch_pool)); SVN_ERR(repack_revprops(fs, revprops, changed_index, changed_index + 1, - changed_index, serialized, new_total_size, - stream, scratch_pool)); + new_total_size, file, scratch_pool)); } if (right_count) { - SVN_ERR(repack_stream_open(&stream, fs, revprops, - revprops->sizes->nelts - right_count, - revprops->sizes->nelts, - files_to_delete, scratch_pool, - scratch_pool)); - SVN_ERR(repack_revprops(fs, revprops, - revprops->sizes->nelts - right_count, - revprops->sizes->nelts, changed_index, - serialized, new_total_size, stream, - scratch_pool)); + SVN_ERR(repack_file_open(&file, fs, revprops, rev + 1, + files_to_delete, batch, + scratch_pool, scratch_pool)); + SVN_ERR(repack_revprops(fs, revprops, count - right_count, count, + new_total_size, file, scratch_pool)); } /* write the new manifest */ *final_path = svn_dirent_join(revprops->folder, PATH_MANIFEST, result_pool); - SVN_ERR(svn_stream_open_unique(&stream, tmp_path, revprops->folder, - svn_io_file_del_none, result_pool, - scratch_pool)); - - for (i = 0; i < revprops->manifest->nelts; ++i) - { - const char *filename = APR_ARRAY_IDX(revprops->manifest, i, - const char*); - SVN_ERR(svn_stream_printf(stream, scratch_pool, "%s\n", filename)); - } - - SVN_ERR(svn_stream_close(stream)); + *tmp_path = apr_pstrcat(result_pool, *final_path, ".tmp", SVN_VA_NULL); + SVN_ERR(svn_fs_x__batch_fsync_open_file(&file, batch, *tmp_path, + scratch_pool)); + SVN_ERR(write_manifest(file, revprops->manifest, scratch_pool)); } return SVN_NO_ERROR; @@ -1611,9 +1389,15 @@ svn_fs_x__set_revision_proplist(svn_fs_t *fs, const char *tmp_path; const char *perms_reference; apr_array_header_t *files_to_delete = NULL; + svn_fs_x__batch_fsync_t *batch; + svn_fs_x__data_t *ffd = fs->fsap_data; SVN_ERR(svn_fs_x__ensure_revision_exists(rev, fs, scratch_pool)); + /* Perform all fsyncs through this instance. */ + SVN_ERR(svn_fs_x__batch_fsync_create(&batch, ffd->flush_to_disk, + scratch_pool)); + /* this info will not change while we hold the global FS write lock */ is_packed = svn_fs_x__is_packed_revprop(fs, rev); @@ -1636,12 +1420,12 @@ svn_fs_x__set_revision_proplist(svn_fs_t *fs, /* Serialize the new revprop data */ if (is_packed) SVN_ERR(write_packed_revprop(&final_path, &tmp_path, &files_to_delete, - fs, rev, proplist, scratch_pool, + fs, rev, proplist, batch, scratch_pool, scratch_pool)); else SVN_ERR(write_non_packed_revprop(&final_path, &tmp_path, - fs, rev, proplist, scratch_pool, - scratch_pool)); + fs, rev, proplist, batch, + scratch_pool, scratch_pool)); /* We use the rev file of this revision as the perms reference, * because when setting revprops for the first time, the revprop @@ -1652,7 +1436,7 @@ svn_fs_x__set_revision_proplist(svn_fs_t *fs, /* Now, switch to the new revprop data. */ SVN_ERR(switch_to_new_revprop(fs, final_path, tmp_path, perms_reference, - files_to_delete, bump_generation, + files_to_delete, bump_generation, batch, scratch_pool)); return SVN_NO_ERROR; @@ -1668,20 +1452,14 @@ svn_fs_x__packed_revprop_available(svn_boolean_t *missing, svn_revnum_t revision, apr_pool_t *scratch_pool) { - svn_fs_x__data_t *ffd = fs->fsap_data; - svn_stringbuf_t *content = NULL; + svn_node_kind_t kind; + packed_revprops_t *revprops; + svn_error_t *err; /* try to read the manifest file */ - const char *folder = svn_fs_x__path_revprops_pack_shard(fs, revision, - scratch_pool); - const char *manifest_path = svn_dirent_join(folder, PATH_MANIFEST, - scratch_pool); - - svn_error_t *err = svn_fs_x__try_stringbuf_from_file(&content, - missing, - manifest_path, - FALSE, - scratch_pool); + revprops = apr_pcalloc(scratch_pool, sizeof(*revprops)); + revprops->revision = revision; + err = get_revprop_packname(fs, revprops, scratch_pool, scratch_pool); /* if the manifest cannot be read, consider the pack files inaccessible * even if the file itself exists. */ @@ -1691,114 +1469,93 @@ svn_fs_x__packed_revprop_available(svn_boolean_t *missing, return FALSE; } - if (*missing) - return FALSE; - - /* parse manifest content until we find the entry for REVISION. - * Revision 0 is never packed. */ - revision = revision < ffd->max_files_per_dir - ? revision - 1 - : revision % ffd->max_files_per_dir; - while (content->data) + /* the respective pack file must exist (and be a file) */ + err = svn_io_check_path(get_revprop_pack_filepath(revprops, + &revprops->entry, + scratch_pool), + &kind, scratch_pool); + if (err) { - char *next = strchr(content->data, '\n'); - if (next) - { - *next = 0; - ++next; - } - - if (revision-- == 0) - { - /* the respective pack file must exist (and be a file) */ - svn_node_kind_t kind; - err = svn_io_check_path(svn_dirent_join(folder, content->data, - scratch_pool), - &kind, scratch_pool); - if (err) - { - svn_error_clear(err); - return FALSE; - } - - *missing = kind == svn_node_none; - return kind == svn_node_file; - } - - content->data = next; + svn_error_clear(err); + return FALSE; } - return FALSE; + *missing = kind == svn_node_none; + return kind == svn_node_file; } /****** Packing FSX shards *********/ -svn_error_t * -svn_fs_x__copy_revprops(const char *pack_file_dir, - const char *pack_filename, - const char *shard_path, - svn_revnum_t start_rev, - svn_revnum_t end_rev, - apr_array_header_t *sizes, - apr_size_t total_size, - int compression_level, - svn_cancel_func_t cancel_func, - void *cancel_baton, - apr_pool_t *scratch_pool) +/* Copy revprop files for revisions [START_REV, END_REV) from SHARD_PATH + * in filesystem FS to the pack file at PACK_FILE_NAME in PACK_FILE_DIR. + * + * The file sizes have already been determined and written to SIZES. + * Please note that this function will be executed while the filesystem + * has been locked and that revprops files will therefore not be modified + * while the pack is in progress. + * + * COMPRESSION_LEVEL defines how well the resulting pack file shall be + * compressed or whether is shall be compressed at all. TOTAL_SIZE is + * a hint on which initial buffer size we should use to hold the pack file + * content. Schedule necessary fsync calls in BATCH. + * + * CANCEL_FUNC and CANCEL_BATON are used as usual. Temporary allocations + * are done in SCRATCH_POOL. + */ +static svn_error_t * +copy_revprops(svn_fs_t *fs, + const char *pack_file_dir, + const char *pack_filename, + const char *shard_path, + svn_revnum_t start_rev, + svn_revnum_t end_rev, + apr_array_header_t *sizes, + apr_size_t total_size, + int compression_level, + svn_fs_x__batch_fsync_t *batch, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *scratch_pool) { - svn_stream_t *pack_stream; apr_file_t *pack_file; svn_revnum_t rev; apr_pool_t *iterpool = svn_pool_create(scratch_pool); - svn_stream_t *stream; - /* create empty data buffer and a write stream on top of it */ - svn_stringbuf_t *uncompressed - = svn_stringbuf_create_ensure(total_size, scratch_pool); - svn_stringbuf_t *compressed - = svn_stringbuf_create_empty(scratch_pool); - pack_stream = svn_stream_from_stringbuf(uncompressed, scratch_pool); - - /* write the pack file header */ - SVN_ERR(serialize_revprops_header(pack_stream, start_rev, sizes, 0, - sizes->nelts, iterpool)); - - /* Some useful paths. */ - SVN_ERR(svn_io_file_open(&pack_file, svn_dirent_join(pack_file_dir, - pack_filename, - scratch_pool), - APR_WRITE | APR_CREATE, APR_OS_DEFAULT, - scratch_pool)); + svn_packed__data_root_t *root = svn_packed__data_create_root(scratch_pool); + svn_packed__byte_stream_t *stream + = svn_packed__create_bytes_stream(root); /* Iterate over the revisions in this shard, squashing them together. */ for (rev = start_rev; rev <= end_rev; rev++) { const char *path; + svn_stringbuf_t *props; svn_pool_clear(iterpool); /* Construct the file name. */ - path = svn_dirent_join(shard_path, apr_psprintf(iterpool, "%ld", rev), - iterpool); + path = svn_fs_x__path_revprops(fs, rev, iterpool); /* Copy all the bits from the non-packed revprop file to the end of * the pack file. */ - SVN_ERR(svn_stream_open_readonly(&stream, path, iterpool, iterpool)); - SVN_ERR(svn_stream_copy3(stream, pack_stream, - cancel_func, cancel_baton, iterpool)); + SVN_ERR(svn_stringbuf_from_file2(&props, path, iterpool)); + SVN_ERR_W(verify_checksum(props, iterpool), + apr_psprintf(iterpool, "Failed to read revprops for r%ld.", + rev)); + + svn_packed__add_bytes(stream, props->data, props->len); } - /* flush stream buffers to content buffer */ - SVN_ERR(svn_stream_close(pack_stream)); + /* Create the auto-fsync'ing pack file. */ + SVN_ERR(svn_fs_x__batch_fsync_open_file(&pack_file, batch, + svn_dirent_join(pack_file_dir, + pack_filename, + scratch_pool), + scratch_pool)); - /* compress the content (or just store it for COMPRESSION_LEVEL 0) */ - SVN_ERR(svn__compress(uncompressed, compressed, compression_level)); - - /* write the pack file content to disk */ - stream = svn_stream_from_aprfile2(pack_file, FALSE, scratch_pool); - SVN_ERR(svn_stream_write(stream, compressed->data, &compressed->len)); - SVN_ERR(svn_stream_close(stream)); + /* write all to disk */ + SVN_ERR(write_packed_data_checksummed(root, pack_file, scratch_pool)); svn_pool_destroy(iterpool); @@ -1806,49 +1563,62 @@ svn_fs_x__copy_revprops(const char *pack_file_dir, } svn_error_t * -svn_fs_x__pack_revprops_shard(const char *pack_file_dir, +svn_fs_x__pack_revprops_shard(svn_fs_t *fs, + const char *pack_file_dir, const char *shard_path, apr_int64_t shard, int max_files_per_dir, - apr_off_t max_pack_size, + apr_int64_t max_pack_size, int compression_level, + svn_fs_x__batch_fsync_t *batch, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *scratch_pool) { const char *manifest_file_path, *pack_filename = NULL; - svn_stream_t *manifest_stream; + apr_file_t *manifest_file; svn_revnum_t start_rev, end_rev, rev; - apr_off_t total_size; + apr_size_t total_size; apr_pool_t *iterpool = svn_pool_create(scratch_pool); apr_array_header_t *sizes; + apr_array_header_t *manifest; + + /* Sanitize config file values. */ + apr_size_t max_size = (apr_size_t)MIN(MAX(max_pack_size, 1), + SVN_MAX_OBJECT_SIZE); /* Some useful paths. */ manifest_file_path = svn_dirent_join(pack_file_dir, PATH_MANIFEST, scratch_pool); - /* Remove any existing pack file for this shard, since it is incomplete. */ - SVN_ERR(svn_io_remove_dir2(pack_file_dir, TRUE, cancel_func, cancel_baton, - scratch_pool)); - - /* Create the new directory and manifest file stream. */ - SVN_ERR(svn_io_dir_make(pack_file_dir, APR_OS_DEFAULT, scratch_pool)); - SVN_ERR(svn_stream_open_writable(&manifest_stream, manifest_file_path, - scratch_pool, scratch_pool)); + /* Create the manifest file. */ + SVN_ERR(svn_fs_x__batch_fsync_open_file(&manifest_file, batch, + manifest_file_path, scratch_pool)); /* revisions to handle. Special case: revision 0 */ start_rev = (svn_revnum_t) (shard * max_files_per_dir); end_rev = (svn_revnum_t) ((shard + 1) * (max_files_per_dir) - 1); if (start_rev == 0) - ++start_rev; - /* Special special case: if max_files_per_dir is 1, then at this point - start_rev == 1 and end_rev == 0 (!). Fortunately, everything just - works. */ + { + /* Never pack revprops for r0, just copy it. */ + SVN_ERR(svn_io_copy_file(svn_fs_x__path_revprops(fs, 0, iterpool), + svn_dirent_join(pack_file_dir, "p0", + scratch_pool), + TRUE, + iterpool)); + + ++start_rev; + /* Special special case: if max_files_per_dir is 1, then at this point + start_rev == 1 and end_rev == 0 (!). Fortunately, everything just + works. */ + } /* initialize the revprop size info */ - sizes = apr_array_make(scratch_pool, max_files_per_dir, sizeof(apr_off_t)); + sizes = apr_array_make(scratch_pool, max_files_per_dir, sizeof(apr_size_t)); total_size = 2 * SVN_INT64_BUFFER_SIZE; + manifest = apr_array_make(scratch_pool, 4, sizeof(manifest_entry_t)); + /* Iterate over the revisions in this shard, determine their size and * squashing them together into pack files. */ for (rev = start_rev; rev <= end_rev; rev++) @@ -1859,20 +1629,22 @@ svn_fs_x__pack_revprops_shard(const char *pack_file_dir, svn_pool_clear(iterpool); /* Get the size of the file. */ - path = svn_dirent_join(shard_path, apr_psprintf(iterpool, "%ld", rev), - iterpool); + path = svn_fs_x__path_revprops(fs, rev, iterpool); SVN_ERR(svn_io_stat(&finfo, path, APR_FINFO_SIZE, iterpool)); - /* if we already have started a pack file and this revprop cannot be - * appended to it, write the previous pack file. */ - if (sizes->nelts != 0 && - total_size + SVN_INT64_BUFFER_SIZE + finfo.size > max_pack_size) + /* If we already have started a pack file and this revprop cannot be + * appended to it, write the previous pack file. Note this overflow + * check works because we enforced MAX_SIZE <= SVN_MAX_OBJECT_SIZE. */ + if (sizes->nelts != 0 + && ( finfo.size > max_size + || total_size > max_size + || SVN_INT64_BUFFER_SIZE + finfo.size > max_size - total_size)) { - SVN_ERR(svn_fs_x__copy_revprops(pack_file_dir, pack_filename, - shard_path, start_rev, rev-1, - sizes, (apr_size_t)total_size, - compression_level, cancel_func, - cancel_baton, iterpool)); + SVN_ERR(copy_revprops(fs, pack_file_dir, pack_filename, + shard_path, start_rev, rev-1, + sizes, (apr_size_t)total_size, + compression_level, batch, cancel_func, + cancel_baton, iterpool)); /* next pack file starts empty again */ apr_array_clear(sizes); @@ -1883,66 +1655,31 @@ svn_fs_x__pack_revprops_shard(const char *pack_file_dir, /* Update the manifest. Allocate a file name for the current pack * file if it is a new one */ if (sizes->nelts == 0) - pack_filename = apr_psprintf(scratch_pool, "%ld.0", rev); + { + manifest_entry_t *entry = apr_array_push(manifest); + entry->start_rev = rev; + entry->tag = 0; - SVN_ERR(svn_stream_printf(manifest_stream, iterpool, "%s\n", - pack_filename)); + pack_filename = apr_psprintf(scratch_pool, "%ld.0", rev); + } /* add to list of files to put into the current pack file */ - APR_ARRAY_PUSH(sizes, apr_off_t) = finfo.size; + APR_ARRAY_PUSH(sizes, apr_size_t) = finfo.size; total_size += SVN_INT64_BUFFER_SIZE + finfo.size; } /* write the last pack file */ if (sizes->nelts != 0) - SVN_ERR(svn_fs_x__copy_revprops(pack_file_dir, pack_filename, shard_path, - start_rev, rev-1, sizes, - (apr_size_t)total_size, compression_level, - cancel_func, cancel_baton, iterpool)); + SVN_ERR(copy_revprops(fs, pack_file_dir, pack_filename, shard_path, + start_rev, rev-1, sizes, + (apr_size_t)total_size, compression_level, + batch, cancel_func, cancel_baton, iterpool)); - /* flush the manifest file and update permissions */ - SVN_ERR(svn_stream_close(manifest_stream)); + SVN_ERR(write_manifest(manifest_file, manifest, iterpool)); + + /* flush all data to disk and update permissions */ SVN_ERR(svn_io_copy_perms(shard_path, pack_file_dir, iterpool)); - svn_pool_destroy(iterpool); return SVN_NO_ERROR; } - -svn_error_t * -svn_fs_x__delete_revprops_shard(const char *shard_path, - apr_int64_t shard, - int max_files_per_dir, - svn_cancel_func_t cancel_func, - void *cancel_baton, - apr_pool_t *scratch_pool) -{ - if (shard == 0) - { - apr_pool_t *iterpool = svn_pool_create(scratch_pool); - int i; - - /* delete all files except the one for revision 0 */ - for (i = 1; i < max_files_per_dir; ++i) - { - const char *path; - svn_pool_clear(iterpool); - - path = svn_dirent_join(shard_path, - apr_psprintf(iterpool, "%d", i), - iterpool); - if (cancel_func) - SVN_ERR((*cancel_func)(cancel_baton)); - - SVN_ERR(svn_io_remove_file2(path, TRUE, iterpool)); - } - - svn_pool_destroy(iterpool); - } - else - SVN_ERR(svn_io_remove_dir2(shard_path, TRUE, - cancel_func, cancel_baton, scratch_pool)); - - return SVN_NO_ERROR; -} - diff --git a/subversion/libsvn_fs_x/revprops.h b/subversion/libsvn_fs_x/revprops.h index c4827c42c222..cf6f63896f1d 100644 --- a/subversion/libsvn_fs_x/revprops.h +++ b/subversion/libsvn_fs_x/revprops.h @@ -20,11 +20,13 @@ * ==================================================================== */ -#ifndef SVN_LIBSVN_FS__REVPROPS_H -#define SVN_LIBSVN_FS__REVPROPS_H +#ifndef SVN_LIBSVN_FS_X_REVPROPS_H +#define SVN_LIBSVN_FS_X_REVPROPS_H #include "svn_fs.h" +#include "batch_fsync.h" + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ @@ -39,44 +41,26 @@ svn_error_t * svn_fs_x__reset_revprop_generation_file(svn_fs_t *fs, apr_pool_t *scratch_pool); -/* In the filesystem FS, pack all revprop shards up to min_unpacked_rev. - * - * NOTE: Keep the old non-packed shards around until after the format bump. - * Otherwise, re-running upgrade will drop the packed revprop shard but - * have no unpacked data anymore. Call upgrade_cleanup_pack_revprops after - * the bump. - * - * NOTIFY_FUNC and NOTIFY_BATON as well as CANCEL_FUNC and CANCEL_BATON are - * used in the usual way. Temporary allocations are done in SCRATCH_POOL. - */ -svn_error_t * -svn_fs_x__upgrade_pack_revprops(svn_fs_t *fs, - svn_fs_upgrade_notify_t notify_func, - void *notify_baton, - svn_cancel_func_t cancel_func, - void *cancel_baton, - apr_pool_t *scratch_pool); +/* Invalidate the cached revprop generation value in FS->FSAP_DATA. + * This enforces a re-read upon the next revprop read. */ +void +svn_fs_x__invalidate_revprop_generation(svn_fs_t *fs); -/* In the filesystem FS, remove all non-packed revprop shards up to - * min_unpacked_rev. Temporary allocations are done in SCRATCH_POOL. +/* Utility function serializing PROPLIST into FILE and adding the checksum. + * Use SCRATCH_POOL for temporary allocations. * - * NOTIFY_FUNC and NOTIFY_BATON as well as CANCEL_FUNC and CANCEL_BATON are - * used in the usual way. Cancellation is supported in the sense that we - * will cleanly abort the operation. However, there will be remnant shards - * that must be removed manually. - * - * See upgrade_pack_revprops for more info. + * Call this only when creating initial revprop file contents. + * For modifications use svn_fs_x__set_revision_proplist. */ svn_error_t * -svn_fs_x__upgrade_cleanup_pack_revprops(svn_fs_t *fs, - svn_fs_upgrade_notify_t notify_func, - void *notify_baton, - svn_cancel_func_t cancel_func, - void *cancel_baton, - apr_pool_t *scratch_pool); +svn_fs_x__write_non_packed_revprops(apr_file_t *file, + apr_hash_t *proplist, + apr_pool_t *scratch_pool); /* Read the revprops for revision REV in FS and return them in *PROPLIST_P. * If BYPASS_CACHE is set, don't consult the disks but always read from disk. + * If REFRESH is set, update the revprop generation info; otherwise access + * potentially outdated cache data directly. * * Allocate the *PROPLIST_P in RESULT_POOL and use SCRATCH_POOL for temporary * allocations. @@ -86,6 +70,7 @@ svn_fs_x__get_revision_proplist(apr_hash_t **proplist_p, svn_fs_t *fs, svn_revnum_t rev, svn_boolean_t bypass_cache, + svn_boolean_t refresh, apr_pool_t *result_pool, apr_pool_t *scratch_pool); @@ -111,37 +96,9 @@ svn_fs_x__packed_revprop_available(svn_boolean_t *missing, /****** Packing FSX shards *********/ -/* Copy revprop files for revisions [START_REV, END_REV) from SHARD_PATH - * to the pack file at PACK_FILE_NAME in PACK_FILE_DIR. - * - * The file sizes have already been determined and written to SIZES. - * Please note that this function will be executed while the filesystem - * has been locked and that revprops files will therefore not be modified - * while the pack is in progress. - * - * COMPRESSION_LEVEL defines how well the resulting pack file shall be - * compressed or whether is shall be compressed at all. TOTAL_SIZE is - * a hint on which initial buffer size we should use to hold the pack file - * content. - * - * CANCEL_FUNC and CANCEL_BATON are used as usual. Temporary allocations - * are done in SCRATCH_POOL. - */ -svn_error_t * -svn_fs_x__copy_revprops(const char *pack_file_dir, - const char *pack_filename, - const char *shard_path, - svn_revnum_t start_rev, - svn_revnum_t end_rev, - apr_array_header_t *sizes, - apr_size_t total_size, - int compression_level, - svn_cancel_func_t cancel_func, - void *cancel_baton, - apr_pool_t *scratch_pool); - /* For the revprop SHARD at SHARD_PATH with exactly MAX_FILES_PER_DIR - * revprop files in it, create a packed shared at PACK_FILE_DIR. + * revprop files in it, create a packed shared at PACK_FILE_DIR in + * filesystem FS. Schedule necessary fsync calls in BATCH. * * COMPRESSION_LEVEL defines how well the resulting pack file shall be * compressed or whether is shall be compressed at all. Individual pack @@ -152,33 +109,20 @@ svn_fs_x__copy_revprops(const char *pack_file_dir, * allocations are done in SCRATCH_POOL. */ svn_error_t * -svn_fs_x__pack_revprops_shard(const char *pack_file_dir, +svn_fs_x__pack_revprops_shard(svn_fs_t *fs, + const char *pack_file_dir, const char *shard_path, apr_int64_t shard, int max_files_per_dir, - apr_off_t max_pack_size, + apr_int64_t max_pack_size, int compression_level, + svn_fs_x__batch_fsync_t *batch, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *scratch_pool); -/* Delete the non-packed revprop SHARD at SHARD_PATH with exactly - * MAX_FILES_PER_DIR revprop files in it. If this is shard 0, keep the - * revprop file for revision 0. - * - * CANCEL_FUNC and CANCEL_BATON are used in the usual way. Temporary - * allocations are done in SCRATCH_POOL. - */ -svn_error_t * -svn_fs_x__delete_revprops_shard(const char *shard_path, - apr_int64_t shard, - int max_files_per_dir, - svn_cancel_func_t cancel_func, - void *cancel_baton, - apr_pool_t *scratch_pool); - #ifdef __cplusplus } #endif /* __cplusplus */ -#endif /* SVN_LIBSVN_FS__REVPROPS_H */ +#endif /* SVN_LIBSVN_FS_X_REVPROPS_H */ diff --git a/subversion/libsvn_fs_x/string_table.c b/subversion/libsvn_fs_x/string_table.c index 7b3b6450cb52..e6a1cffdd2d9 100644 --- a/subversion/libsvn_fs_x/string_table.c +++ b/subversion/libsvn_fs_x/string_table.c @@ -376,7 +376,7 @@ svn_fs_x__string_table_builder_estimate_size(string_table_builder_t *builder) static void create_table(string_sub_table_t *target, builder_table_t *source, - apr_pool_t *pool, + apr_pool_t *result_pool, apr_pool_t *scratch_pool) { int i = 0; @@ -387,7 +387,8 @@ create_table(string_sub_table_t *target, /* pack sub-strings */ target->short_string_count = (apr_size_t)source->short_strings->nelts; - target->short_strings = apr_palloc(pool, sizeof(*target->short_strings) * + target->short_strings = apr_palloc(result_pool, + sizeof(*target->short_strings) * target->short_string_count); for (i = 0; i < source->short_strings->nelts; ++i) { @@ -433,13 +434,14 @@ create_table(string_sub_table_t *target, /* pack long strings */ target->long_string_count = (apr_size_t)source->long_strings->nelts; - target->long_strings = apr_palloc(pool, sizeof(*target->long_strings) * + target->long_strings = apr_palloc(result_pool, + sizeof(*target->long_strings) * target->long_string_count); for (i = 0; i < source->long_strings->nelts; ++i) { svn_string_t *string = &target->long_strings[i]; *string = APR_ARRAY_IDX(source->long_strings, i, svn_string_t); - string->data = apr_pstrmemdup(pool, string->data, string->len); + string->data = apr_pstrmemdup(result_pool, string->data, string->len); } data->len += PADDING; /* add a few extra bytes at the end of the buffer @@ -447,25 +449,25 @@ create_table(string_sub_table_t *target, assert(data->len < data->blocksize); memset(data->data + data->len - PADDING, 0, PADDING); - target->data = apr_pmemdup(pool, data->data, data->len); + target->data = apr_pmemdup(result_pool, data->data, data->len); target->data_size = data->len; } string_table_t * svn_fs_x__string_table_create(const string_table_builder_t *builder, - apr_pool_t *pool) + apr_pool_t *result_pool) { apr_size_t i; - string_table_t *result = apr_pcalloc(pool, sizeof(*result)); + string_table_t *result = apr_pcalloc(result_pool, sizeof(*result)); result->size = (apr_size_t)builder->tables->nelts; result->sub_tables - = apr_pcalloc(pool, result->size * sizeof(*result->sub_tables)); + = apr_pcalloc(result_pool, result->size * sizeof(*result->sub_tables)); for (i = 0; i < result->size; ++i) create_table(&result->sub_tables[i], APR_ARRAY_IDX(builder->tables, i, builder_table_t*), - pool, + result_pool, builder->pool); return result; @@ -542,7 +544,7 @@ const char* svn_fs_x__string_table_get(const string_table_t *table, apr_size_t idx, apr_size_t *length, - apr_pool_t *pool) + apr_pool_t *result_pool) { apr_size_t table_number = idx >> TABLE_SHIFT; apr_size_t sub_index = idx & STRING_INDEX_MASK; @@ -557,7 +559,7 @@ svn_fs_x__string_table_get(const string_table_t *table, if (length) *length = sub_table->long_strings[sub_index].len; - return apr_pstrmemdup(pool, + return apr_pstrmemdup(result_pool, sub_table->long_strings[sub_index].data, sub_table->long_strings[sub_index].len); } @@ -568,7 +570,7 @@ svn_fs_x__string_table_get(const string_table_t *table, { string_header_t *header = sub_table->short_strings + sub_index; apr_size_t len = header->head_length + header->tail_length; - char *result = apr_palloc(pool, len + PADDING); + char *result = apr_palloc(result_pool, len + PADDING); if (length) *length = len; @@ -579,7 +581,7 @@ svn_fs_x__string_table_get(const string_table_t *table, } } - return apr_pstrmemdup(pool, "", 0); + return apr_pstrmemdup(result_pool, "", 0); } svn_error_t * @@ -830,7 +832,7 @@ const char* svn_fs_x__string_table_get_func(const string_table_t *table, apr_size_t idx, apr_size_t *length, - apr_pool_t *pool) + apr_pool_t *result_pool) { apr_size_t table_number = idx >> TABLE_SHIFT; apr_size_t sub_index = idx & STRING_INDEX_MASK; @@ -861,7 +863,7 @@ svn_fs_x__string_table_get_func(const string_table_t *table, if (length) *length = long_strings[sub_index].len; - return apr_pstrmemdup(pool, + return apr_pstrmemdup(result_pool, str_data, long_strings[sub_index].len); } @@ -889,7 +891,7 @@ svn_fs_x__string_table_get_func(const string_table_t *table, /* reconstruct the char data and return it */ header = table_copy.short_strings + sub_index; len = header->head_length + header->tail_length; - result = apr_palloc(pool, len + PADDING); + result = apr_palloc(result_pool, len + PADDING); if (length) *length = len; diff --git a/subversion/libsvn_fs_x/string_table.h b/subversion/libsvn_fs_x/string_table.h index f7ab47698777..eed057232c9f 100644 --- a/subversion/libsvn_fs_x/string_table.h +++ b/subversion/libsvn_fs_x/string_table.h @@ -69,21 +69,21 @@ apr_size_t svn_fs_x__string_table_builder_estimate_size(string_table_builder_t *builder); /* From the given BUILDER object, create a string table object allocated - * in POOL that contains all strings previously added to BUILDER. + * in RESULT_POOL that contains all strings previously added to BUILDER. */ string_table_t * svn_fs_x__string_table_create(const string_table_builder_t *builder, - apr_pool_t *pool); + apr_pool_t *result_pool); /* Extract string number INDEX from TABLE and return a copy of it allocated - * in POOL. If LENGTH is not NULL, set *LENGTH to strlen() of the result - * string. Returns an empty string for invalid indexes. + * in RESULT_POOL. If LENGTH is not NULL, set *LENGTH to strlen() of the + * result string. Returns an empty string for invalid indexes. */ const char* svn_fs_x__string_table_get(const string_table_t *table, apr_size_t index, apr_size_t *length, - apr_pool_t *pool); + apr_pool_t *result_pool); /* Write a serialized representation of the string table TABLE to STREAM. * Use SCRATCH_POOL for temporary allocations. @@ -116,15 +116,15 @@ svn_fs_x__deserialize_string_table(void *buffer, string_table_t **table); /* Extract string number INDEX from the cache serialized representation at - * TABLE and return a copy of it allocated in POOL. If LENGTH is not NULL, - * set *LENGTH to strlen() of the result string. Returns an empty string - * for invalid indexes. + * TABLE and return a copy of it allocated in RESULT_POOL. If LENGTH is not + * NULL, set *LENGTH to strlen() of the result string. Returns an empty + * string for invalid indexes. */ const char* svn_fs_x__string_table_get_func(const string_table_t *table, apr_size_t idx, apr_size_t *length, - apr_pool_t *pool); + apr_pool_t *result_pool); #ifdef __cplusplus } diff --git a/subversion/libsvn_fs_x/temp_serializer.c b/subversion/libsvn_fs_x/temp_serializer.c index 65a2c3fdefde..efabf1b60771 100644 --- a/subversion/libsvn_fs_x/temp_serializer.c +++ b/subversion/libsvn_fs_x/temp_serializer.c @@ -71,13 +71,13 @@ encode_number(apr_int64_t number, char *key_buffer) const char* svn_fs_x__combine_number_and_string(apr_int64_t number, const char *string, - apr_pool_t *pool) + apr_pool_t *result_pool) { apr_size_t len = strlen(string); /* number part requires max. 10x7 bits + 1 space. * Add another 1 for the terminal 0 */ - char *key_buffer = apr_palloc(pool, len + 12); + char *key_buffer = apr_palloc(result_pool, len + 12); const char *key = key_buffer; /* Prepend the number to the string and separate them by space. No other @@ -120,7 +120,7 @@ serialize_svn_string(svn_temp_serializer__context_t *context, /* Utility function to deserialize the STRING inside the BUFFER. */ static void -deserialize_svn_string(void *buffer, svn_string_t **string) +deserialize_svn_string(const void *buffer, svn_string_t **string) { svn_temp_deserializer__resolve(buffer, (void **)string); if (*string == NULL) @@ -173,14 +173,14 @@ svn_fs_x__serialize_apr_array(svn_temp_serializer__context_t *context, void svn_fs_x__deserialize_apr_array(void *buffer, apr_array_header_t **array, - apr_pool_t *pool) + apr_pool_t *result_pool) { svn_temp_deserializer__resolve(buffer, (void **)array); if (*array == NULL) return; svn_temp_deserializer__resolve(*array, (void **)&(*array)->elts); - (*array)->pool = pool; + (*array)->pool = result_pool; } /* auxilliary structure representing the content of a directory array */ @@ -190,6 +190,10 @@ typedef struct dir_data_t * (it's int because the directory is an APR array) */ int count; + /** Current length of the in-txn in-disk representation of the directory. + * SVN_INVALID_FILESIZE if unknown (i.e. committed data). */ + svn_filesize_t txn_filesize; + /* number of unused dir entry buckets in the index */ apr_size_t over_provision; @@ -224,7 +228,7 @@ serialize_dir_entry(svn_temp_serializer__context_t *context, svn_temp_serializer__push(context, (const void * const *)entry_p, - sizeof(svn_fs_x__dirent_t)); + sizeof(**entry_p)); svn_temp_serializer__add_string(context, &entry->name); @@ -234,18 +238,19 @@ serialize_dir_entry(svn_temp_serializer__context_t *context, svn_temp_serializer__pop(context); } -/* Utility function to serialize the ENTRIES into a new serialization +/* Utility function to serialize the DIR into a new serialization * context to be returned. * * Temporary allocation will be made form SCRATCH_POOL. */ static svn_temp_serializer__context_t * -serialize_dir(apr_array_header_t *entries, +serialize_dir(svn_fs_x__dir_data_t *dir, apr_pool_t *scratch_pool) { dir_data_t dir_data; int i = 0; svn_temp_serializer__context_t *context; + apr_array_header_t *entries = dir->entries; /* calculate sizes */ int count = entries->nelts; @@ -254,8 +259,12 @@ serialize_dir(apr_array_header_t *entries, * sizeof(svn_fs_x__dirent_t*); apr_size_t lengths_len = (count + over_provision) * sizeof(apr_uint32_t); + /* Estimate the size of a directory entry + its name. */ + enum { ENTRY_SIZE = sizeof(svn_fs_x__dirent_t) + 32 }; + /* copy the hash entries to an auxiliary struct of known layout */ dir_data.count = count; + dir_data.txn_filesize = dir->txn_filesize; dir_data.over_provision = over_provision; dir_data.operations = 0; dir_data.entries = apr_palloc(scratch_pool, entries_len); @@ -268,7 +277,8 @@ serialize_dir(apr_array_header_t *entries, * estimate for the size of the buffer that we will need. */ context = svn_temp_serializer__init(&dir_data, sizeof(dir_data), - 50 + count * 200 + entries_len, + 50 + count * ENTRY_SIZE + + entries_len + lengths_len, scratch_pool); /* serialize entries references */ @@ -292,24 +302,32 @@ serialize_dir(apr_array_header_t *entries, return context; } -/* Utility function to reconstruct a dir entries array from serialized data - * in BUFFER and DIR_DATA. Allocation will be made form POOL. +/* Utility function to reconstruct a dir entries struct from serialized data + * in BUFFER and DIR_DATA. Allocation will be made form RESULT_POOL. */ -static apr_array_header_t * -deserialize_dir(void *buffer, dir_data_t *dir_data, apr_pool_t *pool) +static svn_fs_x__dir_data_t * +deserialize_dir(void *buffer, + dir_data_t *dir_data, + apr_pool_t *result_pool) { - apr_array_header_t *result - = apr_array_make(pool, dir_data->count, sizeof(svn_fs_x__dirent_t *)); + svn_fs_x__dir_data_t *result; apr_size_t i; apr_size_t count; svn_fs_x__dirent_t *entry; svn_fs_x__dirent_t **entries; + /* Construct empty directory object. */ + result = apr_pcalloc(result_pool, sizeof(*result)); + result->entries + = apr_array_make(result_pool, dir_data->count, + sizeof(svn_fs_x__dirent_t *)); + result->txn_filesize = dir_data->txn_filesize; + /* resolve the reference to the entries array */ svn_temp_deserializer__resolve(buffer, (void **)&dir_data->entries); entries = dir_data->entries; - /* fixup the references within each entry and add it to the hash */ + /* fixup the references within each entry and add it to the RESULT */ for (i = 0, count = dir_data->count; i < count; ++i) { svn_temp_deserializer__resolve(entries, (void **)&entries[i]); @@ -319,16 +337,19 @@ deserialize_dir(void *buffer, dir_data_t *dir_data, apr_pool_t *pool) svn_temp_deserializer__resolve(entry, (void **)&entry->name); /* add the entry to the hash */ - APR_ARRAY_PUSH(result, svn_fs_x__dirent_t *) = entry; + APR_ARRAY_PUSH(result->entries, svn_fs_x__dirent_t *) = entry; } /* return the now complete hash */ return result; } -void -svn_fs_x__noderev_serialize(svn_temp_serializer__context_t *context, - svn_fs_x__noderev_t * const *noderev_p) +/** + * Serialize a NODEREV_P within the serialization CONTEXT. + */ +static void +noderev_serialize(svn_temp_serializer__context_t *context, + svn_fs_x__noderev_t * const *noderev_p) { const svn_fs_x__noderev_t *noderev = *noderev_p; if (noderev == NULL) @@ -351,11 +372,12 @@ svn_fs_x__noderev_serialize(svn_temp_serializer__context_t *context, svn_temp_serializer__pop(context); } - -void -svn_fs_x__noderev_deserialize(void *buffer, - svn_fs_x__noderev_t **noderev_p, - apr_pool_t *pool) +/** + * Deserialize a NODEREV_P within the BUFFER and associate it with. + */ +static void +noderev_deserialize(void *buffer, + svn_fs_x__noderev_t **noderev_p) { svn_fs_x__noderev_t *noderev; @@ -451,7 +473,7 @@ svn_error_t * svn_fs_x__deserialize_txdelta_window(void **item, void *buffer, apr_size_t buffer_size, - apr_pool_t *pool) + apr_pool_t *result_pool) { svn_txdelta_window_t *window; @@ -474,38 +496,6 @@ svn_fs_x__deserialize_txdelta_window(void **item, return SVN_NO_ERROR; } -svn_error_t * -svn_fs_x__serialize_manifest(void **data, - apr_size_t *data_len, - void *in, - apr_pool_t *pool) -{ - apr_array_header_t *manifest = in; - - *data_len = sizeof(apr_off_t) *manifest->nelts; - *data = apr_palloc(pool, *data_len); - memcpy(*data, manifest->elts, *data_len); - - return SVN_NO_ERROR; -} - -svn_error_t * -svn_fs_x__deserialize_manifest(void **out, - void *data, - apr_size_t data_len, - apr_pool_t *pool) -{ - apr_array_header_t *manifest = apr_array_make(pool, 1, sizeof(apr_off_t)); - - manifest->nelts = (int) (data_len / sizeof(apr_off_t)); - manifest->nalloc = (int) (data_len / sizeof(apr_off_t)); - manifest->elts = (char*)data; - - *out = manifest; - - return SVN_NO_ERROR; -} - /* Auxiliary structure representing the content of a properties hash. This structure is much easier to (de-)serialize than an apr_hash. */ @@ -579,7 +569,7 @@ svn_fs_x__serialize_properties(void **data, /* create our auxiliary data structure */ properties.count = apr_hash_count(hash); properties.keys = apr_palloc(pool, sizeof(const char*) * (properties.count + 1)); - properties.values = apr_palloc(pool, sizeof(const char*) * properties.count); + properties.values = apr_palloc(pool, sizeof(const svn_string_t *) * properties.count); /* populate it with the hash entries */ for (hi = apr_hash_first(pool, hash), i=0; hi; hi = apr_hash_next(hi), ++i) @@ -611,9 +601,9 @@ svn_error_t * svn_fs_x__deserialize_properties(void **out, void *data, apr_size_t data_len, - apr_pool_t *pool) + apr_pool_t *result_pool) { - apr_hash_t *hash = svn_hash__make(pool); + apr_hash_t *hash = svn_hash__make(result_pool); properties_data_t *properties = (properties_data_t *)data; size_t i; @@ -661,7 +651,7 @@ svn_fs_x__serialize_node_revision(void **buffer, pool); /* serialize the noderev */ - svn_fs_x__noderev_serialize(context, &noderev); + noderev_serialize(context, &noderev); /* return serialized data */ serialized = svn_temp_serializer__get(context); @@ -675,13 +665,13 @@ svn_error_t * svn_fs_x__deserialize_node_revision(void **item, void *buffer, apr_size_t buffer_size, - apr_pool_t *pool) + apr_pool_t *result_pool) { /* Copy the _full_ buffer as it also contains the sub-structures. */ svn_fs_x__noderev_t *noderev = (svn_fs_x__noderev_t *)buffer; /* fixup of all pointers etc. */ - svn_fs_x__noderev_deserialize(noderev, &noderev, pool); + noderev_deserialize(noderev, &noderev); /* done */ *item = noderev; @@ -689,16 +679,18 @@ svn_fs_x__deserialize_node_revision(void **item, } /* Utility function that returns the directory serialized inside CONTEXT - * to DATA and DATA_LEN. */ + * to DATA and DATA_LEN. If OVERPROVISION is set, allocate some extra + * room for future in-place changes by svn_fs_x__replace_dir_entry. */ static svn_error_t * return_serialized_dir_context(svn_temp_serializer__context_t *context, void **data, - apr_size_t *data_len) + apr_size_t *data_len, + svn_boolean_t overprovision) { svn_stringbuf_t *serialized = svn_temp_serializer__get(context); *data = serialized->data; - *data_len = serialized->blocksize; + *data_len = overprovision ? serialized->blocksize : serialized->len; ((dir_data_t *)serialized->data)->len = serialized->len; return SVN_NO_ERROR; @@ -710,26 +702,27 @@ svn_fs_x__serialize_dir_entries(void **data, void *in, apr_pool_t *pool) { - apr_array_header_t *dir = in; + svn_fs_x__dir_data_t *dir = in; /* serialize the dir content into a new serialization context * and return the serialized data */ return return_serialized_dir_context(serialize_dir(dir, pool), data, - data_len); + data_len, + FALSE); } svn_error_t * svn_fs_x__deserialize_dir_entries(void **out, void *data, apr_size_t data_len, - apr_pool_t *pool) + apr_pool_t *result_pool) { /* Copy the _full_ buffer as it also contains the sub-structures. */ dir_data_t *dir_data = (dir_data_t *)data; /* reconstruct the hash from the serialized data */ - *out = deserialize_dir(dir_data, dir_data, pool); + *out = deserialize_dir(dir_data, dir_data, result_pool); return SVN_NO_ERROR; } @@ -749,6 +742,20 @@ svn_fs_x__get_sharded_offset(void **out, return SVN_NO_ERROR; } +svn_error_t * +svn_fs_x__extract_dir_filesize(void **out, + const void *data, + apr_size_t data_len, + void *baton, + apr_pool_t *pool) +{ + const dir_data_t *dir_data = data; + + *(svn_filesize_t *)out = dir_data->txn_filesize; + + return SVN_NO_ERROR; +} + /* Utility function that returns the lowest index of the first entry in * *ENTRIES that points to a dir entry with a name equal or larger than NAME. * If an exact match has been found, *FOUND will be set to TRUE. COUNT is @@ -832,6 +839,10 @@ svn_fs_x__extract_dir_entry(void **out, const apr_uint32_t *lengths = svn_temp_deserializer__ptr(data, (const void *const *)&dir_data->lengths); + /* Before we return, make sure we tell the caller this data is even still + relevant. */ + b->out_of_date = dir_data->txn_filesize != b->txn_filesize; + /* Special case: Early out for empty directories. That simplifies tests further down the road. */ *out = NULL; @@ -858,8 +869,9 @@ svn_fs_x__extract_dir_entry(void **out, if (found) b->hint = pos; - /* de-serialize that entry or return NULL, if no match has been found */ - if (found) + /* de-serialize that entry or return NULL, if no match has been found. + * Be sure to check that the directory contents is still up-to-date. */ + if (found && !b->out_of_date) { const svn_fs_x__dirent_t *source = svn_temp_deserializer__ptr(entries, (const void *const *)&entries[pos]); @@ -872,8 +884,7 @@ svn_fs_x__extract_dir_entry(void **out, apr_size_t size = lengths[pos]; /* copy & deserialize the entry */ - svn_fs_x__dirent_t *new_entry = apr_palloc(pool, size); - memcpy(new_entry, source, size); + svn_fs_x__dirent_t *new_entry = apr_pmemdup(pool, source, size); svn_temp_deserializer__resolve(new_entry, (void **)&new_entry->name); *(svn_fs_x__dirent_t **)out = new_entry; @@ -893,32 +904,34 @@ slowly_replace_dir_entry(void **data, { replace_baton_t *replace_baton = (replace_baton_t *)baton; dir_data_t *dir_data = (dir_data_t *)*data; - apr_array_header_t *dir; + svn_fs_x__dir_data_t *dir; int idx = -1; svn_fs_x__dirent_t *entry; + apr_array_header_t *entries; SVN_ERR(svn_fs_x__deserialize_dir_entries((void **)&dir, *data, dir_data->len, pool)); - entry = svn_fs_x__find_dir_entry(dir, replace_baton->name, &idx); + entries = dir->entries; + entry = svn_fs_x__find_dir_entry(entries, replace_baton->name, &idx); /* Replacement or removal? */ if (replace_baton->new_entry) { /* Replace ENTRY with / insert the NEW_ENTRY */ if (entry) - APR_ARRAY_IDX(dir, idx, svn_fs_x__dirent_t *) + APR_ARRAY_IDX(entries, idx, svn_fs_x__dirent_t *) = replace_baton->new_entry; else - svn_sort__array_insert(dir, &replace_baton->new_entry, idx); + svn_sort__array_insert(entries, &replace_baton->new_entry, idx); } else { /* Remove the old ENTRY. */ if (entry) - svn_sort__array_delete(dir, idx, 1); + svn_sort__array_delete(entries, idx, 1); } return svn_fs_x__serialize_dir_entries(data, data_len, dir, pool); @@ -940,6 +953,12 @@ svn_fs_x__replace_dir_entry(void **data, svn_temp_serializer__context_t *context; + /* update the cached file length info. + * Because we are writing to the cache, it is fair to assume that the + * caller made sure that the current contents is consistent with the + * previous state of the directory file. */ + dir_data->txn_filesize = replace_baton->txn_filesize; + /* after quite a number of operations, let's re-pack everything. * This is to limit the number of wasted space as we cannot overwrite * existing data but must always append. */ @@ -1012,9 +1031,7 @@ svn_fs_x__replace_dir_entry(void **data, serialize_dir_entry(context, &entries[pos], &length); /* return the updated serialized data */ - SVN_ERR (return_serialized_dir_context(context, - data, - data_len)); + SVN_ERR(return_serialized_dir_context(context, data, data_len, TRUE)); /* since the previous call may have re-allocated the buffer, the lengths * pointer may no longer point to the entry in that buffer. Therefore, @@ -1029,17 +1046,26 @@ svn_fs_x__replace_dir_entry(void **data, return SVN_NO_ERROR; } +svn_error_t * +svn_fs_x__reset_txn_filesize(void **data, + apr_size_t *data_len, + void *baton, + apr_pool_t *pool) +{ + dir_data_t *dir_data = (dir_data_t *)*data; + dir_data->txn_filesize = SVN_INVALID_FILESIZE; + + return SVN_NO_ERROR; +} + svn_error_t * svn_fs_x__serialize_rep_header(void **data, apr_size_t *data_len, void *in, apr_pool_t *pool) { - svn_fs_x__rep_header_t *copy = apr_palloc(pool, sizeof(*copy)); - *copy = *(svn_fs_x__rep_header_t *)in; - *data_len = sizeof(svn_fs_x__rep_header_t); - *data = copy; + *data = in; return SVN_NO_ERROR; } @@ -1048,12 +1074,8 @@ svn_error_t * svn_fs_x__deserialize_rep_header(void **out, void *data, apr_size_t data_len, - apr_pool_t *pool) + apr_pool_t *result_pool) { - svn_fs_x__rep_header_t *copy = apr_palloc(pool, sizeof(*copy)); - SVN_ERR_ASSERT(data_len == sizeof(*copy)); - - *copy = *(svn_fs_x__rep_header_t *)data; *out = data; return SVN_NO_ERROR; @@ -1088,8 +1110,7 @@ serialize_change(svn_temp_serializer__context_t *context, */ static void deserialize_change(void *buffer, - svn_fs_x__change_t **change_p, - apr_pool_t *pool) + svn_fs_x__change_t **change_p) { svn_fs_x__change_t * change; @@ -1105,47 +1126,29 @@ deserialize_change(void *buffer, svn_temp_deserializer__resolve(change, (void **)&change->copyfrom_path); } -/* Auxiliary structure representing the content of a svn_fs_x__change_t array. - This structure is much easier to (de-)serialize than an APR array. - */ -typedef struct changes_data_t -{ - /* number of entries in the array */ - int count; - - /* reference to the changes */ - svn_fs_x__change_t **changes; -} changes_data_t; - svn_error_t * svn_fs_x__serialize_changes(void **data, apr_size_t *data_len, void *in, apr_pool_t *pool) { - apr_array_header_t *array = in; - changes_data_t changes; + svn_fs_x__changes_list_t *changes = in; svn_temp_serializer__context_t *context; svn_stringbuf_t *serialized; int i; - /* initialize our auxiliary data structure and link it to the - * array elements */ - changes.count = array->nelts; - changes.changes = (svn_fs_x__change_t **)array->elts; - /* serialize it and all its elements */ - context = svn_temp_serializer__init(&changes, - sizeof(changes), - changes.count * 250, + context = svn_temp_serializer__init(changes, + sizeof(*changes), + changes->count * 250, pool); svn_temp_serializer__push(context, - (const void * const *)&changes.changes, - changes.count * sizeof(svn_fs_x__change_t*)); + (const void * const *)&changes->changes, + changes->count * sizeof(*changes->changes)); - for (i = 0; i < changes.count; ++i) - serialize_change(context, &changes.changes[i]); + for (i = 0; i < changes->count; ++i) + serialize_change(context, &changes->changes[i]); svn_temp_serializer__pop(context); @@ -1162,12 +1165,10 @@ svn_error_t * svn_fs_x__deserialize_changes(void **out, void *data, apr_size_t data_len, - apr_pool_t *pool) + apr_pool_t *result_pool) { int i; - changes_data_t *changes = (changes_data_t *)data; - apr_array_header_t *array = apr_array_make(pool, 0, - sizeof(svn_fs_x__change_t *)); + svn_fs_x__changes_list_t *changes = (svn_fs_x__changes_list_t *)data; /* de-serialize our auxiliary data structure */ svn_temp_deserializer__resolve(changes, (void**)&changes->changes); @@ -1175,163 +1176,10 @@ svn_fs_x__deserialize_changes(void **out, /* de-serialize each entry and add it to the array */ for (i = 0; i < changes->count; ++i) deserialize_change(changes->changes, - (svn_fs_x__change_t **)&changes->changes[i], - pool); - - /* Use the changes buffer as the array's data buffer - * (DATA remains valid for at least as long as POOL). */ - array->elts = (char *)changes->changes; - array->nelts = changes->count; - array->nalloc = changes->count; + (svn_fs_x__change_t **)&changes->changes[i]); /* done */ - *out = array; + *out = changes; return SVN_NO_ERROR; } - -/* Auxiliary structure representing the content of a svn_mergeinfo_t hash. - This structure is much easier to (de-)serialize than an APR array. - */ -typedef struct mergeinfo_data_t -{ - /* number of paths in the hash */ - unsigned count; - - /* COUNT keys (paths) */ - const char **keys; - - /* COUNT keys lengths (strlen of path) */ - apr_ssize_t *key_lengths; - - /* COUNT entries, each giving the number of ranges for the key */ - int *range_counts; - - /* all ranges in a single, concatenated buffer */ - svn_merge_range_t *ranges; -} mergeinfo_data_t; - -svn_error_t * -svn_fs_x__serialize_mergeinfo(void **data, - apr_size_t *data_len, - void *in, - apr_pool_t *pool) -{ - svn_mergeinfo_t mergeinfo = in; - mergeinfo_data_t merges; - svn_temp_serializer__context_t *context; - svn_stringbuf_t *serialized; - apr_hash_index_t *hi; - unsigned i; - int k; - apr_size_t range_count; - - /* initialize our auxiliary data structure */ - merges.count = apr_hash_count(mergeinfo); - merges.keys = apr_palloc(pool, sizeof(*merges.keys) * merges.count); - merges.key_lengths = apr_palloc(pool, sizeof(*merges.key_lengths) * - merges.count); - merges.range_counts = apr_palloc(pool, sizeof(*merges.range_counts) * - merges.count); - - i = 0; - range_count = 0; - for (hi = apr_hash_first(pool, mergeinfo); hi; hi = apr_hash_next(hi), ++i) - { - svn_rangelist_t *ranges; - apr_hash_this(hi, (const void**)&merges.keys[i], - &merges.key_lengths[i], - (void **)&ranges); - merges.range_counts[i] = ranges->nelts; - range_count += ranges->nelts; - } - - merges.ranges = apr_palloc(pool, sizeof(*merges.ranges) * range_count); - - i = 0; - for (hi = apr_hash_first(pool, mergeinfo); hi; hi = apr_hash_next(hi)) - { - svn_rangelist_t *ranges = apr_hash_this_val(hi); - for (k = 0; k < ranges->nelts; ++k, ++i) - merges.ranges[i] = *APR_ARRAY_IDX(ranges, k, svn_merge_range_t*); - } - - /* serialize it and all its elements */ - context = svn_temp_serializer__init(&merges, - sizeof(merges), - range_count * 30, - pool); - - /* keys array */ - svn_temp_serializer__push(context, - (const void * const *)&merges.keys, - merges.count * sizeof(*merges.keys)); - - for (i = 0; i < merges.count; ++i) - svn_temp_serializer__add_string(context, &merges.keys[i]); - - svn_temp_serializer__pop(context); - - /* key lengths array */ - svn_temp_serializer__add_leaf(context, - (const void * const *)&merges.key_lengths, - merges.count * sizeof(*merges.key_lengths)); - - /* range counts array */ - svn_temp_serializer__add_leaf(context, - (const void * const *)&merges.range_counts, - merges.count * sizeof(*merges.range_counts)); - - /* ranges */ - svn_temp_serializer__add_leaf(context, - (const void * const *)&merges.ranges, - range_count * sizeof(*merges.ranges)); - - /* return the serialized result */ - serialized = svn_temp_serializer__get(context); - - *data = serialized->data; - *data_len = serialized->len; - - return SVN_NO_ERROR; -} - -svn_error_t * -svn_fs_x__deserialize_mergeinfo(void **out, - void *data, - apr_size_t data_len, - apr_pool_t *pool) -{ - unsigned i; - int k, n; - mergeinfo_data_t *merges = (mergeinfo_data_t *)data; - svn_mergeinfo_t mergeinfo; - - /* de-serialize our auxiliary data structure */ - svn_temp_deserializer__resolve(merges, (void**)&merges->keys); - svn_temp_deserializer__resolve(merges, (void**)&merges->key_lengths); - svn_temp_deserializer__resolve(merges, (void**)&merges->range_counts); - svn_temp_deserializer__resolve(merges, (void**)&merges->ranges); - - /* de-serialize keys and add entries to the result */ - n = 0; - mergeinfo = svn_hash__make(pool); - for (i = 0; i < merges->count; ++i) - { - svn_rangelist_t *ranges = apr_array_make(pool, - merges->range_counts[i], - sizeof(svn_merge_range_t*)); - for (k = 0; k < merges->range_counts[i]; ++k, ++n) - APR_ARRAY_PUSH(ranges, svn_merge_range_t*) = &merges->ranges[n]; - - svn_temp_deserializer__resolve(merges->keys, - (void**)&merges->keys[i]); - apr_hash_set(mergeinfo, merges->keys[i], merges->key_lengths[i], ranges); - } - - /* done */ - *out = mergeinfo; - - return SVN_NO_ERROR; -} - diff --git a/subversion/libsvn_fs_x/temp_serializer.h b/subversion/libsvn_fs_x/temp_serializer.h index 80f500484d03..d6156d644743 100644 --- a/subversion/libsvn_fs_x/temp_serializer.h +++ b/subversion/libsvn_fs_x/temp_serializer.h @@ -20,8 +20,8 @@ * ==================================================================== */ -#ifndef SVN_LIBSVN_FS__TEMP_SERIALIZER_H -#define SVN_LIBSVN_FS__TEMP_SERIALIZER_H +#ifndef SVN_LIBSVN_FS_X_TEMP_SERIALIZER_H +#define SVN_LIBSVN_FS_X_TEMP_SERIALIZER_H #include "private/svn_temp_serializer.h" #include "fs.h" @@ -29,28 +29,12 @@ /** * Prepend the @a number to the @a string in a space efficient way such that * no other (number,string) combination can produce the same result. - * Allocate temporaries as well as the result from @a pool. + * Allocate the result from @a result_pool. */ const char* svn_fs_x__combine_number_and_string(apr_int64_t number, const char *string, - apr_pool_t *pool); - -/** - * Serialize a @a noderev_p within the serialization @a context. - */ -void -svn_fs_x__noderev_serialize(struct svn_temp_serializer__context_t *context, - svn_fs_x__noderev_t * const *noderev_p); - -/** - * Deserialize a @a noderev_p within the @a buffer and associate it with - * @a pool. - */ -void -svn_fs_x__noderev_deserialize(void *buffer, - svn_fs_x__noderev_t **noderev_p, - apr_pool_t *pool); + apr_pool_t *result_pool); /** * Serialize APR array @a *a within the serialization @a context. @@ -62,12 +46,12 @@ svn_fs_x__serialize_apr_array(struct svn_temp_serializer__context_t *context, /** * Deserialize APR @a *array within the @a buffer. Set its pool member to - * @a pool. The elements within the array must not contain pointers. + * @a result_pool. The elements within the array must not contain pointers. */ void svn_fs_x__deserialize_apr_array(void *buffer, apr_array_header_t **array, - apr_pool_t *pool); + apr_pool_t *result_pool); /** @@ -104,27 +88,7 @@ svn_error_t * svn_fs_x__deserialize_txdelta_window(void **item, void *buffer, apr_size_t buffer_size, - apr_pool_t *pool); - -/** - * Implements #svn_cache__serialize_func_t for a manifest - * (@a in is an #apr_array_header_t of apr_off_t elements). - */ -svn_error_t * -svn_fs_x__serialize_manifest(void **data, - apr_size_t *data_len, - void *in, - apr_pool_t *pool); - -/** - * Implements #svn_cache__deserialize_func_t for a manifest - * (@a *out is an #apr_array_header_t of apr_off_t elements). - */ -svn_error_t * -svn_fs_x__deserialize_manifest(void **out, - void *data, - apr_size_t data_len, - apr_pool_t *pool); + apr_pool_t *result_pool); /** * Implements #svn_cache__serialize_func_t for a properties hash @@ -144,7 +108,7 @@ svn_error_t * svn_fs_x__deserialize_properties(void **out, void *data, apr_size_t data_len, - apr_pool_t *pool); + apr_pool_t *result_pool); /** * Implements #svn_cache__serialize_func_t for #svn_fs_x__noderev_t @@ -162,10 +126,10 @@ svn_error_t * svn_fs_x__deserialize_node_revision(void **item, void *buffer, apr_size_t buffer_size, - apr_pool_t *pool); + apr_pool_t *result_pool); /** - * Implements #svn_cache__serialize_func_t for a directory contents array + * Implements #svn_cache__serialize_func_t for a #svn_fs_x__dir_data_t */ svn_error_t * svn_fs_x__serialize_dir_entries(void **data, @@ -174,13 +138,13 @@ svn_fs_x__serialize_dir_entries(void **data, apr_pool_t *pool); /** - * Implements #svn_cache__deserialize_func_t for a directory contents array + * Implements #svn_cache__deserialize_func_t for a #svn_fs_x__dir_data_t */ svn_error_t * svn_fs_x__deserialize_dir_entries(void **out, void *data, apr_size_t data_len, - apr_pool_t *pool); + apr_pool_t *result_pool); /** * Implements #svn_cache__partial_getter_func_t. Set (apr_off_t) @a *out @@ -193,6 +157,18 @@ svn_fs_x__get_sharded_offset(void **out, void *baton, apr_pool_t *pool); +/** + * Implements #svn_cache__partial_getter_func_t. + * Set (svn_filesize_t) @a *out to the filesize info stored with the + * serialized directory in @a data of @a data_len. @a baton is unused. + */ +svn_error_t * +svn_fs_x__extract_dir_filesize(void **out, + const void *data, + apr_size_t data_len, + void *baton, + apr_pool_t *pool); + /** * Baton type to be used with svn_fs_x__extract_dir_entry. */ typedef struct svn_fs_x__ede_baton_t @@ -202,12 +178,24 @@ typedef struct svn_fs_x__ede_baton_t /* Lookup hint [in / out] */ apr_size_t hint; + + /** Current length of the in-txn in-disk representation of the directory. + * SVN_INVALID_FILESIZE if unknown. */ + svn_filesize_t txn_filesize; + + /** Will be set by the callback. If FALSE, the cached data is out of date. + * We need this indicator because the svn_cache__t interface will always + * report the lookup as a success (FOUND==TRUE) if the generic lookup was + * successful -- regardless of what the entry extraction callback does. */ + svn_boolean_t out_of_date; } svn_fs_x__ede_baton_t; /** * Implements #svn_cache__partial_getter_func_t for a single * #svn_fs_x__dirent_t within a serialized directory contents hash, - * identified by its name (given in @a svn_fs_x__ede_baton_t @a *baton). + * identified by its name (in (svn_fs_x__ede_baton_t *) @a *baton). + * If the filesize specified in the baton does not match the cached + * value for this directory, @a *out will be NULL as well. */ svn_error_t * svn_fs_x__extract_dir_entry(void **out, @@ -220,7 +208,10 @@ svn_fs_x__extract_dir_entry(void **out, * Describes the change to be done to a directory: Set the entry * identify by @a name to the value @a new_entry. If the latter is * @c NULL, the entry shall be removed if it exists. Otherwise it - * will be replaced or automatically added, respectively. + * will be replaced or automatically added, respectively. The + * @a filesize allows readers to identify stale cache data (e.g. + * due to concurrent access to txns); writers use it to update the + * cached file size info. */ typedef struct replace_baton_t { @@ -229,6 +220,10 @@ typedef struct replace_baton_t /** directory entry to insert instead */ svn_fs_x__dirent_t *new_entry; + + /** Current length of the in-txn in-disk representation of the directory. + * SVN_INVALID_FILESIZE if unknown. */ + svn_filesize_t txn_filesize; } replace_baton_t; /** @@ -242,6 +237,17 @@ svn_fs_x__replace_dir_entry(void **data, void *baton, apr_pool_t *pool); +/** + * Implements #svn_cache__partial_setter_func_t for a #svn_fs_x__dir_data_t + * at @a *data, resetting its txn_filesize field to SVN_INVALID_FILESIZE. + * &a baton should be NULL. + */ +svn_error_t * +svn_fs_x__reset_txn_filesize(void **data, + apr_size_t *data_len, + void *baton, + apr_pool_t *pool); + /** * Implements #svn_cache__serialize_func_t for a #svn_fs_x__rep_header_t. */ @@ -258,11 +264,36 @@ svn_error_t * svn_fs_x__deserialize_rep_header(void **out, void *data, apr_size_t data_len, - apr_pool_t *pool); + apr_pool_t *result_pool); + +/*** Block of changes in a changed paths list. */ +typedef struct svn_fs_x__changes_list_t +{ + /* Offset of the first element in CHANGES within the changed paths list + on disk. */ + apr_off_t start_offset; + + /* Offset of the first element behind CHANGES within the changed paths + list on disk. */ + apr_off_t end_offset; + + /* End of list reached? This may have false negatives in case the number + of elements in the list is a multiple of our block / range size. */ + svn_boolean_t eol; + + /* Array of #svn_fs_x__change_t * representing a consecutive sub-range of + elements in a changed paths list. */ + + /* number of entries in the array */ + int count; + + /* reference to the changes */ + svn_fs_x__change_t **changes; + +} svn_fs_x__changes_list_t; /** - * Implements #svn_cache__serialize_func_t for an #apr_array_header_t of - * #svn_fs_x__change_t *. + * Implements #svn_cache__serialize_func_t for a #svn_fs_x__changes_list_t. */ svn_error_t * svn_fs_x__serialize_changes(void **data, @@ -271,31 +302,12 @@ svn_fs_x__serialize_changes(void **data, apr_pool_t *pool); /** - * Implements #svn_cache__deserialize_func_t for an #apr_array_header_t of - * #svn_fs_x__change_t *. + * Implements #svn_cache__deserialize_func_t for a #svn_fs_x__changes_list_t. */ svn_error_t * svn_fs_x__deserialize_changes(void **out, void *data, apr_size_t data_len, - apr_pool_t *pool); - -/** - * Implements #svn_cache__serialize_func_t for #svn_mergeinfo_t objects. - */ -svn_error_t * -svn_fs_x__serialize_mergeinfo(void **data, - apr_size_t *data_len, - void *in, - apr_pool_t *pool); - -/** - * Implements #svn_cache__deserialize_func_t for #svn_mergeinfo_t objects. - */ -svn_error_t * -svn_fs_x__deserialize_mergeinfo(void **out, - void *data, - apr_size_t data_len, - apr_pool_t *pool); + apr_pool_t *result_pool); #endif diff --git a/subversion/libsvn_fs_x/transaction.c b/subversion/libsvn_fs_x/transaction.c index 5f3adc595e03..52c958f3ece1 100644 --- a/subversion/libsvn_fs_x/transaction.c +++ b/subversion/libsvn_fs_x/transaction.c @@ -25,6 +25,7 @@ #include #include +#include "svn_error_codes.h" #include "svn_hash.h" #include "svn_props.h" #include "svn_sorts.h" @@ -41,6 +42,8 @@ #include "lock.h" #include "rep-cache.h" #include "index.h" +#include "batch_fsync.h" +#include "revprops.h" #include "private/svn_fs_util.h" #include "private/svn_fspath.h" @@ -279,17 +282,33 @@ with_some_lock_file(with_lock_baton_t *baton) ffd->has_write_lock = TRUE; } - /* nobody else will modify the repo state - => read HEAD & pack info once */ if (baton->is_inner_most_lock) { - err = svn_fs_x__update_min_unpacked_rev(fs, pool); - if (!err) - err = svn_fs_x__youngest_rev(&ffd->youngest_rev_cache, fs, pool); - } + /* Use a separate sub-pool for the actual function body and a few + * file accesses. So, the lock-pool only contains the file locks. + */ + apr_pool_t *subpool = svn_pool_create(pool); - if (!err) - err = baton->body(baton->baton, pool); + /* nobody else will modify the repo state + => read HEAD & pack info once */ + err = svn_fs_x__update_min_unpacked_rev(fs, subpool); + if (!err) + err = svn_fs_x__youngest_rev(&ffd->youngest_rev_cache, fs, + subpool); + + /* We performed a few file operations. Clean the pool. */ + svn_pool_clear(subpool); + + if (!err) + err = baton->body(baton->baton, subpool); + + svn_pool_destroy(subpool); + } + else + { + /* Nested lock level */ + err = baton->body(baton->baton, pool); + } } if (baton->is_outer_most_lock) @@ -315,8 +334,8 @@ with_lock(void *baton, /* Enum identifying a filesystem lock. */ typedef enum lock_id_t { - write_lock, txn_lock, + write_lock, pack_lock } lock_id_t; @@ -332,12 +351,6 @@ init_lock_baton(with_lock_baton_t *baton, switch (lock_id) { - case write_lock: - baton->mutex = ffsd->fs_write_lock; - baton->lock_path = svn_fs_x__path_lock(baton->fs, baton->lock_pool); - baton->is_global_lock = TRUE; - break; - case txn_lock: baton->mutex = ffsd->txn_current_lock; baton->lock_path = svn_fs_x__path_txn_current_lock(baton->fs, @@ -345,6 +358,12 @@ init_lock_baton(with_lock_baton_t *baton, baton->is_global_lock = FALSE; break; + case write_lock: + baton->mutex = ffsd->fs_write_lock; + baton->lock_path = svn_fs_x__path_lock(baton->fs, baton->lock_pool); + baton->is_global_lock = TRUE; + break; + case pack_lock: baton->mutex = ffsd->fs_pack_lock; baton->lock_path = svn_fs_x__path_pack_lock(baton->fs, @@ -477,10 +496,10 @@ svn_fs_x__with_all_locks(svn_fs_t *fs, fs_fs_shared_data_t. The lock chain is being created in innermost (last to acquire) -> outermost (first to acquire) order. */ with_lock_baton_t *lock_baton - = create_lock_baton(fs, write_lock, body, baton, scratch_pool); + = create_lock_baton(fs, txn_lock, body, baton, scratch_pool); + lock_baton = chain_lock_baton(write_lock, lock_baton); lock_baton = chain_lock_baton(pack_lock, lock_baton); - lock_baton = chain_lock_baton(txn_lock, lock_baton); return svn_error_trace(with_lock(lock_baton, scratch_pool)); } @@ -702,7 +721,8 @@ get_writable_proto_rev(apr_file_t **file, /* Now open the prototype revision file and seek to the end. */ err = svn_io_file_open(file, svn_fs_x__path_txn_proto_rev(fs, txn_id, pool), - APR_WRITE | APR_BUFFERED, APR_OS_DEFAULT, pool); + APR_READ | APR_WRITE | APR_BUFFERED, APR_OS_DEFAULT, + pool); /* You might expect that we could dispense with the following seek and achieve the same thing by opening the file using APR_APPEND. @@ -858,16 +878,35 @@ unparse_dir_entry(svn_fs_x__dirent_t *dirent, svn_stream_t *stream, apr_pool_t *scratch_pool) { - const char *val - = apr_psprintf(scratch_pool, "%s %s", - (dirent->kind == svn_node_file) ? SVN_FS_X__KIND_FILE - : SVN_FS_X__KIND_DIR, - svn_fs_x__id_unparse(&dirent->id, scratch_pool)->data); + apr_size_t to_write; + apr_size_t name_len = strlen(dirent->name); + + /* A buffer with sufficient space for + * - entry name + 1 terminating NUL + * - 1 byte for the node kind + * - 2 numbers in 7b/8b encoding for the noderev-id + */ + apr_byte_t *buffer = apr_palloc(scratch_pool, + name_len + 2 + 2 * SVN__MAX_ENCODED_UINT_LEN); + + /* Now construct the value. */ + apr_byte_t *p = buffer; + + /* The entry name, terminated by NUL. */ + memcpy(p, dirent->name, name_len + 1); + p += name_len + 1; + + /* The entry type. */ + p = svn__encode_uint(p, dirent->kind); + + /* The ID. */ + p = svn__encode_int(p, dirent->id.change_set); + p = svn__encode_uint(p, dirent->id.number); + + /* Add the entry to the output stream. */ + to_write = p - buffer; + SVN_ERR(svn_stream_write(stream, (const char *)buffer, &to_write)); - SVN_ERR(svn_stream_printf(stream, scratch_pool, "K %" APR_SIZE_T_FMT - "\n%s\nV %" APR_SIZE_T_FMT "\n%s\n", - strlen(dirent->name), dirent->name, - strlen(val), val)); return SVN_NO_ERROR; } @@ -878,8 +917,15 @@ unparse_dir_entries(apr_array_header_t *entries, svn_stream_t *stream, apr_pool_t *scratch_pool) { + apr_byte_t buffer[SVN__MAX_ENCODED_UINT_LEN]; apr_pool_t *iterpool = svn_pool_create(scratch_pool); int i; + + /* Write the number of entries. */ + apr_size_t to_write = svn__encode_uint(buffer, entries->nelts) - buffer; + SVN_ERR(svn_stream_write(stream, (const char *)buffer, &to_write)); + + /* Write all entries */ for (i = 0; i < entries->nelts; ++i) { svn_fs_x__dirent_t *dirent; @@ -889,9 +935,6 @@ unparse_dir_entries(apr_array_header_t *entries, SVN_ERR(unparse_dir_entry(dirent, stream, iterpool)); } - SVN_ERR(svn_stream_printf(stream, scratch_pool, "%s\n", - SVN_HASH_TERMINATOR)); - svn_pool_destroy(iterpool); return SVN_NO_ERROR; } @@ -932,30 +975,10 @@ fold_change(apr_hash_t *changed_paths, /* This path already exists in the hash, so we have to merge this change into the already existing one. */ - /* Sanity check: only allow unused node revision IDs in the - `reset' case. */ - if ((! svn_fs_x__id_used(&change->noderev_id)) - && (change->change_kind != svn_fs_path_change_reset)) - return svn_error_create - (SVN_ERR_FS_CORRUPT, NULL, - _("Missing required node revision ID")); - - /* Sanity check: we should be talking about the same node - revision ID as our last change except where the last change - was a deletion. */ - if (svn_fs_x__id_used(&change->noderev_id) - && (!svn_fs_x__id_eq(&old_change->noderev_id, &change->noderev_id)) - && (old_change->change_kind != svn_fs_path_change_delete)) - return svn_error_create - (SVN_ERR_FS_CORRUPT, NULL, - _("Invalid change ordering: new node revision ID " - "without delete")); - /* Sanity check: an add, replacement, or reset must be the first thing to follow a deletion. */ if ((old_change->change_kind == svn_fs_path_change_delete) && (! ((change->change_kind == svn_fs_path_change_replace) - || (change->change_kind == svn_fs_path_change_reset) || (change->change_kind == svn_fs_path_change_add)))) return svn_error_create (SVN_ERR_FS_CORRUPT, NULL, @@ -964,8 +987,7 @@ fold_change(apr_hash_t *changed_paths, /* Sanity check: an add can't follow anything except a delete or reset. */ if ((change->change_kind == svn_fs_path_change_add) - && (old_change->change_kind != svn_fs_path_change_delete) - && (old_change->change_kind != svn_fs_path_change_reset)) + && (old_change->change_kind != svn_fs_path_change_delete)) return svn_error_create (SVN_ERR_FS_CORRUPT, NULL, _("Invalid change ordering: add change on preexisting path")); @@ -973,12 +995,6 @@ fold_change(apr_hash_t *changed_paths, /* Now, merge that change in. */ switch (change->change_kind) { - case svn_fs_path_change_reset: - /* A reset here will simply remove the path change from the - hash. */ - apr_hash_set(changed_paths, path->data, path->len, NULL); - break; - case svn_fs_path_change_delete: if (old_change->change_kind == svn_fs_path_change_add) { @@ -1207,34 +1223,65 @@ get_and_increment_txn_key_body(void *baton, apr_pool_t *scratch_pool) { get_and_increment_txn_key_baton_t *cb = baton; - const char *txn_current_filename = svn_fs_x__path_txn_current(cb->fs, - scratch_pool); - const char *tmp_filename; + svn_fs_t *fs = cb->fs; + apr_pool_t *iterpool = svn_pool_create(scratch_pool); + const char *txn_current_path = svn_fs_x__path_txn_current(fs, scratch_pool); char new_id_str[SVN_INT64_BUFFER_SIZE]; svn_stringbuf_t *buf; - SVN_ERR(svn_fs_x__read_content(&buf, txn_current_filename, scratch_pool)); + SVN_ERR(svn_fs_x__read_content(&buf, txn_current_path, scratch_pool)); - /* remove trailing newlines */ + /* Parse the txn number, stopping at the next non-digit. + * + * Note that an empty string is being interpreted as "0". + * This gives us implicit recovery if the file contents should be lost + * due to e.g. power failure. + */ cb->txn_number = svn__base36toui64(NULL, buf->data); + if (cb->txn_number == 0) + ++cb->txn_number; + + /* Check for conflicts. Those might happen if the server crashed and we + * had 'svnadmin recover' reset the txn counter. + * + * Once we found an unused txn id, claim it by creating the respective + * txn directory. + * + * Note that this is not racy because we hold the txn-current-lock. + */ + while (TRUE) + { + const char *txn_dir; + svn_node_kind_t kind; + svn_pool_clear(iterpool); + + txn_dir = svn_fs_x__path_txn_dir(fs, cb->txn_number, iterpool); + SVN_ERR(svn_io_check_path(txn_dir, &kind, iterpool)); + if (kind == svn_node_none) + { + svn_io_dir_make(txn_dir, APR_OS_DEFAULT, iterpool); + break; + } + + ++cb->txn_number; + } /* Increment the key and add a trailing \n to the string so the txn-current file has a newline in it. */ - SVN_ERR(svn_io_write_unique(&tmp_filename, - svn_dirent_dirname(txn_current_filename, - scratch_pool), - new_id_str, - svn__ui64tobase36(new_id_str, cb->txn_number+1), - svn_io_file_del_none, scratch_pool)); - SVN_ERR(svn_fs_x__move_into_place(tmp_filename, txn_current_filename, - txn_current_filename, scratch_pool)); + SVN_ERR(svn_io_write_atomic2(txn_current_path, new_id_str, + svn__ui64tobase36(new_id_str, + cb->txn_number + 1), + txn_current_path, FALSE, scratch_pool)); + + svn_pool_destroy(iterpool); return SVN_NO_ERROR; } /* Create a unique directory for a transaction in FS based on revision REV. - Return the ID for this transaction in *ID_P and *TXN_ID. Use a sequence - value in the transaction ID to prevent reuse of transaction IDs. */ + Return the ID for this transaction in *ID_P, allocated from RESULT_POOL + and *TXN_ID. Use a sequence value in the transaction ID to prevent reuse + of transaction IDs. Allocate temporaries from SCRATCH_POOL. */ static svn_error_t * create_txn_dir(const char **id_p, svn_fs_x__txn_id_t *txn_id, @@ -1243,23 +1290,20 @@ create_txn_dir(const char **id_p, apr_pool_t *scratch_pool) { get_and_increment_txn_key_baton_t cb; - const char *txn_dir; /* Get the current transaction sequence value, which is a base-36 - number, from the txn-current file, and write an - incremented value back out to the file. Place the revision - number the transaction is based off into the transaction id. */ + number, from the txn-current file, and write an + incremented value back out to the file. Place the revision + number the transaction is based off into the transaction id. */ cb.fs = fs; SVN_ERR(svn_fs_x__with_txn_current_lock(fs, get_and_increment_txn_key_body, &cb, scratch_pool)); *txn_id = cb.txn_number; - *id_p = svn_fs_x__txn_name(*txn_id, result_pool); - txn_dir = svn_fs_x__path_txn_dir(fs, *txn_id, scratch_pool); - return svn_io_dir_make(txn_dir, APR_OS_DEFAULT, scratch_pool); + return SVN_NO_ERROR; } /* Create a new transaction in filesystem FS, based on revision REV, @@ -1321,15 +1365,16 @@ create_txn(svn_fs_txn_t **txn_p, return SVN_NO_ERROR; } -/* Store the property list for transaction TXN_ID in PROPLIST. - Perform temporary allocations in POOL. */ +/* Store the property list for transaction TXN_ID in *PROPLIST, allocated + from RESULT_POOL. Perform temporary allocations in SCRATCH_POOL. */ static svn_error_t * -get_txn_proplist(apr_hash_t *proplist, +get_txn_proplist(apr_hash_t **proplist, svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool) + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { - svn_stream_t *stream; + svn_stringbuf_t *content; /* Check for issue #3696. (When we find and fix the cause, we can change * this to an assertion.) */ @@ -1339,14 +1384,20 @@ get_txn_proplist(apr_hash_t *proplist, "passed to get_txn_proplist()")); /* Open the transaction properties file. */ - SVN_ERR(svn_stream_open_readonly(&stream, - svn_fs_x__path_txn_props(fs, txn_id, pool), - pool, pool)); + SVN_ERR(svn_stringbuf_from_file2(&content, + svn_fs_x__path_txn_props(fs, txn_id, + scratch_pool), + result_pool)); /* Read in the property list. */ - SVN_ERR(svn_hash_read2(proplist, stream, SVN_HASH_TERMINATOR, pool)); + SVN_ERR_W(svn_fs_x__parse_properties(proplist, + svn_stringbuf__morph_into_string(content), + result_pool), + apr_psprintf(scratch_pool, + _("malformed property list in transaction '%s'"), + svn_fs_x__path_txn_props(fs, txn_id, scratch_pool))); - return svn_stream_close(stream); + return SVN_NO_ERROR; } /* Save the property list PROPS as the revprops for transaction TXN_ID @@ -1355,26 +1406,27 @@ static svn_error_t * set_txn_proplist(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, apr_hash_t *props, - svn_boolean_t final, apr_pool_t *scratch_pool) { - svn_stringbuf_t *buf; svn_stream_t *stream; + const char *temp_path; - /* Write out the new file contents to BUF. */ - buf = svn_stringbuf_create_ensure(1024, scratch_pool); - stream = svn_stream_from_stringbuf(buf, scratch_pool); - SVN_ERR(svn_hash_write2(props, stream, SVN_HASH_TERMINATOR, scratch_pool)); + /* Write the new contents into a temporary file. */ + SVN_ERR(svn_stream_open_unique(&stream, &temp_path, + svn_fs_x__path_txn_dir(fs, txn_id, + scratch_pool), + svn_io_file_del_none, + scratch_pool, scratch_pool)); + SVN_ERR(svn_fs_x__write_properties(stream, props, scratch_pool)); SVN_ERR(svn_stream_close(stream)); - /* Open the transaction properties file and write new contents to it. */ - SVN_ERR(svn_io_write_atomic((final - ? svn_fs_x__path_txn_props_final(fs, txn_id, - scratch_pool) - : svn_fs_x__path_txn_props(fs, txn_id, - scratch_pool)), - buf->data, buf->len, - NULL /* copy_perms_path */, scratch_pool)); + /* Replace the old file with the new one. */ + SVN_ERR(svn_io_file_rename2(temp_path, + svn_fs_x__path_txn_props(fs, txn_id, + scratch_pool), + FALSE, + scratch_pool)); + return SVN_NO_ERROR; } @@ -1402,11 +1454,12 @@ svn_fs_x__change_txn_props(svn_fs_txn_t *txn, apr_pool_t *scratch_pool) { fs_txn_data_t *ftd = txn->fsap_data; - apr_hash_t *txn_prop = apr_hash_make(scratch_pool); + apr_pool_t *subpool = svn_pool_create(scratch_pool); + apr_hash_t *txn_prop; int i; svn_error_t *err; - err = get_txn_proplist(txn_prop, txn->fs, ftd->txn_id, scratch_pool); + err = get_txn_proplist(&txn_prop, txn->fs, ftd->txn_id, subpool, subpool); /* Here - and here only - we need to deal with the possibility that the transaction property file doesn't yet exist. The rest of the implementation assumes that the file exists, but we're called to set the @@ -1423,16 +1476,16 @@ svn_fs_x__change_txn_props(svn_fs_txn_t *txn, if (svn_hash_gets(txn_prop, SVN_FS__PROP_TXN_CLIENT_DATE) && !strcmp(prop->name, SVN_PROP_REVISION_DATE)) svn_hash_sets(txn_prop, SVN_FS__PROP_TXN_CLIENT_DATE, - svn_string_create("1", scratch_pool)); + svn_string_create("1", subpool)); svn_hash_sets(txn_prop, prop->name, prop->value); } /* Create a new version of the file and write out the new props. */ /* Open the transaction properties file. */ - SVN_ERR(set_txn_proplist(txn->fs, ftd->txn_id, txn_prop, FALSE, - scratch_pool)); + SVN_ERR(set_txn_proplist(txn->fs, ftd->txn_id, txn_prop, subpool)); + svn_pool_destroy(subpool); return SVN_NO_ERROR; } @@ -1447,9 +1500,6 @@ svn_fs_x__get_txn(svn_fs_x__transaction_t **txn_p, svn_fs_x__id_t root_id; txn = apr_pcalloc(pool, sizeof(*txn)); - txn->proplist = apr_hash_make(pool); - - SVN_ERR(get_txn_proplist(txn->proplist, fs, txn_id, pool)); svn_fs_x__init_txn_root(&root_id, txn_id); SVN_ERR(svn_fs_x__get_node_revision(&noderev, fs, &root_id, pool, pool)); @@ -1462,8 +1512,8 @@ svn_fs_x__get_txn(svn_fs_x__transaction_t **txn_p, return SVN_NO_ERROR; } -/* If it is supported by the format of file system FS, store the (ITEM_INDEX, - * OFFSET) pair in the log-to-phys proto index file of transaction TXN_ID. +/* Store the (ITEM_INDEX, OFFSET) pair in the log-to-phys proto index file + * of transaction TXN_ID in filesystem FS. * Use SCRATCH_POOL for temporary allocations. */ static svn_error_t * @@ -1483,14 +1533,13 @@ store_l2p_index_entry(svn_fs_t *fs, return SVN_NO_ERROR; } -/* If it is supported by the format of file system FS, store ENTRY in the - * phys-to-log proto index file of transaction TXN_ID. - * Use SCRATCH_POOL for temporary allocations. +/* Store ENTRY in the phys-to-log proto index file of transaction TXN_ID + * in filesystem FS. Use SCRATCH_POOL for temporary allocations. */ static svn_error_t * store_p2l_index_entry(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, - svn_fs_x__p2l_entry_t *entry, + const svn_fs_x__p2l_entry_t *entry, apr_pool_t *scratch_pool) { const char *path = svn_fs_x__path_p2l_proto_index(fs, txn_id, scratch_pool); @@ -1515,19 +1564,24 @@ allocate_item_index(apr_uint64_t *item_index, char buffer[SVN_INT64_BUFFER_SIZE] = { 0 }; svn_boolean_t eof = FALSE; apr_size_t to_write; - apr_size_t read; + apr_size_t bytes_read; apr_off_t offset = 0; /* read number */ SVN_ERR(svn_io_file_open(&file, svn_fs_x__path_txn_item_index(fs, txn_id, scratch_pool), - APR_READ | APR_WRITE - | APR_CREATE | APR_BUFFERED, + APR_READ | APR_WRITE | APR_CREATE, APR_OS_DEFAULT, scratch_pool)); SVN_ERR(svn_io_file_read_full2(file, buffer, sizeof(buffer)-1, - &read, &eof, scratch_pool)); - if (read) + &bytes_read, &eof, scratch_pool)); + + /* Item index file should be shorter than SVN_INT64_BUFFER_SIZE, + otherwise we truncate data. */ + if (!eof) + return svn_error_create(SVN_ERR_FS_CORRUPT, NULL, + _("Unexpected itemidx file length")); + else if (bytes_read) SVN_ERR(svn_cstring_atoui64(item_index, buffer)); else *item_index = SVN_FS_X__ITEM_INDEX_FIRST_USER; @@ -1683,25 +1737,30 @@ svn_fs_x__purge_txn(svn_fs_t *fs, apr_pool_t *scratch_pool) { svn_fs_x__txn_id_t txn_id; + + /* The functions we are calling open files and operate on the OS FS. + Since these may allocate a non-trivial amount of memory, do that + in a SUBPOOL and clear that one up before returning. */ + apr_pool_t *subpool = svn_pool_create(scratch_pool); SVN_ERR(svn_fs_x__txn_by_name(&txn_id, txn_id_str)); /* Remove the shared transaction object associated with this transaction. */ - SVN_ERR(purge_shared_txn(fs, txn_id, scratch_pool)); + SVN_ERR(purge_shared_txn(fs, txn_id, subpool)); /* Remove the directory associated with this transaction. */ - SVN_ERR(svn_io_remove_dir2(svn_fs_x__path_txn_dir(fs, txn_id, scratch_pool), - FALSE, NULL, NULL, scratch_pool)); + SVN_ERR(svn_io_remove_dir2(svn_fs_x__path_txn_dir(fs, txn_id, subpool), + FALSE, NULL, NULL, subpool)); - /* Delete protorev and its lock, which aren't in the txn - directory. It's OK if they don't exist (for example, if this - is post-commit and the proto-rev has been moved into - place). */ + /* Delete protorev and its lock, which aren't in the txn directory. + It's OK if they don't exist (for example, if this is post-commit + and the proto-rev has been moved into place). */ SVN_ERR(svn_io_remove_file2( - svn_fs_x__path_txn_proto_rev(fs, txn_id, scratch_pool), - TRUE, scratch_pool)); + svn_fs_x__path_txn_proto_rev(fs, txn_id, subpool), + TRUE, subpool)); SVN_ERR(svn_io_remove_file2( - svn_fs_x__path_txn_proto_rev_lock(fs, txn_id, scratch_pool), - TRUE, scratch_pool)); + svn_fs_x__path_txn_proto_rev_lock(fs, txn_id, subpool), + TRUE, subpool)); + svn_pool_destroy(subpool); return SVN_NO_ERROR; } @@ -1736,12 +1795,16 @@ svn_fs_x__set_entry(svn_fs_t *fs, scratch_pool, scratch_pool); apr_file_t *file; svn_stream_t *out; + svn_filesize_t filesize; svn_fs_x__data_t *ffd = fs->fsap_data; apr_pool_t *subpool = svn_pool_create(scratch_pool); + const svn_fs_x__id_t *key = &(parent_noderev->noderev_id); + svn_fs_x__dirent_t entry; if (!rep || !svn_fs_x__is_txn(rep->id.change_set)) { apr_array_header_t *entries; + svn_fs_x__dir_data_t dir_data; /* Before we can modify the directory, we need to dump its old contents into a mutable representation file. */ @@ -1753,8 +1816,6 @@ svn_fs_x__set_entry(svn_fs_t *fs, out = svn_stream_from_aprfile2(file, TRUE, scratch_pool); SVN_ERR(unparse_dir_entries(entries, out, subpool)); - svn_pool_clear(subpool); - /* Provide the parent with a data rep if it had none before (directories so far empty). */ if (!rep) @@ -1769,23 +1830,86 @@ svn_fs_x__set_entry(svn_fs_t *fs, /* Save noderev to disk. */ SVN_ERR(svn_fs_x__put_node_revision(fs, parent_noderev, subpool)); + + /* Immediately populate the txn dir cache to avoid re-reading + * the file we just wrote. */ + + /* Flush APR buffers. */ + SVN_ERR(svn_io_file_flush(file, subpool)); + + /* Obtain final file size to update txn_dir_cache. */ + SVN_ERR(svn_io_file_size_get(&filesize, file, subpool)); + + /* Store in the cache. */ + dir_data.entries = entries; + dir_data.txn_filesize = filesize; + SVN_ERR(svn_cache__set(ffd->dir_cache, key, &dir_data, subpool)); + + svn_pool_clear(subpool); } else { + svn_boolean_t found; + svn_filesize_t cached_filesize; + /* The directory rep is already mutable, so just open it for append. */ SVN_ERR(svn_io_file_open(&file, filename, APR_WRITE | APR_APPEND, - APR_OS_DEFAULT, scratch_pool)); - out = svn_stream_from_aprfile2(file, TRUE, scratch_pool); + APR_OS_DEFAULT, subpool)); + out = svn_stream_from_aprfile2(file, TRUE, subpool); + + /* If the cache contents is stale, drop it. + * + * Note that the directory file is append-only, i.e. if the size + * did not change, the contents didn't either. */ + + /* Get the file size that corresponds to the cached contents + * (if any). */ + SVN_ERR(svn_cache__get_partial((void **)&cached_filesize, &found, + ffd->dir_cache, key, + svn_fs_x__extract_dir_filesize, + NULL, subpool)); + + /* File size info still matches? + * If not, we need to drop the cache entry. */ + if (found) + { + SVN_ERR(svn_io_file_size_get(&filesize, file, subpool)); + + if (cached_filesize != filesize) + SVN_ERR(svn_cache__set(ffd->dir_cache, key, NULL, subpool)); + } } + /* Append an incremental hash entry for the entry change. + A deletion is represented by an "unused" noderev-id. */ + if (id) + entry.id = *id; + else + svn_fs_x__id_reset(&entry.id); + + entry.name = name; + entry.kind = kind; + + SVN_ERR(unparse_dir_entry(&entry, out, subpool)); + + /* Flush APR buffers. */ + SVN_ERR(svn_io_file_flush(file, subpool)); + + /* Obtain final file size to update txn_dir_cache. */ + SVN_ERR(svn_io_file_size_get(&filesize, file, subpool)); + + /* Close file. */ + SVN_ERR(svn_io_file_close(file, subpool)); + svn_pool_clear(subpool); + /* update directory cache */ { - /* build parameters: (name, new entry) pair */ - const svn_fs_x__id_t *key = &(parent_noderev->noderev_id); + /* build parameters: name, new entry, new file size */ replace_baton_t baton; baton.name = name; baton.new_entry = NULL; + baton.txn_filesize = filesize; if (id) { @@ -1800,25 +1924,7 @@ svn_fs_x__set_entry(svn_fs_t *fs, svn_fs_x__replace_dir_entry, &baton, subpool)); } - svn_pool_clear(subpool); - /* Append an incremental hash entry for the entry change. */ - if (id) - { - svn_fs_x__dirent_t entry; - entry.name = name; - entry.id = *id; - entry.kind = kind; - - SVN_ERR(unparse_dir_entry(&entry, out, subpool)); - } - else - { - SVN_ERR(svn_stream_printf(out, subpool, "D %" APR_SIZE_T_FMT "\n%s\n", - strlen(name), name)); - } - - SVN_ERR(svn_io_file_close(file, subpool)); svn_pool_destroy(subpool); return SVN_NO_ERROR; } @@ -1827,7 +1933,6 @@ svn_error_t * svn_fs_x__add_change(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, const char *path, - const svn_fs_x__id_t *id, svn_fs_path_change_kind_t change_kind, svn_boolean_t text_mod, svn_boolean_t prop_mod, @@ -1850,7 +1955,6 @@ svn_fs_x__add_change(svn_fs_t *fs, change.path.data = path; change.path.len = strlen(path); - change.noderev_id = *id; change.change_kind = change_kind; change.text_mod = text_mod; change.prop_mod = prop_mod; @@ -1975,8 +2079,7 @@ shards_spanned(int *spanned, /* Given a node-revision NODEREV in filesystem FS, return the representation in *REP to use as the base for a text representation delta if PROPS is FALSE. If PROPS has been set, a suitable props - base representation will be returned. Perform temporary allocations - in *POOL. */ + base representation will be returned. Perform allocations in POOL. */ static svn_error_t * choose_delta_base(svn_fs_x__representation_t **rep, svn_fs_t *fs, @@ -1984,9 +2087,10 @@ choose_delta_base(svn_fs_x__representation_t **rep, svn_boolean_t props, apr_pool_t *pool) { - /* The zero-based index (counting from the "oldest" end), along NODEREVs line - * predecessors, of the node-rev we will use as delta base. */ + /* The zero-based index (counting from the "oldest" end), along NODEREVs + * line predecessors, of the node-rev we will use as delta base. */ int count; + /* The length of the linear part of a delta chain. (Delta chains use * skip-delta bits for the high-order bits and are linear in the low-order * bits.) */ @@ -2175,7 +2279,7 @@ rep_write_get_baton(rep_write_baton_t **wb_p, b->local_pool), b->local_pool); - SVN_ERR(svn_fs_x__get_file_offset(&b->rep_offset, file, b->local_pool)); + SVN_ERR(svn_io_file_get_offset(&b->rep_offset, file, b->local_pool)); /* Get the base for this delta. */ SVN_ERR(choose_delta_base(&base_rep, fs, noderev, FALSE, b->local_pool)); @@ -2195,11 +2299,10 @@ rep_write_get_baton(rep_write_baton_t **wb_p, header.type = svn_fs_x__rep_self_delta; } SVN_ERR(svn_fs_x__write_rep_header(&header, b->rep_stream, - b->local_pool)); + b->local_pool)); /* Now determine the offset of the actual svndiff data. */ - SVN_ERR(svn_fs_x__get_file_offset(&b->delta_start, file, - b->local_pool)); + SVN_ERR(svn_io_file_get_offset(&b->delta_start, file, b->local_pool)); /* Cleanup in case something goes wrong. */ apr_pool_cleanup_register(b->local_pool, b, rep_write_cleanup, @@ -2222,18 +2325,26 @@ rep_write_get_baton(rep_write_baton_t **wb_p, } /* For REP->SHA1_CHECKSUM, try to find an already existing representation - in FS and return it in *OUT_REP. If no such representation exists or + in FS and return it in *OLD_REP. If no such representation exists or if rep sharing has been disabled for FS, NULL will be returned. Since there may be new duplicate representations within the same uncommitted revision, those can be passed in REPS_HASH (maps a sha1 digest onto svn_fs_x__representation_t*), otherwise pass in NULL for REPS_HASH. + + The content of both representations will be compared, taking REP's content + from FILE at OFFSET. Only if they actually match, will *OLD_REP not be + NULL. + Use RESULT_POOL for *OLD_REP allocations and SCRATCH_POOL for temporaries. The lifetime of *OLD_REP is limited by both, RESULT_POOL and REP lifetime. */ static svn_error_t * get_shared_rep(svn_fs_x__representation_t **old_rep, svn_fs_t *fs, + svn_fs_x__txn_id_t txn_id, svn_fs_x__representation_t *rep, + apr_file_t *file, + apr_off_t offset, apr_hash_t *reps_hash, apr_pool_t *result_pool, apr_pool_t *scratch_pool) @@ -2241,14 +2352,22 @@ get_shared_rep(svn_fs_x__representation_t **old_rep, svn_error_t *err; svn_fs_x__data_t *ffd = fs->fsap_data; + svn_checksum_t checksum; + checksum.digest = rep->sha1_digest; + checksum.kind = svn_checksum_sha1; + /* Return NULL, if rep sharing has been disabled. */ *old_rep = NULL; if (!ffd->rep_sharing_allowed) return SVN_NO_ERROR; + /* Can't look up if we don't know the key (happens for directories). */ + if (!rep->has_sha1) + return SVN_NO_ERROR; + /* Check and see if we already have a representation somewhere that's identical to the one we just wrote out. Start with the hash lookup - because it is cheepest. */ + because it is cheapest. */ if (reps_hash) *old_rep = apr_hash_get(reps_hash, rep->sha1_digest, @@ -2257,9 +2376,6 @@ get_shared_rep(svn_fs_x__representation_t **old_rep, /* If we haven't found anything yet, try harder and consult our DB. */ if (*old_rep == NULL) { - svn_checksum_t checksum; - checksum.digest = rep->sha1_digest; - checksum.kind = svn_checksum_sha1; err = svn_fs_x__get_rep_reference(old_rep, fs, &checksum, result_pool, scratch_pool); @@ -2318,17 +2434,125 @@ get_shared_rep(svn_fs_x__representation_t **old_rep, } } - /* Add information that is missing in the cached data. */ + if (!*old_rep) + return SVN_NO_ERROR; + + /* A simple guard against general rep-cache induced corruption. */ + if ((*old_rep)->expanded_size != rep->expanded_size) + { + /* Make the problem show up in the server log. + + Because not sharing reps is always a safe option, + terminating the request would be inappropriate. + */ + err = svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, + "Rep size %s mismatches rep-cache.db value %s " + "for SHA1 %s.\n" + "You should delete the rep-cache.db and " + "verify the repository. The cached rep will " + "not be shared.", + apr_psprintf(scratch_pool, + "%" SVN_FILESIZE_T_FMT, + rep->expanded_size), + apr_psprintf(scratch_pool, + "%" SVN_FILESIZE_T_FMT, + (*old_rep)->expanded_size), + svn_checksum_to_cstring_display(&checksum, + scratch_pool)); + + (fs->warning)(fs->warning_baton, err); + svn_error_clear(err); + + /* Ignore the shared rep. */ + *old_rep = NULL; + } + else + { + /* Add information that is missing in the cached data. + Use the old rep for this content. */ + memcpy((*old_rep)->md5_digest, rep->md5_digest, sizeof(rep->md5_digest)); + } + + /* If we (very likely) found a matching representation, compare the actual + * contents such that we can be sure that no rep-cache.db corruption or + * hash collision produced a false positive. */ if (*old_rep) { - /* Use the old rep for this content. */ - memcpy((*old_rep)->md5_digest, rep->md5_digest, sizeof(rep->md5_digest)); + apr_off_t old_position; + svn_stream_t *contents; + svn_stream_t *old_contents; + svn_boolean_t same; + + /* Make sure we can later restore FILE's current position. */ + SVN_ERR(svn_io_file_get_offset(&old_position, file, scratch_pool)); + + /* Compare the two representations. + * Note that the stream comparison might also produce MD5 checksum + * errors or other failures in case of SHA1 collisions. */ + SVN_ERR(svn_fs_x__get_contents_from_file(&contents, fs, rep, file, + offset, scratch_pool)); + if ((*old_rep)->id.change_set == rep->id.change_set) + { + /* Comparing with contents from the same transaction means + * reading the same prote-rev FILE. In the commit stage, + * the file will already have been moved and the IDs already + * bumped to the final revision. Hence, we must determine + * the OFFSET "manually". */ + svn_fs_x__revision_file_t *rev_file; + apr_uint32_t sub_item = 0; + svn_fs_x__id_t id; + id.change_set = svn_fs_x__change_set_by_txn(txn_id); + id.number = (*old_rep)->id.number; + + SVN_ERR(svn_fs_x__rev_file_wrap_temp(&rev_file, fs, file, + scratch_pool)); + SVN_ERR(svn_fs_x__item_offset(&offset, &sub_item, fs, rev_file, + &id, scratch_pool)); + + SVN_ERR(svn_fs_x__get_contents_from_file(&old_contents, fs, + *old_rep, file, + offset, scratch_pool)); + } + else + { + SVN_ERR(svn_fs_x__get_contents(&old_contents, fs, *old_rep, + FALSE, scratch_pool)); + } + err = svn_stream_contents_same2(&same, contents, old_contents, + scratch_pool); + + /* A mismatch should be extremely rare. + * If it does happen, reject the commit. */ + if (!same || err) + { + /* SHA1 collision or worse. */ + svn_stringbuf_t *old_rep_str + = svn_fs_x__unparse_representation(*old_rep, FALSE, + scratch_pool, + scratch_pool); + svn_stringbuf_t *rep_str + = svn_fs_x__unparse_representation(rep, FALSE, + scratch_pool, + scratch_pool); + const char *checksum__str + = svn_checksum_to_cstring_display(&checksum, scratch_pool); + + return svn_error_createf(SVN_ERR_FS_AMBIGUOUS_CHECKSUM_REP, + err, "SHA1 of reps '%s' and '%s' " + "matches (%s) but contents differ", + old_rep_str->data, rep_str->data, + checksum__str); + } + + /* Restore FILE's read / write position. */ + SVN_ERR(svn_io_file_seek(file, APR_SET, &old_position, scratch_pool)); } return SVN_NO_ERROR; } /* Copy the hash sum calculation results from MD5_CTX, SHA1_CTX into REP. + * SHA1 results are only be set if SHA1_CTX is not NULL. * Use SCRATCH_POOL for temporary allocations. */ static svn_error_t * @@ -2341,10 +2565,12 @@ digests_final(svn_fs_x__representation_t *rep, SVN_ERR(svn_checksum_final(&checksum, md5_ctx, scratch_pool)); memcpy(rep->md5_digest, checksum->digest, svn_checksum_size(checksum)); - SVN_ERR(svn_checksum_final(&checksum, sha1_ctx, scratch_pool)); - rep->has_sha1 = checksum != NULL; + rep->has_sha1 = sha1_ctx != NULL; if (rep->has_sha1) - memcpy(rep->sha1_digest, checksum->digest, svn_checksum_size(checksum)); + { + SVN_ERR(svn_checksum_final(&checksum, sha1_ctx, scratch_pool)); + memcpy(rep->sha1_digest, checksum->digest, svn_checksum_size(checksum)); + } return SVN_NO_ERROR; } @@ -2368,7 +2594,7 @@ rep_write_contents_close(void *baton) SVN_ERR(svn_stream_close(b->delta_stream)); /* Determine the length of the svndiff data. */ - SVN_ERR(svn_fs_x__get_file_offset(&offset, b->file, b->local_pool)); + SVN_ERR(svn_io_file_get_offset(&offset, b->file, b->local_pool)); rep->size = offset - b->delta_start; /* Fill in the rest of the representation field. */ @@ -2382,8 +2608,8 @@ rep_write_contents_close(void *baton) /* Check and see if we already have a representation somewhere that's identical to the one we just wrote out. */ - SVN_ERR(get_shared_rep(&old_rep, b->fs, rep, NULL, b->result_pool, - b->local_pool)); + SVN_ERR(get_shared_rep(&old_rep, b->fs, txn_id, rep, b->file, b->rep_offset, + NULL, b->result_pool, b->local_pool)); if (old_rep) { @@ -2420,18 +2646,23 @@ rep_write_contents_close(void *baton) noderev_id.number = rep->id.number; entry.offset = b->rep_offset; - SVN_ERR(svn_fs_x__get_file_offset(&offset, b->file, b->local_pool)); + SVN_ERR(svn_io_file_get_offset(&offset, b->file, b->local_pool)); entry.size = offset - b->rep_offset; entry.type = SVN_FS_X__ITEM_TYPE_FILE_REP; entry.item_count = 1; entry.items = &noderev_id; entry.fnv1_checksum = b->fnv1a_checksum; - SVN_ERR(store_sha1_rep_mapping(b->fs, b->noderev, b->local_pool)); SVN_ERR(store_p2l_index_entry(b->fs, txn_id, &entry, b->local_pool)); } SVN_ERR(svn_io_file_close(b->file, b->local_pool)); + + /* Write the sha1->rep mapping *after* we successfully written node + * revision to disk. */ + if (!old_rep) + SVN_ERR(store_sha1_rep_mapping(b->fs, b->noderev, b->local_pool)); + SVN_ERR(unlock_proto_rev(b->fs, txn_id, b->lockcookie, b->local_pool)); svn_pool_destroy(b->local_pool); @@ -2520,7 +2751,7 @@ svn_fs_x__set_proplist(svn_fs_t *fs, APR_WRITE | APR_CREATE | APR_TRUNCATE | APR_BUFFERED, APR_OS_DEFAULT, scratch_pool)); out = svn_stream_from_aprfile2(file, TRUE, scratch_pool); - SVN_ERR(svn_hash_write2(proplist, out, SVN_HASH_TERMINATOR, scratch_pool)); + SVN_ERR(svn_fs_x__write_properties(out, proplist, scratch_pool)); SVN_ERR(svn_io_file_close(file, scratch_pool)); /* Mark the node-rev's prop rep as mutable, if not already done. */ @@ -2529,7 +2760,8 @@ svn_fs_x__set_proplist(svn_fs_t *fs, { svn_fs_x__txn_id_t txn_id = svn_fs_x__get_txn_id(noderev->noderev_id.change_set); - noderev->prop_rep = apr_pcalloc(scratch_pool, sizeof(*noderev->prop_rep)); + noderev->prop_rep = apr_pcalloc(scratch_pool, + sizeof(*noderev->prop_rep)); noderev->prop_rep->id.change_set = id->change_set; SVN_ERR(allocate_item_index(&noderev->prop_rep->id.number, fs, txn_id, scratch_pool)); @@ -2547,6 +2779,8 @@ typedef struct write_container_baton_t apr_size_t size; svn_checksum_ctx_t *md5_ctx; + + /* SHA1 calculation is optional. If not needed, this will be NULL. */ svn_checksum_ctx_t *sha1_ctx; } write_container_baton_t; @@ -2561,7 +2795,8 @@ write_container_handler(void *baton, write_container_baton_t *whb = baton; SVN_ERR(svn_checksum_update(whb->md5_ctx, data, *len)); - SVN_ERR(svn_checksum_update(whb->sha1_ctx, data, *len)); + if (whb->sha1_ctx) + SVN_ERR(svn_checksum_update(whb->sha1_ctx, data, *len)); SVN_ERR(svn_stream_write(whb->stream, data, len)); whb->size += *len; @@ -2583,7 +2818,7 @@ write_hash_to_stream(svn_stream_t *stream, apr_pool_t *scratch_pool) { apr_hash_t *hash = baton; - SVN_ERR(svn_hash_write2(hash, stream, SVN_HASH_TERMINATOR, scratch_pool)); + SVN_ERR(svn_fs_x__write_properties(stream, hash, scratch_pool)); return SVN_NO_ERROR; } @@ -2605,11 +2840,14 @@ write_directory_to_stream(svn_stream_t *stream, /* Write out the COLLECTION pertaining to the NODEREV in FS as a deltified text representation to file FILE using WRITER. In the process, record the total size and the md5 digest in REP and add the representation of type - ITEM_TYPE to the indexes if necessary. If rep sharing has been enabled and - REPS_HASH is not NULL, it will be used in addition to the on-disk cache to - find earlier reps with the same content. When such existing reps can be - found, we will truncate the one just written from the file and return the - existing rep. + ITEM_TYPE to the indexes if necessary. + + If ALLOW_REP_SHARING is FALSE, rep-sharing will not be used, regardless + of any other option and rep-sharing settings. If rep sharing has been + enabled and REPS_HASH is not NULL, it will be used in addition to the + on-disk cache to find earlier reps with the same content. If such + existing reps can be found, we will truncate the one just written from + the file and return the existing rep. If ITEM_TYPE is IS_PROPS equals SVN_FS_FS__ITEM_TYPE_*_PROPS, assume that we want to a props representation as the base for our delta. @@ -2626,6 +2864,7 @@ write_container_delta_rep(svn_fs_x__representation_t *rep, svn_fs_x__txn_id_t txn_id, svn_fs_x__noderev_t *noderev, apr_hash_t *reps_hash, + svn_boolean_t allow_rep_sharing, apr_uint32_t item_type, svn_revnum_t final_revision, apr_pool_t *scratch_pool) @@ -2637,7 +2876,7 @@ write_container_delta_rep(svn_fs_x__representation_t *rep, svn_stream_t *file_stream; svn_stream_t *stream; svn_fs_x__representation_t *base_rep; - svn_fs_x__representation_t *old_rep; + svn_fs_x__representation_t *old_rep = NULL; svn_fs_x__p2l_entry_t entry; svn_stream_t *source; svn_fs_x__rep_header_t header = { 0 }; @@ -2655,7 +2894,7 @@ write_container_delta_rep(svn_fs_x__representation_t *rep, SVN_ERR(choose_delta_base(&base_rep, fs, noderev, is_props, scratch_pool)); SVN_ERR(svn_fs_x__get_contents(&source, fs, base_rep, FALSE, scratch_pool)); - SVN_ERR(svn_fs_x__get_file_offset(&offset, file, scratch_pool)); + SVN_ERR(svn_io_file_get_offset(&offset, file, scratch_pool)); /* Write out the rep header. */ if (base_rep) @@ -2676,7 +2915,7 @@ write_container_delta_rep(svn_fs_x__representation_t *rep, scratch_pool), scratch_pool); SVN_ERR(svn_fs_x__write_rep_header(&header, file_stream, scratch_pool)); - SVN_ERR(svn_fs_x__get_file_offset(&delta_start, file, scratch_pool)); + SVN_ERR(svn_io_file_get_offset(&delta_start, file, scratch_pool)); /* Prepare to write the svndiff data. */ svn_txdelta_to_svndiff3(&diff_wh, @@ -2691,7 +2930,8 @@ write_container_delta_rep(svn_fs_x__representation_t *rep, scratch_pool); whb->size = 0; whb->md5_ctx = svn_checksum_ctx_create(svn_checksum_md5, scratch_pool); - whb->sha1_ctx = svn_checksum_ctx_create(svn_checksum_sha1, scratch_pool); + if (item_type != SVN_FS_X__ITEM_TYPE_DIR_REP) + whb->sha1_ctx = svn_checksum_ctx_create(svn_checksum_sha1, scratch_pool); /* serialize the hash */ stream = svn_stream_create(whb, scratch_pool); @@ -2703,10 +2943,16 @@ write_container_delta_rep(svn_fs_x__representation_t *rep, /* Store the results. */ SVN_ERR(digests_final(rep, whb->md5_ctx, whb->sha1_ctx, scratch_pool)); + /* Update size info. */ + SVN_ERR(svn_io_file_get_offset(&rep_end, file, scratch_pool)); + rep->size = rep_end - delta_start; + rep->expanded_size = whb->size; + /* Check and see if we already have a representation somewhere that's identical to the one we just wrote out. */ - SVN_ERR(get_shared_rep(&old_rep, fs, rep, reps_hash, scratch_pool, - scratch_pool)); + if (allow_rep_sharing) + SVN_ERR(get_shared_rep(&old_rep, fs, txn_id, rep, file, offset, reps_hash, + scratch_pool, scratch_pool)); if (old_rep) { @@ -2723,7 +2969,6 @@ write_container_delta_rep(svn_fs_x__representation_t *rep, svn_fs_x__id_t noderev_id; /* Write out our cosmetic end marker. */ - SVN_ERR(svn_fs_x__get_file_offset(&rep_end, file, scratch_pool)); SVN_ERR(svn_stream_puts(file_stream, "ENDREP\n")); SVN_ERR(svn_stream_close(file_stream)); @@ -2736,7 +2981,7 @@ write_container_delta_rep(svn_fs_x__representation_t *rep, noderev_id.number = rep->id.number; entry.offset = offset; - SVN_ERR(svn_fs_x__get_file_offset(&offset, file, scratch_pool)); + SVN_ERR(svn_io_file_get_offset(&offset, file, scratch_pool)); entry.size = offset - entry.offset; entry.type = item_type; entry.item_count = 1; @@ -2745,7 +2990,6 @@ write_container_delta_rep(svn_fs_x__representation_t *rep, SVN_ERR(store_p2l_index_entry(fs, txn_id, &entry, scratch_pool)); /* update the representation */ - rep->expanded_size = whb->size; rep->size = rep_end - delta_start; } @@ -2791,7 +3035,7 @@ validate_root_noderev(svn_fs_t *fs, Normally (rev == root_noderev->predecessor_count), but here we use a more roundabout check that should only trigger on new instances - of the corruption, rather then trigger on each and every new commit + of the corruption, rather than trigger on each and every new commit to a repository that has triggered the bug somewhere in its root noderev's history. */ @@ -2836,6 +3080,9 @@ get_final_id(svn_fs_x__id_t *part, INITIAL_OFFSET is the offset of the proto-rev-file on entry to commit_body. + Collect the pair_cache_key_t of all directories written to the + committed cache in DIRECTORY_IDS. + If REPS_TO_CACHE is not NULL, append to it a copy (allocated in REPS_POOL) of each data rep that is new in this revision. @@ -2847,6 +3094,10 @@ get_final_id(svn_fs_x__id_t *part, node-revision. It is only controls additional sanity checking logic. + CHANGED_PATHS is the changed paths hash for the new revision. + The noderev-ids in it will be updated as soon as the respective + nodesrevs got their final IDs assigned. + Temporary allocations are also from SCRATCH_POOL. */ static svn_error_t * write_final_rev(svn_fs_x__id_t *new_id_p, @@ -2855,10 +3106,12 @@ write_final_rev(svn_fs_x__id_t *new_id_p, svn_fs_t *fs, const svn_fs_x__id_t *id, apr_off_t initial_offset, + apr_array_header_t *directory_ids, apr_array_header_t *reps_to_cache, apr_hash_t *reps_hash, apr_pool_t *reps_pool, svn_boolean_t at_root, + apr_hash_t *changed_paths, apr_pool_t *scratch_pool) { svn_fs_x__noderev_t *noderev; @@ -2899,24 +3152,44 @@ write_final_rev(svn_fs_x__id_t *new_id_p, svn_pool_clear(subpool); SVN_ERR(write_final_rev(&new_id, file, rev, fs, &dirent->id, - initial_offset, reps_to_cache, reps_hash, - reps_pool, FALSE, subpool)); - if ( svn_fs_x__id_used(&new_id) - && (svn_fs_x__get_revnum(new_id.change_set) == rev)) + initial_offset, directory_ids, + reps_to_cache, reps_hash, + reps_pool, FALSE, changed_paths, subpool)); + if (new_id.change_set == change_set) dirent->id = new_id; } if (noderev->data_rep && ! svn_fs_x__is_revision(noderev->data_rep->id.change_set)) { + svn_fs_x__pair_cache_key_t *key; + svn_fs_x__dir_data_t dir_data; + /* Write out the contents of this directory as a text rep. */ noderev->data_rep->id.change_set = change_set; SVN_ERR(write_container_delta_rep(noderev->data_rep, file, entries, write_directory_to_stream, - fs, txn_id, noderev, NULL, + fs, txn_id, noderev, NULL, FALSE, SVN_FS_X__ITEM_TYPE_DIR_REP, rev, scratch_pool)); + + /* Cache the new directory contents. Otherwise, subsequent reads + * or commits will likely have to reconstruct, verify and parse + * it again. */ + key = apr_array_push(directory_ids); + key->revision = noderev->data_rep->id.change_set; + key->second = noderev->data_rep->id.number; + + /* Store directory contents under the new revision number but mark + * it as "stale" by setting the file length to 0. Committed dirs + * will report -1, in-txn dirs will report > 0, so that this can + * never match. We reset that to -1 after the commit is complete. + */ + dir_data.entries = entries; + dir_data.txn_filesize = 0; + + SVN_ERR(svn_cache__set(ffd->dir_cache, key, &dir_data, subpool)); } } else @@ -2949,8 +3222,8 @@ write_final_rev(svn_fs_x__id_t *new_id_p, SVN_ERR(write_container_delta_rep(noderev->prop_rep, file, proplist, write_hash_to_stream, fs, txn_id, - noderev, reps_hash, item_type, rev, - scratch_pool)); + noderev, reps_hash, TRUE, item_type, + rev, scratch_pool)); } /* Convert our temporary ID into a permanent revision one. */ @@ -2961,7 +3234,7 @@ write_final_rev(svn_fs_x__id_t *new_id_p, if (noderev->copyroot_rev == SVN_INVALID_REVNUM) noderev->copyroot_rev = rev; - SVN_ERR(svn_fs_x__get_file_offset(&my_offset, file, scratch_pool)); + SVN_ERR(svn_io_file_get_offset(&my_offset, file, scratch_pool)); SVN_ERR(store_l2p_index_entry(fs, txn_id, my_offset, noderev->noderev_id.number, scratch_pool)); @@ -3020,7 +3293,7 @@ write_final_rev(svn_fs_x__id_t *new_id_p, noderev_id.change_set = SVN_FS_X__INVALID_CHANGE_SET; entry.offset = my_offset; - SVN_ERR(svn_fs_x__get_file_offset(&my_offset, file, scratch_pool)); + SVN_ERR(svn_io_file_get_offset(&my_offset, file, scratch_pool)); entry.size = my_offset - entry.offset; entry.type = SVN_FS_X__ITEM_TYPE_NODEREV; entry.item_count = 1; @@ -3054,7 +3327,7 @@ write_final_changed_path_info(apr_off_t *offset_p, svn_fs_x__id_t rev_item = {SVN_INVALID_REVNUM, SVN_FS_X__ITEM_INDEX_CHANGES}; - SVN_ERR(svn_fs_x__get_file_offset(&offset, file, scratch_pool)); + SVN_ERR(svn_io_file_get_offset(&offset, file, scratch_pool)); /* write to target file & calculate checksum */ stream = svn_checksum__wrap_write_stream_fnv1a_32x4(&entry.fnv1_checksum, @@ -3068,7 +3341,7 @@ write_final_changed_path_info(apr_off_t *offset_p, /* reference changes from the indexes */ entry.offset = offset; - SVN_ERR(svn_fs_x__get_file_offset(&offset, file, scratch_pool)); + SVN_ERR(svn_io_file_get_offset(&offset, file, scratch_pool)); entry.size = offset - entry.offset; entry.type = SVN_FS_X__ITEM_TYPE_CHANGES; entry.item_count = 1; @@ -3199,62 +3472,52 @@ verify_locks(svn_fs_t *fs, return SVN_NO_ERROR; } -/* Return in *PATH the path to a file containing the properties that - make up the final revision properties file. This involves setting - svn:date and removing any temporary properties associated with the - commit flags. */ +/* Based on the transaction properties of TXN, write the final revision + properties for REVISION into their final location. Return that location + in *PATH and schedule the necessary fsync calls in BATCH. This involves + setting svn:date and removing any temporary properties associated with + the commit flags. */ static svn_error_t * write_final_revprop(const char **path, svn_fs_txn_t *txn, - svn_fs_x__txn_id_t txn_id, - apr_pool_t *pool) + svn_revnum_t revision, + svn_fs_x__batch_fsync_t *batch, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { - apr_hash_t *txnprops; - svn_boolean_t final_mods = FALSE; + apr_hash_t *props; svn_string_t date; svn_string_t *client_date; + apr_file_t *file; - SVN_ERR(svn_fs_x__txn_proplist(&txnprops, txn, pool)); + SVN_ERR(svn_fs_x__txn_proplist(&props, txn, scratch_pool)); /* Remove any temporary txn props representing 'flags'. */ - if (svn_hash_gets(txnprops, SVN_FS__PROP_TXN_CHECK_OOD)) - { - svn_hash_sets(txnprops, SVN_FS__PROP_TXN_CHECK_OOD, NULL); - final_mods = TRUE; - } + if (svn_hash_gets(props, SVN_FS__PROP_TXN_CHECK_OOD)) + svn_hash_sets(props, SVN_FS__PROP_TXN_CHECK_OOD, NULL); - if (svn_hash_gets(txnprops, SVN_FS__PROP_TXN_CHECK_LOCKS)) - { - svn_hash_sets(txnprops, SVN_FS__PROP_TXN_CHECK_LOCKS, NULL); - final_mods = TRUE; - } + if (svn_hash_gets(props, SVN_FS__PROP_TXN_CHECK_LOCKS)) + svn_hash_sets(props, SVN_FS__PROP_TXN_CHECK_LOCKS, NULL); - client_date = svn_hash_gets(txnprops, SVN_FS__PROP_TXN_CLIENT_DATE); + client_date = svn_hash_gets(props, SVN_FS__PROP_TXN_CLIENT_DATE); if (client_date) - { - svn_hash_sets(txnprops, SVN_FS__PROP_TXN_CLIENT_DATE, NULL); - final_mods = TRUE; - } + svn_hash_sets(props, SVN_FS__PROP_TXN_CLIENT_DATE, NULL); /* Update commit time to ensure that svn:date revprops remain ordered if requested. */ if (!client_date || strcmp(client_date->data, "1")) { - date.data = svn_time_to_cstring(apr_time_now(), pool); + date.data = svn_time_to_cstring(apr_time_now(), scratch_pool); date.len = strlen(date.data); - svn_hash_sets(txnprops, SVN_PROP_REVISION_DATE, &date); - final_mods = TRUE; + svn_hash_sets(props, SVN_PROP_REVISION_DATE, &date); } - if (final_mods) - { - SVN_ERR(set_txn_proplist(txn->fs, txn_id, txnprops, TRUE, pool)); - *path = svn_fs_x__path_txn_props_final(txn->fs, txn_id, pool); - } - else - { - *path = svn_fs_x__path_txn_props(txn->fs, txn_id, pool); - } + /* Create a file at the final revprops location. */ + *path = svn_fs_x__path_revprops(txn->fs, revision, result_pool); + SVN_ERR(svn_fs_x__batch_fsync_open_file(&file, batch, *path, scratch_pool)); + + /* Write the new contents to the final revprops file. */ + SVN_ERR(svn_fs_x__write_non_packed_revprops(file, props, scratch_pool)); return SVN_NO_ERROR; } @@ -3302,6 +3565,190 @@ svn_fs_x__add_index_data(svn_fs_t *fs, return SVN_NO_ERROR; } +/* Make sure that the shard folder for REVSION exists in FS. If we had to + create them, schedule their fsync in BATCH. Use SCRATCH_POOL for + temporary allocations. */ +static svn_error_t * +auto_create_shard(svn_fs_t *fs, + svn_revnum_t revision, + svn_fs_x__batch_fsync_t *batch, + apr_pool_t *scratch_pool) +{ + svn_fs_x__data_t *ffd = fs->fsap_data; + if (revision % ffd->max_files_per_dir == 0) + { + const char *new_dir = svn_fs_x__path_shard(fs, revision, scratch_pool); + svn_error_t *err = svn_io_dir_make(new_dir, APR_OS_DEFAULT, + scratch_pool); + + if (err && !APR_STATUS_IS_EEXIST(err->apr_err)) + return svn_error_trace(err); + svn_error_clear(err); + + SVN_ERR(svn_io_copy_perms(svn_dirent_join(fs->path, PATH_REVS_DIR, + scratch_pool), + new_dir, scratch_pool)); + SVN_ERR(svn_fs_x__batch_fsync_new_path(batch, new_dir, scratch_pool)); + } + + return SVN_NO_ERROR; +} + +/* Move the protype revision file of transaction TXN_ID in FS to the final + location for REVISION and return a handle to it in *FILE. Schedule any + fsyncs in BATCH and use SCRATCH_POOL for temporaries. + + Note that the lifetime of *FILE is determined by BATCH instead of + SCRATCH_POOL. It will be invalidated by either BATCH being cleaned up + itself of by running svn_fs_x__batch_fsync_run on it. + + This function will "destroy" the transaction by removing its prototype + revision file, so it can at most be called once per transaction. Also, + later attempts to modify this txn will fail due to get_writable_proto_rev + not finding the protorev file. Therefore, we will take out the lock for + it only until we move the file to its final location. + + If the prototype revision file is already locked, return error + SVN_ERR_FS_REP_BEING_WRITTEN. */ +static svn_error_t * +get_writable_final_rev(apr_file_t **file, + svn_fs_t *fs, + svn_fs_x__txn_id_t txn_id, + svn_revnum_t revision, + svn_fs_x__batch_fsync_t *batch, + apr_pool_t *scratch_pool) +{ + get_writable_proto_rev_baton_t baton; + apr_off_t end_offset = 0; + void *lockcookie; + + const char *proto_rev_filename + = svn_fs_x__path_txn_proto_rev(fs, txn_id, scratch_pool); + const char *final_rev_filename + = svn_fs_x__path_rev(fs, revision, scratch_pool); + + /* Acquire exclusive access to the proto-rev file. */ + baton.lockcookie = &lockcookie; + baton.txn_id = txn_id; + + SVN_ERR(with_txnlist_lock(fs, get_writable_proto_rev_body, &baton, + scratch_pool)); + + /* Move the proto-rev file to its final location as revision data file. + After that, we don't need to protect it anymore and can unlock it. */ + SVN_ERR(svn_error_compose_create(svn_io_file_rename2(proto_rev_filename, + final_rev_filename, + FALSE, + scratch_pool), + unlock_proto_rev(fs, txn_id, lockcookie, + scratch_pool))); + SVN_ERR(svn_fs_x__batch_fsync_new_path(batch, final_rev_filename, + scratch_pool)); + + /* Now open the prototype revision file and seek to the end. + Note that BATCH always seeks to position 0 before returning the file. */ + SVN_ERR(svn_fs_x__batch_fsync_open_file(file, batch, final_rev_filename, + scratch_pool)); + SVN_ERR(svn_io_file_seek(*file, APR_END, &end_offset, scratch_pool)); + + /* We don't want unused sections (such as leftovers from failed delta + stream) in our file. Detect and fix those cases by truncating the + protorev file. */ + SVN_ERR(auto_truncate_proto_rev(fs, *file, end_offset, txn_id, + scratch_pool)); + + return SVN_NO_ERROR; +} + +/* Write REVISION into FS' 'next' file and schedule necessary fsyncs in BATCH. + Use SCRATCH_POOL for temporary allocations. */ +static svn_error_t * +write_next_file(svn_fs_t *fs, + svn_revnum_t revision, + svn_fs_x__batch_fsync_t *batch, + apr_pool_t *scratch_pool) +{ + apr_file_t *file; + const char *path = svn_fs_x__path_next(fs, scratch_pool); + const char *perms_path = svn_fs_x__path_current(fs, scratch_pool); + char *buf; + + /* Create / open the 'next' file. */ + SVN_ERR(svn_fs_x__batch_fsync_open_file(&file, batch, path, scratch_pool)); + + /* Write its contents. */ + buf = apr_psprintf(scratch_pool, "%ld\n", revision); + SVN_ERR(svn_io_file_write_full(file, buf, strlen(buf), NULL, scratch_pool)); + + /* Adjust permissions. */ + SVN_ERR(svn_io_copy_perms(perms_path, path, scratch_pool)); + + return SVN_NO_ERROR; +} + +/* Bump the 'current' file in FS to NEW_REV. Schedule fsyncs in BATCH. + * Use SCRATCH_POOL for temporary allocations. */ +static svn_error_t * +bump_current(svn_fs_t *fs, + svn_revnum_t new_rev, + svn_fs_x__batch_fsync_t *batch, + apr_pool_t *scratch_pool) +{ + const char *current_filename; + + /* Write the 'next' file. */ + SVN_ERR(write_next_file(fs, new_rev, batch, scratch_pool)); + + /* Commit all changes to disk. */ + SVN_ERR(svn_fs_x__batch_fsync_run(batch, scratch_pool)); + + /* Make the revision visible to all processes and threads. */ + current_filename = svn_fs_x__path_current(fs, scratch_pool); + SVN_ERR(svn_fs_x__move_into_place(svn_fs_x__path_next(fs, scratch_pool), + current_filename, current_filename, + batch, scratch_pool)); + + /* Make the new revision permanently visible. */ + SVN_ERR(svn_fs_x__batch_fsync_run(batch, scratch_pool)); + + return SVN_NO_ERROR; +} + +/* Mark the directories cached in FS with the keys from DIRECTORY_IDS + * as "valid" now. Use SCRATCH_POOL for temporaries. */ +static svn_error_t * +promote_cached_directories(svn_fs_t *fs, + apr_array_header_t *directory_ids, + apr_pool_t *scratch_pool) +{ + svn_fs_x__data_t *ffd = fs->fsap_data; + apr_pool_t *iterpool; + int i; + + if (!ffd->dir_cache) + return SVN_NO_ERROR; + + iterpool = svn_pool_create(scratch_pool); + for (i = 0; i < directory_ids->nelts; ++i) + { + const svn_fs_x__pair_cache_key_t *key + = &APR_ARRAY_IDX(directory_ids, i, svn_fs_x__pair_cache_key_t); + + svn_pool_clear(iterpool); + + /* Currently, the entry for KEY - if it still exists - is marked + * as "stale" and would not be used. Mark it as current for in- + * revison data. */ + SVN_ERR(svn_cache__set_partial(ffd->dir_cache, key, + svn_fs_x__reset_txn_filesize, NULL, + iterpool)); + } + + svn_pool_destroy(iterpool); + + return SVN_NO_ERROR; +} + /* Baton used for commit_body below. */ typedef struct commit_baton_t { svn_revnum_t *new_rev_p; @@ -3321,15 +3768,22 @@ commit_body(void *baton, { commit_baton_t *cb = baton; svn_fs_x__data_t *ffd = cb->fs->fsap_data; - const char *old_rev_filename, *rev_filename, *proto_filename; - const char *revprop_filename, *final_revprop; + const char *old_rev_filename, *rev_filename; + const char *revprop_filename; svn_fs_x__id_t root_id, new_root_id; svn_revnum_t old_rev, new_rev; apr_file_t *proto_file; - void *proto_file_lockcookie; apr_off_t initial_offset, changed_path_offset; svn_fs_x__txn_id_t txn_id = svn_fs_x__txn_get_id(cb->txn); apr_hash_t *changed_paths; + svn_fs_x__batch_fsync_t *batch; + apr_array_header_t *directory_ids + = apr_array_make(scratch_pool, 4, sizeof(svn_fs_x__pair_cache_key_t)); + + /* We perform a sequence of (potentially) large allocations. + Keep the peak memory usage low by using a SUBPOOL and cleaning it + up frequently. */ + apr_pool_t *subpool = svn_pool_create(scratch_pool); /* Re-Read the current repository format. All our repo upgrade and config evaluation strategies are such that existing information in @@ -3338,17 +3792,12 @@ commit_body(void *baton, Although we don't recommend upgrading hot repositories, people may still do it and we must make sure to either handle them gracefully or to error out. - - Committing pre-format 3 txns will fail after upgrade to format 3+ - because the proto-rev cannot be found; no further action needed. - Upgrades from pre-f7 to f7+ means a potential change in addressing - mode for the final rev. We must be sure to detect that cause because - the failure would only manifest once the new revision got committed. */ - SVN_ERR(svn_fs_x__read_format_file(cb->fs, scratch_pool)); + SVN_ERR(svn_fs_x__read_format_file(cb->fs, subpool)); /* Get the current youngest revision. */ - SVN_ERR(svn_fs_x__youngest_rev(&old_rev, cb->fs, scratch_pool)); + SVN_ERR(svn_fs_x__youngest_rev(&old_rev, cb->fs, subpool)); + svn_pool_clear(subpool); /* Check to make sure this transaction is based off the most recent revision. */ @@ -3365,111 +3814,70 @@ commit_body(void *baton, previous svn_fs.h functions and svn_fs_commit_txn(), so we need to re-examine every changed-path in the txn and re-verify all discovered locks. */ - SVN_ERR(verify_locks(cb->fs, txn_id, changed_paths, scratch_pool)); + SVN_ERR(verify_locks(cb->fs, txn_id, changed_paths, subpool)); + svn_pool_clear(subpool); /* We are going to be one better than this puny old revision. */ new_rev = old_rev + 1; - /* Get a write handle on the proto revision file. */ - SVN_ERR(get_writable_proto_rev(&proto_file, &proto_file_lockcookie, - cb->fs, txn_id, scratch_pool)); - SVN_ERR(svn_fs_x__get_file_offset(&initial_offset, proto_file, - scratch_pool)); + /* Use this to force all data to be flushed to physical storage + (to the degree our environment will allow). */ + SVN_ERR(svn_fs_x__batch_fsync_create(&batch, ffd->flush_to_disk, + scratch_pool)); - /* Write out all the node-revisions and directory contents. */ - svn_fs_x__init_txn_root(&root_id, txn_id); - SVN_ERR(write_final_rev(&new_root_id, proto_file, new_rev, cb->fs, &root_id, - initial_offset, cb->reps_to_cache, cb->reps_hash, - cb->reps_pool, TRUE, scratch_pool)); + /* Set up the target directory. */ + SVN_ERR(auto_create_shard(cb->fs, new_rev, batch, subpool)); - /* Write the changed-path information. */ - SVN_ERR(write_final_changed_path_info(&changed_path_offset, proto_file, - cb->fs, txn_id, changed_paths, - new_rev, scratch_pool)); - - /* Append the index data to the rev file. */ - SVN_ERR(svn_fs_x__add_index_data(cb->fs, proto_file, - svn_fs_x__path_l2p_proto_index(cb->fs, txn_id, scratch_pool), - svn_fs_x__path_p2l_proto_index(cb->fs, txn_id, scratch_pool), - new_rev, scratch_pool)); - - SVN_ERR(svn_io_file_flush_to_disk(proto_file, scratch_pool)); - SVN_ERR(svn_io_file_close(proto_file, scratch_pool)); - - /* We don't unlock the prototype revision file immediately to avoid a - race with another caller writing to the prototype revision file - before we commit it. */ - - /* Create the shard for the rev and revprop file, if we're sharding and - this is the first revision of a new shard. We don't care if this - fails because the shard already existed for some reason. */ - if (new_rev % ffd->max_files_per_dir == 0) - { - /* Create the revs shard. */ - { - const char *new_dir - = svn_fs_x__path_rev_shard(cb->fs, new_rev, scratch_pool); - svn_error_t *err = svn_io_dir_make(new_dir, APR_OS_DEFAULT, - scratch_pool); - if (err && !APR_STATUS_IS_EEXIST(err->apr_err)) - return svn_error_trace(err); - svn_error_clear(err); - SVN_ERR(svn_io_copy_perms(svn_dirent_join(cb->fs->path, - PATH_REVS_DIR, - scratch_pool), - new_dir, scratch_pool)); - } - - /* Create the revprops shard. */ - SVN_ERR_ASSERT(! svn_fs_x__is_packed_revprop(cb->fs, new_rev)); - { - const char *new_dir - = svn_fs_x__path_revprops_shard(cb->fs, new_rev, scratch_pool); - svn_error_t *err = svn_io_dir_make(new_dir, APR_OS_DEFAULT, - scratch_pool); - if (err && !APR_STATUS_IS_EEXIST(err->apr_err)) - return svn_error_trace(err); - svn_error_clear(err); - SVN_ERR(svn_io_copy_perms(svn_dirent_join(cb->fs->path, - PATH_REVPROPS_DIR, - scratch_pool), - new_dir, scratch_pool)); - } - } - - /* Move the finished rev file into place. + /* Get a write handle on the proto revision file. ### This "breaks" the transaction by removing the protorev file ### but the revision is not yet complete. If this commit does ### not complete for any reason the transaction will be lost. */ - old_rev_filename = svn_fs_x__path_rev_absolute(cb->fs, old_rev, - scratch_pool); + SVN_ERR(get_writable_final_rev(&proto_file, cb->fs, txn_id, new_rev, + batch, subpool)); + SVN_ERR(svn_io_file_get_offset(&initial_offset, proto_file, subpool)); + svn_pool_clear(subpool); - rev_filename = svn_fs_x__path_rev(cb->fs, new_rev, scratch_pool); - proto_filename = svn_fs_x__path_txn_proto_rev(cb->fs, txn_id, - scratch_pool); - SVN_ERR(svn_fs_x__move_into_place(proto_filename, rev_filename, - old_rev_filename, scratch_pool)); + /* Write out all the node-revisions and directory contents. */ + svn_fs_x__init_txn_root(&root_id, txn_id); + SVN_ERR(write_final_rev(&new_root_id, proto_file, new_rev, cb->fs, &root_id, + initial_offset, directory_ids, cb->reps_to_cache, + cb->reps_hash, cb->reps_pool, TRUE, changed_paths, + subpool)); + svn_pool_clear(subpool); - /* Now that we've moved the prototype revision file out of the way, - we can unlock it (since further attempts to write to the file - will fail as it no longer exists). We must do this so that we can - remove the transaction directory later. */ - SVN_ERR(unlock_proto_rev(cb->fs, txn_id, proto_file_lockcookie, - scratch_pool)); + /* Write the changed-path information. */ + SVN_ERR(write_final_changed_path_info(&changed_path_offset, proto_file, + cb->fs, txn_id, changed_paths, + new_rev, subpool)); + svn_pool_clear(subpool); + + /* Append the index data to the rev file. */ + SVN_ERR(svn_fs_x__add_index_data(cb->fs, proto_file, + svn_fs_x__path_l2p_proto_index(cb->fs, txn_id, subpool), + svn_fs_x__path_p2l_proto_index(cb->fs, txn_id, subpool), + new_rev, subpool)); + svn_pool_clear(subpool); + + /* Set the correct permissions. */ + old_rev_filename = svn_fs_x__path_rev_absolute(cb->fs, old_rev, subpool); + rev_filename = svn_fs_x__path_rev(cb->fs, new_rev, subpool); + SVN_ERR(svn_io_copy_perms(rev_filename, old_rev_filename, subpool)); /* Move the revprops file into place. */ SVN_ERR_ASSERT(! svn_fs_x__is_packed_revprop(cb->fs, new_rev)); - SVN_ERR(write_final_revprop(&revprop_filename, cb->txn, txn_id, - scratch_pool)); - final_revprop = svn_fs_x__path_revprops(cb->fs, new_rev, scratch_pool); - SVN_ERR(svn_fs_x__move_into_place(revprop_filename, final_revprop, - old_rev_filename, scratch_pool)); + SVN_ERR(write_final_revprop(&revprop_filename, cb->txn, new_rev, batch, + subpool, subpool)); + SVN_ERR(svn_io_copy_perms(revprop_filename, old_rev_filename, subpool)); + svn_pool_clear(subpool); - /* Update the 'current' file. */ + /* Verify contents (no-op outside DEBUG mode). */ + SVN_ERR(svn_io_file_flush(proto_file, subpool)); SVN_ERR(verify_as_revision_before_current_plus_plus(cb->fs, new_rev, - scratch_pool)); - SVN_ERR(svn_fs_x__write_current(cb->fs, new_rev, scratch_pool)); + subpool)); + + /* Bump 'current'. */ + SVN_ERR(bump_current(cb->fs, new_rev, batch, subpool)); /* At this point the new revision is committed and globally visible so let the caller know it succeeded by giving it the new revision @@ -3480,9 +3888,14 @@ commit_body(void *baton, ffd->youngest_rev_cache = new_rev; - /* Remove this transaction directory. */ - SVN_ERR(svn_fs_x__purge_txn(cb->fs, cb->txn->id, scratch_pool)); + /* Make the directory contents already cached for the new revision + * visible. */ + SVN_ERR(promote_cached_directories(cb->fs, directory_ids, subpool)); + /* Remove this transaction directory. */ + SVN_ERR(svn_fs_x__purge_txn(cb->fs, cb->txn->id, subpool)); + + svn_pool_destroy(subpool); return SVN_NO_ERROR; } @@ -3542,6 +3955,8 @@ svn_fs_x__commit(svn_revnum_t *new_rev_p, if (ffd->rep_sharing_allowed) { + svn_error_t *err; + SVN_ERR(svn_fs_x__open_rep_cache(fs, scratch_pool)); /* Write new entries to the rep-sharing database. @@ -3552,9 +3967,21 @@ svn_fs_x__commit(svn_revnum_t *new_rev_p, /* ### A commit that touches thousands of files will starve other (reader/writer) commits for the duration of the below call. Maybe write in batches? */ - SVN_SQLITE__WITH_TXN( - write_reps_to_cache(fs, cb.reps_to_cache, scratch_pool), - ffd->rep_cache_db); + SVN_ERR(svn_sqlite__begin_transaction(ffd->rep_cache_db)); + err = write_reps_to_cache(fs, cb.reps_to_cache, scratch_pool); + err = svn_sqlite__finish_transaction(ffd->rep_cache_db, err); + + if (svn_error_find_cause(err, SVN_ERR_SQLITE_ROLLBACK_FAILED)) + { + /* Failed rollback means that our db connection is unusable, and + the only thing we can do is close it. The connection will be + reopened during the next operation with rep-cache.db. */ + return svn_error_trace( + svn_error_compose_create(err, + svn_fs_x__close_rep_cache(fs))); + } + else if (err) + return svn_error_trace(err); } return SVN_NO_ERROR; @@ -3650,10 +4077,8 @@ svn_fs_x__txn_proplist(apr_hash_t **table_p, svn_fs_txn_t *txn, apr_pool_t *pool) { - apr_hash_t *proplist = apr_hash_make(pool); - SVN_ERR(get_txn_proplist(proplist, txn->fs, svn_fs_x__txn_get_id(txn), - pool)); - *table_p = proplist; + SVN_ERR(get_txn_proplist(table_p, txn->fs, svn_fs_x__txn_get_id(txn), + pool, pool)); return SVN_NO_ERROR; } @@ -3776,7 +4201,7 @@ svn_fs_x__begin_txn(svn_fs_txn_t **txn_p, svn_string_create("0", scratch_pool)); ftd = (*txn_p)->fsap_data; - SVN_ERR(set_txn_proplist(fs, ftd->txn_id, props, FALSE, scratch_pool)); + SVN_ERR(set_txn_proplist(fs, ftd->txn_id, props, scratch_pool)); return SVN_NO_ERROR; } diff --git a/subversion/libsvn_fs_x/transaction.h b/subversion/libsvn_fs_x/transaction.h index 490f716d4333..9ed655bc8adf 100644 --- a/subversion/libsvn_fs_x/transaction.h +++ b/subversion/libsvn_fs_x/transaction.h @@ -20,8 +20,8 @@ * ==================================================================== */ -#ifndef SVN_LIBSVN_FS__TRANSACTION_H -#define SVN_LIBSVN_FS__TRANSACTION_H +#ifndef SVN_LIBSVN_FS_X_TRANSACTION_H +#define SVN_LIBSVN_FS_X_TRANSACTION_H #include "fs.h" @@ -64,8 +64,8 @@ svn_fs_x__with_txn_current_lock(svn_fs_t *fs, call BODY with BATON and that subpool, destroy the subpool (releasing the locks) and return what BODY returned. - This combines svn_fs_fs__with_write_lock, svn_fs_fs__with_pack_lock, - and svn_fs_fs__with_txn_current_lock, ensuring correct lock ordering. */ + This combines svn_fs_x__with_write_lock, svn_fs_x__with_pack_lock, + and svn_fs_x__with_txn_current_lock, ensuring correct lock ordering. */ svn_error_t * svn_fs_x__with_all_locks(svn_fs_t *fs, svn_error_t *(*body)(void *baton, @@ -128,7 +128,7 @@ svn_fs_x__reserve_copy_id(svn_fs_x__id_t *copy_id_p, /* Create an entirely new mutable node in the filesystem FS, whose node-revision is NODEREV. COPY_ID is the copy_id to use in the node revision ID. TXN_ID is the Subversion transaction under - which this occurs. */ + which this occurs. Use SCRATCH_POOL for temporary allocations. */ svn_error_t * svn_fs_x__create_node(svn_fs_t *fs, svn_fs_x__noderev_t *noderev, @@ -167,9 +167,9 @@ svn_fs_x__set_entry(svn_fs_t *fs, apr_pool_t *scratch_pool); /* Add a change to the changes record for filesystem FS in transaction - TXN_ID. Mark path PATH, having noderev-id ID, as changed according to - the type in CHANGE_KIND. If the text representation was changed set - TEXT_MOD to TRUE, and likewise for PROP_MOD as well as MERGEINFO_MOD. + TXN_ID. Mark path PATH as changed according to the type in + CHANGE_KIND. If the text representation was changed set TEXT_MOD + to TRUE, and likewise for PROP_MOD as well as MERGEINFO_MOD. If this change was the result of a copy, set COPYFROM_REV and COPYFROM_PATH to the revision and path of the copy source, otherwise they should be set to SVN_INVALID_REVNUM and NULL. Perform any @@ -178,7 +178,6 @@ svn_error_t * svn_fs_x__add_change(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, const char *path, - const svn_fs_x__id_t *id, svn_fs_path_change_kind_t change_kind, svn_boolean_t text_mod, svn_boolean_t prop_mod, diff --git a/subversion/libsvn_fs_x/tree.c b/subversion/libsvn_fs_x/tree.c index ce247658d30d..36374afc1cce 100644 --- a/subversion/libsvn_fs_x/tree.c +++ b/subversion/libsvn_fs_x/tree.c @@ -53,6 +53,7 @@ #include "fs.h" #include "dag.h" +#include "dag_cache.h" #include "lock.h" #include "tree.h" #include "fs_x.h" @@ -90,19 +91,8 @@ typedef struct fs_txn_root_data_t { /* TXN_ID value from the main struct but as a struct instead of a string */ svn_fs_x__txn_id_t txn_id; - - /* Cache of txn DAG nodes (without their nested noderevs, because - * it's mutable). Same keys/values as ffd->rev_node_cache. */ - svn_cache__t *txn_node_cache; } fs_txn_root_data_t; -/* Declared here to resolve the circular dependencies. */ -static svn_error_t * -get_dag(dag_node_t **dag_node_p, - svn_fs_root_t *root, - const char *path, - apr_pool_t *pool); - static svn_fs_root_t * make_revision_root(svn_fs_t *fs, svn_revnum_t rev, @@ -123,391 +113,6 @@ x_closest_copy(svn_fs_root_t **root_p, const char *path, apr_pool_t *pool); - -/*** Node Caching ***/ - -/* 1st level cache */ - -/* An entry in the first-level cache. REVISION and PATH form the key that - will ultimately be matched. - */ -typedef struct cache_entry_t -{ - /* hash value derived from PATH, REVISION. - Used to short-circuit failed lookups. */ - apr_uint32_t hash_value; - - /* revision to which the NODE belongs */ - svn_revnum_t revision; - - /* path of the NODE */ - char *path; - - /* cached value of strlen(PATH). */ - apr_size_t path_len; - - /* the node allocated in the cache's pool. NULL for empty entries. */ - dag_node_t *node; -} cache_entry_t; - -/* Number of entries in the cache. Keep this low to keep pressure on the - CPU caches low as well. A binary value is most efficient. If we walk - a directory tree, we want enough entries to store nodes for all files - without overwriting the nodes for the parent folder. That way, there - will be no unnecessary misses (except for a few random ones caused by - hash collision). - - The actual number of instances may be higher but entries that got - overwritten are no longer visible. - */ -enum { BUCKET_COUNT = 256 }; - -/* The actual cache structure. All nodes will be allocated in POOL. - When the number of INSERTIONS (i.e. objects created form that pool) - exceeds a certain threshold, the pool will be cleared and the cache - with it. - */ -struct svn_fs_x__dag_cache_t -{ - /* fixed number of (possibly empty) cache entries */ - cache_entry_t buckets[BUCKET_COUNT]; - - /* pool used for all node allocation */ - apr_pool_t *pool; - - /* number of entries created from POOL since the last cleanup */ - apr_size_t insertions; - - /* Property lookups etc. have a very high locality (75% re-hit). - Thus, remember the last hit location for optimistic lookup. */ - apr_size_t last_hit; - - /* Position of the last bucket hit that actually had a DAG node in it. - LAST_HIT may refer to a bucket that matches path@rev but has not - its NODE element set, yet. - This value is a mere hint for optimistic lookup and any value is - valid (as long as it is < BUCKET_COUNT). */ - apr_size_t last_non_empty; -}; - -svn_fs_x__dag_cache_t* -svn_fs_x__create_dag_cache(apr_pool_t *result_pool) -{ - svn_fs_x__dag_cache_t *result = apr_pcalloc(result_pool, sizeof(*result)); - result->pool = svn_pool_create(result_pool); - - return result; -} - -/* Clears the CACHE at regular intervals (destroying all cached nodes) - */ -static void -auto_clear_dag_cache(svn_fs_x__dag_cache_t* cache) -{ - if (cache->insertions > BUCKET_COUNT) - { - svn_pool_clear(cache->pool); - - memset(cache->buckets, 0, sizeof(cache->buckets)); - cache->insertions = 0; - } -} - -/* For the given REVISION and PATH, return the respective entry in CACHE. - If the entry is empty, its NODE member will be NULL and the caller - may then set it to the corresponding DAG node allocated in CACHE->POOL. - */ -static cache_entry_t * -cache_lookup( svn_fs_x__dag_cache_t *cache - , svn_revnum_t revision - , const char *path) -{ - apr_size_t i, bucket_index; - apr_size_t path_len = strlen(path); - apr_uint32_t hash_value = (apr_uint32_t)revision; - -#if SVN_UNALIGNED_ACCESS_IS_OK - /* "randomizing" / distributing factor used in our hash function */ - const apr_uint32_t factor = 0xd1f3da69; -#endif - - /* optimistic lookup: hit the same bucket again? */ - cache_entry_t *result = &cache->buckets[cache->last_hit]; - if ( (result->revision == revision) - && (result->path_len == path_len) - && !memcmp(result->path, path, path_len)) - { - /* Remember the position of the last node we found in this cache. */ - if (result->node) - cache->last_non_empty = cache->last_hit; - - return result; - } - - /* need to do a full lookup. Calculate the hash value - (HASH_VALUE has been initialized to REVISION). */ - i = 0; -#if SVN_UNALIGNED_ACCESS_IS_OK - /* We relax the dependency chain between iterations by processing - two chunks from the input per hash_value self-multiplication. - The HASH_VALUE update latency is now 1 MUL latency + 1 ADD latency - per 2 chunks instead of 1 chunk. - */ - for (; i + 8 <= path_len; i += 8) - hash_value = hash_value * factor * factor - + ( *(const apr_uint32_t*)(path + i) * factor - + *(const apr_uint32_t*)(path + i + 4)); -#endif - - for (; i < path_len; ++i) - /* Help GCC to minimize the HASH_VALUE update latency by splitting the - MUL 33 of the naive implementation: h = h * 33 + path[i]. This - shortens the dependency chain from 1 shift + 2 ADDs to 1 shift + 1 ADD. - */ - hash_value = hash_value * 32 + (hash_value + (unsigned char)path[i]); - - bucket_index = hash_value + (hash_value >> 16); - bucket_index = (bucket_index + (bucket_index >> 8)) % BUCKET_COUNT; - - /* access the corresponding bucket and remember its location */ - result = &cache->buckets[bucket_index]; - cache->last_hit = bucket_index; - - /* if it is *NOT* a match, clear the bucket, expect the caller to fill - in the node and count it as an insertion */ - if ( (result->hash_value != hash_value) - || (result->revision != revision) - || (result->path_len != path_len) - || memcmp(result->path, path, path_len)) - { - result->hash_value = hash_value; - result->revision = revision; - if (result->path_len < path_len) - result->path = apr_palloc(cache->pool, path_len + 1); - result->path_len = path_len; - memcpy(result->path, path, path_len + 1); - - result->node = NULL; - - cache->insertions++; - } - else if (result->node) - { - /* This bucket is valid & has a suitable DAG node in it. - Remember its location. */ - cache->last_non_empty = bucket_index; - } - - return result; -} - -/* Optimistic lookup using the last seen non-empty location in CACHE. - Return the node of that entry, if it is still in use and matches PATH. - Return NULL otherwise. Since the caller usually already knows the path - length, provide it in PATH_LEN. */ -static dag_node_t * -cache_lookup_last_path(svn_fs_x__dag_cache_t *cache, - const char *path, - apr_size_t path_len) -{ - cache_entry_t *result = &cache->buckets[cache->last_non_empty]; - assert(strlen(path) == path_len); - - if ( result->node - && (result->path_len == path_len) - && !memcmp(result->path, path, path_len)) - { - return result->node; - } - - return NULL; -} - -/* 2nd level cache */ - -/* Find and return the DAG node cache for ROOT and the key that - should be used for PATH. - - RESULT_POOL will only be used for allocating a new keys if necessary. */ -static void -locate_cache(svn_cache__t **cache, - const char **key, - svn_fs_root_t *root, - const char *path, - apr_pool_t *result_pool) -{ - if (root->is_txn_root) - { - fs_txn_root_data_t *frd = root->fsap_data; - - if (cache) - *cache = frd->txn_node_cache; - if (key && path) - *key = path; - } - else - { - svn_fs_x__data_t *ffd = root->fs->fsap_data; - - if (cache) - *cache = ffd->rev_node_cache; - if (key && path) - *key = svn_fs_x__combine_number_and_string(root->rev, path, - result_pool); - } -} - -/* Return NODE for PATH from ROOT's node cache, or NULL if the node - isn't cached; read it from the FS. *NODE remains valid until either - POOL or the FS gets cleared or destroyed (whichever comes first). - */ -static svn_error_t * -dag_node_cache_get(dag_node_t **node_p, - svn_fs_root_t *root, - const char *path, - apr_pool_t *pool) -{ - svn_boolean_t found; - dag_node_t *node = NULL; - svn_cache__t *cache; - const char *key; - - SVN_ERR_ASSERT(*path == '/'); - - if (!root->is_txn_root) - { - /* immutable DAG node. use the global caches for it */ - - svn_fs_x__data_t *ffd = root->fs->fsap_data; - cache_entry_t *bucket; - - auto_clear_dag_cache(ffd->dag_node_cache); - bucket = cache_lookup(ffd->dag_node_cache, root->rev, path); - if (bucket->node == NULL) - { - locate_cache(&cache, &key, root, path, pool); - SVN_ERR(svn_cache__get((void **)&node, &found, cache, key, - ffd->dag_node_cache->pool)); - if (found && node) - { - /* Patch up the FS, since this might have come from an old FS - * object. */ - svn_fs_x__dag_set_fs(node, root->fs); - bucket->node = node; - } - } - else - { - node = bucket->node; - } - } - else - { - /* DAG is mutable / may become invalid. Use the TXN-local cache */ - - locate_cache(&cache, &key, root, path, pool); - - SVN_ERR(svn_cache__get((void **) &node, &found, cache, key, pool)); - if (found && node) - { - /* Patch up the FS, since this might have come from an old FS - * object. */ - svn_fs_x__dag_set_fs(node, root->fs); - } - } - - *node_p = node; - - return SVN_NO_ERROR; -} - - -/* Add the NODE for PATH to ROOT's node cache. */ -static svn_error_t * -dag_node_cache_set(svn_fs_root_t *root, - const char *path, - dag_node_t *node, - apr_pool_t *scratch_pool) -{ - svn_cache__t *cache; - const char *key; - - SVN_ERR_ASSERT(*path == '/'); - - /* Do *not* attempt to dup and put the node into L1. - * dup() is twice as expensive as an L2 lookup (which will set also L1). - */ - locate_cache(&cache, &key, root, path, scratch_pool); - - return svn_cache__set(cache, key, node, scratch_pool); -} - - -/* Baton for find_descendants_in_cache. */ -typedef struct fdic_baton_t -{ - const char *path; - apr_array_header_t *list; - apr_pool_t *pool; -} fdic_baton_t; - -/* If the given item is a descendant of BATON->PATH, push - * it onto BATON->LIST (copying into BATON->POOL). Implements - * the svn_iter_apr_hash_cb_t prototype. */ -static svn_error_t * -find_descendants_in_cache(void *baton, - const void *key, - apr_ssize_t klen, - void *val, - apr_pool_t *pool) -{ - fdic_baton_t *b = baton; - const char *item_path = key; - - if (svn_fspath__skip_ancestor(b->path, item_path)) - APR_ARRAY_PUSH(b->list, const char *) = apr_pstrdup(b->pool, item_path); - - return SVN_NO_ERROR; -} - -/* Invalidate cache entries for PATH and any of its children. This - should *only* be called on a transaction root! */ -static svn_error_t * -dag_node_cache_invalidate(svn_fs_root_t *root, - const char *path, - apr_pool_t *scratch_pool) -{ - fdic_baton_t b; - svn_cache__t *cache; - apr_pool_t *iterpool; - int i; - - b.path = path; - b.pool = svn_pool_create(scratch_pool); - b.list = apr_array_make(b.pool, 1, sizeof(const char *)); - - SVN_ERR_ASSERT(root->is_txn_root); - locate_cache(&cache, NULL, root, NULL, b.pool); - - - SVN_ERR(svn_cache__iter(NULL, cache, find_descendants_in_cache, - &b, b.pool)); - - iterpool = svn_pool_create(b.pool); - - for (i = 0; i < b.list->nelts; i++) - { - const char *descendant = APR_ARRAY_IDX(b.list, i, const char *); - svn_pool_clear(iterpool); - SVN_ERR(svn_cache__set(cache, descendant, NULL, iterpool)); - } - - svn_pool_destroy(iterpool); - svn_pool_destroy(b.pool); - return SVN_NO_ERROR; -} - - /* Creating transaction and revision root nodes. */ @@ -554,8 +159,8 @@ svn_fs_x__revision_root(svn_fs_root_t **root_p, /* Getting dag nodes for roots. */ /* Return the transaction ID to a given transaction ROOT. */ -static svn_fs_x__txn_id_t -root_txn_id(svn_fs_root_t *root) +svn_fs_x__txn_id_t +svn_fs_x__root_txn_id(svn_fs_root_t *root) { fs_txn_root_data_t *frd = root->fsap_data; assert(root->is_txn_root); @@ -563,105 +168,32 @@ root_txn_id(svn_fs_root_t *root) return frd->txn_id; } -/* Set *NODE_P to a freshly opened dag node referring to the root - directory of ROOT, allocating from RESULT_POOL. Use SCRATCH_POOL - for temporary allocations. */ -static svn_error_t * -root_node(dag_node_t **node_p, - svn_fs_root_t *root, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) +/* Return the change set to a given ROOT. */ +svn_fs_x__change_set_t +svn_fs_x__root_change_set(svn_fs_root_t *root) { if (root->is_txn_root) - { - /* It's a transaction root. Open a fresh copy. */ - return svn_fs_x__dag_txn_root(node_p, root->fs, root_txn_id(root), - result_pool, scratch_pool); - } - else - { - /* It's a revision root, so we already have its root directory - opened. */ - return svn_fs_x__dag_revision_root(node_p, root->fs, root->rev, - result_pool, scratch_pool); - } + return svn_fs_x__change_set_by_txn(svn_fs_x__root_txn_id(root)); + + return svn_fs_x__change_set_by_rev(root->rev); } -/* Set *NODE_P to a mutable root directory for ROOT, cloning if - necessary, allocating in RESULT_POOL. ROOT must be a transaction root. - Use ERROR_PATH in error messages. Use SCRATCH_POOL for temporaries.*/ -static svn_error_t * -mutable_root_node(dag_node_t **node_p, - svn_fs_root_t *root, - const char *error_path, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) -{ - if (root->is_txn_root) - { - /* It's a transaction root. Open a fresh copy. */ - return svn_fs_x__dag_txn_root(node_p, root->fs, root_txn_id(root), - result_pool, scratch_pool); - } - else - /* If it's not a transaction root, we can't change its contents. */ - return SVN_FS__ERR_NOT_MUTABLE(root->fs, root->rev, error_path); -} - /* Traversing directory paths. */ -typedef enum copy_id_inherit_t -{ - copy_id_inherit_unknown = 0, - copy_id_inherit_self, - copy_id_inherit_parent, - copy_id_inherit_new - -} copy_id_inherit_t; - -/* A linked list representing the path from a node up to a root - directory. We use this for cloning, and for operations that need - to deal with both a node and its parent directory. For example, a - `delete' operation needs to know that the node actually exists, but - also needs to change the parent directory. */ -typedef struct parent_path_t -{ - - /* A node along the path. This could be the final node, one of its - parents, or the root. Every parent path ends with an element for - the root directory. */ - dag_node_t *node; - - /* The name NODE has in its parent directory. This is zero for the - root directory, which (obviously) has no name in its parent. */ - char *entry; - - /* The parent of NODE, or zero if NODE is the root directory. */ - struct parent_path_t *parent; - - /* The copy ID inheritance style. */ - copy_id_inherit_t copy_inherit; - - /* If copy ID inheritance style is copy_id_inherit_new, this is the - path which should be implicitly copied; otherwise, this is NULL. */ - const char *copy_src_path; - -} parent_path_t; - -/* Return a text string describing the absolute path of parent_path - PARENT_PATH. It will be allocated in POOL. */ +/* Return a text string describing the absolute path of parent path + DAG_PATH. It will be allocated in POOL. */ static const char * -parent_path_path(parent_path_t *parent_path, +parent_path_path(svn_fs_x__dag_path_t *dag_path, apr_pool_t *pool) { const char *path_so_far = "/"; - if (parent_path->parent) - path_so_far = parent_path_path(parent_path->parent, pool); - return parent_path->entry - ? svn_fspath__join(path_so_far, parent_path->entry, pool) + if (dag_path->parent) + path_so_far = parent_path_path(dag_path->parent, pool); + return dag_path->entry + ? svn_fspath__join(path_so_far, dag_path->entry, pool) : path_so_far; } @@ -669,12 +201,12 @@ parent_path_path(parent_path_t *parent_path, /* Return the FS path for the parent path chain object CHILD relative to its ANCESTOR in the same chain, allocated in POOL. */ static const char * -parent_path_relpath(parent_path_t *child, - parent_path_t *ancestor, +parent_path_relpath(svn_fs_x__dag_path_t *child, + svn_fs_x__dag_path_t *ancestor, apr_pool_t *pool) { const char *path_so_far = ""; - parent_path_t *this_node = child; + svn_fs_x__dag_path_t *this_node = child; while (this_node != ancestor) { assert(this_node != NULL); @@ -686,583 +218,22 @@ parent_path_relpath(parent_path_t *child, -/* Choose a copy ID inheritance method *INHERIT_P to be used in the - event that immutable node CHILD in FS needs to be made mutable. If - the inheritance method is copy_id_inherit_new, also return a - *COPY_SRC_PATH on which to base the new copy ID (else return NULL - for that path). CHILD must have a parent (it cannot be the root - node). Allocations are taken from POOL. */ -static svn_error_t * -get_copy_inheritance(copy_id_inherit_t *inherit_p, - const char **copy_src_path, - svn_fs_t *fs, - parent_path_t *child, - apr_pool_t *pool) -{ - svn_fs_x__id_t child_copy_id, parent_copy_id; - svn_boolean_t related; - const char *id_path = NULL; - svn_fs_root_t *copyroot_root; - dag_node_t *copyroot_node; - svn_revnum_t copyroot_rev; - const char *copyroot_path; - - SVN_ERR_ASSERT(child && child->parent); - - /* Initialize some convenience variables. */ - SVN_ERR(svn_fs_x__dag_get_copy_id(&child_copy_id, child->node)); - SVN_ERR(svn_fs_x__dag_get_copy_id(&parent_copy_id, child->parent->node)); - - /* If this child is already mutable, we have nothing to do. */ - if (svn_fs_x__dag_check_mutable(child->node)) - { - *inherit_p = copy_id_inherit_self; - *copy_src_path = NULL; - return SVN_NO_ERROR; - } - - /* From this point on, we'll assume that the child will just take - its copy ID from its parent. */ - *inherit_p = copy_id_inherit_parent; - *copy_src_path = NULL; - - /* Special case: if the child's copy ID is '0', use the parent's - copy ID. */ - if (svn_fs_x__id_is_root(&child_copy_id)) - return SVN_NO_ERROR; - - /* Compare the copy IDs of the child and its parent. If they are - the same, then the child is already on the same branch as the - parent, and should use the same mutability copy ID that the - parent will use. */ - if (svn_fs_x__id_eq(&child_copy_id, &parent_copy_id)) - return SVN_NO_ERROR; - - /* If the child is on the same branch that the parent is on, the - child should just use the same copy ID that the parent would use. - Else, the child needs to generate a new copy ID to use should it - need to be made mutable. We will claim that child is on the same - branch as its parent if the child itself is not a branch point, - or if it is a branch point that we are accessing via its original - copy destination path. */ - SVN_ERR(svn_fs_x__dag_get_copyroot(©root_rev, ©root_path, - child->node)); - SVN_ERR(svn_fs_x__revision_root(©root_root, fs, copyroot_rev, pool)); - SVN_ERR(get_dag(©root_node, copyroot_root, copyroot_path, pool)); - - SVN_ERR(svn_fs_x__dag_related_node(&related, copyroot_node, child->node)); - if (!related) - return SVN_NO_ERROR; - - /* Determine if we are looking at the child via its original path or - as a subtree item of a copied tree. */ - id_path = svn_fs_x__dag_get_created_path(child->node); - if (strcmp(id_path, parent_path_path(child, pool)) == 0) - { - *inherit_p = copy_id_inherit_self; - return SVN_NO_ERROR; - } - - /* We are pretty sure that the child node is an unedited nested - branched node. When it needs to be made mutable, it should claim - a new copy ID. */ - *inherit_p = copy_id_inherit_new; - *copy_src_path = id_path; - return SVN_NO_ERROR; -} - -/* Allocate a new parent_path_t node from RESULT_POOL, referring to NODE, - ENTRY, PARENT, and COPY_ID. */ -static parent_path_t * -make_parent_path(dag_node_t *node, - char *entry, - parent_path_t *parent, - apr_pool_t *result_pool) -{ - parent_path_t *parent_path = apr_pcalloc(result_pool, sizeof(*parent_path)); - if (node) - parent_path->node = svn_fs_x__dag_copy_into_pool(node, result_pool); - parent_path->entry = entry; - parent_path->parent = parent; - parent_path->copy_inherit = copy_id_inherit_unknown; - parent_path->copy_src_path = NULL; - return parent_path; -} - - -/* Flags for open_path. */ -typedef enum open_path_flags_t { - - /* The last component of the PATH need not exist. (All parent - directories must exist, as usual.) If the last component doesn't - exist, simply leave the `node' member of the bottom parent_path - component zero. */ - open_path_last_optional = 1, - - /* When this flag is set, don't bother to lookup the DAG node in - our caches because we already tried this. Ignoring this flag - has no functional impact. */ - open_path_uncached = 2, - - /* The caller does not care about the parent node chain but only - the final DAG node. */ - open_path_node_only = 4, - - /* The caller wants a NULL path object instead of an error if the - path cannot be found. */ - open_path_allow_null = 8 -} open_path_flags_t; - -/* Try a short-cut for the open_path() function using the last node accessed. - * If that ROOT is that nodes's "created rev" and PATH of PATH_LEN chars is - * its "created path", return the node in *NODE_P. Set it to NULL otherwise. - * - * This function is used to support ra_serf-style access patterns where we - * are first asked for path@rev and then for path@c_rev of the same node. - * The shortcut works by ignoring the "rev" part of the cache key and then - * checking whether we got lucky. Lookup and verification are both quick - * plus there are many early outs for common types of mismatch. - */ -static svn_error_t * -try_match_last_node(dag_node_t **node_p, - svn_fs_root_t *root, - const char *path, - apr_size_t path_len, - apr_pool_t *scratch_pool) -{ - svn_fs_x__data_t *ffd = root->fs->fsap_data; - - /* Optimistic lookup: if the last node returned from the cache applied to - the same PATH, return it in NODE. */ - dag_node_t *node - = cache_lookup_last_path(ffd->dag_node_cache, path, path_len); - - /* Did we get a bucket with a committed node? */ - if (node && !svn_fs_x__dag_check_mutable(node)) - { - /* Get the path&rev pair at which this node was created. - This is repository location for which this node is _known_ to be - the right lookup result irrespective of how we found it. */ - const char *created_path - = svn_fs_x__dag_get_created_path(node); - svn_revnum_t revision = svn_fs_x__dag_get_revision(node); - - /* Is it an exact match? */ - if (revision == root->rev && strcmp(created_path, path) == 0) - { - /* Cache it under its full path@rev access path. */ - SVN_ERR(dag_node_cache_set(root, path, node, scratch_pool)); - - *node_p = node; - return SVN_NO_ERROR; - } - } - - *node_p = NULL; - return SVN_NO_ERROR; -} - - -/* Open the node identified by PATH in ROOT, allocating in POOL. Set - *PARENT_PATH_P to a path from the node up to ROOT. The resulting - **PARENT_PATH_P value is guaranteed to contain at least one - *element, for the root directory. PATH must be in canonical form. - - If resulting *PARENT_PATH_P will eventually be made mutable and - modified, or if copy ID inheritance information is otherwise needed, - IS_TXN_PATH must be set. If IS_TXN_PATH is FALSE, no copy ID - inheritance information will be calculated for the *PARENT_PATH_P chain. - - If FLAGS & open_path_last_optional is zero, return the error - SVN_ERR_FS_NOT_FOUND if the node PATH refers to does not exist. If - non-zero, require all the parent directories to exist as normal, - but if the final path component doesn't exist, simply return a path - whose bottom `node' member is zero. This option is useful for - callers that create new nodes --- we find the parent directory for - them, and tell them whether the entry exists already. - - The remaining bits in FLAGS are hints that allow this function - to take shortcuts based on knowledge that the caller provides, - such as the caller is not actually being interested in PARENT_PATH_P, - but only in (*PARENT_PATH_P)->NODE. - - NOTE: Public interfaces which only *read* from the filesystem - should not call this function directly, but should instead use - get_dag(). -*/ -static svn_error_t * -open_path(parent_path_t **parent_path_p, - svn_fs_root_t *root, - const char *path, - int flags, - svn_boolean_t is_txn_path, - apr_pool_t *pool) -{ - svn_fs_t *fs = root->fs; - dag_node_t *here = NULL; /* The directory we're currently looking at. */ - parent_path_t *parent_path; /* The path from HERE up to the root. */ - const char *rest = NULL; /* The portion of PATH we haven't traversed yet. */ - apr_pool_t *iterpool = svn_pool_create(pool); - - /* path to the currently processed entry without trailing '/'. - We will reuse this across iterations by simply putting a NUL terminator - at the respective position and replacing that with a '/' in the next - iteration. This is correct as we assert() PATH to be canonical. */ - svn_stringbuf_t *path_so_far = svn_stringbuf_create(path, pool); - apr_size_t path_len = path_so_far->len; - - /* Callers often traverse the DAG in some path-based order or along the - history segments. That allows us to try a few guesses about where to - find the next item. This is only useful if the caller didn't request - the full parent chain. */ - assert(svn_fs__is_canonical_abspath(path)); - path_so_far->len = 0; /* "" */ - if (flags & open_path_node_only) - { - const char *directory; - - /* First attempt: Assume that we access the DAG for the same path as - in the last lookup but for a different revision that happens to be - the last revision that touched the respective node. This is a - common pattern when e.g. checking out over ra_serf. Note that this - will only work for committed data as the revision info for nodes in - txns is bogus. - - This shortcut is quick and will exit this function upon success. - So, try it first. */ - if (!root->is_txn_root) - { - dag_node_t *node; - SVN_ERR(try_match_last_node(&node, root, path, path_len, iterpool)); - - /* Did the shortcut work? */ - if (node) - { - /* Construct and return the result. */ - svn_pool_destroy(iterpool); - - parent_path = make_parent_path(node, 0, 0, pool); - parent_path->copy_inherit = copy_id_inherit_self; - *parent_path_p = parent_path; - - return SVN_NO_ERROR; - } - } - - /* Second attempt: Try starting the lookup immediately at the parent - node. We will often have recently accessed either a sibling or - said parent DIRECTORY itself for the same revision. */ - directory = svn_dirent_dirname(path, pool); - if (directory[1] != 0) /* root nodes are covered anyway */ - { - SVN_ERR(dag_node_cache_get(&here, root, directory, pool)); - - /* Did the shortcut work? */ - if (here) - { - apr_size_t dirname_len = strlen(directory); - path_so_far->len = dirname_len; - rest = path + dirname_len + 1; - } - } - } - - /* did the shortcut work? */ - if (!here) - { - /* Make a parent_path item for the root node, using its own current - copy id. */ - SVN_ERR(root_node(&here, root, pool, iterpool)); - rest = path + 1; /* skip the leading '/', it saves in iteration */ - } - - path_so_far->data[path_so_far->len] = '\0'; - parent_path = make_parent_path(here, 0, 0, pool); - parent_path->copy_inherit = copy_id_inherit_self; - - /* Whenever we are at the top of this loop: - - HERE is our current directory, - - ID is the node revision ID of HERE, - - REST is the path we're going to find in HERE, and - - PARENT_PATH includes HERE and all its parents. */ - for (;;) - { - const char *next; - char *entry; - dag_node_t *child; - - svn_pool_clear(iterpool); - - /* The NODE in PARENT_PATH always lives in POOL, i.e. it will - * survive the cleanup of ITERPOOL and the DAG cache.*/ - here = parent_path->node; - - /* Parse out the next entry from the path. */ - entry = svn_fs__next_entry_name(&next, rest, pool); - - /* Update the path traversed thus far. */ - path_so_far->data[path_so_far->len] = '/'; - path_so_far->len += strlen(entry) + 1; - path_so_far->data[path_so_far->len] = '\0'; - - /* Given the behavior of svn_fs__next_entry_name(), ENTRY may be an - empty string when the path either starts or ends with a slash. - In either case, we stay put: the current directory stays the - same, and we add nothing to the parent path. We only need to - process non-empty path segments. */ - if (*entry != '\0') - { - copy_id_inherit_t inherit; - const char *copy_path = NULL; - dag_node_t *cached_node = NULL; - - /* If we found a directory entry, follow it. First, we - check our node cache, and, failing that, we hit the DAG - layer. Don't bother to contact the cache for the last - element if we already know the lookup to fail for the - complete path. */ - if (next || !(flags & open_path_uncached)) - SVN_ERR(dag_node_cache_get(&cached_node, root, path_so_far->data, - pool)); - if (cached_node) - child = cached_node; - else - SVN_ERR(svn_fs_x__dag_open(&child, here, entry, pool, iterpool)); - - /* "file not found" requires special handling. */ - if (child == NULL) - { - /* If this was the last path component, and the caller - said it was optional, then don't return an error; - just put a NULL node pointer in the path. */ - - if ((flags & open_path_last_optional) - && (! next || *next == '\0')) - { - parent_path = make_parent_path(NULL, entry, parent_path, - pool); - break; - } - else if (flags & open_path_allow_null) - { - parent_path = NULL; - break; - } - else - { - /* Build a better error message than svn_fs_x__dag_open - can provide, giving the root and full path name. */ - return SVN_FS__NOT_FOUND(root, path); - } - } - - if (flags & open_path_node_only) - { - /* Shortcut: the caller only wants the final DAG node. */ - parent_path->node = svn_fs_x__dag_copy_into_pool(child, pool); - } - else - { - /* Now, make a parent_path item for CHILD. */ - parent_path = make_parent_path(child, entry, parent_path, pool); - if (is_txn_path) - { - SVN_ERR(get_copy_inheritance(&inherit, ©_path, fs, - parent_path, iterpool)); - parent_path->copy_inherit = inherit; - parent_path->copy_src_path = apr_pstrdup(pool, copy_path); - } - } - - /* Cache the node we found (if it wasn't already cached). */ - if (! cached_node) - SVN_ERR(dag_node_cache_set(root, path_so_far->data, child, - iterpool)); - } - - /* Are we finished traversing the path? */ - if (! next) - break; - - /* The path isn't finished yet; we'd better be in a directory. */ - if (svn_fs_x__dag_node_kind(child) != svn_node_dir) - SVN_ERR_W(SVN_FS__ERR_NOT_DIRECTORY(fs, path_so_far->data), - apr_psprintf(iterpool, _("Failure opening '%s'"), path)); - - rest = next; - } - - svn_pool_destroy(iterpool); - *parent_path_p = parent_path; - return SVN_NO_ERROR; -} - - -/* Make the node referred to by PARENT_PATH mutable, if it isn't already, - allocating from RESULT_POOL. ROOT must be the root from which - PARENT_PATH descends. Clone any parent directories as needed. - Adjust the dag nodes in PARENT_PATH to refer to the clones. Use - ERROR_PATH in error messages. Use SCRATCH_POOL for temporaries. */ -static svn_error_t * -make_path_mutable(svn_fs_root_t *root, - parent_path_t *parent_path, - const char *error_path, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) -{ - dag_node_t *clone; - svn_fs_x__txn_id_t txn_id = root_txn_id(root); - - /* Is the node mutable already? */ - if (svn_fs_x__dag_check_mutable(parent_path->node)) - return SVN_NO_ERROR; - - /* Are we trying to clone the root, or somebody's child node? */ - if (parent_path->parent) - { - svn_fs_x__id_t copy_id = { SVN_INVALID_REVNUM, 0 }; - svn_fs_x__id_t *copy_id_ptr = ©_id; - copy_id_inherit_t inherit = parent_path->copy_inherit; - const char *clone_path, *copyroot_path; - svn_revnum_t copyroot_rev; - svn_boolean_t is_parent_copyroot = FALSE; - svn_fs_root_t *copyroot_root; - dag_node_t *copyroot_node; - svn_boolean_t related; - - /* We're trying to clone somebody's child. Make sure our parent - is mutable. */ - SVN_ERR(make_path_mutable(root, parent_path->parent, - error_path, result_pool, scratch_pool)); - - switch (inherit) - { - case copy_id_inherit_parent: - SVN_ERR(svn_fs_x__dag_get_copy_id(©_id, - parent_path->parent->node)); - break; - - case copy_id_inherit_new: - SVN_ERR(svn_fs_x__reserve_copy_id(©_id, root->fs, txn_id, - scratch_pool)); - break; - - case copy_id_inherit_self: - copy_id_ptr = NULL; - break; - - case copy_id_inherit_unknown: - default: - SVN_ERR_MALFUNCTION(); /* uh-oh -- somebody didn't calculate copy-ID - inheritance data. */ - } - - /* Determine what copyroot our new child node should use. */ - SVN_ERR(svn_fs_x__dag_get_copyroot(©root_rev, ©root_path, - parent_path->node)); - SVN_ERR(svn_fs_x__revision_root(©root_root, root->fs, - copyroot_rev, scratch_pool)); - SVN_ERR(get_dag(©root_node, copyroot_root, copyroot_path, - result_pool)); - - SVN_ERR(svn_fs_x__dag_related_node(&related, copyroot_node, - parent_path->node)); - if (!related) - is_parent_copyroot = TRUE; - - /* Now make this node mutable. */ - clone_path = parent_path_path(parent_path->parent, scratch_pool); - SVN_ERR(svn_fs_x__dag_clone_child(&clone, - parent_path->parent->node, - clone_path, - parent_path->entry, - copy_id_ptr, txn_id, - is_parent_copyroot, - result_pool, - scratch_pool)); - - /* Update the path cache. */ - SVN_ERR(dag_node_cache_set(root, - parent_path_path(parent_path, scratch_pool), - clone, scratch_pool)); - } - else - { - /* We're trying to clone the root directory. */ - SVN_ERR(mutable_root_node(&clone, root, error_path, result_pool, - scratch_pool)); - } - - /* Update the PARENT_PATH link to refer to the clone. */ - parent_path->node = clone; - - return SVN_NO_ERROR; -} - - -/* Open the node identified by PATH in ROOT. Set DAG_NODE_P to the - node we find, allocated in POOL. Return the error - SVN_ERR_FS_NOT_FOUND if this node doesn't exist. - */ -static svn_error_t * -get_dag(dag_node_t **dag_node_p, - svn_fs_root_t *root, - const char *path, - apr_pool_t *pool) -{ - parent_path_t *parent_path; - dag_node_t *node = NULL; - - /* First we look for the DAG in our cache - (if the path may be canonical). */ - if (*path == '/') - SVN_ERR(dag_node_cache_get(&node, root, path, pool)); - - if (! node) - { - /* Canonicalize the input PATH. As it turns out, >95% of all paths - * seen here during e.g. svnadmin verify are non-canonical, i.e. - * miss the leading '/'. Unconditional canonicalization has a net - * performance benefit over previously checking path for being - * canonical. */ - path = svn_fs__canonicalize_abspath(path, pool); - SVN_ERR(dag_node_cache_get(&node, root, path, pool)); - - if (! node) - { - /* Call open_path with no flags, as we want this to return an - * error if the node for which we are searching doesn't exist. */ - SVN_ERR(open_path(&parent_path, root, path, - open_path_uncached | open_path_node_only, - FALSE, pool)); - node = parent_path->node; - - /* No need to cache our find -- open_path() will do that for us. */ - } - } - - *dag_node_p = svn_fs_x__dag_copy_into_pool(node, pool); - return SVN_NO_ERROR; -} - /* Populating the `changes' table. */ /* Add a change to the changes table in FS, keyed on transaction id TXN_ID, and indicated that a change of kind CHANGE_KIND occurred on - PATH (whose node revision id is--or was, in the case of a - deletion--NODEREV_ID), and optionally that TEXT_MODs, PROP_MODs or - MERGEINFO_MODs occurred. If the change resulted from a copy, - COPYFROM_REV and COPYFROM_PATH specify under which revision and path - the node was copied from. If this was not part of a copy, COPYFROM_REV - should be SVN_INVALID_REVNUM. Use SCRATCH_POOL for temporary allocations. + PATH, and optionally that TEXT_MODs, PROP_MODs or MERGEINFO_MODs + occurred. If the change resulted from a copy, COPYFROM_REV and + COPYFROM_PATH specify under which revision and path the node was + copied from. If this was not part of a copy, COPYFROM_REV should + be SVN_INVALID_REVNUM. Use SCRATCH_POOL for temporary allocations. */ static svn_error_t * add_change(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, const char *path, - const svn_fs_x__id_t *noderev_id, svn_fs_path_change_kind_t change_kind, svn_boolean_t text_mod, svn_boolean_t prop_mod, @@ -1275,8 +246,7 @@ add_change(svn_fs_t *fs, return svn_fs_x__add_change(fs, txn_id, svn_fs__canonicalize_abspath(path, scratch_pool), - noderev_id, change_kind, - text_mod, prop_mod, mergeinfo_mod, + change_kind, text_mod, prop_mod, mergeinfo_mod, node_kind, copyfrom_rev, copyfrom_path, scratch_pool); } @@ -1306,10 +276,12 @@ x_node_id(const svn_fs_id_t **id_p, } else { + apr_pool_t *scratch_pool = svn_pool_create(pool); dag_node_t *node; - SVN_ERR(get_dag(&node, root, path, pool)); + SVN_ERR(svn_fs_x__get_temp_dag_node(&node, root, path, scratch_pool)); noderev_id = *svn_fs_x__dag_get_id(node); + svn_pool_destroy(scratch_pool); } *id_p = svn_fs_x__id_create(svn_fs_x__id_create_context(root->fs, pool), @@ -1361,13 +333,13 @@ x_node_relation(svn_fs_node_relation_t *relation, /* We checked for all separations between ID spaces (repos, txn). * Now, we can simply test for the ID values themselves. */ - SVN_ERR(get_dag(&node, root_a, path_a, scratch_pool)); + SVN_ERR(svn_fs_x__get_temp_dag_node(&node, root_a, path_a, scratch_pool)); noderev_id_a = *svn_fs_x__dag_get_id(node); - SVN_ERR(svn_fs_x__dag_get_node_id(&node_id_a, node)); + node_id_a = *svn_fs_x__dag_get_node_id(node); - SVN_ERR(get_dag(&node, root_b, path_b, scratch_pool)); + SVN_ERR(svn_fs_x__get_temp_dag_node(&node, root_b, path_b, scratch_pool)); noderev_id_b = *svn_fs_x__dag_get_id(node); - SVN_ERR(svn_fs_x__dag_get_node_id(&node_id_b, node)); + node_id_b = *svn_fs_x__dag_get_node_id(node); /* In FSX, even in-txn IDs are globally unique. * So, we can simply compare them. */ @@ -1389,7 +361,7 @@ svn_fs_x__node_created_rev(svn_revnum_t *revision, { dag_node_t *node; - SVN_ERR(get_dag(&node, root, path, scratch_pool)); + SVN_ERR(svn_fs_x__get_temp_dag_node(&node, root, path, scratch_pool)); *revision = svn_fs_x__dag_get_revision(node); return SVN_NO_ERROR; @@ -1406,28 +378,8 @@ x_node_created_path(const char **created_path, { dag_node_t *node; - SVN_ERR(get_dag(&node, root, path, pool)); - *created_path = svn_fs_x__dag_get_created_path(node); - - return SVN_NO_ERROR; -} - - -/* Set *KIND_P to the type of node located at PATH under ROOT. - Perform temporary allocations in SCRATCH_POOL. */ -static svn_error_t * -node_kind(svn_node_kind_t *kind_p, - svn_fs_root_t *root, - const char *path, - apr_pool_t *scratch_pool) -{ - dag_node_t *node; - - /* Get the node id. */ - SVN_ERR(get_dag(&node, root, path, scratch_pool)); - - /* Use the node id to get the real kind. */ - *kind_p = svn_fs_x__dag_node_kind(node); + SVN_ERR(svn_fs_x__get_temp_dag_node(&node, root, path, pool)); + *created_path = apr_pstrdup(pool, svn_fs_x__dag_get_created_path(node)); return SVN_NO_ERROR; } @@ -1442,7 +394,16 @@ svn_fs_x__check_path(svn_node_kind_t *kind_p, const char *path, apr_pool_t *scratch_pool) { - svn_error_t *err = node_kind(kind_p, root, path, scratch_pool); + dag_node_t *node; + + /* Get the node id. */ + svn_error_t *err = svn_fs_x__get_temp_dag_node(&node, root, path, + scratch_pool); + + /* Use the node id to get the real kind. */ + if (!err) + *kind_p = svn_fs_x__dag_node_kind(node); + if (err && ((err->apr_err == SVN_ERR_FS_NOT_FOUND) || (err->apr_err == SVN_ERR_FS_NOT_DIRECTORY))) @@ -1469,11 +430,12 @@ x_node_prop(svn_string_t **value_p, apr_hash_t *proplist; apr_pool_t *scratch_pool = svn_pool_create(pool); - SVN_ERR(get_dag(&node, root, path, pool)); - SVN_ERR(svn_fs_x__dag_get_proplist(&proplist, node, pool, scratch_pool)); + SVN_ERR(svn_fs_x__get_temp_dag_node(&node, root, path, scratch_pool)); + SVN_ERR(svn_fs_x__dag_get_proplist(&proplist, node, scratch_pool, + scratch_pool)); *value_p = NULL; if (proplist) - *value_p = svn_hash_gets(proplist, propname); + *value_p = svn_string_dup(svn_hash_gets(proplist, propname), pool); svn_pool_destroy(scratch_pool); return SVN_NO_ERROR; @@ -1493,7 +455,7 @@ x_node_proplist(apr_hash_t **table_p, dag_node_t *node; apr_pool_t *scratch_pool = svn_pool_create(pool); - SVN_ERR(get_dag(&node, root, path, pool)); + SVN_ERR(svn_fs_x__get_temp_dag_node(&node, root, path, scratch_pool)); SVN_ERR(svn_fs_x__dag_get_proplist(table_p, node, pool, scratch_pool)); svn_pool_destroy(scratch_pool); @@ -1516,7 +478,7 @@ x_node_has_props(svn_boolean_t *has_props, } static svn_error_t * -increment_mergeinfo_up_tree(parent_path_t *pp, +increment_mergeinfo_up_tree(svn_fs_x__dag_path_t *pp, apr_int64_t increment, apr_pool_t *scratch_pool) { @@ -1546,7 +508,7 @@ x_change_node_prop(svn_fs_root_t *root, const svn_string_t *value, apr_pool_t *scratch_pool) { - parent_path_t *parent_path; + svn_fs_x__dag_path_t *dag_path; apr_hash_t *proplist; svn_fs_x__txn_id_t txn_id; svn_boolean_t mergeinfo_mod = FALSE; @@ -1554,10 +516,10 @@ x_change_node_prop(svn_fs_root_t *root, if (! root->is_txn_root) return SVN_FS__NOT_TXN(root); - txn_id = root_txn_id(root); + txn_id = svn_fs_x__root_txn_id(root); - path = svn_fs__canonicalize_abspath(path, subpool); - SVN_ERR(open_path(&parent_path, root, path, 0, TRUE, subpool)); + SVN_ERR(svn_fs_x__get_dag_path(&dag_path, root, path, 0, TRUE, subpool, + subpool)); /* Check (non-recursively) to see if path is locked; if so, check that we can use it. */ @@ -1565,8 +527,9 @@ x_change_node_prop(svn_fs_root_t *root, SVN_ERR(svn_fs_x__allow_locked_operation(path, root->fs, FALSE, FALSE, subpool)); - SVN_ERR(make_path_mutable(root, parent_path, path, subpool, subpool)); - SVN_ERR(svn_fs_x__dag_get_proplist(&proplist, parent_path->node, subpool, + SVN_ERR(svn_fs_x__make_path_mutable(root, dag_path, path, subpool, + subpool)); + SVN_ERR(svn_fs_x__dag_get_proplist(&proplist, dag_path->node, subpool, subpool)); /* If there's no proplist, but we're just deleting a property, exit now. */ @@ -1580,8 +543,8 @@ x_change_node_prop(svn_fs_root_t *root, if (strcmp(name, SVN_PROP_MERGEINFO) == 0) { apr_int64_t increment = 0; - svn_boolean_t had_mergeinfo; - SVN_ERR(svn_fs_x__dag_has_mergeinfo(&had_mergeinfo, parent_path->node)); + svn_boolean_t had_mergeinfo + = svn_fs_x__dag_has_mergeinfo(dag_path->node); if (value && !had_mergeinfo) increment = 1; @@ -1590,8 +553,8 @@ x_change_node_prop(svn_fs_root_t *root, if (increment != 0) { - SVN_ERR(increment_mergeinfo_up_tree(parent_path, increment, subpool)); - SVN_ERR(svn_fs_x__dag_set_has_mergeinfo(parent_path->node, + SVN_ERR(increment_mergeinfo_up_tree(dag_path, increment, subpool)); + SVN_ERR(svn_fs_x__dag_set_has_mergeinfo(dag_path->node, (value != NULL), subpool)); } @@ -1602,14 +565,13 @@ x_change_node_prop(svn_fs_root_t *root, svn_hash_sets(proplist, name, value); /* Overwrite the node's proplist. */ - SVN_ERR(svn_fs_x__dag_set_proplist(parent_path->node, proplist, + SVN_ERR(svn_fs_x__dag_set_proplist(dag_path->node, proplist, subpool)); /* Make a record of this modification in the changes table. */ SVN_ERR(add_change(root->fs, txn_id, path, - svn_fs_x__dag_get_id(parent_path->node), svn_fs_path_change_modify, FALSE, TRUE, mergeinfo_mod, - svn_fs_x__dag_node_kind(parent_path->node), + svn_fs_x__dag_node_kind(dag_path->node), SVN_INVALID_REVNUM, NULL, subpool)); svn_pool_destroy(subpool); @@ -1639,8 +601,8 @@ x_props_changed(svn_boolean_t *changed_p, (SVN_ERR_FS_GENERAL, NULL, _("Cannot compare property value between two different filesystems")); - SVN_ERR(get_dag(&node1, root1, path1, subpool)); - SVN_ERR(get_dag(&node2, root2, path2, subpool)); + SVN_ERR(svn_fs_x__get_dag_node(&node1, root1, path1, subpool, subpool)); + SVN_ERR(svn_fs_x__get_temp_dag_node(&node2, root2, path2, subpool)); SVN_ERR(svn_fs_x__dag_things_different(changed_p, NULL, node1, node2, strict, subpool)); svn_pool_destroy(subpool); @@ -1654,9 +616,12 @@ x_props_changed(svn_boolean_t *changed_p, /* Set *NODE to the root node of ROOT. */ static svn_error_t * -get_root(dag_node_t **node, svn_fs_root_t *root, apr_pool_t *pool) +get_root(dag_node_t **node, + svn_fs_root_t *root, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { - return get_dag(node, root, "/", pool); + return svn_fs_x__get_dag_node(node, root, "/", result_pool, scratch_pool); } @@ -1714,7 +679,6 @@ compare_dir_structure(svn_boolean_t *changed, if (strcmp(lhs_entry->name, rhs_entry->name) == 0) { - svn_boolean_t same_history; dag_node_t *lhs_node, *rhs_node; /* Unchanged entry? */ @@ -1729,9 +693,7 @@ compare_dir_structure(svn_boolean_t *changed, iterpool, iterpool)); SVN_ERR(svn_fs_x__dag_get_node(&rhs_node, fs, &rhs_entry->id, iterpool, iterpool)); - SVN_ERR(svn_fs_x__dag_same_line_of_history(&same_history, - lhs_node, rhs_node)); - if (same_history) + if (svn_fs_x__dag_same_line_of_history(lhs_node, rhs_node)) continue; } @@ -1974,15 +936,11 @@ merge(svn_stringbuf_t *conflict_p, process, but the transaction did not touch this entry. */ else if (t_entry && svn_fs_x__id_eq(&a_entry->id, &t_entry->id)) { - apr_int64_t mergeinfo_start; - apr_int64_t mergeinfo_end; - dag_node_t *t_ent_node; SVN_ERR(svn_fs_x__dag_get_node(&t_ent_node, fs, &t_entry->id, iterpool, iterpool)); - SVN_ERR(svn_fs_x__dag_get_mergeinfo_count(&mergeinfo_start, - t_ent_node)); - mergeinfo_increment -= mergeinfo_start; + mergeinfo_increment + -= svn_fs_x__dag_get_mergeinfo_count(t_ent_node); if (s_entry) { @@ -1990,9 +948,8 @@ merge(svn_stringbuf_t *conflict_p, SVN_ERR(svn_fs_x__dag_get_node(&s_ent_node, fs, &s_entry->id, iterpool, iterpool)); - SVN_ERR(svn_fs_x__dag_get_mergeinfo_count(&mergeinfo_end, - s_ent_node)); - mergeinfo_increment += mergeinfo_end; + mergeinfo_increment + += svn_fs_x__dag_get_mergeinfo_count(s_ent_node); SVN_ERR(svn_fs_x__dag_set_entry(target, a_entry->name, &s_entry->id, @@ -2015,7 +972,6 @@ merge(svn_stringbuf_t *conflict_p, dag_node_t *s_ent_node, *t_ent_node, *a_ent_node; const char *new_tpath; apr_int64_t sub_mergeinfo_increment; - svn_boolean_t s_a_same, t_a_same; /* If SOURCE-ENTRY and TARGET-ENTRY are both null, that's a double delete; if one of them is null, that's a delete versus @@ -2045,11 +1001,8 @@ merge(svn_stringbuf_t *conflict_p, /* If either SOURCE-ENTRY or TARGET-ENTRY is not a direct modification of ANCESTOR-ENTRY, declare a conflict. */ - SVN_ERR(svn_fs_x__dag_same_line_of_history(&s_a_same, s_ent_node, - a_ent_node)); - SVN_ERR(svn_fs_x__dag_same_line_of_history(&t_a_same, t_ent_node, - a_ent_node)); - if (!s_a_same || !t_a_same) + if ( !svn_fs_x__dag_same_line_of_history(s_ent_node, a_ent_node) + || !svn_fs_x__dag_same_line_of_history(t_ent_node, a_ent_node)) return conflict_err(conflict_p, svn_fspath__join(target_path, a_entry->name, @@ -2073,7 +1026,6 @@ merge(svn_stringbuf_t *conflict_p, { svn_fs_x__dirent_t *a_entry, *s_entry, *t_entry; dag_node_t *s_ent_node; - apr_int64_t mergeinfo_s; svn_pool_clear(iterpool); @@ -2094,8 +1046,7 @@ merge(svn_stringbuf_t *conflict_p, SVN_ERR(svn_fs_x__dag_get_node(&s_ent_node, fs, &s_entry->id, iterpool, iterpool)); - SVN_ERR(svn_fs_x__dag_get_mergeinfo_count(&mergeinfo_s, s_ent_node)); - mergeinfo_increment += mergeinfo_s; + mergeinfo_increment += svn_fs_x__dag_get_mergeinfo_count(s_ent_node); SVN_ERR(svn_fs_x__dag_set_entry (target, s_entry->name, &s_entry->id, s_entry->kind, @@ -2135,21 +1086,21 @@ merge_changes(dag_node_t *ancestor_node, dag_node_t *txn_root_node; svn_fs_t *fs = txn->fs; svn_fs_x__txn_id_t txn_id = svn_fs_x__txn_get_id(txn); - svn_boolean_t related; - SVN_ERR(svn_fs_x__dag_txn_root(&txn_root_node, fs, txn_id, scratch_pool, - scratch_pool)); + SVN_ERR(svn_fs_x__dag_root(&txn_root_node, fs, + svn_fs_x__change_set_by_txn(txn_id), + scratch_pool, scratch_pool)); if (ancestor_node == NULL) { svn_revnum_t base_rev; SVN_ERR(svn_fs_x__get_base_rev(&base_rev, fs, txn_id, scratch_pool)); - SVN_ERR(svn_fs_x__dag_revision_root(&ancestor_node, fs, base_rev, - scratch_pool, scratch_pool)); + SVN_ERR(svn_fs_x__dag_root(&ancestor_node, fs, + svn_fs_x__change_set_by_rev(base_rev), + scratch_pool, scratch_pool)); } - SVN_ERR(svn_fs_x__dag_related_node(&related, ancestor_node, txn_root_node)); - if (!related) + if (!svn_fs_x__dag_related_node(ancestor_node, txn_root_node)) { /* If no changes have been made in TXN since its current base, then it can't conflict with any changes since that base. @@ -2249,7 +1200,8 @@ svn_fs_x__commit_txn(const char **conflict_p, note that the youngest rev may have changed by then -- that's why we're careful to get this root in its own bdb txn here). */ - SVN_ERR(get_root(&youngish_root_node, youngish_root, iterpool)); + SVN_ERR(get_root(&youngish_root_node, youngish_root, iterpool, + iterpool)); /* Try to merge. If the merge succeeds, the base root node of TARGET's txn will become the same as youngish_root_node, so @@ -2299,7 +1251,7 @@ svn_fs_x__commit_txn(const char **conflict_p, if (ffd->pack_after_commit) { - SVN_ERR(svn_fs_x__pack(fs, NULL, NULL, NULL, NULL, pool)); + SVN_ERR(svn_fs_x__pack(fs, 0, NULL, NULL, NULL, NULL, pool)); } return SVN_NO_ERROR; @@ -2350,10 +1302,10 @@ x_merge(const char **conflict_p, */ /* Get the ancestor node. */ - SVN_ERR(get_root(&ancestor, ancestor_root, pool)); + SVN_ERR(get_root(&ancestor, ancestor_root, pool, pool)); /* Get the source node. */ - SVN_ERR(get_root(&source, source_root, pool)); + SVN_ERR(get_root(&source, source_root, pool, pool)); /* Open a txn for the txn root into which we're merging. */ SVN_ERR(svn_fs_x__open_txn(&txn, ancestor_root->fs, target_root->txn, @@ -2404,7 +1356,7 @@ x_dir_entries(apr_hash_t **table_p, apr_pool_t *scratch_pool = svn_pool_create(pool); /* Get the entries for this path in the caller's pool. */ - SVN_ERR(get_dag(&node, root, path, scratch_pool)); + SVN_ERR(svn_fs_x__get_temp_dag_node(&node, root, path, scratch_pool)); SVN_ERR(svn_fs_x__dag_dir_entries(&table, node, scratch_pool, scratch_pool)); @@ -2454,14 +1406,14 @@ x_make_dir(svn_fs_root_t *root, const char *path, apr_pool_t *scratch_pool) { - parent_path_t *parent_path; + svn_fs_x__dag_path_t *dag_path; dag_node_t *sub_dir; - svn_fs_x__txn_id_t txn_id = root_txn_id(root); + svn_fs_x__txn_id_t txn_id = svn_fs_x__root_txn_id(root); apr_pool_t *subpool = svn_pool_create(scratch_pool); - path = svn_fs__canonicalize_abspath(path, subpool); - SVN_ERR(open_path(&parent_path, root, path, open_path_last_optional, - TRUE, subpool)); + SVN_ERR(svn_fs_x__get_dag_path(&dag_path, root, path, + svn_fs_x__dag_path_last_optional, + TRUE, subpool, subpool)); /* Check (recursively) to see if some lock is 'reserving' a path at that location, or even some child-path; if so, check that we can @@ -2472,26 +1424,25 @@ x_make_dir(svn_fs_root_t *root, /* If there's already a sub-directory by that name, complain. This also catches the case of trying to make a subdirectory named `/'. */ - if (parent_path->node) + if (dag_path->node) return SVN_FS__ALREADY_EXISTS(root, path); /* Create the subdirectory. */ - SVN_ERR(make_path_mutable(root, parent_path->parent, path, subpool, - subpool)); + SVN_ERR(svn_fs_x__make_path_mutable(root, dag_path->parent, path, subpool, + subpool)); SVN_ERR(svn_fs_x__dag_make_dir(&sub_dir, - parent_path->parent->node, - parent_path_path(parent_path->parent, + dag_path->parent->node, + parent_path_path(dag_path->parent, subpool), - parent_path->entry, + dag_path->entry, txn_id, subpool, subpool)); /* Add this directory to the path cache. */ - SVN_ERR(dag_node_cache_set(root, parent_path_path(parent_path, subpool), - sub_dir, subpool)); + svn_fs_x__update_dag_cache(sub_dir); /* Make a record of this modification in the changes table. */ - SVN_ERR(add_change(root->fs, txn_id, path, svn_fs_x__dag_get_id(sub_dir), + SVN_ERR(add_change(root->fs, txn_id, path, svn_fs_path_change_add, FALSE, FALSE, FALSE, svn_node_dir, SVN_INVALID_REVNUM, NULL, subpool)); @@ -2507,7 +1458,7 @@ x_delete_node(svn_fs_root_t *root, const char *path, apr_pool_t *scratch_pool) { - parent_path_t *parent_path; + svn_fs_x__dag_path_t *dag_path; svn_fs_x__txn_id_t txn_id; apr_int64_t mergeinfo_count = 0; svn_node_kind_t kind; @@ -2516,13 +1467,13 @@ x_delete_node(svn_fs_root_t *root, if (! root->is_txn_root) return SVN_FS__NOT_TXN(root); - txn_id = root_txn_id(root); - path = svn_fs__canonicalize_abspath(path, subpool); - SVN_ERR(open_path(&parent_path, root, path, 0, TRUE, subpool)); - kind = svn_fs_x__dag_node_kind(parent_path->node); + txn_id = svn_fs_x__root_txn_id(root); + SVN_ERR(svn_fs_x__get_dag_path(&dag_path, root, path, 0, TRUE, subpool, + subpool)); + kind = svn_fs_x__dag_node_kind(dag_path->node); /* We can't remove the root of the filesystem. */ - if (! parent_path->parent) + if (! dag_path->parent) return svn_error_create(SVN_ERR_FS_ROOT_DIR, NULL, _("The root directory cannot be deleted")); @@ -2533,28 +1484,24 @@ x_delete_node(svn_fs_root_t *root, subpool)); /* Make the parent directory mutable, and do the deletion. */ - SVN_ERR(make_path_mutable(root, parent_path->parent, path, subpool, - subpool)); - SVN_ERR(svn_fs_x__dag_get_mergeinfo_count(&mergeinfo_count, - parent_path->node)); - SVN_ERR(svn_fs_x__dag_delete(parent_path->parent->node, - parent_path->entry, + SVN_ERR(svn_fs_x__make_path_mutable(root, dag_path->parent, path, subpool, + subpool)); + mergeinfo_count = svn_fs_x__dag_get_mergeinfo_count(dag_path->node); + SVN_ERR(svn_fs_x__dag_delete(dag_path->parent->node, + dag_path->entry, txn_id, subpool)); /* Remove this node and any children from the path cache. */ - SVN_ERR(dag_node_cache_invalidate(root, parent_path_path(parent_path, - subpool), - subpool)); + svn_fs_x__invalidate_dag_cache(root, parent_path_path(dag_path, subpool)); /* Update mergeinfo counts for parents */ if (mergeinfo_count > 0) - SVN_ERR(increment_mergeinfo_up_tree(parent_path->parent, + SVN_ERR(increment_mergeinfo_up_tree(dag_path->parent, -mergeinfo_count, subpool)); /* Make a record of this modification in the changes table. */ SVN_ERR(add_change(root->fs, txn_id, path, - svn_fs_x__dag_get_id(parent_path->node), svn_fs_path_change_delete, FALSE, FALSE, FALSE, kind, SVN_INVALID_REVNUM, NULL, subpool)); @@ -2588,8 +1535,8 @@ copy_helper(svn_fs_root_t *from_root, apr_pool_t *scratch_pool) { dag_node_t *from_node; - parent_path_t *to_parent_path; - svn_fs_x__txn_id_t txn_id = root_txn_id(to_root); + svn_fs_x__dag_path_t *to_dag_path; + svn_fs_x__txn_id_t txn_id = svn_fs_x__root_txn_id(to_root); svn_boolean_t same_p; /* Use an error check, not an assert, because even the caller cannot @@ -2613,13 +1560,15 @@ copy_helper(svn_fs_root_t *from_root, _("Copy immutable tree not supported")); /* Get the NODE for FROM_PATH in FROM_ROOT.*/ - SVN_ERR(get_dag(&from_node, from_root, from_path, scratch_pool)); + SVN_ERR(svn_fs_x__get_dag_node(&from_node, from_root, from_path, + scratch_pool, scratch_pool)); /* Build up the parent path from TO_PATH in TO_ROOT. If the last component does not exist, it's not that big a deal. We'll just make one there. */ - SVN_ERR(open_path(&to_parent_path, to_root, to_path, - open_path_last_optional, TRUE, scratch_pool)); + SVN_ERR(svn_fs_x__get_dag_path(&to_dag_path, to_root, to_path, + svn_fs_x__dag_path_last_optional, TRUE, + scratch_pool, scratch_pool)); /* Check to see if path (or any child thereof) is locked; if so, check that we can use the existing lock(s). */ @@ -2631,9 +1580,9 @@ copy_helper(svn_fs_root_t *from_root, source (in other words, this operation would result in nothing happening at all), just do nothing an return successfully, proud that you saved yourself from a tiresome task. */ - if (to_parent_path->node && + if (to_dag_path->node && svn_fs_x__id_eq(svn_fs_x__dag_get_id(from_node), - svn_fs_x__dag_get_id(to_parent_path->node))) + svn_fs_x__dag_get_id(to_dag_path->node))) return SVN_NO_ERROR; if (! from_root->is_txn_root) @@ -2646,11 +1595,11 @@ copy_helper(svn_fs_root_t *from_root, /* If TO_PATH already existed prior to the copy, note that this operation is a replacement, not an addition. */ - if (to_parent_path->node) + if (to_dag_path->node) { kind = svn_fs_path_change_replace; - SVN_ERR(svn_fs_x__dag_get_mergeinfo_count(&mergeinfo_start, - to_parent_path->node)); + mergeinfo_start + = svn_fs_x__dag_get_mergeinfo_count(to_dag_path->node); } else { @@ -2658,17 +1607,18 @@ copy_helper(svn_fs_root_t *from_root, mergeinfo_start = 0; } - SVN_ERR(svn_fs_x__dag_get_mergeinfo_count(&mergeinfo_end, from_node)); + mergeinfo_end = svn_fs_x__dag_get_mergeinfo_count(from_node); /* Make sure the target node's parents are mutable. */ - SVN_ERR(make_path_mutable(to_root, to_parent_path->parent, - to_path, scratch_pool, scratch_pool)); + SVN_ERR(svn_fs_x__make_path_mutable(to_root, to_dag_path->parent, + to_path, scratch_pool, + scratch_pool)); /* Canonicalize the copyfrom path. */ from_canonpath = svn_fs__canonicalize_abspath(from_path, scratch_pool); - SVN_ERR(svn_fs_x__dag_copy(to_parent_path->parent->node, - to_parent_path->entry, + SVN_ERR(svn_fs_x__dag_copy(to_dag_path->parent->node, + to_dag_path->entry, from_node, preserve_history, from_root->rev, @@ -2676,20 +1626,19 @@ copy_helper(svn_fs_root_t *from_root, txn_id, scratch_pool)); if (kind != svn_fs_path_change_add) - SVN_ERR(dag_node_cache_invalidate(to_root, - parent_path_path(to_parent_path, - scratch_pool), - scratch_pool)); + svn_fs_x__invalidate_dag_cache(to_root, + parent_path_path(to_dag_path, + scratch_pool)); if (mergeinfo_start != mergeinfo_end) - SVN_ERR(increment_mergeinfo_up_tree(to_parent_path->parent, + SVN_ERR(increment_mergeinfo_up_tree(to_dag_path->parent, mergeinfo_end - mergeinfo_start, scratch_pool)); /* Make a record of this modification in the changes table. */ - SVN_ERR(get_dag(&new_node, to_root, to_path, scratch_pool)); - SVN_ERR(add_change(to_root->fs, txn_id, to_path, - svn_fs_x__dag_get_id(new_node), kind, FALSE, + SVN_ERR(svn_fs_x__get_dag_node(&new_node, to_root, to_path, + scratch_pool, scratch_pool)); + SVN_ERR(add_change(to_root->fs, txn_id, to_path, kind, FALSE, FALSE, FALSE, svn_fs_x__dag_node_kind(from_node), from_root->rev, from_canonpath, scratch_pool)); } @@ -2775,11 +1724,10 @@ x_copied_from(svn_revnum_t *rev_p, { dag_node_t *node; - /* There is no cached entry, look it up the old-fashioned - way. */ - SVN_ERR(get_dag(&node, root, path, pool)); - SVN_ERR(svn_fs_x__dag_get_copyfrom_rev(rev_p, node)); - SVN_ERR(svn_fs_x__dag_get_copyfrom_path(path_p, node)); + /* There is no cached entry, look it up the old-fashioned way. */ + SVN_ERR(svn_fs_x__get_temp_dag_node(&node, root, path, pool)); + *rev_p = svn_fs_x__dag_get_copyfrom_rev(node); + *path_p = svn_fs_x__dag_get_copyfrom_path(node); return SVN_NO_ERROR; } @@ -2795,18 +1743,18 @@ x_make_file(svn_fs_root_t *root, const char *path, apr_pool_t *scratch_pool) { - parent_path_t *parent_path; + svn_fs_x__dag_path_t *dag_path; dag_node_t *child; - svn_fs_x__txn_id_t txn_id = root_txn_id(root); + svn_fs_x__txn_id_t txn_id = svn_fs_x__root_txn_id(root); apr_pool_t *subpool = svn_pool_create(scratch_pool); - path = svn_fs__canonicalize_abspath(path, subpool); - SVN_ERR(open_path(&parent_path, root, path, open_path_last_optional, - TRUE, subpool)); + SVN_ERR(svn_fs_x__get_dag_path(&dag_path, root, path, + svn_fs_x__dag_path_last_optional, + TRUE, subpool, subpool)); /* If there's already a file by that name, complain. This also catches the case of trying to make a file named `/'. */ - if (parent_path->node) + if (dag_path->node) return SVN_FS__ALREADY_EXISTS(root, path); /* Check (non-recursively) to see if path is locked; if so, check @@ -2816,22 +1764,21 @@ x_make_file(svn_fs_root_t *root, subpool)); /* Create the file. */ - SVN_ERR(make_path_mutable(root, parent_path->parent, path, subpool, - subpool)); + SVN_ERR(svn_fs_x__make_path_mutable(root, dag_path->parent, path, subpool, + subpool)); SVN_ERR(svn_fs_x__dag_make_file(&child, - parent_path->parent->node, - parent_path_path(parent_path->parent, + dag_path->parent->node, + parent_path_path(dag_path->parent, subpool), - parent_path->entry, + dag_path->entry, txn_id, subpool, subpool)); /* Add this file to the path cache. */ - SVN_ERR(dag_node_cache_set(root, parent_path_path(parent_path, subpool), - child, subpool)); + svn_fs_x__update_dag_cache(child); /* Make a record of this modification in the changes table. */ - SVN_ERR(add_change(root->fs, txn_id, path, svn_fs_x__dag_get_id(child), + SVN_ERR(add_change(root->fs, txn_id, path, svn_fs_path_change_add, TRUE, FALSE, FALSE, svn_node_file, SVN_INVALID_REVNUM, NULL, subpool)); @@ -2851,7 +1798,7 @@ x_file_length(svn_filesize_t *length_p, dag_node_t *file; /* First create a dag_node_t from the root/path pair. */ - SVN_ERR(get_dag(&file, root, path, scratch_pool)); + SVN_ERR(svn_fs_x__get_temp_dag_node(&file, root, path, scratch_pool)); /* Now fetch its length */ return svn_fs_x__dag_file_length(length_p, file); @@ -2870,7 +1817,7 @@ x_file_checksum(svn_checksum_t **checksum, { dag_node_t *file; - SVN_ERR(get_dag(&file, root, path, pool)); + SVN_ERR(svn_fs_x__get_temp_dag_node(&file, root, path, pool)); return svn_fs_x__dag_file_checksum(checksum, file, kind, pool); } @@ -2889,7 +1836,7 @@ x_file_contents(svn_stream_t **contents, svn_stream_t *file_stream; /* First create a dag_node_t from the root/path pair. */ - SVN_ERR(get_dag(&node, root, path, pool)); + SVN_ERR(svn_fs_x__get_temp_dag_node(&node, root, path, pool)); /* Then create a readable stream from the dag_node_t. */ SVN_ERR(svn_fs_x__dag_get_contents(&file_stream, node, pool)); @@ -2912,7 +1859,7 @@ x_try_process_file_contents(svn_boolean_t *success, apr_pool_t *pool) { dag_node_t *node; - SVN_ERR(get_dag(&node, root, path, pool)); + SVN_ERR(svn_fs_x__get_temp_dag_node(&node, root, path, pool)); return svn_fs_x__dag_try_process_file_contents(success, node, processor, baton, pool); @@ -2983,12 +1930,13 @@ apply_textdelta(void *baton, apr_pool_t *scratch_pool) { txdelta_baton_t *tb = (txdelta_baton_t *) baton; - parent_path_t *parent_path; - svn_fs_x__txn_id_t txn_id = root_txn_id(tb->root); + svn_fs_x__dag_path_t *dag_path; + svn_fs_x__txn_id_t txn_id = svn_fs_x__root_txn_id(tb->root); /* Call open_path with no flags, as we want this to return an error if the node for which we are searching doesn't exist. */ - SVN_ERR(open_path(&parent_path, tb->root, tb->path, 0, TRUE, scratch_pool)); + SVN_ERR(svn_fs_x__get_dag_path(&dag_path, tb->root, tb->path, 0, TRUE, + scratch_pool, scratch_pool)); /* Check (non-recursively) to see if path is locked; if so, check that we can use it. */ @@ -2997,9 +1945,9 @@ apply_textdelta(void *baton, FALSE, FALSE, scratch_pool)); /* Now, make sure this path is mutable. */ - SVN_ERR(make_path_mutable(tb->root, parent_path, tb->path, scratch_pool, - scratch_pool)); - tb->node = svn_fs_x__dag_dup(parent_path->node, tb->pool); + SVN_ERR(svn_fs_x__make_path_mutable(tb->root, dag_path, tb->path, + scratch_pool, scratch_pool)); + tb->node = svn_fs_x__dag_dup(dag_path->node, tb->pool); if (tb->base_checksum) { @@ -3038,7 +1986,6 @@ apply_textdelta(void *baton, /* Make a record of this modification in the changes table. */ return add_change(tb->root->fs, txn_id, tb->path, - svn_fs_x__dag_get_id(tb->node), svn_fs_path_change_modify, TRUE, FALSE, FALSE, svn_node_file, SVN_INVALID_REVNUM, NULL, scratch_pool); } @@ -3149,12 +2096,13 @@ apply_text(void *baton, apr_pool_t *scratch_pool) { text_baton_t *tb = baton; - parent_path_t *parent_path; - svn_fs_x__txn_id_t txn_id = root_txn_id(tb->root); + svn_fs_x__dag_path_t *dag_path; + svn_fs_x__txn_id_t txn_id = svn_fs_x__root_txn_id(tb->root); /* Call open_path with no flags, as we want this to return an error if the node for which we are searching doesn't exist. */ - SVN_ERR(open_path(&parent_path, tb->root, tb->path, 0, TRUE, scratch_pool)); + SVN_ERR(svn_fs_x__get_dag_path(&dag_path, tb->root, tb->path, 0, TRUE, + scratch_pool, scratch_pool)); /* Check (non-recursively) to see if path is locked; if so, check that we can use it. */ @@ -3163,9 +2111,9 @@ apply_text(void *baton, FALSE, FALSE, scratch_pool)); /* Now, make sure this path is mutable. */ - SVN_ERR(make_path_mutable(tb->root, parent_path, tb->path, scratch_pool, - scratch_pool)); - tb->node = svn_fs_x__dag_dup(parent_path->node, tb->pool); + SVN_ERR(svn_fs_x__make_path_mutable(tb->root, dag_path, tb->path, + scratch_pool, scratch_pool)); + tb->node = svn_fs_x__dag_dup(dag_path->node, tb->pool); /* Make a writable stream for replacing the file's text. */ SVN_ERR(svn_fs_x__dag_get_edit_stream(&(tb->file_stream), tb->node, @@ -3178,7 +2126,6 @@ apply_text(void *baton, /* Make a record of this modification in the changes table. */ return add_change(tb->root->fs, txn_id, tb->path, - svn_fs_x__dag_get_id(tb->node), svn_fs_path_change_modify, TRUE, FALSE, FALSE, svn_node_file, SVN_INVALID_REVNUM, NULL, scratch_pool); } @@ -3234,23 +2181,18 @@ x_contents_changed(svn_boolean_t *changed_p, (SVN_ERR_FS_GENERAL, NULL, _("Cannot compare file contents between two different filesystems")); - /* Check that both paths are files. */ - { - svn_node_kind_t kind; + SVN_ERR(svn_fs_x__get_dag_node(&node1, root1, path1, subpool, subpool)); + /* Make sure that path is file. */ + if (svn_fs_x__dag_node_kind(node1) != svn_node_file) + return svn_error_createf + (SVN_ERR_FS_GENERAL, NULL, _("'%s' is not a file"), path1); - SVN_ERR(svn_fs_x__check_path(&kind, root1, path1, subpool)); - if (kind != svn_node_file) - return svn_error_createf - (SVN_ERR_FS_GENERAL, NULL, _("'%s' is not a file"), path1); + SVN_ERR(svn_fs_x__get_temp_dag_node(&node2, root2, path2, subpool)); + /* Make sure that path is file. */ + if (svn_fs_x__dag_node_kind(node2) != svn_node_file) + return svn_error_createf + (SVN_ERR_FS_GENERAL, NULL, _("'%s' is not a file"), path2); - SVN_ERR(svn_fs_x__check_path(&kind, root2, path2, subpool)); - if (kind != svn_node_file) - return svn_error_createf - (SVN_ERR_FS_GENERAL, NULL, _("'%s' is not a file"), path2); - } - - SVN_ERR(get_dag(&node1, root1, path1, subpool)); - SVN_ERR(get_dag(&node2, root2, path2, subpool)); SVN_ERR(svn_fs_x__dag_things_different(NULL, changed_p, node1, node2, strict, subpool)); @@ -3274,10 +2216,12 @@ x_get_file_delta_stream(svn_txdelta_stream_t **stream_p, apr_pool_t *scratch_pool = svn_pool_create(pool); if (source_root && source_path) - SVN_ERR(get_dag(&source_node, source_root, source_path, scratch_pool)); + SVN_ERR(svn_fs_x__get_dag_node(&source_node, source_root, source_path, + scratch_pool, scratch_pool)); else source_node = NULL; - SVN_ERR(get_dag(&target_node, target_root, target_path, scratch_pool)); + SVN_ERR(svn_fs_x__get_temp_dag_node(&target_node, target_root, target_path, + scratch_pool)); /* Create a delta stream that turns the source into the target. */ SVN_ERR(svn_fs_x__dag_get_file_delta_stream(stream_p, source_node, @@ -3292,90 +2236,141 @@ x_get_file_delta_stream(svn_txdelta_stream_t **stream_p, /* Finding Changes */ -/* Copy CHANGE into a FS API object allocated in RESULT_POOL and return - it in *RESULT_P. Pass CONTEXT to the ID API object being created. */ +/* Implement changes_iterator_vtable_t.get for in-txn change lists. + There is no specific FSAP data type, a simple APR hash iterator + to the underlying collection is sufficient. */ static svn_error_t * -construct_fs_path_change(svn_fs_path_change2_t **result_p, - svn_fs_x__id_context_t *context, - svn_fs_x__change_t *change, - apr_pool_t *result_pool) +x_txn_changes_iterator_get(svn_fs_path_change3_t **change, + svn_fs_path_change_iterator_t *iterator) { - const svn_fs_id_t *id - = svn_fs_x__id_create(context, &change->noderev_id, result_pool); - svn_fs_path_change2_t *result - = svn_fs__path_change_create_internal(id, change->change_kind, - result_pool); + apr_hash_index_t *hi = iterator->fsap_data; - result->text_mod = change->text_mod; - result->prop_mod = change->prop_mod; - result->node_kind = change->node_kind; - - result->copyfrom_known = change->copyfrom_known; - result->copyfrom_rev = change->copyfrom_rev; - result->copyfrom_path = change->copyfrom_path; - - result->mergeinfo_mod = change->mergeinfo_mod; - - *result_p = result; - - return SVN_NO_ERROR; -} - -/* Set *CHANGED_PATHS_P to a newly allocated hash containing - descriptions of the paths changed under ROOT. The hash is keyed - with const char * paths and has svn_fs_path_change2_t * values. Use - POOL for all allocations. */ -static svn_error_t * -x_paths_changed(apr_hash_t **changed_paths_p, - svn_fs_root_t *root, - apr_pool_t *pool) -{ - apr_hash_t *changed_paths; - svn_fs_path_change2_t *path_change; - svn_fs_x__id_context_t *context - = svn_fs_x__id_create_context(root->fs, pool); - - if (root->is_txn_root) + if (hi) { - apr_hash_index_t *hi; - SVN_ERR(svn_fs_x__txn_changes_fetch(&changed_paths, root->fs, - root_txn_id(root), pool)); - for (hi = apr_hash_first(pool, changed_paths); - hi; - hi = apr_hash_next(hi)) - { - svn_fs_x__change_t *change = apr_hash_this_val(hi); - SVN_ERR(construct_fs_path_change(&path_change, context, change, - pool)); - apr_hash_set(changed_paths, - apr_hash_this_key(hi), apr_hash_this_key_len(hi), - path_change); - } + *change = apr_hash_this_val(hi); + iterator->fsap_data = apr_hash_next(hi); } else { - apr_array_header_t *changes; - int i; - - SVN_ERR(svn_fs_x__get_changes(&changes, root->fs, root->rev, pool)); - - changed_paths = svn_hash__make(pool); - for (i = 0; i < changes->nelts; ++i) - { - svn_fs_x__change_t *change = APR_ARRAY_IDX(changes, i, - svn_fs_x__change_t *); - SVN_ERR(construct_fs_path_change(&path_change, context, change, - pool)); - apr_hash_set(changed_paths, change->path.data, change->path.len, - path_change); - } + *change = NULL; } - *changed_paths_p = changed_paths; - return SVN_NO_ERROR; } +static changes_iterator_vtable_t txn_changes_iterator_vtable = +{ + x_txn_changes_iterator_get +}; + +/* FSAP data structure for in-revision changes list iterators. */ +typedef struct fs_revision_changes_iterator_data_t +{ + /* Context that tells the lower layers from where to fetch the next + block of changes. */ + svn_fs_x__changes_context_t *context; + + /* Changes to send. */ + apr_array_header_t *changes; + + /* Current indexes within CHANGES. */ + int idx; + + /* A cleanable scratch pool in case we need one. + No further sub-pool creation necessary. */ + apr_pool_t *scratch_pool; +} fs_revision_changes_iterator_data_t; + +static svn_error_t * +x_revision_changes_iterator_get(svn_fs_path_change3_t **change, + svn_fs_path_change_iterator_t *iterator) +{ + fs_revision_changes_iterator_data_t *data = iterator->fsap_data; + + /* If we exhausted our block of changes and did not reach the end of the + list, yet, fetch the next block. Note that that block may be empty. */ + if ((data->idx >= data->changes->nelts) && !data->context->eol) + { + apr_pool_t *changes_pool = data->changes->pool; + + /* Drop old changes block, read new block. */ + svn_pool_clear(changes_pool); + SVN_ERR(svn_fs_x__get_changes(&data->changes, data->context, + changes_pool, data->scratch_pool)); + data->idx = 0; + + /* Immediately release any temporary data. */ + svn_pool_clear(data->scratch_pool); + } + + if (data->idx < data->changes->nelts) + { + *change = APR_ARRAY_IDX(data->changes, data->idx, + svn_fs_x__change_t *); + ++data->idx; + } + else + { + *change = NULL; + } + + return SVN_NO_ERROR; +} + +static changes_iterator_vtable_t rev_changes_iterator_vtable = +{ + x_revision_changes_iterator_get +}; + +static svn_error_t * +x_report_changes(svn_fs_path_change_iterator_t **iterator, + svn_fs_root_t *root, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_fs_path_change_iterator_t *result = apr_pcalloc(result_pool, + sizeof(*result)); + if (root->is_txn_root) + { + apr_hash_t *changed_paths; + SVN_ERR(svn_fs_x__txn_changes_fetch(&changed_paths, root->fs, + svn_fs_x__root_txn_id(root), + result_pool)); + + result->fsap_data = apr_hash_first(result_pool, changed_paths); + result->vtable = &txn_changes_iterator_vtable; + } + else + { + /* The block of changes that we retrieve need to live in a separately + cleanable pool. */ + apr_pool_t *changes_pool = svn_pool_create(result_pool); + + /* Our iteration context info. */ + fs_revision_changes_iterator_data_t *data = apr_pcalloc(result_pool, + sizeof(*data)); + + /* This pool must remain valid as long as ITERATOR lives but will + be used only for temporary allocations and will be cleaned up + frequently. So, this must be a sub-pool of RESULT_POOL. */ + data->scratch_pool = svn_pool_create(result_pool); + + /* Fetch the first block of data. */ + SVN_ERR(svn_fs_x__create_changes_context(&data->context, + root->fs, root->rev, + result_pool, scratch_pool)); + SVN_ERR(svn_fs_x__get_changes(&data->changes, data->context, + changes_pool, scratch_pool)); + + /* Return the fully initialized object. */ + result->fsap_data = data; + result->vtable = &rev_changes_iterator_vtable; + } + + *iterator = result; + + return SVN_NO_ERROR; +} /* Our coolio opaque history object. */ @@ -3394,6 +2389,15 @@ typedef struct fs_history_data_t /* FALSE until the first call to svn_fs_history_prev(). */ svn_boolean_t is_interesting; + + /* If not SVN_INVALID_REVISION, we know that the next copy operation + is at this revision. */ + svn_revnum_t next_copy; + + /* If used, see svn_fs_x__id_used, this is the noderev ID of + PATH@REVISION. */ + svn_fs_x__id_t current_id; + } fs_history_data_t; static svn_fs_history_t * @@ -3403,6 +2407,8 @@ assemble_history(svn_fs_t *fs, svn_boolean_t is_interesting, const char *path_hint, svn_revnum_t rev_hint, + svn_revnum_t next_copy, + const svn_fs_x__id_t *current_id, apr_pool_t *result_pool); @@ -3429,17 +2435,18 @@ x_node_history(svn_fs_history_t **history_p, /* Okay, all seems well. Build our history object and return it. */ *history_p = assemble_history(root->fs, path, root->rev, FALSE, NULL, - SVN_INVALID_REVNUM, result_pool); + SVN_INVALID_REVNUM, SVN_INVALID_REVNUM, + NULL, result_pool); return SVN_NO_ERROR; } -/* Find the youngest copyroot for path PARENT_PATH or its parents in +/* Find the youngest copyroot for path DAG_PATH or its parents in filesystem FS, and store the copyroot in *REV_P and *PATH_P. */ static svn_error_t * find_youngest_copyroot(svn_revnum_t *rev_p, const char **path_p, svn_fs_t *fs, - parent_path_t *parent_path) + svn_fs_x__dag_path_t *dag_path) { svn_revnum_t rev_mine; svn_revnum_t rev_parent = SVN_INVALID_REVNUM; @@ -3447,13 +2454,12 @@ find_youngest_copyroot(svn_revnum_t *rev_p, const char *path_parent = NULL; /* First find our parent's youngest copyroot. */ - if (parent_path->parent) + if (dag_path->parent) SVN_ERR(find_youngest_copyroot(&rev_parent, &path_parent, fs, - parent_path->parent)); + dag_path->parent)); /* Find our copyroot. */ - SVN_ERR(svn_fs_x__dag_get_copyroot(&rev_mine, &path_mine, - parent_path->node)); + svn_fs_x__dag_get_copyroot(&rev_mine, &path_mine, dag_path->node); /* If a parent and child were copied to in the same revision, prefer the child copy target, since it is the copy relevant to the @@ -3481,26 +2487,25 @@ x_closest_copy(svn_fs_root_t **root_p, apr_pool_t *pool) { svn_fs_t *fs = root->fs; - parent_path_t *parent_path, *copy_dst_parent_path; + svn_fs_x__dag_path_t *dag_path, *copy_dst_dag_path; svn_revnum_t copy_dst_rev, created_rev; const char *copy_dst_path; svn_fs_root_t *copy_dst_root; dag_node_t *copy_dst_node; - svn_boolean_t related; apr_pool_t *scratch_pool = svn_pool_create(pool); /* Initialize return values. */ *root_p = NULL; *path_p = NULL; - path = svn_fs__canonicalize_abspath(path, scratch_pool); - SVN_ERR(open_path(&parent_path, root, path, 0, FALSE, scratch_pool)); + SVN_ERR(svn_fs_x__get_dag_path(&dag_path, root, path, 0, FALSE, + scratch_pool, scratch_pool)); /* Find the youngest copyroot in the path of this node-rev, which will indicate the target of the innermost copy affecting the node-rev. */ SVN_ERR(find_youngest_copyroot(©_dst_rev, ©_dst_path, - fs, parent_path)); + fs, dag_path)); if (copy_dst_rev == 0) /* There are no copies affecting this node-rev. */ { svn_pool_destroy(scratch_pool); @@ -3511,19 +2516,17 @@ x_closest_copy(svn_fs_root_t **root_p, revision between COPY_DST_REV and REV. Make sure that PATH exists as of COPY_DST_REV and is related to this node-rev. */ SVN_ERR(svn_fs_x__revision_root(©_dst_root, fs, copy_dst_rev, pool)); - SVN_ERR(open_path(©_dst_parent_path, copy_dst_root, path, - open_path_node_only | open_path_allow_null, FALSE, - scratch_pool)); - if (copy_dst_parent_path == NULL) + SVN_ERR(svn_fs_x__get_dag_path(©_dst_dag_path, copy_dst_root, path, + svn_fs_x__dag_path_allow_null, FALSE, + scratch_pool, scratch_pool)); + if (copy_dst_dag_path == NULL) { svn_pool_destroy(scratch_pool); return SVN_NO_ERROR; } - copy_dst_node = copy_dst_parent_path->node; - SVN_ERR(svn_fs_x__dag_related_node(&related, copy_dst_node, - parent_path->node)); - if (!related) + copy_dst_node = copy_dst_dag_path->node; + if (!svn_fs_x__dag_related_node(copy_dst_node, dag_path->node)) { svn_pool_destroy(scratch_pool); return SVN_NO_ERROR; @@ -3545,15 +2548,11 @@ x_closest_copy(svn_fs_root_t **root_p, */ created_rev = svn_fs_x__dag_get_revision(copy_dst_node); if (created_rev == copy_dst_rev) - { - svn_fs_x__id_t pred; - SVN_ERR(svn_fs_x__dag_get_predecessor_id(&pred, copy_dst_node)); - if (!svn_fs_x__id_used(&pred)) - { - svn_pool_destroy(scratch_pool); - return SVN_NO_ERROR; - } - } + if (!svn_fs_x__id_used(svn_fs_x__dag_get_predecessor_id(copy_dst_node))) + { + svn_pool_destroy(scratch_pool); + return SVN_NO_ERROR; + } /* The copy destination checks out. Return it. */ *root_p = copy_dst_root; @@ -3573,10 +2572,8 @@ x_node_origin_rev(svn_revnum_t *revision, svn_fs_x__id_t node_id; dag_node_t *node; - path = svn_fs__canonicalize_abspath(path, scratch_pool); - - SVN_ERR(get_dag(&node, root, path, scratch_pool)); - SVN_ERR(svn_fs_x__dag_get_node_id(&node_id, node)); + SVN_ERR(svn_fs_x__get_temp_dag_node(&node, root, path, scratch_pool)); + node_id = *svn_fs_x__dag_get_node_id(node); *revision = svn_fs_x__get_revnum(node_id.change_set); @@ -3596,16 +2593,56 @@ history_prev(svn_fs_history_t **prev_history, svn_revnum_t commit_rev, src_rev, dst_rev; svn_revnum_t revision = fhd->revision; svn_fs_t *fs = fhd->fs; - parent_path_t *parent_path; + svn_fs_x__dag_path_t *dag_path; dag_node_t *node; svn_fs_root_t *root; svn_boolean_t reported = fhd->is_interesting; svn_revnum_t copyroot_rev; const char *copyroot_path; + svn_fs_x__id_t pred_id; /* Initialize our return value. */ *prev_history = NULL; + /* When following history, there tend to be long sections of linear + history where there are no copies at PATH or its parents. Within + these sections, we only need to follow the node history. */ + if ( SVN_IS_VALID_REVNUM(fhd->next_copy) + && revision > fhd->next_copy + && svn_fs_x__id_used(&fhd->current_id)) + { + /* We know the last reported node (CURRENT_ID) and the NEXT_COPY + revision is somewhat further in the past. */ + svn_fs_x__noderev_t *noderev; + assert(reported); + + /* Get the previous node change. If there is none, then we already + reported the initial addition and this history traversal is done. */ + SVN_ERR(svn_fs_x__get_node_revision(&noderev, fs, &fhd->current_id, + scratch_pool, scratch_pool)); + if (! svn_fs_x__id_used(&noderev->predecessor_id)) + return SVN_NO_ERROR; + + /* If the previous node change is younger than the next copy, it is + part of the linear history section. */ + commit_rev = svn_fs_x__get_revnum(noderev->predecessor_id.change_set); + if (commit_rev > fhd->next_copy) + { + /* Within the linear history, simply report all node changes and + continue with the respective predecessor. */ + *prev_history = assemble_history(fs, noderev->created_path, + commit_rev, TRUE, NULL, + SVN_INVALID_REVNUM, + fhd->next_copy, + &noderev->predecessor_id, + result_pool); + + return SVN_NO_ERROR; + } + + /* We hit a copy. Fall back to the standard code path. */ + } + /* If our last history report left us hints about where to pickup the chase, then our last report was on the destination of a copy. If we are crossing copies, start from those locations, @@ -3624,10 +2661,12 @@ history_prev(svn_fs_history_t **prev_history, /* Open PATH/REVISION, and get its node and a bunch of other goodies. */ - SVN_ERR(open_path(&parent_path, root, path, 0, FALSE, scratch_pool)); - node = parent_path->node; + SVN_ERR(svn_fs_x__get_dag_path(&dag_path, root, path, 0, FALSE, + scratch_pool, scratch_pool)); + node = dag_path->node; commit_path = svn_fs_x__dag_get_created_path(node); commit_rev = svn_fs_x__dag_get_revision(node); + svn_fs_x__id_reset(&pred_id); /* The Subversion filesystem is written in such a way that a given line of history may have at most one interesting history point @@ -3644,7 +2683,9 @@ history_prev(svn_fs_history_t **prev_history, need now to do so) ... */ *prev_history = assemble_history(fs, commit_path, commit_rev, TRUE, NULL, - SVN_INVALID_REVNUM, result_pool); + SVN_INVALID_REVNUM, + SVN_INVALID_REVNUM, NULL, + result_pool); return SVN_NO_ERROR; } else @@ -3652,9 +2693,7 @@ history_prev(svn_fs_history_t **prev_history, /* ... or we *have* reported on this revision, and must now progress toward this node's predecessor (unless there is no predecessor, in which case we're all done!). */ - svn_fs_x__id_t pred_id; - - SVN_ERR(svn_fs_x__dag_get_predecessor_id(&pred_id, node)); + pred_id = *svn_fs_x__dag_get_predecessor_id(node); if (!svn_fs_x__id_used(&pred_id)) return SVN_NO_ERROR; @@ -3670,7 +2709,7 @@ history_prev(svn_fs_history_t **prev_history, /* Find the youngest copyroot in the path of this node, including itself. */ SVN_ERR(find_youngest_copyroot(©root_rev, ©root_path, fs, - parent_path)); + dag_path)); /* Initialize some state variables. */ src_path = NULL; @@ -3685,7 +2724,8 @@ history_prev(svn_fs_history_t **prev_history, SVN_ERR(svn_fs_x__revision_root(©root_root, fs, copyroot_rev, scratch_pool)); - SVN_ERR(get_dag(&node, copyroot_root, copyroot_path, scratch_pool)); + SVN_ERR(svn_fs_x__get_temp_dag_node(&node, copyroot_root, + copyroot_path, scratch_pool)); copy_dst = svn_fs_x__dag_get_created_path(node); /* If our current path was the very destination of the copy, @@ -3703,8 +2743,8 @@ history_prev(svn_fs_history_t **prev_history, /* If we get here, then our current path is the destination of, or the child of the destination of, a copy. Fill in the return values and get outta here. */ - SVN_ERR(svn_fs_x__dag_get_copyfrom_rev(&src_rev, node)); - SVN_ERR(svn_fs_x__dag_get_copyfrom_path(©_src, node)); + src_rev = svn_fs_x__dag_get_copyfrom_rev(node); + copy_src = svn_fs_x__dag_get_copyfrom_path(node); dst_rev = copyroot_rev; src_path = svn_fspath__join(copy_src, remainder_path, scratch_pool); @@ -3725,12 +2765,18 @@ history_prev(svn_fs_history_t **prev_history, retry = TRUE; *prev_history = assemble_history(fs, path, dst_rev, ! retry, - src_path, src_rev, result_pool); + src_path, src_rev, + SVN_INVALID_REVNUM, NULL, + result_pool); } else { + /* We know the next copy revision. If we are not at the copy rev + itself, we will also know the predecessor node ID and the next + invocation will use the optimized "linear history" code path. */ *prev_history = assemble_history(fs, commit_path, commit_rev, TRUE, - NULL, SVN_INVALID_REVNUM, result_pool); + NULL, SVN_INVALID_REVNUM, + copyroot_rev, &pred_id, result_pool); } return SVN_NO_ERROR; @@ -3761,10 +2807,12 @@ fs_history_prev(svn_fs_history_t **prev_history_p, if (! fhd->is_interesting) prev_history = assemble_history(fs, "/", fhd->revision, 1, NULL, SVN_INVALID_REVNUM, + SVN_INVALID_REVNUM, NULL, result_pool); else if (fhd->revision > 0) prev_history = assemble_history(fs, "/", fhd->revision - 1, 1, NULL, SVN_INVALID_REVNUM, + SVN_INVALID_REVNUM, NULL, result_pool); } else @@ -3824,6 +2872,8 @@ assemble_history(svn_fs_t *fs, svn_boolean_t is_interesting, const char *path_hint, svn_revnum_t rev_hint, + svn_revnum_t next_copy, + const svn_fs_x__id_t *current_id, apr_pool_t *result_pool) { svn_fs_history_t *history = apr_pcalloc(result_pool, sizeof(*history)); @@ -3835,8 +2885,14 @@ assemble_history(svn_fs_t *fs, ? svn_fs__canonicalize_abspath(path_hint, result_pool) : NULL; fhd->rev_hint = rev_hint; + fhd->next_copy = next_copy; fhd->fs = fs; + if (current_id) + fhd->current_id = *current_id; + else + svn_fs_x__id_reset(&fhd->current_id); + history->vtable = &history_vtable; history->fsap_data = fhd; return history; @@ -3848,21 +2904,19 @@ assemble_history(svn_fs_t *fs, /* DIR_DAG is a directory DAG node which has mergeinfo in its descendants. This function iterates over its children. For each - child with immediate mergeinfo, it adds its mergeinfo to - RESULT_CATALOG. appropriate arguments. For each child with - descendants with mergeinfo, it recurses. Note that it does *not* - call the action on the path for DIR_DAG itself. + child with immediate mergeinfo, call RECEIVER with it and BATON. + For each child with descendants with mergeinfo, it recurses. Note + that it does *not* call the action on the path for DIR_DAG itself. - POOL is used for temporary allocations, including the mergeinfo - hashes passed to actions; RESULT_POOL is used for the mergeinfo added - to RESULT_CATALOG. + SCRATCH_POOL is used for temporary allocations, including the mergeinfo + hashes passed to actions. */ static svn_error_t * crawl_directory_dag_for_mergeinfo(svn_fs_root_t *root, const char *this_path, dag_node_t *dir_dag, - svn_mergeinfo_catalog_t result_catalog, - apr_pool_t *result_pool, + svn_fs_mergeinfo_receiver_t receiver, + void *baton, apr_pool_t *scratch_pool) { apr_array_header_t *entries; @@ -3873,20 +2927,18 @@ crawl_directory_dag_for_mergeinfo(svn_fs_root_t *root, iterpool)); for (i = 0; i < entries->nelts; ++i) { - svn_fs_x__dirent_t *dirent = APR_ARRAY_IDX(entries, i, svn_fs_x__dirent_t *); + svn_fs_x__dirent_t *dirent + = APR_ARRAY_IDX(entries, i, svn_fs_x__dirent_t *); const char *kid_path; dag_node_t *kid_dag; - svn_boolean_t has_mergeinfo, go_down; svn_pool_clear(iterpool); kid_path = svn_fspath__join(this_path, dirent->name, iterpool); - SVN_ERR(get_dag(&kid_dag, root, kid_path, iterpool)); + SVN_ERR(svn_fs_x__get_temp_dag_node(&kid_dag, root, kid_path, + iterpool)); - SVN_ERR(svn_fs_x__dag_has_mergeinfo(&has_mergeinfo, kid_dag)); - SVN_ERR(svn_fs_x__dag_has_descendants_with_mergeinfo(&go_down, kid_dag)); - - if (has_mergeinfo) + if (svn_fs_x__dag_has_mergeinfo(kid_dag)) { /* Save this particular node's mergeinfo. */ apr_hash_t *proplist; @@ -3912,7 +2964,7 @@ crawl_directory_dag_for_mergeinfo(svn_fs_root_t *root, error. */ err = svn_mergeinfo_parse(&kid_mergeinfo, mergeinfo_string->data, - result_pool); + iterpool); if (err) { if (err->apr_err == SVN_ERR_MERGEINFO_PARSE_ERROR) @@ -3922,17 +2974,16 @@ crawl_directory_dag_for_mergeinfo(svn_fs_root_t *root, } else { - svn_hash_sets(result_catalog, apr_pstrdup(result_pool, kid_path), - kid_mergeinfo); + SVN_ERR(receiver(kid_path, kid_mergeinfo, baton, iterpool)); } } - if (go_down) + if (svn_fs_x__dag_has_descendants_with_mergeinfo(kid_dag)) SVN_ERR(crawl_directory_dag_for_mergeinfo(root, kid_path, kid_dag, - result_catalog, - result_pool, + receiver, + baton, iterpool)); } @@ -3940,62 +2991,39 @@ crawl_directory_dag_for_mergeinfo(svn_fs_root_t *root, return SVN_NO_ERROR; } -/* Return the cache key as a combination of REV_ROOT->REV, the inheritance - flags INHERIT and ADJUST_INHERITED_MERGEINFO, and the PATH. The result - will be allocated in RESULT_POOL. - */ -static const char * -mergeinfo_cache_key(const char *path, - svn_fs_root_t *rev_root, - svn_mergeinfo_inheritance_t inherit, - svn_boolean_t adjust_inherited_mergeinfo, - apr_pool_t *result_pool) -{ - apr_int64_t number = rev_root->rev; - number = number * 4 - + (inherit == svn_mergeinfo_nearest_ancestor ? 2 : 0) - + (adjust_inherited_mergeinfo ? 1 : 0); - - return svn_fs_x__combine_number_and_string(number, path, result_pool); -} - /* Calculates the mergeinfo for PATH under REV_ROOT using inheritance type INHERIT. Returns it in *MERGEINFO, or NULL if there is none. The result is allocated in RESULT_POOL; SCRATCH_POOL is used for temporary allocations. */ static svn_error_t * -get_mergeinfo_for_path_internal(svn_mergeinfo_t *mergeinfo, - svn_fs_root_t *rev_root, - const char *path, - svn_mergeinfo_inheritance_t inherit, - svn_boolean_t adjust_inherited_mergeinfo, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) +get_mergeinfo_for_path(svn_mergeinfo_t *mergeinfo, + svn_fs_root_t *rev_root, + const char *path, + svn_mergeinfo_inheritance_t inherit, + svn_boolean_t adjust_inherited_mergeinfo, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { - parent_path_t *parent_path, *nearest_ancestor; + svn_fs_x__dag_path_t *dag_path, *nearest_ancestor; apr_hash_t *proplist; svn_string_t *mergeinfo_string; - path = svn_fs__canonicalize_abspath(path, scratch_pool); + *mergeinfo = NULL; + SVN_ERR(svn_fs_x__get_dag_path(&dag_path, rev_root, path, 0, FALSE, + scratch_pool, scratch_pool)); - SVN_ERR(open_path(&parent_path, rev_root, path, 0, FALSE, scratch_pool)); - - if (inherit == svn_mergeinfo_nearest_ancestor && ! parent_path->parent) + if (inherit == svn_mergeinfo_nearest_ancestor && ! dag_path->parent) return SVN_NO_ERROR; if (inherit == svn_mergeinfo_nearest_ancestor) - nearest_ancestor = parent_path->parent; + nearest_ancestor = dag_path->parent; else - nearest_ancestor = parent_path; + nearest_ancestor = dag_path; while (TRUE) { - svn_boolean_t has_mergeinfo; - - SVN_ERR(svn_fs_x__dag_has_mergeinfo(&has_mergeinfo, - nearest_ancestor->node)); - if (has_mergeinfo) + if (svn_fs_x__dag_has_mergeinfo(nearest_ancestor->node)) break; /* No need to loop if we're looking for explicit mergeinfo. */ @@ -4046,7 +3074,7 @@ get_mergeinfo_for_path_internal(svn_mergeinfo_t *mergeinfo, can return the mergeinfo results directly. Otherwise, we're inheriting the mergeinfo, so we need to a) remove non-inheritable ranges and b) telescope the merged-from paths. */ - if (adjust_inherited_mergeinfo && (nearest_ancestor != parent_path)) + if (adjust_inherited_mergeinfo && (nearest_ancestor != dag_path)) { svn_mergeinfo_t tmp_mergeinfo; @@ -4056,7 +3084,7 @@ get_mergeinfo_for_path_internal(svn_mergeinfo_t *mergeinfo, scratch_pool, scratch_pool)); SVN_ERR(svn_fs__append_to_merged_froms(mergeinfo, tmp_mergeinfo, parent_path_relpath( - parent_path, nearest_ancestor, + dag_path, nearest_ancestor, scratch_pool), result_pool)); } @@ -4064,99 +3092,44 @@ get_mergeinfo_for_path_internal(svn_mergeinfo_t *mergeinfo, return SVN_NO_ERROR; } -/* Caching wrapper around get_mergeinfo_for_path_internal(). - */ +/* Invoke RECEIVER with BATON for each mergeinfo found on descendants of + PATH (but not PATH itself). Use SCRATCH_POOL for temporary values. */ static svn_error_t * -get_mergeinfo_for_path(svn_mergeinfo_t *mergeinfo, - svn_fs_root_t *rev_root, - const char *path, - svn_mergeinfo_inheritance_t inherit, - svn_boolean_t adjust_inherited_mergeinfo, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) -{ - svn_fs_x__data_t *ffd = rev_root->fs->fsap_data; - const char *cache_key; - svn_boolean_t found = FALSE; - svn_stringbuf_t *mergeinfo_exists; - - *mergeinfo = NULL; - - cache_key = mergeinfo_cache_key(path, rev_root, inherit, - adjust_inherited_mergeinfo, scratch_pool); - if (ffd->mergeinfo_existence_cache) - { - SVN_ERR(svn_cache__get((void **)&mergeinfo_exists, &found, - ffd->mergeinfo_existence_cache, - cache_key, result_pool)); - if (found && mergeinfo_exists->data[0] == '1') - SVN_ERR(svn_cache__get((void **)mergeinfo, &found, - ffd->mergeinfo_cache, - cache_key, result_pool)); - } - - if (! found) - { - SVN_ERR(get_mergeinfo_for_path_internal(mergeinfo, rev_root, path, - inherit, - adjust_inherited_mergeinfo, - result_pool, scratch_pool)); - if (ffd->mergeinfo_existence_cache) - { - mergeinfo_exists = svn_stringbuf_create(*mergeinfo ? "1" : "0", - scratch_pool); - SVN_ERR(svn_cache__set(ffd->mergeinfo_existence_cache, - cache_key, mergeinfo_exists, scratch_pool)); - if (*mergeinfo) - SVN_ERR(svn_cache__set(ffd->mergeinfo_cache, - cache_key, *mergeinfo, scratch_pool)); - } - } - - return SVN_NO_ERROR; -} - -/* Adds mergeinfo for each descendant of PATH (but not PATH itself) - under ROOT to RESULT_CATALOG. Returned values are allocated in - RESULT_POOL; temporary values in POOL. */ -static svn_error_t * -add_descendant_mergeinfo(svn_mergeinfo_catalog_t result_catalog, - svn_fs_root_t *root, +add_descendant_mergeinfo(svn_fs_root_t *root, const char *path, - apr_pool_t *result_pool, + svn_fs_mergeinfo_receiver_t receiver, + void *baton, apr_pool_t *scratch_pool) { dag_node_t *this_dag; - svn_boolean_t go_down; - SVN_ERR(get_dag(&this_dag, root, path, scratch_pool)); - SVN_ERR(svn_fs_x__dag_has_descendants_with_mergeinfo(&go_down, - this_dag)); - if (go_down) + SVN_ERR(svn_fs_x__get_temp_dag_node(&this_dag, root, path, scratch_pool)); + if (svn_fs_x__dag_has_descendants_with_mergeinfo(this_dag)) SVN_ERR(crawl_directory_dag_for_mergeinfo(root, path, this_dag, - result_catalog, - result_pool, + receiver, + baton, scratch_pool)); return SVN_NO_ERROR; } -/* Get the mergeinfo for a set of paths, returned in - *MERGEINFO_CATALOG. Returned values are allocated in - POOL, while temporary values are allocated in a sub-pool. */ +/* Find all the mergeinfo for a set of PATHS under ROOT and report it + through RECEIVER with BATON. INHERITED, INCLUDE_DESCENDANTS and + ADJUST_INHERITED_MERGEINFO are the same as in the FS API. + + Allocate temporary values are allocated in SCRATCH_POOL. */ static svn_error_t * get_mergeinfos_for_paths(svn_fs_root_t *root, - svn_mergeinfo_catalog_t *mergeinfo_catalog, const apr_array_header_t *paths, svn_mergeinfo_inheritance_t inherit, svn_boolean_t include_descendants, svn_boolean_t adjust_inherited_mergeinfo, - apr_pool_t *result_pool, + svn_fs_mergeinfo_receiver_t receiver, + void *baton, apr_pool_t *scratch_pool) { - svn_mergeinfo_catalog_t result_catalog = svn_hash__make(result_pool); apr_pool_t *iterpool = svn_pool_create(scratch_pool); int i; @@ -4170,7 +3143,7 @@ get_mergeinfos_for_paths(svn_fs_root_t *root, err = get_mergeinfo_for_path(&path_mergeinfo, root, path, inherit, adjust_inherited_mergeinfo, - result_pool, iterpool); + iterpool, iterpool); if (err) { if (err->apr_err == SVN_ERR_MERGEINFO_PARSE_ERROR) @@ -4186,27 +3159,26 @@ get_mergeinfos_for_paths(svn_fs_root_t *root, } if (path_mergeinfo) - svn_hash_sets(result_catalog, path, path_mergeinfo); + SVN_ERR(receiver(path, path_mergeinfo, baton, iterpool)); if (include_descendants) - SVN_ERR(add_descendant_mergeinfo(result_catalog, root, path, - result_pool, scratch_pool)); + SVN_ERR(add_descendant_mergeinfo(root, path, receiver, baton, + iterpool)); } svn_pool_destroy(iterpool); - *mergeinfo_catalog = result_catalog; return SVN_NO_ERROR; } /* Implements svn_fs_get_mergeinfo. */ static svn_error_t * -x_get_mergeinfo(svn_mergeinfo_catalog_t *catalog, - svn_fs_root_t *root, +x_get_mergeinfo(svn_fs_root_t *root, const apr_array_header_t *paths, svn_mergeinfo_inheritance_t inherit, svn_boolean_t include_descendants, svn_boolean_t adjust_inherited_mergeinfo, - apr_pool_t *result_pool, + svn_fs_mergeinfo_receiver_t receiver, + void *baton, apr_pool_t *scratch_pool) { /* We require a revision root. */ @@ -4214,17 +3186,18 @@ x_get_mergeinfo(svn_mergeinfo_catalog_t *catalog, return svn_error_create(SVN_ERR_FS_NOT_REVISION_ROOT, NULL, NULL); /* Retrieve a path -> mergeinfo hash mapping. */ - return get_mergeinfos_for_paths(root, catalog, paths, - inherit, + return get_mergeinfos_for_paths(root, paths, inherit, include_descendants, adjust_inherited_mergeinfo, - result_pool, scratch_pool); + receiver, baton, + scratch_pool); } /* The vtable associated with root objects. */ static root_vtable_t root_vtable = { - x_paths_changed, + NULL, + x_report_changes, svn_fs_x__check_path, x_node_history, x_node_id, @@ -4308,20 +3281,6 @@ make_txn_root(svn_fs_root_t **root_p, root->txn = svn_fs_x__txn_name(txn_id, root->pool); root->txn_flags = flags; root->rev = base_rev; - - /* Because this cache actually tries to invalidate elements, keep - the number of elements per page down. - - Note that since dag_node_cache_invalidate uses svn_cache__iter, - this *cannot* be a memcache-based cache. */ - SVN_ERR(svn_cache__create_inprocess(&(frd->txn_node_cache), - svn_fs_x__dag_serialize, - svn_fs_x__dag_deserialize, - APR_HASH_KEY_STRING, - 32, 20, FALSE, - root->txn, - root->pool)); - root->fsap_data = frd; *root_p = root; @@ -4370,10 +3329,10 @@ verify_node(dag_node_t *node, } /* Fetch some data. */ - SVN_ERR(svn_fs_x__dag_has_mergeinfo(&has_mergeinfo, node)); - SVN_ERR(svn_fs_x__dag_get_mergeinfo_count(&mergeinfo_count, node)); - SVN_ERR(svn_fs_x__dag_get_predecessor_id(&pred_id, node)); - SVN_ERR(svn_fs_x__dag_get_predecessor_count(&pred_count, node)); + has_mergeinfo = svn_fs_x__dag_has_mergeinfo(node); + mergeinfo_count = svn_fs_x__dag_get_mergeinfo_count(node); + pred_id = *svn_fs_x__dag_get_predecessor_id(node); + pred_count = svn_fs_x__dag_get_predecessor_count(node); kind = svn_fs_x__dag_node_kind(node); /* Sanity check. */ @@ -4390,7 +3349,7 @@ verify_node(dag_node_t *node, int pred_pred_count; SVN_ERR(svn_fs_x__dag_get_node(&pred, fs, &pred_id, iterpool, iterpool)); - SVN_ERR(svn_fs_x__dag_get_predecessor_count(&pred_pred_count, pred)); + pred_pred_count = svn_fs_x__dag_get_predecessor_count(pred); if (pred_pred_count+1 != pred_count) return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, "Predecessor count mismatch: " @@ -4442,8 +3401,7 @@ verify_node(dag_node_t *node, SVN_ERR(svn_fs_x__dag_get_node(&child, fs, &dirent->id, iterpool, iterpool)); SVN_ERR(verify_node(child, rev, parent_nodes, iterpool)); - SVN_ERR(svn_fs_x__dag_get_mergeinfo_count(&child_mergeinfo, - child)); + child_mergeinfo = svn_fs_x__dag_get_mergeinfo_count(child); } else { @@ -4490,7 +3448,9 @@ svn_fs_x__verify_root(svn_fs_root_t *root, When this code is called in the library, we want to ensure we use the on-disk data --- rather than some data that was read in the possibly-distance past and cached since. */ - SVN_ERR(root_node(&root_dir, root, scratch_pool, scratch_pool)); + SVN_ERR(svn_fs_x__dag_root(&root_dir, root->fs, + svn_fs_x__root_change_set(root), + scratch_pool, scratch_pool)); /* Recursively verify ROOT_DIR. */ parent_nodes = apr_array_make(scratch_pool, 16, sizeof(dag_node_t *)); @@ -4502,7 +3462,7 @@ svn_fs_x__verify_root(svn_fs_root_t *root, svn_boolean_t has_predecessor; /* Only r0 should have no predecessor. */ - SVN_ERR(svn_fs_x__dag_get_predecessor_id(&pred_id, root_dir)); + pred_id = *svn_fs_x__dag_get_predecessor_id(root_dir); has_predecessor = svn_fs_x__id_used(&pred_id); if (!root->is_txn_root && has_predecessor != !!root->rev) return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, diff --git a/subversion/libsvn_fs_x/tree.h b/subversion/libsvn_fs_x/tree.h index 9c5d44aba842..58ad0dadabbb 100644 --- a/subversion/libsvn_fs_x/tree.h +++ b/subversion/libsvn_fs_x/tree.h @@ -20,10 +20,11 @@ * ==================================================================== */ -#ifndef SVN_LIBSVN_FS_TREE_H -#define SVN_LIBSVN_FS_TREE_H +#ifndef SVN_LIBSVN_FS_X_TREE_H +#define SVN_LIBSVN_FS_X_TREE_H #include "fs.h" +#include "dag.h" #ifdef __cplusplus extern "C" { @@ -31,9 +32,13 @@ extern "C" { -/* In RESULT_POOL, create an instance of a DAG node 1st level cache. */ -svn_fs_x__dag_cache_t* -svn_fs_x__create_dag_cache(apr_pool_t *result_pool); +/* Return the transaction ID to a given transaction ROOT. */ +svn_fs_x__txn_id_t +svn_fs_x__root_txn_id(svn_fs_root_t *root); + +/* Return the change set to a given ROOT. */ +svn_fs_x__change_set_t +svn_fs_x__root_change_set(svn_fs_root_t *root); /* Set *ROOT_P to the root directory of revision REV in filesystem FS. Allocate the structure in POOL. */ @@ -109,4 +114,4 @@ svn_fs_x__info_config_files(apr_array_header_t **files, } #endif /* __cplusplus */ -#endif /* SVN_LIBSVN_FS_TREE_H */ +#endif /* SVN_LIBSVN_FS_X_TREE_H */ diff --git a/subversion/libsvn_fs_x/util.c b/subversion/libsvn_fs_x/util.c index da004ad8febb..bab47fc6d01c 100644 --- a/subversion/libsvn_fs_x/util.c +++ b/subversion/libsvn_fs_x/util.c @@ -109,12 +109,18 @@ svn_fs_x__path_current(svn_fs_t *fs, return svn_dirent_join(fs->path, PATH_CURRENT, result_pool); } +const char * +svn_fs_x__path_next(svn_fs_t *fs, + apr_pool_t *result_pool) +{ + return svn_dirent_join(fs->path, PATH_NEXT, result_pool); +} + const char * svn_fs_x__path_txn_current(svn_fs_t *fs, apr_pool_t *result_pool) { - return svn_dirent_join(fs->path, PATH_TXN_CURRENT, - result_pool); + return svn_dirent_join(fs->path, PATH_TXN_CURRENT, result_pool); } const char * @@ -147,14 +153,12 @@ svn_fs_x__path_revprop_generation(svn_fs_t *fs, /* Return the full path of the file FILENAME within revision REV's shard in * FS. If FILENAME is NULL, return the shard directory directory itself. - * REVPROPS indicates the parent of the shard parent folder ("revprops" or - * "revs"). PACKED says whether we want the packed shard's name. + * PACKED says whether we want the packed shard's name. * * Allocate the result in RESULT_POOL. */static const char* construct_shard_sub_path(svn_fs_t *fs, svn_revnum_t rev, - svn_boolean_t revprops, svn_boolean_t packed, const char *filename, apr_pool_t *result_pool) @@ -162,9 +166,6 @@ construct_shard_sub_path(svn_fs_t *fs, svn_fs_x__data_t *ffd = fs->fsap_data; char buffer[SVN_INT64_BUFFER_SIZE + sizeof(PATH_EXT_PACKED_SHARD)] = { 0 }; - /* Select the appropriate parent path constant. */ - const char *parent = revprops ? PATH_REVPROPS_DIR : PATH_REVS_DIR; - /* String containing the shard number. */ apr_size_t len = svn__i64toa(buffer, rev / ffd->max_files_per_dir); @@ -173,7 +174,7 @@ construct_shard_sub_path(svn_fs_t *fs, strncpy(buffer + len, PATH_EXT_PACKED_SHARD, sizeof(buffer) - len - 1); /* This will also work for NULL FILENAME as well. */ - return svn_dirent_join_many(result_pool, fs->path, parent, buffer, + return svn_dirent_join_many(result_pool, fs->path, PATH_REVS_DIR, buffer, filename, SVN_VA_NULL); } @@ -184,15 +185,15 @@ svn_fs_x__path_rev_packed(svn_fs_t *fs, apr_pool_t *result_pool) { assert(svn_fs_x__is_packed_rev(fs, rev)); - return construct_shard_sub_path(fs, rev, FALSE, TRUE, kind, result_pool); + return construct_shard_sub_path(fs, rev, TRUE, kind, result_pool); } const char * -svn_fs_x__path_rev_shard(svn_fs_t *fs, - svn_revnum_t rev, - apr_pool_t *result_pool) +svn_fs_x__path_shard(svn_fs_t *fs, + svn_revnum_t rev, + apr_pool_t *result_pool) { - return construct_shard_sub_path(fs, rev, FALSE, FALSE, NULL, result_pool); + return construct_shard_sub_path(fs, rev, FALSE, NULL, result_pool); } const char * @@ -200,11 +201,12 @@ svn_fs_x__path_rev(svn_fs_t *fs, svn_revnum_t rev, apr_pool_t *result_pool) { - char buffer[SVN_INT64_BUFFER_SIZE]; - svn__i64toa(buffer, rev); + char buffer[SVN_INT64_BUFFER_SIZE + 1]; + buffer[0] = 'r'; + svn__i64toa(buffer + 1, rev); assert(! svn_fs_x__is_packed_rev(fs, rev)); - return construct_shard_sub_path(fs, rev, FALSE, FALSE, buffer, result_pool); + return construct_shard_sub_path(fs, rev, FALSE, buffer, result_pool); } const char * @@ -218,19 +220,11 @@ svn_fs_x__path_rev_absolute(svn_fs_t *fs, } const char * -svn_fs_x__path_revprops_shard(svn_fs_t *fs, - svn_revnum_t rev, - apr_pool_t *result_pool) -{ - return construct_shard_sub_path(fs, rev, TRUE, FALSE, NULL, result_pool); -} - -const char * -svn_fs_x__path_revprops_pack_shard(svn_fs_t *fs, +svn_fs_x__path_pack_shard(svn_fs_t *fs, svn_revnum_t rev, apr_pool_t *result_pool) { - return construct_shard_sub_path(fs, rev, TRUE, TRUE, NULL, result_pool); + return construct_shard_sub_path(fs, rev, TRUE, NULL, result_pool); } const char * @@ -238,11 +232,17 @@ svn_fs_x__path_revprops(svn_fs_t *fs, svn_revnum_t rev, apr_pool_t *result_pool) { - char buffer[SVN_INT64_BUFFER_SIZE]; - svn__i64toa(buffer, rev); + char buffer[SVN_INT64_BUFFER_SIZE + 1]; + buffer[0] = 'p'; + svn__i64toa(buffer + 1, rev); assert(! svn_fs_x__is_packed_revprop(fs, rev)); - return construct_shard_sub_path(fs, rev, TRUE, FALSE, buffer, result_pool); + + /* Revprops for packed r0 are not packed, yet stored in the packed shard. + Hence, the second flag must check for packed _rev_ - not revprop. */ + return construct_shard_sub_path(fs, rev, + svn_fs_x__is_packed_rev(fs, rev) /* sic! */, + buffer, result_pool); } const char * @@ -340,14 +340,6 @@ svn_fs_x__path_txn_props(svn_fs_t *fs, return construct_txn_path(fs, txn_id, PATH_TXN_PROPS, result_pool); } -const char * -svn_fs_x__path_txn_props_final(svn_fs_t *fs, - svn_fs_x__txn_id_t txn_id, - apr_pool_t *result_pool) -{ - return construct_txn_path(fs, txn_id, PATH_TXN_PROPS_FINAL, result_pool); -} - const char* svn_fs_x__path_l2p_proto_index(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, @@ -543,6 +535,7 @@ svn_fs_x__write_min_unpacked_rev(svn_fs_t *fs, svn_revnum_t revnum, apr_pool_t *scratch_pool) { + svn_fs_x__data_t *ffd = fs->fsap_data; const char *final_path; char buf[SVN_INT64_BUFFER_SIZE]; apr_size_t len = svn__i64toa(buf, revnum); @@ -550,8 +543,9 @@ svn_fs_x__write_min_unpacked_rev(svn_fs_t *fs, final_path = svn_fs_x__path_min_unpacked_rev(fs, scratch_pool); - SVN_ERR(svn_io_write_atomic(final_path, buf, len + 1, - final_path /* copy_perms */, scratch_pool)); + SVN_ERR(svn_io_write_atomic2(final_path, buf, len + 1, + final_path /* copy_perms */, + ffd->flush_to_disk, scratch_pool)); return SVN_NO_ERROR; } @@ -574,7 +568,7 @@ svn_fs_x__read_current(svn_revnum_t *rev, return SVN_NO_ERROR; } -/* Atomically update the 'current' file to hold the specifed REV. +/* Atomically update the 'current' file to hold the specified REV. Perform temporary allocations in SCRATCH_POOL. */ svn_error_t * svn_fs_x__write_current(svn_fs_t *fs, @@ -583,17 +577,28 @@ svn_fs_x__write_current(svn_fs_t *fs, { char *buf; const char *tmp_name, *name; + apr_file_t *file; /* Now we can just write out this line. */ buf = apr_psprintf(scratch_pool, "%ld\n", rev); name = svn_fs_x__path_current(fs, scratch_pool); - SVN_ERR(svn_io_write_unique(&tmp_name, - svn_dirent_dirname(name, scratch_pool), - buf, strlen(buf), - svn_io_file_del_none, scratch_pool)); + tmp_name = svn_fs_x__path_next(fs, scratch_pool); - return svn_fs_x__move_into_place(tmp_name, name, name, scratch_pool); + SVN_ERR(svn_io_file_open(&file, tmp_name, + APR_WRITE | APR_CREATE | APR_BUFFERED, + APR_OS_DEFAULT, scratch_pool)); + SVN_ERR(svn_io_file_write_full(file, buf, strlen(buf), NULL, + scratch_pool)); + SVN_ERR(svn_io_file_close(file, scratch_pool)); + + /* Copying permissions is a no-op on WIN32. */ + SVN_ERR(svn_io_copy_perms(name, tmp_name, scratch_pool)); + + /* Move the file into place. */ + SVN_ERR(svn_io_file_rename2(tmp_name, name, TRUE, scratch_pool)); + + return SVN_NO_ERROR; } @@ -639,22 +644,6 @@ svn_fs_x__try_stringbuf_from_file(svn_stringbuf_t **content, } /* Fetch the current offset of FILE into *OFFSET_P. */ -svn_error_t * -svn_fs_x__get_file_offset(apr_off_t *offset_p, - apr_file_t *file, - apr_pool_t *scratch_pool) -{ - apr_off_t offset; - - /* Note that, for buffered files, one (possibly surprising) side-effect - of this call is to flush any unwritten data to disk. */ - offset = 0; - SVN_ERR(svn_io_file_seek(file, APR_CUR, &offset, scratch_pool)); - *offset_p = offset; - - return SVN_NO_ERROR; -} - svn_error_t * svn_fs_x__read_content(svn_stringbuf_t **content, const char *fname, @@ -711,66 +700,33 @@ svn_fs_x__read_number_from_stream(apr_int64_t *result, return SVN_NO_ERROR; } - -/* Move a file into place from OLD_FILENAME in the transactions - directory to its final location NEW_FILENAME in the repository. On - Unix, match the permissions of the new file to the permissions of - PERMS_REFERENCE. Temporary allocations are from SCRATCH_POOL. - - This function almost duplicates svn_io_file_move(), but it tries to - guarantee a flush. */ svn_error_t * svn_fs_x__move_into_place(const char *old_filename, const char *new_filename, const char *perms_reference, + svn_fs_x__batch_fsync_t *batch, apr_pool_t *scratch_pool) { - svn_error_t *err; - + /* Copying permissions is a no-op on WIN32. */ SVN_ERR(svn_io_copy_perms(perms_reference, old_filename, scratch_pool)); + /* We use specific 'fsyncing move' Win32 API calls on Windows while the + * directory update fsync is POSIX-only. Moreover, there tend to be only + * a few moved files (1 or 2) per batch. + * + * Therefore, we use the platform-optimized "immediate" fsyncs on all + * non-POSIX platforms and the "scheduled" fsyncs on POSIX only. + */ +#if defined(SVN_ON_POSIX) /* Move the file into place. */ - err = svn_io_file_rename(old_filename, new_filename, scratch_pool); - if (err && APR_STATUS_IS_EXDEV(err->apr_err)) - { - apr_file_t *file; + SVN_ERR(svn_io_file_rename2(old_filename, new_filename, FALSE, + scratch_pool)); - /* Can't rename across devices; fall back to copying. */ - svn_error_clear(err); - err = SVN_NO_ERROR; - SVN_ERR(svn_io_copy_file(old_filename, new_filename, TRUE, - scratch_pool)); - - /* Flush the target of the copy to disk. */ - SVN_ERR(svn_io_file_open(&file, new_filename, APR_READ, - APR_OS_DEFAULT, scratch_pool)); - /* ### BH: Does this really guarantee a flush of the data written - ### via a completely different handle on all operating systems? - ### - ### Maybe we should perform the copy ourselves instead of making - ### apr do that and flush the real handle? */ - SVN_ERR(svn_io_file_flush_to_disk(file, scratch_pool)); - SVN_ERR(svn_io_file_close(file, scratch_pool)); - } - if (err) - return svn_error_trace(err); - -#ifdef __linux__ - { - /* Linux has the unusual feature that fsync() on a file is not - enough to ensure that a file's directory entries have been - flushed to disk; you have to fsync the directory as well. - On other operating systems, we'd only be asking for trouble - by trying to open and fsync a directory. */ - const char *dirname; - apr_file_t *file; - - dirname = svn_dirent_dirname(new_filename, scratch_pool); - SVN_ERR(svn_io_file_open(&file, dirname, APR_READ, APR_OS_DEFAULT, - scratch_pool)); - SVN_ERR(svn_io_file_flush_to_disk(file, scratch_pool)); - SVN_ERR(svn_io_file_close(file, scratch_pool)); - } + /* Schedule for synchronization. */ + SVN_ERR(svn_fs_x__batch_fsync_new_path(batch, new_filename, scratch_pool)); +#else + SVN_ERR(svn_io_file_rename2(old_filename, new_filename, TRUE, + scratch_pool)); #endif return SVN_NO_ERROR; diff --git a/subversion/libsvn_fs_x/util.h b/subversion/libsvn_fs_x/util.h index 0010723ed4bf..9622328ae771 100644 --- a/subversion/libsvn_fs_x/util.h +++ b/subversion/libsvn_fs_x/util.h @@ -20,11 +20,12 @@ * ==================================================================== */ -#ifndef SVN_LIBSVN_FS__UTIL_H -#define SVN_LIBSVN_FS__UTIL_H +#ifndef SVN_LIBSVN_FS_X_UTIL_H +#define SVN_LIBSVN_FS_X_UTIL_H #include "svn_fs.h" #include "id.h" +#include "batch_fsync.h" /* Functions for dealing with recoverable errors on mutable files * @@ -102,6 +103,12 @@ const char * svn_fs_x__path_current(svn_fs_t *fs, apr_pool_t *result_pool); +/* Return the path to the 'next' file in FS. + Perform allocation in RESULT_POOL. */ +const char * +svn_fs_x__path_next(svn_fs_t *fs, + apr_pool_t *result_pool); + /* Return the full path of the "uuid" file in FS. * The result will be allocated in RESULT_POOL. */ @@ -158,9 +165,9 @@ svn_fs_x__path_rev_packed(svn_fs_t *fs, * revision REV in FS. Allocate the result in RESULT_POOL. */ const char * -svn_fs_x__path_rev_shard(svn_fs_t *fs, - svn_revnum_t rev, - apr_pool_t *result_pool); +svn_fs_x__path_shard(svn_fs_t *fs, + svn_revnum_t rev, + apr_pool_t *result_pool); /* Return the full path of the non-packed rev file containing revision REV * in FS. Allocate the result in RESULT_POOL. @@ -183,23 +190,13 @@ svn_fs_x__path_rev_absolute(svn_fs_t *fs, svn_revnum_t rev, apr_pool_t *result_pool); -/* Return the full path of the revision properties shard directory that - * will contain the properties of revision REV in FS. - * Allocate the result in RESULT_POOL. +/* Return the full path of the pack shard directory that will contain the + * packed revision REV in FS. Allocate the result in RESULT_POOL. */ const char * -svn_fs_x__path_revprops_shard(svn_fs_t *fs, - svn_revnum_t rev, - apr_pool_t *result_pool); - -/* Return the full path of the revision properties pack shard directory - * that will contain the packed properties of revision REV in FS. - * Allocate the result in RESULT_POOL. - */ -const char * -svn_fs_x__path_revprops_pack_shard(svn_fs_t *fs, - svn_revnum_t rev, - apr_pool_t *result_pool); +svn_fs_x__path_pack_shard(svn_fs_t *fs, + svn_revnum_t rev, + apr_pool_t *result_pool); /* Return the full path of the non-packed revision properties file that * contains the props for revision REV in FS. @@ -287,15 +284,6 @@ svn_fs_x__path_txn_props(svn_fs_t *fs, svn_fs_x__txn_id_t txn_id, apr_pool_t *result_pool); -/* Return the path of the file containing the "final" transaction - * properties for the transaction identified by TXN_ID in FS. - * The result will be allocated in RESULT_POOL. - */ -const char * -svn_fs_x__path_txn_props_final(svn_fs_t *fs, - svn_fs_x__txn_id_t txn_id, - apr_pool_t *result_pool); - /* Return the path of the file containing the node and copy ID counters for * the transaction identified by TXN_ID in FS. * The result will be allocated in RESULT_POOL. @@ -381,7 +369,7 @@ svn_fs_x__check_file_buffer_numeric(const char *buf, apr_pool_t *scratch_pool); /* Set *MIN_UNPACKED_REV to the integer value read from the file returned - * by #svn_fs_fs__path_min_unpacked_rev() for FS. + * by #svn_fs_x__path_min_unpacked_rev() for FS. * Use SCRATCH_POOL for temporary allocations. */ svn_error_t * @@ -434,13 +422,6 @@ svn_fs_x__try_stringbuf_from_file(svn_stringbuf_t **content, svn_boolean_t last_attempt, apr_pool_t *result_pool); -/* Fetch the current offset of FILE into *OFFSET_P. - * Perform temporary allocations in SCRATCH_POOL. */ -svn_error_t * -svn_fs_x__get_file_offset(apr_off_t *offset_p, - apr_file_t *file, - apr_pool_t *scratch_pool); - /* Read the file FNAME and store the contents in *BUF. Allocations are performed in RESULT_POOL. */ svn_error_t * @@ -460,17 +441,20 @@ svn_fs_x__read_number_from_stream(apr_int64_t *result, svn_stream_t *stream, apr_pool_t *scratch_pool); -/* Move a file into place from OLD_FILENAME in the transactions - directory to its final location NEW_FILENAME in the repository. On - Unix, match the permissions of the new file to the permissions of - PERMS_REFERENCE. Temporary allocations are from SCRATCH_POOL. +/* Move a file into place from temporary OLD_FILENAME to its final + location NEW_FILENAME, which must be on to the same volume. Schedule + any necessary fsync calls in BATCH. On Unix, match the permissions + of the new file to the permissions of PERMS_REFERENCE. + + Temporary allocations are from SCRATCH_POOL. This function almost duplicates svn_io_file_move(), but it tries to - guarantee a flush. */ + guarantee a flush if BATCH->FLUSH_TO_DISK is non-zero. */ svn_error_t * svn_fs_x__move_into_place(const char *old_filename, const char *new_filename, const char *perms_reference, + svn_fs_x__batch_fsync_t *batch, apr_pool_t *scratch_pool); #endif diff --git a/subversion/libsvn_fs_x/verify.c b/subversion/libsvn_fs_x/verify.c index 4ea0728f7d5f..6f03201b2b8e 100644 --- a/subversion/libsvn_fs_x/verify.c +++ b/subversion/libsvn_fs_x/verify.c @@ -27,6 +27,7 @@ #include "cached_data.h" #include "rep-cache.h" +#include "revprops.h" #include "util.h" #include "index.h" @@ -141,30 +142,27 @@ verify_rep_cache(svn_fs_t *fs, * indedx NAME in the error message. Supports cancellation with CANCEL_FUNC * and CANCEL_BATON. SCRATCH_POOL is for temporary allocations. */ static svn_error_t * -verify_index_checksum(apr_file_t *file, +verify_index_checksum(svn_fs_x__revision_file_t *file, const char *name, - apr_off_t start, - apr_off_t end, - svn_checksum_t *expected, + svn_fs_x__index_info_t *index_info, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *scratch_pool) { unsigned char buffer[SVN__STREAM_CHUNK_SIZE]; - apr_off_t size = end - start; + apr_off_t size = index_info->end - index_info->start; svn_checksum_t *actual; svn_checksum_ctx_t *context = svn_checksum_ctx_create(svn_checksum_md5, scratch_pool); /* Calculate the index checksum. */ - SVN_ERR(svn_io_file_seek(file, APR_SET, &start, scratch_pool)); + SVN_ERR(svn_fs_x__rev_file_seek(file, NULL, index_info->start)); while (size > 0) { apr_size_t to_read = size > sizeof(buffer) ? sizeof(buffer) : (apr_size_t)size; - SVN_ERR(svn_io_file_read_full2(file, buffer, to_read, NULL, NULL, - scratch_pool)); + SVN_ERR(svn_fs_x__rev_file_read(file, buffer, to_read)); SVN_ERR(svn_checksum_update(context, buffer, to_read)); size -= to_read; @@ -175,12 +173,13 @@ verify_index_checksum(apr_file_t *file, SVN_ERR(svn_checksum_final(&actual, context, scratch_pool)); /* Verify that it matches the expected checksum. */ - if (!svn_checksum_match(expected, actual)) + if (!svn_checksum_match(index_info->checksum, actual)) { const char *file_name; - SVN_ERR(svn_io_file_name_get(&file_name, file, scratch_pool)); - SVN_ERR(svn_checksum_mismatch_err(expected, actual, scratch_pool, + SVN_ERR(svn_fs_x__rev_file_name(&file_name, file, scratch_pool)); + SVN_ERR(svn_checksum_mismatch_err(index_info->checksum, actual, + scratch_pool, _("%s checksum mismatch in file %s"), name, file_name)); } @@ -201,20 +200,18 @@ verify_index_checksums(svn_fs_t *fs, apr_pool_t *scratch_pool) { svn_fs_x__revision_file_t *rev_file; + svn_fs_x__index_info_t l2p_index_info; + svn_fs_x__index_info_t p2l_index_info; /* Open the rev / pack file and read the footer */ - SVN_ERR(svn_fs_x__open_pack_or_rev_file(&rev_file, fs, start, - scratch_pool, scratch_pool)); - SVN_ERR(svn_fs_x__auto_read_footer(rev_file)); + SVN_ERR(svn_fs_x__rev_file_init(&rev_file, fs, start, scratch_pool)); + SVN_ERR(svn_fs_x__rev_file_l2p_info(&l2p_index_info, rev_file)); + SVN_ERR(svn_fs_x__rev_file_p2l_info(&p2l_index_info, rev_file)); /* Verify the index contents against the checksum from the footer. */ - SVN_ERR(verify_index_checksum(rev_file->file, "L2P index", - rev_file->l2p_offset, rev_file->p2l_offset, - rev_file->l2p_checksum, + SVN_ERR(verify_index_checksum(rev_file, "L2P index", &l2p_index_info, cancel_func, cancel_baton, scratch_pool)); - SVN_ERR(verify_index_checksum(rev_file->file, "P2L index", - rev_file->p2l_offset, rev_file->footer_offset, - rev_file->p2l_checksum, + SVN_ERR(verify_index_checksum(rev_file, "P2L index", &p2l_index_info, cancel_func, cancel_baton, scratch_pool)); /* Done. */ @@ -242,8 +239,7 @@ compare_l2p_to_p2l_index(svn_fs_t *fs, /* common file access structure */ svn_fs_x__revision_file_t *rev_file; - SVN_ERR(svn_fs_x__open_pack_or_rev_file(&rev_file, fs, start, scratch_pool, - iterpool)); + SVN_ERR(svn_fs_x__rev_file_init(&rev_file, fs, start, scratch_pool)); /* determine the range of items to check for each revision */ SVN_ERR(svn_fs_x__l2p_get_max_ids(&max_ids, fs, start, count, scratch_pool, @@ -334,8 +330,7 @@ compare_p2l_to_l2p_index(svn_fs_t *fs, /* common file access structure */ svn_fs_x__revision_file_t *rev_file; - SVN_ERR(svn_fs_x__open_pack_or_rev_file(&rev_file, fs, start, scratch_pool, - iterpool)); + SVN_ERR(svn_fs_x__rev_file_init(&rev_file, fs, start, scratch_pool)); /* get the size of the rev / pack file as covered by the P2L index */ SVN_ERR(svn_fs_x__p2l_get_max_offset(&max_offset, fs, rev_file, start, @@ -424,7 +419,7 @@ compare_p2l_to_l2p_index(svn_fs_t *fs, * exceed STREAM_THRESHOLD. Use SCRATCH_POOL for temporary allocations. */ static svn_error_t * -expect_buffer_nul(apr_file_t *file, +expect_buffer_nul(svn_fs_x__revision_file_t *file, apr_off_t size, apr_pool_t *scratch_pool) { @@ -439,8 +434,7 @@ expect_buffer_nul(apr_file_t *file, /* read the whole data block; error out on failure */ data.chunks[(size - 1)/ sizeof(apr_uint64_t)] = 0; - SVN_ERR(svn_io_file_read_full2(file, data.buffer, size, NULL, NULL, - scratch_pool)); + SVN_ERR(svn_fs_x__rev_file_read(file, data.buffer, size)); /* chunky check */ for (i = 0; i < size / sizeof(apr_uint64_t); ++i) @@ -454,8 +448,8 @@ expect_buffer_nul(apr_file_t *file, const char *file_name; apr_off_t offset; - SVN_ERR(svn_io_file_name_get(&file_name, file, scratch_pool)); - SVN_ERR(svn_fs_x__get_file_offset(&offset, file, scratch_pool)); + SVN_ERR(svn_fs_x__rev_file_name(&file_name, file, scratch_pool)); + SVN_ERR(svn_fs_x__rev_file_offset(&offset, file)); offset -= size - i; return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, @@ -472,7 +466,7 @@ expect_buffer_nul(apr_file_t *file, * Use SCRATCH_POOL for temporary allocations. */ static svn_error_t * -read_all_nul(apr_file_t *file, +read_all_nul(svn_fs_x__revision_file_t *file, apr_off_t size, apr_pool_t *scratch_pool) { @@ -490,7 +484,7 @@ read_all_nul(apr_file_t *file, * in error message. Allocate temporary data in SCRATCH_POOL. */ static svn_error_t * -expected_checksum(apr_file_t *file, +expected_checksum(svn_fs_x__revision_file_t *file, svn_fs_x__p2l_entry_t *entry, apr_uint32_t actual, apr_pool_t *scratch_pool) @@ -499,8 +493,7 @@ expected_checksum(apr_file_t *file, { const char *file_name; - SVN_ERR(svn_io_file_name_get(&file_name, file, scratch_pool)); - SVN_ERR(svn_io_file_name_get(&file_name, file, scratch_pool)); + SVN_ERR(svn_fs_x__rev_file_name(&file_name, file, scratch_pool)); return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, _("Checksum mismatch in item at offset %s of " "length %s bytes in file %s"), @@ -517,15 +510,14 @@ expected_checksum(apr_file_t *file, * exceed STREAM_THRESHOLD. Use SCRATCH_POOL for temporary allocations. */ static svn_error_t * -expected_buffered_checksum(apr_file_t *file, +expected_buffered_checksum(svn_fs_x__revision_file_t *file, svn_fs_x__p2l_entry_t *entry, apr_pool_t *scratch_pool) { unsigned char buffer[STREAM_THRESHOLD]; SVN_ERR_ASSERT(entry->size <= STREAM_THRESHOLD); - SVN_ERR(svn_io_file_read_full2(file, buffer, (apr_size_t)entry->size, - NULL, NULL, scratch_pool)); + SVN_ERR(svn_fs_x__rev_file_read(file, buffer, (apr_size_t)entry->size)); SVN_ERR(expected_checksum(file, entry, svn__fnv1a_32x4(buffer, (apr_size_t)entry->size), scratch_pool)); @@ -538,7 +530,7 @@ expected_buffered_checksum(apr_file_t *file, * Use SCRATCH_POOL for temporary allocations. */ static svn_error_t * -expected_streamed_checksum(apr_file_t *file, +expected_streamed_checksum(svn_fs_x__revision_file_t *file, svn_fs_x__p2l_entry_t *entry, apr_pool_t *scratch_pool) { @@ -553,8 +545,7 @@ expected_streamed_checksum(apr_file_t *file, apr_size_t to_read = size > sizeof(buffer) ? sizeof(buffer) : (apr_size_t)size; - SVN_ERR(svn_io_file_read_full2(file, buffer, to_read, NULL, NULL, - scratch_pool)); + SVN_ERR(svn_fs_x__rev_file_read(file, buffer, to_read)); SVN_ERR(svn_checksum_update(context, buffer, to_read)); size -= to_read; } @@ -588,28 +579,27 @@ compare_p2l_to_rev(svn_fs_t *fs, apr_off_t max_offset; apr_off_t offset = 0; svn_fs_x__revision_file_t *rev_file; + svn_fs_x__index_info_t l2p_index_info; /* open the pack / rev file that is covered by the p2l index */ - SVN_ERR(svn_fs_x__open_pack_or_rev_file(&rev_file, fs, start, scratch_pool, - iterpool)); + SVN_ERR(svn_fs_x__rev_file_init(&rev_file, fs, start, scratch_pool)); /* check file size vs. range covered by index */ - SVN_ERR(svn_fs_x__auto_read_footer(rev_file)); + SVN_ERR(svn_fs_x__rev_file_l2p_info(&l2p_index_info, rev_file)); SVN_ERR(svn_fs_x__p2l_get_max_offset(&max_offset, fs, rev_file, start, scratch_pool)); - if (rev_file->l2p_offset != max_offset) + if (l2p_index_info.start != max_offset) return svn_error_createf(SVN_ERR_FS_INDEX_INCONSISTENT, NULL, _("File size of %s for revision r%ld does " "not match p2l index size of %s"), apr_off_t_toa(scratch_pool, - rev_file->l2p_offset), + l2p_index_info.start), start, apr_off_t_toa(scratch_pool, max_offset)); - SVN_ERR(svn_io_file_aligned_seek(rev_file->file, ffd->block_size, NULL, 0, - scratch_pool)); + SVN_ERR(svn_fs_x__rev_file_seek(rev_file, NULL, 0)); /* for all offsets in the file, get the P2L index entries and check them against the L2P index */ @@ -627,8 +617,7 @@ compare_p2l_to_rev(svn_fs_t *fs, /* The above might have moved the file pointer. * Ensure we actually start reading at OFFSET. */ - SVN_ERR(svn_io_file_aligned_seek(rev_file->file, ffd->block_size, - NULL, offset, iterpool)); + SVN_ERR(svn_fs_x__rev_file_seek(rev_file, NULL, offset)); /* process all entries (and later continue with the next block) */ for (i = 0; i < entries->nelts; ++i) @@ -661,15 +650,15 @@ compare_p2l_to_rev(svn_fs_t *fs, { /* skip filler entry at the end of the p2l index */ if (entry->offset != max_offset) - SVN_ERR(read_all_nul(rev_file->file, entry->size, iterpool)); + SVN_ERR(read_all_nul(rev_file, entry->size, iterpool)); } else { if (entry->size < STREAM_THRESHOLD) - SVN_ERR(expected_buffered_checksum(rev_file->file, entry, + SVN_ERR(expected_buffered_checksum(rev_file, entry, iterpool)); else - SVN_ERR(expected_streamed_checksum(rev_file->file, entry, + SVN_ERR(expected_streamed_checksum(rev_file, entry, iterpool)); } @@ -703,6 +692,10 @@ verify_revprops(svn_fs_t *fs, svn_revnum_t revision; apr_pool_t *iterpool = svn_pool_create(scratch_pool); + /* Invalidate the revprop generation once. + * Use the cache inside the loop to speed up packed revprop access. */ + svn_fs_x__invalidate_revprop_generation(fs); + for (revision = start; revision < end; ++revision) { svn_string_t *date; @@ -713,7 +706,7 @@ verify_revprops(svn_fs_t *fs, /* Access the svn:date revprop. * This implies parsing all revprops for that revision. */ SVN_ERR(svn_fs_x__revision_prop(&date, fs, revision, - SVN_PROP_REVISION_DATE, + SVN_PROP_REVISION_DATE, FALSE, iterpool, iterpool)); /* The time stamp is the only revprop that, if given, needs to @@ -790,8 +783,15 @@ verify_metadata_consistency(svn_fs_t *fs, /* concurrent packing is one of the reasons why verification may fail. Make sure, we operate on up-to-date information. */ if (err) - SVN_ERR(svn_fs_x__read_min_unpacked_rev(&ffd->min_unpacked_rev, - fs, scratch_pool)); + { + svn_error_t *err2 + = svn_fs_x__read_min_unpacked_rev(&ffd->min_unpacked_rev, + fs, scratch_pool); + + /* Be careful to not leak ERR. */ + if (err2) + return svn_error_trace(svn_error_compose_create(err, err2)); + } /* retry the whole shard if it got packed in the meantime */ if (err && count != svn_fs_x__pack_size(fs, revision)) @@ -824,14 +824,14 @@ svn_fs_x__verify(svn_fs_t *fs, void *cancel_baton, apr_pool_t *scratch_pool) { - svn_fs_x__data_t *ffd = fs->fsap_data; - svn_revnum_t youngest = ffd->youngest_rev_cache; /* cache is current */ - /* Input validation. */ if (! SVN_IS_VALID_REVNUM(start)) start = 0; if (! SVN_IS_VALID_REVNUM(end)) - end = youngest; + { + SVN_ERR(svn_fs_x__youngest_rev(&end, fs, scratch_pool)); + } + SVN_ERR(svn_fs_x__ensure_revision_exists(start, fs, scratch_pool)); SVN_ERR(svn_fs_x__ensure_revision_exists(end, fs, scratch_pool)); diff --git a/subversion/libsvn_fs_x/verify.h b/subversion/libsvn_fs_x/verify.h index 805f65496150..8b76be9ea0b9 100644 --- a/subversion/libsvn_fs_x/verify.h +++ b/subversion/libsvn_fs_x/verify.h @@ -1,4 +1,4 @@ -/* verify.h : verification interface of the native filesystem layer +/* verify.h : verification interface of the FSX filesystem * * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one @@ -20,8 +20,8 @@ * ==================================================================== */ -#ifndef SVN_LIBSVN_FS__VERIFY_H -#define SVN_LIBSVN_FS__VERIFY_H +#ifndef SVN_LIBSVN_FS_X_VERIFY_H +#define SVN_LIBSVN_FS_X_VERIFY_H #include "fs.h" diff --git a/subversion/libsvn_ra/ra_loader.c b/subversion/libsvn_ra/ra_loader.c index 3a782f239f9b..ac07545e2ba0 100644 --- a/subversion/libsvn_ra/ra_loader.c +++ b/subversion/libsvn_ra/ra_loader.c @@ -80,7 +80,7 @@ static const struct ra_lib_defn { { "svn", svn_schemes, -#ifdef SVN_LIBSVN_CLIENT_LINKS_RA_SVN +#ifdef SVN_LIBSVN_RA_LINKS_RA_SVN svn_ra_svn__init, svn_ra_svn__deprecated_init #endif @@ -89,7 +89,7 @@ static const struct ra_lib_defn { { "local", local_schemes, -#ifdef SVN_LIBSVN_CLIENT_LINKS_RA_LOCAL +#ifdef SVN_LIBSVN_RA_LINKS_RA_LOCAL svn_ra_local__init, svn_ra_local__deprecated_init #endif @@ -98,7 +98,7 @@ static const struct ra_lib_defn { { "serf", dav_schemes, -#ifdef SVN_LIBSVN_CLIENT_LINKS_RA_SERF +#ifdef SVN_LIBSVN_RA_LINKS_RA_SERF svn_ra_serf__init, svn_ra_serf__deprecated_init #endif @@ -143,7 +143,7 @@ load_ra_module(svn_ra__init_func_t *func, const char *compat_funcname; apr_status_t status; - libname = apr_psprintf(pool, "libsvn_ra_%s-%d.so.%d", + libname = apr_psprintf(pool, "libsvn_ra_%s-" SVN_DSO_SUFFIX_FMT, ra_name, SVN_VER_MAJOR, SVN_SOVERSION); funcname = apr_psprintf(pool, "svn_ra_%s__init", ra_name); compat_funcname = apr_psprintf(pool, "svn_ra_%s_init", ra_name); @@ -410,6 +410,9 @@ svn_error_t *svn_ra_open4(svn_ra_session_t **session_p, return SVN_NO_ERROR; } + if (vtable->set_svn_ra_open) + SVN_ERR(vtable->set_svn_ra_open(session, svn_ra_open4)); + /* Check the UUID. */ if (uuid) { @@ -468,6 +471,9 @@ svn_ra__dup_session(svn_ra_session_t **new_session, result_pool, scratch_pool)); + if (session->vtable->set_svn_ra_open) + SVN_ERR(session->vtable->set_svn_ra_open(session, svn_ra_open4)); + *new_session = session; return SVN_NO_ERROR; } @@ -639,6 +645,29 @@ svn_error_t *svn_ra_get_dir2(svn_ra_session_t *session, path, revision, dirent_fields, pool); } +svn_error_t * +svn_ra_list(svn_ra_session_t *session, + const char *path, + svn_revnum_t revision, + const apr_array_header_t *patterns, + svn_depth_t depth, + apr_uint32_t dirent_fields, + svn_ra_dirent_receiver_t receiver, + void *receiver_baton, + apr_pool_t *scratch_pool) +{ + SVN_ERR_ASSERT(svn_relpath_is_canonical(path)); + if (!session->vtable->list) + return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, NULL); + + SVN_ERR(svn_ra__assert_capable_server(session, SVN_RA_CAPABILITY_LIST, + NULL, scratch_pool)); + + return session->vtable->list(session, path, revision, patterns, depth, + dirent_fields, receiver, receiver_baton, + scratch_pool); +} + svn_error_t *svn_ra_get_mergeinfo(svn_ra_session_t *session, svn_mergeinfo_catalog_t *catalog, const apr_array_header_t *paths, @@ -953,6 +982,7 @@ svn_error_t *svn_ra_get_locations(svn_ra_session_t *session, { svn_error_t *err; + SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(peg_revision)); SVN_ERR_ASSERT(svn_relpath_is_canonical(path)); err = session->vtable->get_locations(session, locations, path, peg_revision, location_revisions, pool); @@ -1120,6 +1150,8 @@ svn_error_t *svn_ra_replay(svn_ra_session_t *session, void *edit_baton, apr_pool_t *pool) { + SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(revision) + && SVN_IS_VALID_REVNUM(low_water_mark)); return session->vtable->replay(session, revision, low_water_mark, text_deltas, editor, edit_baton, pool); } @@ -1187,7 +1219,14 @@ svn_ra_replay_range(svn_ra_session_t *session, void *replay_baton, apr_pool_t *pool) { - svn_error_t *err = + svn_error_t *err; + + SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(start_revision) + && SVN_IS_VALID_REVNUM(end_revision) + && start_revision <= end_revision + && SVN_IS_VALID_REVNUM(low_water_mark)); + + err = session->vtable->replay_range(session, start_revision, end_revision, low_water_mark, text_deltas, revstart_func, revfinish_func, @@ -1518,7 +1557,7 @@ svn_ra_get_ra_library(svn_ra_plugin_t **library, implementation for svn_ra_foo_init which returns a "not implemented" error. */ -#ifndef SVN_LIBSVN_CLIENT_LINKS_RA_NEON +#ifndef SVN_LIBSVN_RA_LINKS_RA_NEON svn_error_t * svn_ra_dav_init(int abi_version, apr_pool_t *pool, @@ -1526,9 +1565,9 @@ svn_ra_dav_init(int abi_version, { return svn_error_create(SVN_ERR_RA_NOT_IMPLEMENTED, NULL, NULL); } -#endif /* ! SVN_LIBSVN_CLIENT_LINKS_RA_NEON */ +#endif /* ! SVN_LIBSVN_RA_LINKS_RA_NEON */ -#ifndef SVN_LIBSVN_CLIENT_LINKS_RA_SVN +#ifndef SVN_LIBSVN_RA_LINKS_RA_SVN svn_error_t * svn_ra_svn_init(int abi_version, apr_pool_t *pool, @@ -1536,9 +1575,9 @@ svn_ra_svn_init(int abi_version, { return svn_error_create(SVN_ERR_RA_NOT_IMPLEMENTED, NULL, NULL); } -#endif /* ! SVN_LIBSVN_CLIENT_LINKS_RA_SVN */ +#endif /* ! SVN_LIBSVN_RA_LINKS_RA_SVN */ -#ifndef SVN_LIBSVN_CLIENT_LINKS_RA_LOCAL +#ifndef SVN_LIBSVN_RA_LINKS_RA_LOCAL svn_error_t * svn_ra_local_init(int abi_version, apr_pool_t *pool, @@ -1546,9 +1585,9 @@ svn_ra_local_init(int abi_version, { return svn_error_create(SVN_ERR_RA_NOT_IMPLEMENTED, NULL, NULL); } -#endif /* ! SVN_LIBSVN_CLIENT_LINKS_RA_LOCAL */ +#endif /* ! SVN_LIBSVN_RA_LINKS_RA_LOCAL */ -#ifndef SVN_LIBSVN_CLIENT_LINKS_RA_SERF +#ifndef SVN_LIBSVN_RA_LINKS_RA_SERF svn_error_t * svn_ra_serf_init(int abi_version, apr_pool_t *pool, @@ -1556,4 +1595,4 @@ svn_ra_serf_init(int abi_version, { return svn_error_create(SVN_ERR_RA_NOT_IMPLEMENTED, NULL, NULL); } -#endif /* ! SVN_LIBSVN_CLIENT_LINKS_RA_SERF */ +#endif /* ! SVN_LIBSVN_RA_LINKS_RA_SERF */ diff --git a/subversion/libsvn_ra/ra_loader.h b/subversion/libsvn_ra/ra_loader.h index f371f273feca..c20b5bf92253 100644 --- a/subversion/libsvn_ra/ra_loader.h +++ b/subversion/libsvn_ra/ra_loader.h @@ -38,6 +38,17 @@ extern "C" { #endif +/* Prototype of most recent version of svn_ra_openX() api, optionally + handed to the ra api to allow opening other ra sessions. */ +typedef svn_error_t * (*svn_ra__open_func_t)(svn_ra_session_t **session_p, + const char **corrected_url, + const char *repos_URL, + const char *uuid, + const svn_ra_callbacks2_t *callbacks, + void *callback_baton, + apr_hash_t *config, + apr_pool_t *pool); + /* The RA layer vtable. */ typedef struct svn_ra__vtable_t { /* This field should always remain first in the vtable. */ @@ -308,10 +319,6 @@ typedef struct svn_ra__vtable_t { svn_revnum_t end_revision, svn_revnum_t *revision_deleted, apr_pool_t *pool); - - /* See svn_ra__register_editor_shim_callbacks() */ - svn_error_t *(*register_editor_shim_callbacks)(svn_ra_session_t *session, - svn_delta_shim_callbacks_t *callbacks); /* See svn_ra_get_inherited_props(). */ svn_error_t *(*get_inherited_props)(svn_ra_session_t *session, apr_array_header_t **iprops, @@ -319,6 +326,28 @@ typedef struct svn_ra__vtable_t { svn_revnum_t revision, apr_pool_t *result_pool, apr_pool_t *scratch_pool); + /* If not NULL, receives a pointer to svn_ra_open, to alllow opening + a new ra session from inside the ra layer without a circular + library dependency*/ + svn_error_t *(*set_svn_ra_open)(svn_ra_session_t *session, + svn_ra__open_func_t func); + + /* See svn_ra_list(). */ + svn_error_t *(*list)(svn_ra_session_t *session, + const char *path, + svn_revnum_t revision, + const apr_array_header_t *patterns, + svn_depth_t depth, + apr_uint32_t dirent_fields, + svn_ra_dirent_receiver_t receiver, + void *receiver_baton, + apr_pool_t *scratch_pool); + + /* Experimental support below here */ + + /* See svn_ra__register_editor_shim_callbacks() */ + svn_error_t *(*register_editor_shim_callbacks)(svn_ra_session_t *session, + svn_delta_shim_callbacks_t *callbacks); /* See svn_ra__get_commit_ev2() */ svn_error_t *(*get_commit_ev2)( svn_editor_t **editor, diff --git a/subversion/libsvn_ra_local/ra_plugin.c b/subversion/libsvn_ra_local/ra_plugin.c index bb09162f0e0a..7bff85f3b84a 100644 --- a/subversion/libsvn_ra_local/ra_plugin.c +++ b/subversion/libsvn_ra_local/ra_plugin.c @@ -909,6 +909,28 @@ svn_ra_local__get_commit_editor(svn_ra_session_t *session, } +/* Implements svn_repos_mergeinfo_receiver_t. + * It add MERGEINFO for PATH to the svn_mergeinfo_catalog_t BATON. + */ +static svn_error_t * +mergeinfo_receiver(const char *path, + svn_mergeinfo_t mergeinfo, + void *baton, + apr_pool_t *scratch_pool) +{ + svn_mergeinfo_catalog_t catalog = baton; + apr_pool_t *result_pool = apr_hash_pool_get(catalog); + apr_size_t len = strlen(path); + + apr_hash_set(catalog, + apr_pstrmemdup(result_pool, path, len), + len, + svn_mergeinfo_dup(mergeinfo, result_pool)); + + return SVN_NO_ERROR; +} + + static svn_error_t * svn_ra_local__get_mergeinfo(svn_ra_session_t *session, svn_mergeinfo_catalog_t *catalog, @@ -919,7 +941,7 @@ svn_ra_local__get_mergeinfo(svn_ra_session_t *session, apr_pool_t *pool) { svn_ra_local__session_baton_t *sess = session->priv; - svn_mergeinfo_catalog_t tmp_catalog; + svn_mergeinfo_catalog_t tmp_catalog = svn_hash__make(pool); int i; apr_array_header_t *abs_paths = apr_array_make(pool, 0, sizeof(const char *)); @@ -931,9 +953,11 @@ svn_ra_local__get_mergeinfo(svn_ra_session_t *session, svn_fspath__join(sess->fs_path->data, relative_path, pool); } - SVN_ERR(svn_repos_fs_get_mergeinfo(&tmp_catalog, sess->repos, abs_paths, - revision, inherit, include_descendants, - NULL, NULL, pool)); + SVN_ERR(svn_repos_fs_get_mergeinfo2(sess->repos, abs_paths, revision, + inherit, include_descendants, + NULL, NULL, + mergeinfo_receiver, tmp_catalog, + pool)); if (apr_hash_count(tmp_catalog) > 0) SVN_ERR(svn_mergeinfo__remove_prefix_from_catalog(catalog, tmp_catalog, @@ -1134,19 +1158,19 @@ svn_ra_local__get_log(svn_ra_session_t *session, receiver = log_receiver_wrapper; receiver_baton = &lb; - return svn_repos_get_logs4(sess->repos, - abs_paths, - start, - end, - limit, - discover_changed_paths, - strict_node_history, - include_merged_revisions, - revprops, - NULL, NULL, - receiver, - receiver_baton, - pool); + return svn_repos__get_logs_compat(sess->repos, + abs_paths, + start, + end, + limit, + discover_changed_paths, + strict_node_history, + include_merged_revisions, + revprops, + NULL, NULL, + receiver, + receiver_baton, + pool); } @@ -1362,8 +1386,8 @@ svn_ra_local__get_dir(svn_ra_session_t *session, if (dirent_fields & SVN_DIRENT_SIZE) { /* size */ - if (entry->kind == svn_node_dir) - entry->size = 0; + if (fs_entry->kind == svn_node_dir) + entry->size = SVN_INVALID_FILESIZE; else SVN_ERR(svn_fs_file_length(&(entry->size), root, fullpath, iterpool)); @@ -1648,6 +1672,7 @@ svn_ra_local__has_capability(svn_ra_session_t *session, || strcmp(capability, SVN_RA_CAPABILITY_INHERITED_PROPS) == 0 || strcmp(capability, SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS) == 0 || strcmp(capability, SVN_RA_CAPABILITY_GET_FILE_REVS_REVERSE) == 0 + || strcmp(capability, SVN_RA_CAPABILITY_LIST) == 0 ) { *has = TRUE; @@ -1700,23 +1725,13 @@ svn_ra_local__get_inherited_props(svn_ra_session_t *session, apr_pool_t *scratch_pool) { svn_fs_root_t *root; - svn_revnum_t youngest_rev; svn_ra_local__session_baton_t *sess = session->priv; const char *abs_path = svn_fspath__join(sess->fs_path->data, path, scratch_pool); svn_node_kind_t node_kind; /* Open the revision's root. */ - if (! SVN_IS_VALID_REVNUM(revision)) - { - SVN_ERR(svn_fs_youngest_rev(&youngest_rev, sess->fs, scratch_pool)); - SVN_ERR(svn_fs_revision_root(&root, sess->fs, youngest_rev, - scratch_pool)); - } - else - { - SVN_ERR(svn_fs_revision_root(&root, sess->fs, revision, scratch_pool)); - } + SVN_ERR(svn_fs_revision_root(&root, sess->fs, revision, scratch_pool)); SVN_ERR(svn_fs_check_path(&node_kind, root, abs_path, scratch_pool)); if (node_kind == svn_node_none) @@ -1800,6 +1815,54 @@ svn_ra_local__get_commit_ev2(svn_editor_t **editor, result_pool, scratch_pool)); } +/* Trivially forward repos-layer callbacks to RA-layer callbacks. + * Their signatures are the same. */ +typedef struct dirent_receiver_baton_t +{ + svn_ra_dirent_receiver_t receiver; + void *receiver_baton; +} dirent_receiver_baton_t; + +static svn_error_t * +dirent_receiver(const char *rel_path, + svn_dirent_t *dirent, + void *baton, + apr_pool_t *pool) +{ + dirent_receiver_baton_t *b = baton; + return b->receiver(rel_path, dirent, b->receiver_baton, pool); +} + +static svn_error_t * +svn_ra_local__list(svn_ra_session_t *session, + const char *path, + svn_revnum_t revision, + const apr_array_header_t *patterns, + svn_depth_t depth, + apr_uint32_t dirent_fields, + svn_ra_dirent_receiver_t receiver, + void *receiver_baton, + apr_pool_t *pool) +{ + svn_ra_local__session_baton_t *sess = session->priv; + svn_fs_root_t *root; + svn_boolean_t path_info_only = (dirent_fields & ~SVN_DIRENT_KIND) == 0; + + dirent_receiver_baton_t baton; + baton.receiver = receiver; + baton.receiver_baton = receiver_baton; + + SVN_ERR(svn_fs_revision_root(&root, sess->fs, revision, pool)); + path = svn_dirent_join(sess->fs_path->data, path, pool); + return svn_error_trace(svn_repos_list(root, path, patterns, depth, + path_info_only, NULL, NULL, + dirent_receiver, &baton, + sess->callbacks + ? sess->callbacks->cancel_func + : NULL, + sess->callback_baton, pool)); +} + /*----------------------------------------------------------------*/ static const svn_version_t * @@ -1848,9 +1911,12 @@ static const svn_ra__vtable_t ra_local_vtable = svn_ra_local__has_capability, svn_ra_local__replay_range, svn_ra_local__get_deleted_rev, - svn_ra_local__register_editor_shim_callbacks, svn_ra_local__get_inherited_props, - svn_ra_local__get_commit_ev2 + NULL /* set_svn_ra_open */, + svn_ra_local__list , + svn_ra_local__register_editor_shim_callbacks, + svn_ra_local__get_commit_ev2, + NULL /* replay_range_ev2 */ }; @@ -1883,7 +1949,7 @@ svn_ra_local__init(const svn_version_t *loader_version, SVN_ERR(svn_ver_check_list2(ra_local_version(), checklist, svn_ver_equal)); -#ifndef SVN_LIBSVN_CLIENT_LINKS_RA_LOCAL +#ifndef SVN_LIBSVN_RA_LINKS_RA_LOCAL /* This means the library was loaded as a DSO, so use the DSO pool. */ SVN_ERR(svn_fs_initialize(svn_dso__pool())); #endif diff --git a/subversion/libsvn_ra_serf/README b/subversion/libsvn_ra_serf/README deleted file mode 100644 index 98a48a636af8..000000000000 --- a/subversion/libsvn_ra_serf/README +++ /dev/null @@ -1,84 +0,0 @@ -ra_serf status -============== - -This library is an RA-layer implementation of a WebDAV client that uses Serf. - -Serf's homepage is at: - http://code.google.com/p/serf/ - -The latest serf releases can be fetched at: - http://code.google.com/p/serf/downloads/list - -The latest serf sources can be fetched via SVN at: - http://serf.googlecode.com/svn/trunk/ - -ra_serf can be enabled with the following configure flags: - "--with-serf=/path/to/serf/install" -As Neon is currently Subversion's default RA DAV layer, you also need -to add "http-library = serf" to your ~/.subversion/servers file to -choose ra_serf at runtime. Alternately, you can build with only -support for ra_serf: - "--without-neon --with-serf=/path/to/serf/install" - -For more about how ra_serf/ra_neon talk WebDAV, consult notes/webdav-protocol. - -Working copies are interchangeable between ra_serf and ra_neon. (They both use -the svn:wc:ra_dav:version-url property to store the latest revision of a file.) - -Completed tasks ---------------- -- Core functionality complete (see regression test status below) -- https support (SSL) -- Basic authentication -- Update parallelization/pipelining (also for status/diff/switch/etc) - - Does not require inline base64-encoding of content - - 4 connections are open on an update (matches browser's default behavior) - - 1 connection is used for the REPORT; 3 are used to fetch files & props -- Supports http-compression config flag -- SSL client and server certificates -- Proxy support -- NTLM/SSPI integration for Windows folks -- REPORT body buckets can now be read twice (#3212) - -Regression test status ----------------------- -All current regression tests are known to pass on: - - Debian/AMD64 with APR 1.3.x - - Mac OS X - - Solaris - - Windows - -Things to do before the next release (1.6.x timeframe) ------------------------------------------------------- - -- Digest authentication - -- Fix the editor API violation (TBC, #2932) - -Nice to haves -------------- - -- Move some of the code from ra_serf into serf. Serf doesn't have a very - high-level API; but the code in util.c can go a long way towards that. - -- Commit parallellization/pipelining - - Determine how to use HTTP pipelining and multiple connections for commit - - May need response from CHECKOUT to issue PUT/PROPPATCH - - ra_svn has a custom commit pipelining that may be worth investigating too - -- Use PROPFIND Depth: 1 when we are adding a directory locally to skip - fetching properties on files - -- Discover server's keep-alive setting via OPTIONS requests and notify serf - -- Fix bug in mod_dav_svn that omits remove-prop in the update-report when a - lock is broken and send-all is false. - (See upd_change_xxx_prop in mod_dav_svn/update.c) - -- Fix bug in mod_dav_svn/mod_deflate that causes it to hold onto the entire - REPORT response until it is completed. (This is why ra_serf doesn't request - gzip compression on the REPORT requests.) - -- Remove remaining abort()s - ;-) aka add better debug logging - -- Support for HTTP/1.0 pnly proxies. diff --git a/subversion/libsvn_ra_serf/blame.c b/subversion/libsvn_ra_serf/blame.c index d915a19104cd..3ea45ed20dfb 100644 --- a/subversion/libsvn_ra_serf/blame.c +++ b/subversion/libsvn_ra_serf/blame.c @@ -81,6 +81,8 @@ typedef struct blame_context_t { svn_stream_t *stream; + svn_ra_serf__session_t *session; + } blame_context_t; @@ -318,6 +320,20 @@ create_file_revs_body(serf_bucket_t **body_bkt, return SVN_NO_ERROR; } +/* Implements svn_ra_serf__request_header_delegate_t */ +static svn_error_t * +setup_headers(serf_bucket_t *headers, + void *baton, + apr_pool_t *request_pool, + apr_pool_t *scratch_pool) +{ + blame_context_t *blame_ctx = baton; + + svn_ra_serf__setup_svndiff_accept_encoding(headers, blame_ctx->session); + + return SVN_NO_ERROR; +} + svn_error_t * svn_ra_serf__get_file_revs(svn_ra_session_t *ra_session, const char *path, @@ -343,6 +359,7 @@ svn_ra_serf__get_file_revs(svn_ra_session_t *ra_session, blame_ctx->start = start; blame_ctx->end = end; blame_ctx->include_merged_revisions = include_merged_revisions; + blame_ctx->session = session; /* Since Subversion 1.8 we allow retrieving blames backwards. So we can't just unconditionally use end_rev as the peg revision as before */ @@ -369,6 +386,9 @@ svn_ra_serf__get_file_revs(svn_ra_session_t *ra_session, handler->body_type = "text/xml"; handler->body_delegate = create_file_revs_body; handler->body_delegate_baton = blame_ctx; + handler->custom_accept_encoding = TRUE; + handler->header_delegate = setup_headers; + handler->header_delegate_baton = blame_ctx; SVN_ERR(svn_ra_serf__context_run_one(handler, pool)); diff --git a/subversion/libsvn_ra_serf/commit.c b/subversion/libsvn_ra_serf/commit.c index b1e81c7870e3..63a6f0bfa45b 100644 --- a/subversion/libsvn_ra_serf/commit.c +++ b/subversion/libsvn_ra_serf/commit.c @@ -71,6 +71,7 @@ typedef struct commit_context_t { const char *checked_in_url; /* checked-in root to base CHECKOUTs from */ const char *vcc_url; /* vcc url */ + int open_batons; /* Number of open batons */ } commit_context_t; #define USING_HTTPV2_COMMIT_SUPPORT(commit_ctx) ((commit_ctx)->txn_url != NULL) @@ -117,9 +118,6 @@ typedef struct dir_context_t { HTTP v2, for PROPPATCH in HTTP v2). */ const char *url; - /* How many pending changes we have left in this directory. */ - unsigned int ref_count; - /* Is this directory being added? (Otherwise, just opened.) */ svn_boolean_t added; @@ -172,11 +170,14 @@ typedef struct file_context_t { const char *copy_path; svn_revnum_t copy_revision; - /* stream */ + /* Stream for collecting the svndiff. */ svn_stream_t *stream; - /* Temporary file containing the svndiff. */ - apr_file_t *svndiff; + /* Buffer holding the svndiff (can spill to disk). */ + svn_ra_serf__request_body_t *svndiff; + + /* Did we send the svndiff in apply_textdelta_stream()? */ + svn_boolean_t svndiff_sent; /* Our base checksum as reported by the WC. */ const char *base_checksum; @@ -184,6 +185,9 @@ typedef struct file_context_t { /* Our resulting checksum as reported by the WC. */ const char *result_checksum; + /* Our resulting checksum as reported by the server. */ + svn_checksum_t *remote_result_checksum; + /* Changed properties (const char * -> svn_prop_t *) */ apr_hash_t *prop_changes; @@ -683,7 +687,7 @@ maybe_set_lock_token_header(serf_bucket_t *headers, { const char *token; - if (! (*relpath && commit_ctx->lock_tokens)) + if (! commit_ctx->lock_tokens) return SVN_NO_ERROR; if (! svn_hash_gets(commit_ctx->deleted_entries, relpath)) @@ -869,35 +873,6 @@ proppatch_resource(svn_ra_serf__session_t *session, return svn_error_trace(err); } -/* Implements svn_ra_serf__request_body_delegate_t */ -static svn_error_t * -create_put_body(serf_bucket_t **body_bkt, - void *baton, - serf_bucket_alloc_t *alloc, - apr_pool_t *pool /* request pool */, - apr_pool_t *scratch_pool) -{ - file_context_t *ctx = baton; - apr_off_t offset; - - /* We need to flush the file, make it unbuffered (so that it can be - * zero-copied via mmap), and reset the position before attempting to - * deliver the file. - * - * N.B. If we have APR 1.3+, we can unbuffer the file to let us use mmap - * and zero-copy the PUT body. However, on older APR versions, we can't - * check the buffer status; but serf will fall through and create a file - * bucket for us on the buffered svndiff handle. - */ - SVN_ERR(svn_io_file_flush(ctx->svndiff, pool)); - apr_file_buffer_set(ctx->svndiff, NULL, 0); - offset = 0; - SVN_ERR(svn_io_file_seek(ctx->svndiff, APR_SET, &offset, pool)); - - *body_bkt = serf_bucket_file_create(ctx->svndiff, alloc); - return SVN_NO_ERROR; -} - /* Implements svn_ra_serf__request_body_delegate_t */ static svn_error_t * create_empty_put_body(serf_bucket_t **body_bkt, @@ -1259,6 +1234,8 @@ open_root(void *edit_baton, const char *proppatch_target = NULL; apr_pool_t *scratch_pool = svn_pool_create(dir_pool); + commit_ctx->open_batons++; + if (SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(commit_ctx->session)) { post_response_ctx_t *prc; @@ -1545,6 +1522,8 @@ add_directory(const char *path, dir->name = svn_relpath_basename(dir->relpath, NULL); dir->prop_changes = apr_hash_make(dir->pool); + dir->commit_ctx->open_batons++; + if (USING_HTTPV2_COMMIT_SUPPORT(dir->commit_ctx)) { dir->url = svn_path_url_add_component2(parent->commit_ctx->txn_root_url, @@ -1635,6 +1614,8 @@ open_directory(const char *path, dir->name = svn_relpath_basename(dir->relpath, NULL); dir->prop_changes = apr_hash_make(dir->pool); + dir->commit_ctx->open_batons++; + if (USING_HTTPV2_COMMIT_SUPPORT(dir->commit_ctx)) { dir->url = svn_path_url_add_component2(parent->commit_ctx->txn_root_url, @@ -1713,6 +1694,8 @@ close_directory(void *dir_baton, proppatch_ctx, dir->pool)); } + dir->commit_ctx->open_batons--; + return SVN_NO_ERROR; } @@ -1732,8 +1715,6 @@ add_file(const char *path, new_file = apr_pcalloc(file_pool, sizeof(*new_file)); new_file->pool = file_pool; - dir->ref_count++; - new_file->parent_dir = dir; new_file->commit_ctx = dir->commit_ctx; new_file->relpath = apr_pstrdup(new_file->pool, path); @@ -1744,6 +1725,8 @@ add_file(const char *path, new_file->copy_revision = copy_revision; new_file->prop_changes = apr_hash_make(new_file->pool); + dir->commit_ctx->open_batons++; + /* Ensure that the file doesn't exist by doing a HEAD on the resource. If we're using HTTP v2, we'll just look into the transaction root tree for this thing. */ @@ -1854,8 +1837,6 @@ open_file(const char *path, new_file = apr_pcalloc(file_pool, sizeof(*new_file)); new_file->pool = file_pool; - parent->ref_count++; - new_file->parent_dir = parent; new_file->commit_ctx = parent->commit_ctx; new_file->relpath = apr_pstrdup(new_file->pool, path); @@ -1864,6 +1845,8 @@ open_file(const char *path, new_file->base_revision = base_revision; new_file->prop_changes = apr_hash_make(new_file->pool); + parent->commit_ctx->open_batons++; + if (USING_HTTPV2_COMMIT_SUPPORT(parent->commit_ctx)) { new_file->url = svn_path_url_add_component2(parent->commit_ctx->txn_root_url, @@ -1882,21 +1865,73 @@ open_file(const char *path, return SVN_NO_ERROR; } -/* Implements svn_stream_lazyopen_func_t for apply_textdelta */ -static svn_error_t * -delayed_commit_stream_open(svn_stream_t **stream, - void *baton, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) +static void +negotiate_put_encoding(int *svndiff_version_p, + int *svndiff_compression_level_p, + svn_ra_serf__session_t *session) { - file_context_t *file_ctx = baton; + int svndiff_version; + int compression_level; - SVN_ERR(svn_io_open_unique_file3(&file_ctx->svndiff, NULL, NULL, - svn_io_file_del_on_pool_cleanup, - file_ctx->pool, scratch_pool)); + if (session->using_compression == svn_tristate_unknown) + { + /* With http-compression=auto, prefer svndiff2 to svndiff1 with a + * low latency connection (assuming the underlying network has high + * bandwidth), as it is faster and in this case, we don't care about + * worse compression ratio. + * + * Note: For future compatibility, we also handle a theoretically + * possible case where the server has advertised only svndiff2 support. + */ + if (session->supports_svndiff2 && + svn_ra_serf__is_low_latency_connection(session)) + svndiff_version = 2; + else if (session->supports_svndiff1) + svndiff_version = 1; + else if (session->supports_svndiff2) + svndiff_version = 2; + else + svndiff_version = 0; + } + else if (session->using_compression == svn_tristate_true) + { + /* Otherwise, prefer svndiff1, as svndiff2 is not a reasonable + * substitute for svndiff1 with default compression level. (It gives + * better speed and compression ratio comparable to svndiff1 with + * compression level 1, but not 5). + * + * Note: For future compatibility, we also handle a theoretically + * possible case where the server has advertised only svndiff2 support. + */ + if (session->supports_svndiff1) + svndiff_version = 1; + else if (session->supports_svndiff2) + svndiff_version = 2; + else + svndiff_version = 0; + } + else + { + /* Difference between svndiff formats 0 and 1/2 that format 1/2 allows + * compression. Uncompressed svndiff0 should also be slightly more + * effective if the compression is not required at all. + * + * If the server cannot handle svndiff1/2, or compression is disabled + * with the 'http-compression = no' client configuration option, fall + * back to uncompressed svndiff0 format. As a bonus, users can force + * the usage of the uncompressed format by setting the corresponding + * client configuration option, if they want to. + */ + svndiff_version = 0; + } - *stream = svn_stream_from_aprfile2(file_ctx->svndiff, TRUE, result_pool); - return SVN_NO_ERROR; + if (svndiff_version == 0) + compression_level = SVN_DELTA_COMPRESSION_LEVEL_NONE; + else + compression_level = SVN_DELTA_COMPRESSION_LEVEL_DEFAULT; + + *svndiff_version_p = svndiff_version; + *svndiff_compression_level_p = compression_level; } static svn_error_t * @@ -1907,21 +1942,31 @@ apply_textdelta(void *file_baton, void **handler_baton) { file_context_t *ctx = file_baton; + int svndiff_version; + int compression_level; - /* Store the stream in a temporary file; we'll give it to serf when we + /* Construct a holder for the request body; we'll give it to serf when we * close this file. * - * TODO: There should be a way we can stream the request body instead of - * writing to a temporary file (ugh). A special svn stream serf bucket - * that returns EAGAIN until we receive the done call? But, when - * would we run through the serf context? Grr. + * Please note that if this callback is used, large request bodies will + * be spilled into temporary files (that requires disk space and prevents + * simultaneous processing by the server and the client). A better approach + * that streams the request body is implemented in apply_textdelta_stream(). + * It will be used with most recent servers having the "send result checksum + * in response to a PUT" capability, and only if the editor driver uses the + * new callback. */ + ctx->svndiff = + svn_ra_serf__request_body_create(SVN_RA_SERF__REQUEST_BODY_IN_MEM_SIZE, + ctx->pool); + ctx->stream = svn_ra_serf__request_body_get_stream(ctx->svndiff); - ctx->stream = svn_stream_lazyopen_create(delayed_commit_stream_open, - ctx, FALSE, ctx->pool); - - svn_txdelta_to_svndiff3(handler, handler_baton, ctx->stream, 0, - SVN_DELTA_COMPRESSION_LEVEL_DEFAULT, pool); + negotiate_put_encoding(&svndiff_version, &compression_level, + ctx->commit_ctx->session); + /* Disown the stream; we'll close it explicitly in close_file(). */ + svn_txdelta_to_svndiff3(handler, handler_baton, + svn_stream_disown(ctx->stream, pool), + svndiff_version, compression_level, pool); if (base_checksum) ctx->base_checksum = apr_pstrdup(ctx->pool, base_checksum); @@ -1929,6 +1974,146 @@ apply_textdelta(void *file_baton, return SVN_NO_ERROR; } +typedef struct open_txdelta_baton_t +{ + svn_ra_serf__session_t *session; + svn_txdelta_stream_open_func_t open_func; + void *open_baton; + svn_error_t *err; +} open_txdelta_baton_t; + +static void +txdelta_stream_errfunc(void *baton, svn_error_t *err) +{ + open_txdelta_baton_t *b = baton; + + /* Remember extended error info from the stream bucket. Note that + * theoretically this errfunc could be called multiple times -- say, + * if the request gets restarted after an error. Compose the errors + * so we don't leak one of them if this happens. */ + b->err = svn_error_compose_create(b->err, svn_error_dup(err)); +} + +/* Implements svn_ra_serf__request_body_delegate_t */ +static svn_error_t * +create_body_from_txdelta_stream(serf_bucket_t **body_bkt, + void *baton, + serf_bucket_alloc_t *alloc, + apr_pool_t *pool /* request pool */, + apr_pool_t *scratch_pool) +{ + open_txdelta_baton_t *b = baton; + svn_txdelta_stream_t *txdelta_stream; + svn_stream_t *stream; + int svndiff_version; + int compression_level; + + SVN_ERR(b->open_func(&txdelta_stream, b->open_baton, pool, scratch_pool)); + + negotiate_put_encoding(&svndiff_version, &compression_level, b->session); + stream = svn_txdelta_to_svndiff_stream(txdelta_stream, svndiff_version, + compression_level, pool); + *body_bkt = svn_ra_serf__create_stream_bucket(stream, alloc, + txdelta_stream_errfunc, b); + + return SVN_NO_ERROR; +} + +/* Handler baton for PUT request. */ +typedef struct put_response_ctx_t +{ + svn_ra_serf__handler_t *handler; + file_context_t *file_ctx; +} put_response_ctx_t; + +/* Implements svn_ra_serf__response_handler_t */ +static svn_error_t * +put_response_handler(serf_request_t *request, + serf_bucket_t *response, + void *baton, + apr_pool_t *scratch_pool) +{ + put_response_ctx_t *prc = baton; + serf_bucket_t *hdrs; + const char *val; + + hdrs = serf_bucket_response_get_headers(response); + val = serf_bucket_headers_get(hdrs, SVN_DAV_RESULT_FULLTEXT_MD5_HEADER); + SVN_ERR(svn_checksum_parse_hex(&prc->file_ctx->remote_result_checksum, + svn_checksum_md5, val, prc->file_ctx->pool)); + + return svn_error_trace( + svn_ra_serf__expect_empty_body(request, response, + prc->handler, scratch_pool)); +} + +static svn_error_t * +apply_textdelta_stream(const svn_delta_editor_t *editor, + void *file_baton, + const char *base_checksum, + svn_txdelta_stream_open_func_t open_func, + void *open_baton, + apr_pool_t *scratch_pool) +{ + file_context_t *ctx = file_baton; + open_txdelta_baton_t open_txdelta_baton = {0}; + svn_ra_serf__handler_t *handler; + put_response_ctx_t *prc; + int expected_result; + svn_error_t *err; + + /* Remember that we have sent the svndiff. A case when we need to + * perform a zero-byte file PUT (during add_file, close_file editor + * sequences) is handled in close_file(). + */ + ctx->svndiff_sent = TRUE; + ctx->base_checksum = base_checksum; + + handler = svn_ra_serf__create_handler(ctx->commit_ctx->session, + scratch_pool); + handler->method = "PUT"; + handler->path = ctx->url; + + prc = apr_pcalloc(scratch_pool, sizeof(*prc)); + prc->handler = handler; + prc->file_ctx = ctx; + + handler->response_handler = put_response_handler; + handler->response_baton = prc; + + open_txdelta_baton.session = ctx->commit_ctx->session; + open_txdelta_baton.open_func = open_func; + open_txdelta_baton.open_baton = open_baton; + open_txdelta_baton.err = SVN_NO_ERROR; + + handler->body_delegate = create_body_from_txdelta_stream; + handler->body_delegate_baton = &open_txdelta_baton; + handler->body_type = SVN_SVNDIFF_MIME_TYPE; + + handler->header_delegate = setup_put_headers; + handler->header_delegate_baton = ctx; + + err = svn_ra_serf__context_run_one(handler, scratch_pool); + /* Do we have an error from the stream bucket? If yes, use it. */ + if (open_txdelta_baton.err) + { + svn_error_clear(err); + return svn_error_trace(open_txdelta_baton.err); + } + else if (err) + return svn_error_trace(err); + + if (ctx->added && !ctx->copy_path) + expected_result = 201; /* Created */ + else + expected_result = 204; /* Updated */ + + if (handler->sline.code != expected_result) + return svn_error_trace(svn_ra_serf__unexpected_status(handler)); + + return SVN_NO_ERROR; +} + static svn_error_t * change_file_prop(void *file_baton, const char *name, @@ -1964,8 +2149,8 @@ close_file(void *file_baton, if ((!ctx->svndiff) && ctx->added && (!ctx->copy_path)) put_empty_file = TRUE; - /* If we had a stream of changes, push them to the server... */ - if (ctx->svndiff || put_empty_file) + /* If we have a stream of changes, push them to the server... */ + if ((ctx->svndiff || put_empty_file) && !ctx->svndiff_sent) { svn_ra_serf__handler_t *handler; int expected_result; @@ -1987,8 +2172,11 @@ close_file(void *file_baton, } else { - handler->body_delegate = create_put_body; - handler->body_delegate_baton = ctx; + SVN_ERR(svn_stream_close(ctx->stream)); + + svn_ra_serf__request_body_get_delegate(&handler->body_delegate, + &handler->body_delegate_baton, + ctx->svndiff); handler->body_type = SVN_SVNDIFF_MIME_TYPE; } @@ -2006,8 +2194,9 @@ close_file(void *file_baton, return svn_error_trace(svn_ra_serf__unexpected_status(handler)); } + /* Don't keep open file handles longer than necessary. */ if (ctx->svndiff) - SVN_ERR(svn_io_file_close(ctx->svndiff, scratch_pool)); + SVN_ERR(svn_ra_serf__request_body_cleanup(ctx->svndiff, scratch_pool)); /* If we had any prop changes, push them via PROPPATCH. */ if (apr_hash_count(ctx->prop_changes)) @@ -2026,6 +2215,24 @@ close_file(void *file_baton, proppatch, scratch_pool)); } + if (ctx->result_checksum && ctx->remote_result_checksum) + { + svn_checksum_t *result_checksum; + + SVN_ERR(svn_checksum_parse_hex(&result_checksum, svn_checksum_md5, + ctx->result_checksum, scratch_pool)); + + if (!svn_checksum_match(result_checksum, ctx->remote_result_checksum)) + return svn_checksum_mismatch_err(result_checksum, + ctx->remote_result_checksum, + scratch_pool, + _("Checksum mismatch for '%s'"), + svn_dirent_local_style(ctx->relpath, + scratch_pool)); + } + + ctx->commit_ctx->open_batons--; + return SVN_NO_ERROR; } @@ -2039,6 +2246,11 @@ close_edit(void *edit_baton, const svn_commit_info_t *commit_info; svn_error_t *err = NULL; + if (ctx->open_batons > 0) + return svn_error_create( + SVN_ERR_FS_INCORRECT_EDITOR_COMPLETION, NULL, + _("Closing editor with directories or files open")); + /* MERGE our activity */ SVN_ERR(svn_ra_serf__run_merge(&commit_info, ctx->session, @@ -2194,6 +2406,12 @@ svn_ra_serf__get_commit_editor(svn_ra_session_t *ra_session, editor->close_file = close_file; editor->close_edit = close_edit; editor->abort_edit = abort_edit; + /* Only install the callback that allows streaming PUT request bodies + * if the server has the necessary capability. Otherwise, this will + * fallback to the default implementation using the temporary files. + * See default_editor.c:apply_textdelta_stream(). */ + if (session->supports_put_result_checksum) + editor->apply_textdelta_stream = apply_textdelta_stream; *ret_editor = editor; *edit_baton = ctx; diff --git a/subversion/libsvn_ra_serf/eagain_bucket.c b/subversion/libsvn_ra_serf/eagain_bucket.c index 16387be91b9d..da9b127d3a3d 100644 --- a/subversion/libsvn_ra_serf/eagain_bucket.c +++ b/subversion/libsvn_ra_serf/eagain_bucket.c @@ -66,7 +66,7 @@ eagain_bucket_read(serf_bucket_t *bucket, return APR_EAGAIN; } - +#if !SERF_VERSION_AT_LEAST(1, 4, 0) static apr_status_t eagain_bucket_readline(serf_bucket_t *bucket, int acceptable, @@ -79,6 +79,7 @@ eagain_bucket_readline(serf_bucket_t *bucket, "Not implemented.")); return APR_ENOTIMPL; } +#endif static apr_status_t @@ -98,7 +99,11 @@ eagain_bucket_peek(serf_bucket_t *bucket, static const serf_bucket_type_t delay_bucket_vtable = { "BUF-EAGAIN", eagain_bucket_read, +#if SERF_VERSION_AT_LEAST(1, 4, 0) + serf_default_readline, +#else eagain_bucket_readline, +#endif serf_default_read_iovec, serf_default_read_for_sendfile, serf_default_read_bucket, diff --git a/subversion/libsvn_ra_serf/get_file.c b/subversion/libsvn_ra_serf/get_file.c index cb63b7dd438b..aee89453dce6 100644 --- a/subversion/libsvn_ra_serf/get_file.c +++ b/subversion/libsvn_ra_serf/get_file.c @@ -60,7 +60,7 @@ typedef struct stream_ctx_t { /* Have we read our response headers yet? */ svn_boolean_t read_headers; - svn_boolean_t using_compression; + svn_ra_serf__session_t *session; /* This flag is set when our response is aborted before we reach the * end and we decide to requeue this request. @@ -88,7 +88,7 @@ headers_fetch(serf_bucket_t *headers, { stream_ctx_t *fetch_ctx = baton; - if (fetch_ctx->using_compression) + if (fetch_ctx->session->using_compression != svn_tristate_false) { serf_bucket_headers_setn(headers, "Accept-Encoding", "gzip"); } @@ -321,17 +321,19 @@ svn_ra_serf__get_file(svn_ra_session_t *ra_session, svn_stream_t *stream, svn_revnum_t *fetched_rev, apr_hash_t **props, - apr_pool_t *pool) + apr_pool_t *result_pool) { svn_ra_serf__session_t *session = ra_session->priv; const char *fetch_url; const svn_ra_serf__dav_props_t *which_props; svn_ra_serf__handler_t *propfind_handler; + apr_pool_t *scratch_pool = svn_pool_create(result_pool); struct file_prop_baton_t fb; /* Fetch properties. */ - fetch_url = svn_path_url_add_component2(session->session_url.path, path, pool); + fetch_url = svn_path_url_add_component2(session->session_url.path, path, + scratch_pool); /* The simple case is if we want HEAD - then a GET on the fetch_url is fine. * @@ -343,7 +345,7 @@ svn_ra_serf__get_file(svn_ra_session_t *ra_session, SVN_ERR(svn_ra_serf__get_stable_url(&fetch_url, fetched_rev, session, fetch_url, revision, - pool, pool)); + scratch_pool, scratch_pool)); revision = SVN_INVALID_REVNUM; } /* REVISION is always SVN_INVALID_REVNUM */ @@ -356,8 +358,8 @@ svn_ra_serf__get_file(svn_ra_session_t *ra_session, else which_props = check_path_props; - fb.result_pool = pool; - fb.props = props ? apr_hash_make(pool) : NULL; + fb.result_pool = result_pool; + fb.props = props ? apr_hash_make(result_pool) : NULL; fb.kind = svn_node_unknown; fb.sha1_checksum = NULL; @@ -365,9 +367,9 @@ svn_ra_serf__get_file(svn_ra_session_t *ra_session, fetch_url, SVN_INVALID_REVNUM, "0", which_props, get_file_prop_cb, &fb, - pool)); + scratch_pool)); - SVN_ERR(svn_ra_serf__context_run_one(propfind_handler, pool)); + SVN_ERR(svn_ra_serf__context_run_one(propfind_handler, scratch_pool)); /* Verify that resource type is not collection. */ if (fb.kind != svn_node_file) @@ -382,7 +384,8 @@ svn_ra_serf__get_file(svn_ra_session_t *ra_session, if (stream) { svn_boolean_t found; - SVN_ERR(try_get_wc_contents(&found, session, fb.sha1_checksum, stream, pool)); + SVN_ERR(try_get_wc_contents(&found, session, fb.sha1_checksum, stream, + scratch_pool)); /* No contents found in the WC, let's fetch from server. */ if (!found) @@ -391,11 +394,11 @@ svn_ra_serf__get_file(svn_ra_session_t *ra_session, svn_ra_serf__handler_t *handler; /* Create the fetch context. */ - stream_ctx = apr_pcalloc(pool, sizeof(*stream_ctx)); + stream_ctx = apr_pcalloc(scratch_pool, sizeof(*stream_ctx)); stream_ctx->result_stream = stream; - stream_ctx->using_compression = session->using_compression; + stream_ctx->session = session; - handler = svn_ra_serf__create_handler(session, pool); + handler = svn_ra_serf__create_handler(session, scratch_pool); handler->method = "GET"; handler->path = fetch_url; @@ -414,12 +417,14 @@ svn_ra_serf__get_file(svn_ra_session_t *ra_session, stream_ctx->handler = handler; - SVN_ERR(svn_ra_serf__context_run_one(handler, pool)); + SVN_ERR(svn_ra_serf__context_run_one(handler, scratch_pool)); if (handler->sline.code != 200) return svn_error_trace(svn_ra_serf__unexpected_status(handler)); } } + svn_pool_destroy(scratch_pool); + return SVN_NO_ERROR; } diff --git a/subversion/libsvn_ra_serf/getlocations.c b/subversion/libsvn_ra_serf/getlocations.c index 063272ec3c68..ea25c598c385 100644 --- a/subversion/libsvn_ra_serf/getlocations.c +++ b/subversion/libsvn_ra_serf/getlocations.c @@ -193,9 +193,8 @@ svn_ra_serf__get_locations(svn_ra_session_t *ra_session, SVN_ERR(svn_ra_serf__context_run_one(handler, pool)); - SVN_ERR(svn_ra_serf__error_on_status(handler->sline, - handler->path, - handler->location)); + if (handler->sline.code != 200) + SVN_ERR(svn_ra_serf__unexpected_status(handler)); return SVN_NO_ERROR; } diff --git a/subversion/libsvn_ra_serf/getlocationsegments.c b/subversion/libsvn_ra_serf/getlocationsegments.c index 884ab5daa5b4..cf1f23899291 100644 --- a/subversion/libsvn_ra_serf/getlocationsegments.c +++ b/subversion/libsvn_ra_serf/getlocationsegments.c @@ -196,12 +196,8 @@ svn_ra_serf__get_location_segments(svn_ra_session_t *ra_session, err = svn_ra_serf__context_run_one(handler, pool); - if (!err) - { - err = svn_ra_serf__error_on_status(handler->sline, - handler->path, - handler->location); - } + if (!err && handler->sline.code != 200) + err = svn_ra_serf__unexpected_status(handler); if (err && (err->apr_err == SVN_ERR_UNSUPPORTED_FEATURE)) return svn_error_create(SVN_ERR_RA_NOT_IMPLEMENTED, err, NULL); diff --git a/subversion/libsvn_ra_serf/libsvn_ra_serf.pc.in b/subversion/libsvn_ra_serf/libsvn_ra_serf.pc.in index e02ef12afb20..81285ed468d3 100644 --- a/subversion/libsvn_ra_serf/libsvn_ra_serf.pc.in +++ b/subversion/libsvn_ra_serf/libsvn_ra_serf.pc.in @@ -8,5 +8,5 @@ Description: Subversion HTTP/WebDAV Protocol Repository Access Library Version: @PACKAGE_VERSION@ Requires: apr-util-@SVN_APR_MAJOR_VERSION@ apr-@SVN_APR_MAJOR_VERSION@ Requires.private: libsvn_delta libsvn_subr serf-1 -Libs: -L${libdir} -lsvn_ra_serf @SVN_XML_LIBS@ @SVN_ZLIB_LIBS@ +Libs: -L${libdir} -lsvn_ra_serf @SVN_ZLIB_LIBS@ Cflags: -I${includedir} diff --git a/subversion/libsvn_ra_serf/list.c b/subversion/libsvn_ra_serf/list.c new file mode 100644 index 000000000000..722a946d3645 --- /dev/null +++ b/subversion/libsvn_ra_serf/list.c @@ -0,0 +1,301 @@ +/* + * list.c : entry point for the list RA function in ra_serf + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + + + + +#include +#include + +#include "svn_hash.h" +#include "svn_pools.h" +#include "svn_ra.h" +#include "svn_dav.h" +#include "svn_base64.h" +#include "svn_xml.h" +#include "svn_config.h" +#include "svn_path.h" +#include "svn_props.h" +#include "svn_time.h" + +#include "private/svn_dav_protocol.h" +#include "private/svn_string_private.h" +#include "private/svn_subr_private.h" +#include "svn_private_config.h" + +#include "ra_serf.h" +#include "../libsvn_ra/ra_loader.h" + + + +/* + * This enum represents the current state of our XML parsing for a REPORT. + */ +enum list_state_e { + INITIAL = XML_STATE_INITIAL, + REPORT, + ITEM, + AUTHOR +}; + +typedef struct list_context_t { + apr_pool_t *pool; + + /* parameters set by our caller */ + const char *path; + svn_revnum_t revision; + const apr_array_header_t *patterns; + svn_depth_t depth; + apr_uint32_t dirent_fields; + apr_array_header_t *props; + + /* Buffer the author info for the current item. + * We use the AUTHOR pointer to differentiate between 0-length author + * strings and missing / NULL authors. */ + const char *author; + svn_stringbuf_t *author_buf; + + /* log receiver function and baton */ + svn_ra_dirent_receiver_t receiver; + void *receiver_baton; +} list_context_t; + +#define D_ "DAV:" +#define S_ SVN_XML_NAMESPACE +static const svn_ra_serf__xml_transition_t log_ttable[] = { + { INITIAL, S_, "list-report", REPORT, + FALSE, { NULL }, FALSE }, + + { REPORT, S_, "item", ITEM, + TRUE, { "node-kind", "?size", "?has-props", "?created-rev", + "?date", NULL }, TRUE }, + + { ITEM, D_, "creator-displayname", AUTHOR, + TRUE, { "?encoding", NULL }, TRUE }, + + { 0 } +}; + +/* Conforms to svn_ra_serf__xml_closed_t */ +static svn_error_t * +item_closed(svn_ra_serf__xml_estate_t *xes, + void *baton, + int leaving_state, + const svn_string_t *cdata, + apr_hash_t *attrs, + apr_pool_t *scratch_pool) +{ + list_context_t *list_ctx = baton; + + if (leaving_state == AUTHOR) + { + /* For compatibility with liveprops, current servers will not use + * base64-encoding for "binary" user names bu simply drop the + * offending control chars. + * + * We might want to switch to revprop-style encoding, though, + * and this is the code to do that. */ + const char *encoding = svn_hash_gets(attrs, "encoding"); + if (encoding) + { + /* Check for a known encoding type. This is easy -- there's + only one. */ + if (strcmp(encoding, "base64") != 0) + { + return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL, + _("Unsupported encoding '%s'"), + encoding); + } + + cdata = svn_base64_decode_string(cdata, scratch_pool); + } + + /* Remember until the next ITEM closing tag. */ + svn_stringbuf_set(list_ctx->author_buf, cdata->data); + list_ctx->author = list_ctx->author_buf->data; + } + else if (leaving_state == ITEM) + { + const char *dirent_path = cdata->data; + const char *kind_word, *date, *crev, *size; + svn_dirent_t dirent = { 0 }; + + kind_word = svn_hash_gets(attrs, "node-kind"); + size = svn_hash_gets(attrs, "size"); + + dirent.has_props = svn_hash__get_bool(attrs, "has-props", FALSE); + crev = svn_hash_gets(attrs, "created-rev"); + date = svn_hash_gets(attrs, "date"); + + /* Convert data. */ + dirent.kind = svn_node_kind_from_word(kind_word); + + if (size) + SVN_ERR(svn_cstring_atoi64(&dirent.size, size)); + else + dirent.size = SVN_INVALID_FILESIZE; + + if (crev) + SVN_ERR(svn_revnum_parse(&dirent.created_rev, crev, NULL)); + else + dirent.created_rev = SVN_INVALID_REVNUM; + + if (date) + SVN_ERR(svn_time_from_cstring(&dirent.time, date, scratch_pool)); + + if (list_ctx->author) + dirent.last_author = list_ctx->author; + + /* Invoke RECEIVER */ + SVN_ERR(list_ctx->receiver(dirent_path, &dirent, + list_ctx->receiver_baton, scratch_pool)); + + /* Reset buffered info. */ + list_ctx->author = NULL; + } + + return SVN_NO_ERROR; +} + +/* Implements svn_ra_serf__request_body_delegate_t */ +static svn_error_t * +create_list_body(serf_bucket_t **body_bkt, + void *baton, + serf_bucket_alloc_t *alloc, + apr_pool_t *pool /* request pool */, + apr_pool_t *scratch_pool) +{ + serf_bucket_t *buckets; + list_context_t *list_ctx = baton; + int i; + + buckets = serf_bucket_aggregate_create(alloc); + + svn_ra_serf__add_open_tag_buckets(buckets, alloc, + "S:list-report", + "xmlns:S", SVN_XML_NAMESPACE, + SVN_VA_NULL); + + svn_ra_serf__add_tag_buckets(buckets, + "S:path", list_ctx->path, + alloc); + svn_ra_serf__add_tag_buckets(buckets, + "S:revision", + apr_ltoa(pool, list_ctx->revision), + alloc); + svn_ra_serf__add_tag_buckets(buckets, + "S:depth", svn_depth_to_word(list_ctx->depth), + alloc); + + if (list_ctx->patterns) + { + for (i = 0; i < list_ctx->patterns->nelts; i++) + { + char *name = APR_ARRAY_IDX(list_ctx->patterns, i, char *); + svn_ra_serf__add_tag_buckets(buckets, + "S:pattern", name, + alloc); + } + if (list_ctx->patterns->nelts == 0) + { + svn_ra_serf__add_empty_tag_buckets(buckets, alloc, + "S:no-patterns", SVN_VA_NULL); + } + } + + for (i = 0; i < list_ctx->props->nelts; i++) + { + const svn_ra_serf__dav_props_t *prop + = &APR_ARRAY_IDX(list_ctx->props, i, const svn_ra_serf__dav_props_t); + const char *name + = apr_pstrcat(pool, prop->xmlns, prop->name, SVN_VA_NULL); + + svn_ra_serf__add_tag_buckets(buckets, "S:prop", name, alloc); + } + + svn_ra_serf__add_close_tag_buckets(buckets, alloc, + "S:list-report"); + + *body_bkt = buckets; + return SVN_NO_ERROR; +} + + +svn_error_t * +svn_ra_serf__list(svn_ra_session_t *ra_session, + const char *path, + svn_revnum_t revision, + const apr_array_header_t *patterns, + svn_depth_t depth, + apr_uint32_t dirent_fields, + svn_ra_dirent_receiver_t receiver, + void *receiver_baton, + apr_pool_t *scratch_pool) +{ + list_context_t *list_ctx; + svn_ra_serf__session_t *session = ra_session->priv; + svn_ra_serf__handler_t *handler; + svn_ra_serf__xml_context_t *xmlctx; + const char *req_url; + + list_ctx = apr_pcalloc(scratch_pool, sizeof(*list_ctx)); + list_ctx->pool = scratch_pool; + list_ctx->receiver = receiver; + list_ctx->receiver_baton = receiver_baton; + list_ctx->path = path; + list_ctx->revision = revision; + list_ctx->patterns = patterns; + list_ctx->depth = depth; + list_ctx->dirent_fields = dirent_fields; + list_ctx->props = svn_ra_serf__get_dirent_props(dirent_fields, session, + scratch_pool); + list_ctx->author_buf = svn_stringbuf_create_empty(scratch_pool); + + /* At this point, we may have a deleted file. So, we'll match ra_neon's + * behavior and use the larger of start or end as our 'peg' rev. + */ + SVN_ERR(svn_ra_serf__get_stable_url(&req_url, NULL /* latest_revnum */, + session, + NULL /* url */, revision, + scratch_pool, scratch_pool)); + + xmlctx = svn_ra_serf__xml_context_create(log_ttable, + NULL, item_closed, NULL, + list_ctx, + scratch_pool); + handler = svn_ra_serf__create_expat_handler(session, xmlctx, NULL, + scratch_pool); + + handler->method = "REPORT"; + handler->path = req_url; + handler->body_delegate = create_list_body; + handler->body_delegate_baton = list_ctx; + handler->body_type = "text/xml"; + + SVN_ERR(svn_ra_serf__context_run_one(handler, scratch_pool)); + + if (handler->sline.code != 200) + SVN_ERR(svn_ra_serf__unexpected_status(handler)); + + return SVN_NO_ERROR; +} diff --git a/subversion/libsvn_ra_serf/lock.c b/subversion/libsvn_ra_serf/lock.c index dd045e3a1751..d303104b3684 100644 --- a/subversion/libsvn_ra_serf/lock.c +++ b/subversion/libsvn_ra_serf/lock.c @@ -267,10 +267,9 @@ run_locks(svn_ra_serf__session_t *sess, /* ### Authz can also lead to 403. */ err = svn_error_createf(SVN_ERR_FS_LOCK_OWNER_MISMATCH, NULL, - _("Unlock of '%s' failed (%d %s)"), - ctx->path, - ctx->handler->sline.code, - ctx->handler->sline.reason); + _("Not authorized to perform lock " + "operation on '%s'"), + ctx->path); break; case 405: err = svn_error_createf(SVN_ERR_FS_OUT_OF_DATE, @@ -282,13 +281,20 @@ run_locks(svn_ra_serf__session_t *sess, ctx->handler->sline.reason); break; case 423: - err = svn_error_createf(SVN_ERR_FS_PATH_ALREADY_LOCKED, - NULL, - _("Path '%s' already locked " - "(%d %s)"), - ctx->path, - ctx->handler->sline.code, - ctx->handler->sline.reason); + if (server_err + && SVN_ERROR_IN_CATEGORY(server_err->apr_err, + SVN_ERR_FS_CATEGORY_START)) + { + err = NULL; + } + else + err = svn_error_createf(SVN_ERR_FS_PATH_ALREADY_LOCKED, + NULL, + _("Path '%s' already locked " + "(%d %s)"), + ctx->path, + ctx->handler->sline.code, + ctx->handler->sline.reason); break; case 404: diff --git a/subversion/libsvn_ra_serf/log.c b/subversion/libsvn_ra_serf/log.c index 773ae5c9c162..fb9494aee10d 100644 --- a/subversion/libsvn_ra_serf/log.c +++ b/subversion/libsvn_ra_serf/log.c @@ -272,7 +272,7 @@ log_closed(svn_ra_serf__xml_estate_t *xes, svn_log_entry_t *log_entry; const char *rev_str; - if (log_ctx->limit && (log_ctx->nest_level == 0) + if ((log_ctx->limit > 0) && (log_ctx->nest_level == 0) && (++log_ctx->count > log_ctx->limit)) { return SVN_NO_ERROR; @@ -598,8 +598,8 @@ svn_ra_serf__get_log(svn_ra_session_t *ra_session, SVN_ERR(svn_ra_serf__context_run_one(handler, pool)); - return svn_error_trace( - svn_ra_serf__error_on_status(handler->sline, - req_url, - handler->location)); + if (handler->sline.code != 200) + SVN_ERR(svn_ra_serf__unexpected_status(handler)); + + return SVN_NO_ERROR; } diff --git a/subversion/libsvn_ra_serf/merge.c b/subversion/libsvn_ra_serf/merge.c index 0a2fd5465b59..227670b9a229 100644 --- a/subversion/libsvn_ra_serf/merge.c +++ b/subversion/libsvn_ra_serf/merge.c @@ -79,6 +79,7 @@ typedef struct merge_context_t apr_hash_t *lock_tokens; svn_boolean_t keep_locks; + svn_boolean_t disable_merge_response; const char *merge_resource_url; /* URL of resource to be merged. */ const char *merge_url; /* URL at which the MERGE request is aimed. */ @@ -275,12 +276,17 @@ setup_merge_headers(serf_bucket_t *headers, apr_pool_t *scratch_pool) { merge_context_t *ctx = baton; + apr_array_header_t *vals = apr_array_make(scratch_pool, 2, + sizeof(const char *)); if (!ctx->keep_locks) - { - serf_bucket_headers_set(headers, SVN_DAV_OPTIONS_HEADER, - SVN_DAV_OPTION_RELEASE_LOCKS); - } + APR_ARRAY_PUSH(vals, const char *) = SVN_DAV_OPTION_RELEASE_LOCKS; + if (ctx->disable_merge_response) + APR_ARRAY_PUSH(vals, const char *) = SVN_DAV_OPTION_NO_MERGE_RESPONSE; + + if (vals->nelts > 0) + serf_bucket_headers_set(headers, SVN_DAV_OPTIONS_HEADER, + svn_cstring_join2(vals, " ", FALSE, scratch_pool)); return SVN_NO_ERROR; } @@ -412,6 +418,13 @@ svn_ra_serf__run_merge(const svn_commit_info_t **commit_info, merge_ctx->lock_tokens = lock_tokens; merge_ctx->keep_locks = keep_locks; + /* We don't need the full merge response when working over HTTPv2. + * Over HTTPv1, this response is only required with a non-null + * svn_ra_push_wc_prop_func_t callback. */ + merge_ctx->disable_merge_response = + SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(session) || + session->wc_callbacks->push_wc_prop == NULL; + merge_ctx->commit_info = svn_create_commit_info(result_pool); merge_ctx->merge_url = session->session_url.path; diff --git a/subversion/libsvn_ra_serf/mergeinfo.c b/subversion/libsvn_ra_serf/mergeinfo.c index 589ff0768ca7..38f165bc3010 100644 --- a/subversion/libsvn_ra_serf/mergeinfo.c +++ b/subversion/libsvn_ra_serf/mergeinfo.c @@ -228,8 +228,8 @@ svn_ra_serf__get_mergeinfo(svn_ra_session_t *ra_session, SVN_ERR(svn_ra_serf__context_run_one(handler, pool)); - SVN_ERR(svn_ra_serf__error_on_status(handler->sline, handler->path, - handler->location)); + if (handler->sline.code != 200) + SVN_ERR(svn_ra_serf__unexpected_status(handler)); if (apr_hash_count(mergeinfo_ctx->result_catalog)) *catalog = mergeinfo_ctx->result_catalog; diff --git a/subversion/libsvn_ra_serf/multistatus.c b/subversion/libsvn_ra_serf/multistatus.c index 9c269c39bedd..00642401e893 100644 --- a/subversion/libsvn_ra_serf/multistatus.c +++ b/subversion/libsvn_ra_serf/multistatus.c @@ -707,7 +707,16 @@ svn_ra_serf__handle_server_error(svn_ra_serf__server_error_t *server_error, clear the error and return - allowing serf to wait for more data. */ if (!err || SERF_BUCKET_READ_ERROR(err->apr_err)) - return svn_error_trace(err); + { + /* Perhaps we already parsed some server generated message. Let's pass + all information we can get.*/ + if (err) + err = svn_error_compose_create( + svn_ra_serf__server_error_create(handler, scratch_pool), + err); + + return svn_error_trace(err); + } if (!APR_STATUS_IS_EOF(err->apr_err)) { diff --git a/subversion/libsvn_ra_serf/options.c b/subversion/libsvn_ra_serf/options.c index a52977bbf1f8..9cb507c8f470 100644 --- a/subversion/libsvn_ra_serf/options.c +++ b/subversion/libsvn_ra_serf/options.c @@ -226,6 +226,26 @@ capabilities_headers_iterator_callback(void *baton, { session->supports_rev_rsrc_replay = TRUE; } + if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_SVNDIFF1, vals)) + { + /* Use compressed svndiff1 format for servers that properly + advertise this capability (Subversion 1.10 and greater). */ + session->supports_svndiff1 = TRUE; + } + if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_LIST, vals)) + { + svn_hash_sets(session->capabilities, + SVN_RA_CAPABILITY_LIST, capability_yes); + } + if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_SVNDIFF2, vals)) + { + /* Same for svndiff2. */ + session->supports_svndiff2 = TRUE; + } + if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_PUT_RESULT_CHECKSUM, vals)) + { + session->supports_put_result_checksum = TRUE; + } } /* SVN-specific headers -- if present, server supports HTTP protocol v2 */ @@ -350,6 +370,7 @@ options_response_handler(serf_request_t *request, { svn_ra_serf__session_t *session = opt_ctx->session; serf_bucket_t *hdrs = serf_bucket_response_get_headers(response); + serf_connection_t *conn; /* Start out assuming all capabilities are unsupported. */ svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_PARTIAL_REPLAY, @@ -368,6 +389,8 @@ options_response_handler(serf_request_t *request, capability_no); svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_GET_FILE_REVS_REVERSE, capability_no); + svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_LIST, + capability_no); /* Then see which ones we can discover. */ serf_bucket_headers_do(hdrs, capabilities_headers_iterator_callback, @@ -379,6 +402,10 @@ options_response_handler(serf_request_t *request, svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_MERGEINFO, capability_no); + /* Remember our latency. */ + conn = serf_request_get_conn(request); + session->conn_latency = serf_connection_get_latency(conn); + opt_ctx->headers_processed = TRUE; } diff --git a/subversion/libsvn_ra_serf/property.c b/subversion/libsvn_ra_serf/property.c index b7e03183c4c7..a3dcb627d25d 100644 --- a/subversion/libsvn_ra_serf/property.c +++ b/subversion/libsvn_ra_serf/property.c @@ -390,6 +390,26 @@ create_propfind_body(serf_bucket_t **bkt, requested_allprop = TRUE; } + prop++; + } + + tmp = SERF_BUCKET_SIMPLE_STRING_LEN(PROPFIND_HEADER, + sizeof(PROPFIND_HEADER)-1, + alloc); + serf_bucket_aggregate_append(body_bkt, tmp); + + /* If we're not doing an allprop, add tags. */ + if (!requested_allprop) + { + tmp = SERF_BUCKET_SIMPLE_STRING_LEN("", + sizeof("")-1, + alloc); + serf_bucket_aggregate_append(body_bkt, tmp); + } + + prop = ctx->find_props; + while (prop && prop->xmlns) + { /* <*propname* xmlns="*propns*" /> */ tmp = SERF_BUCKET_SIMPLE_STRING_LEN("<", 1, alloc); serf_bucket_aggregate_append(body_bkt, tmp); @@ -412,21 +432,6 @@ create_propfind_body(serf_bucket_t **bkt, prop++; } - /* If we're not doing an allprop, add tags. */ - if (!requested_allprop) - { - tmp = SERF_BUCKET_SIMPLE_STRING_LEN("", - sizeof("")-1, - alloc); - serf_bucket_aggregate_prepend(body_bkt, tmp); - } - - tmp = SERF_BUCKET_SIMPLE_STRING_LEN(PROPFIND_HEADER, - sizeof(PROPFIND_HEADER)-1, - alloc); - - serf_bucket_aggregate_prepend(body_bkt, tmp); - if (!requested_allprop) { tmp = SERF_BUCKET_SIMPLE_STRING_LEN("", diff --git a/subversion/libsvn_ra_serf/ra_serf.h b/subversion/libsvn_ra_serf/ra_serf.h index fcef73777a03..9191d073bbc4 100644 --- a/subversion/libsvn_ra_serf/ra_serf.h +++ b/subversion/libsvn_ra_serf/ra_serf.h @@ -26,7 +26,6 @@ #include -#include /* for XML_Parser */ #include #include "svn_types.h" @@ -114,8 +113,12 @@ struct svn_ra_serf__session_t { /* Are we using ssl */ svn_boolean_t using_ssl; - /* Should we ask for compressed responses? */ - svn_boolean_t using_compression; + /* Tristate flag that indicates if we should use compression for + network transmissions. If svn_tristate_true or svn_tristate_false, + the compression should be enabled and disabled, respectively. + If svn_tristate_unknown, determine this automatically based + on network parameters. */ + svn_tristate_t using_compression; /* The user agent string */ const char *useragent; @@ -137,6 +140,10 @@ struct svn_ra_serf__session_t { HTTP/1.0. Thus, we cannot send chunked requests. */ svn_boolean_t http10; + /* We are talking to the server via http/2. Responses of scheduled + requests may come in any order */ + svn_boolean_t http20; + /* Should we use Transfer-Encoding: chunked for HTTP/1.1 servers. */ svn_boolean_t using_chunked_requests; @@ -255,6 +262,18 @@ struct svn_ra_serf__session_t { /* Indicates whether the server supports issuing replay REPORTs against rev resources (children of `rev_stub', elsestruct). */ svn_boolean_t supports_rev_rsrc_replay; + + /* Indicates whether the server can understand svndiff version 1. */ + svn_boolean_t supports_svndiff1; + + /* Indicates whether the server can understand svndiff version 2. */ + svn_boolean_t supports_svndiff2; + + /* Indicates whether the server sends the result checksum in the response + * to a successful PUT request. */ + svn_boolean_t supports_put_result_checksum; + + apr_interval_time_t conn_latency; }; #define SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(sess) ((sess)->me_resource != NULL) @@ -1412,6 +1431,18 @@ svn_ra_serf__get_locks(svn_ra_session_t *ra_session, svn_depth_t depth, apr_pool_t *pool); +/* Implements svn_ra__vtable_t.list(). */ +svn_error_t * +svn_ra_serf__list(svn_ra_session_t *ra_session, + const char *path, + svn_revnum_t revision, + const apr_array_header_t *patterns, + svn_depth_t depth, + apr_uint32_t dirent_fields, + svn_ra_dirent_receiver_t receiver, + void *receiver_baton, + apr_pool_t *scratch_pool); + /* Request a mergeinfo-report from the URL attached to SESSION, and fill in the MERGEINFO hash with the results. @@ -1515,6 +1546,11 @@ svn_ra_serf__error_on_status(serf_status_line sline, svn_error_t * svn_ra_serf__unexpected_status(svn_ra_serf__handler_t *handler); +/* Make sure handler is no longer scheduled on its connection. Resetting + the connection if necessary */ +void +svn_ra_serf__unschedule_handler(svn_ra_serf__handler_t *handler); + /* ###? */ svn_error_t * @@ -1557,6 +1593,70 @@ svn_ra_serf__uri_parse(apr_uri_t *uri, const char *url_str, apr_pool_t *result_pool); +/* Setup the "Accept-Encoding" header value for requests that expect + svndiff-encoded deltas, depending on the SESSION state. */ +void +svn_ra_serf__setup_svndiff_accept_encoding(serf_bucket_t *headers, + svn_ra_serf__session_t *session); + +svn_boolean_t +svn_ra_serf__is_low_latency_connection(svn_ra_serf__session_t *session); + +/* Return an APR array of svn_ra_serf__dav_props_t containing the + * properties (names and namespaces) corresponding to the flegs set + * in DIRENT_FIELDS. If SESSION does not support deadprops, only + * the generic "DAV:allprop" will be returned. Allocate the result + * in RESULT_POOL. */ +apr_array_header_t * +svn_ra_serf__get_dirent_props(apr_uint32_t dirent_fields, + svn_ra_serf__session_t *session, + apr_pool_t *result_pool); + +/* Default limit for in-memory size of a request body. */ +#define SVN_RA_SERF__REQUEST_BODY_IN_MEM_SIZE 256 * 1024 + +/* An opaque structure used to prepare a request body. */ +typedef struct svn_ra_serf__request_body_t svn_ra_serf__request_body_t; + +/* Constructor for svn_ra_serf__request_body_t. Creates a new writable + buffer for the request body. Request bodies under IN_MEMORY_SIZE + bytes will be held in memory, otherwise, the body content will be + spilled to a temporary file. */ +svn_ra_serf__request_body_t * +svn_ra_serf__request_body_create(apr_size_t in_memory_size, + apr_pool_t *result_pool); + +/* Get the writable stream associated with BODY. */ +svn_stream_t * +svn_ra_serf__request_body_get_stream(svn_ra_serf__request_body_t *body); + +/* Get a svn_ra_serf__request_body_delegate_t and baton for BODY. */ +void +svn_ra_serf__request_body_get_delegate(svn_ra_serf__request_body_delegate_t *del, + void **baton, + svn_ra_serf__request_body_t *body); + +/* Release intermediate resources associated with BODY. These resources + (such as open file handles) will be automatically released when the + pool used to construct BODY is cleared or destroyed, but this optional + function allows doing that explicitly. */ +svn_error_t * +svn_ra_serf__request_body_cleanup(svn_ra_serf__request_body_t *body, + apr_pool_t *scratch_pool); + +/* Callback used in svn_ra_serf__create_stream_bucket(). ERR will be + will be cleared and becomes invalid after the callback returns, + use svn_error_dup() to preserve it. */ +typedef void +(*svn_ra_serf__stream_bucket_errfunc_t)(void *baton, svn_error_t *err); + +/* Create a bucket that wraps a generic readable STREAM. This function + takes ownership of the passed-in stream, and will close it. */ +serf_bucket_t * +svn_ra_serf__create_stream_bucket(svn_stream_t *stream, + serf_bucket_alloc_t *allocator, + svn_ra_serf__stream_bucket_errfunc_t errfunc, + void *errfunc_baton); #if defined(SVN_DEBUG) /* Wrapper macros to collect file and line information */ diff --git a/subversion/libsvn_ra_serf/replay.c b/subversion/libsvn_ra_serf/replay.c index 8d2da69fa4eb..bb90ad4a8041 100644 --- a/subversion/libsvn_ra_serf/replay.c +++ b/subversion/libsvn_ra_serf/replay.c @@ -166,6 +166,8 @@ typedef struct revision_report_t { svn_ra_serf__handler_t *propfind_handler; svn_ra_serf__handler_t *report_handler; /* For done handler */ + svn_ra_serf__session_t *session; + } revision_report_t; /* Conforms to svn_ra_serf__xml_opened_t */ @@ -427,10 +429,11 @@ replay_closed(svn_ra_serf__xml_estate_t *xes, { struct replay_node_t *node = ctx->current_node; - if (! node || ! node->file || ! node->stream) + if (! node || ! node->file) return svn_error_create(SVN_ERR_XML_MALFORMED, NULL, NULL); - SVN_ERR(svn_stream_close(node->stream)); + if (node->stream) + SVN_ERR(svn_stream_close(node->stream)); node->stream = NULL; } @@ -565,10 +568,10 @@ svn_ra_serf__replay(svn_ra_session_t *ra_session, SVN_ERR(svn_ra_serf__context_run_one(handler, scratch_pool)); - return svn_error_trace( - svn_ra_serf__error_on_status(handler->sline, - handler->path, - handler->location)); + if (handler->sline.code != 200) + SVN_ERR(svn_ra_serf__unexpected_status(handler)); + + return SVN_NO_ERROR; } /* The maximum number of outstanding requests at any time. When this @@ -629,6 +632,20 @@ replay_done(serf_request_t *request, return SVN_NO_ERROR; } +/* Implements svn_ra_serf__request_header_delegate_t */ +static svn_error_t * +setup_headers(serf_bucket_t *headers, + void *baton, + apr_pool_t *request_pool, + apr_pool_t *scratch_pool) +{ + struct revision_report_t *ctx = baton; + + svn_ra_serf__setup_svndiff_accept_encoding(headers, ctx->session); + + return SVN_NO_ERROR; +} + svn_error_t * svn_ra_serf__replay_range(svn_ra_session_t *ra_session, svn_revnum_t start_revision, @@ -646,9 +663,28 @@ svn_ra_serf__replay_range(svn_ra_session_t *ra_session, int active_reports = 0; const char *include_path; svn_boolean_t done; + apr_pool_t *subpool = svn_pool_create(scratch_pool); + + if (session->http20) { + /* ### Auch... this doesn't work yet... + + This code relies on responses coming in in an exact order, while + http2 does everything to deliver responses as fast as possible. + + With http/1.1 we were quite lucky that this worked, as serf doesn't + promise in order delivery.... (Please do not use authz with keys + that expire) + + For now fall back to the legacy callback in libsvn_ra that is + used by all the other ra layers as workaround. + + ### TODO: Optimize + */ + return svn_error_create(SVN_ERR_RA_NOT_IMPLEMENTED, NULL, NULL); + } SVN_ERR(svn_ra_serf__report_resource(&report_target, session, - scratch_pool)); + subpool)); /* Prior to 1.8, mod_dav_svn expect to get replay REPORT requests aimed at the session URL. But that's incorrect -- these reports @@ -671,7 +707,7 @@ svn_ra_serf__replay_range(svn_ra_session_t *ra_session, { SVN_ERR(svn_ra_serf__get_relative_path(&include_path, session->session_url.path, - session, scratch_pool)); + session, subpool)); } else { @@ -689,7 +725,7 @@ svn_ra_serf__replay_range(svn_ra_session_t *ra_session, { struct revision_report_t *rev_ctx; svn_ra_serf__handler_t *handler; - apr_pool_t *rev_pool = svn_pool_create(scratch_pool); + apr_pool_t *rev_pool = svn_pool_create(subpool); svn_ra_serf__xml_context_t *xmlctx; const char *replay_target; @@ -704,6 +740,7 @@ svn_ra_serf__replay_range(svn_ra_session_t *ra_session, rev_ctx->revision = rev; rev_ctx->low_water_mark = low_water_mark; rev_ctx->send_deltas = send_deltas; + rev_ctx->session = session; /* Request all properties of a certain revision. */ rev_ctx->rev_props = apr_hash_make(rev_ctx->pool); @@ -761,6 +798,10 @@ svn_ra_serf__replay_range(svn_ra_session_t *ra_session, handler->done_delegate = replay_done; handler->done_delegate_baton = rev_ctx; + handler->custom_accept_encoding = TRUE; + handler->header_delegate = setup_headers; + handler->header_delegate_baton = rev_ctx; + rev_ctx->report_handler = handler; svn_ra_serf__request_create(handler); @@ -770,13 +811,23 @@ svn_ra_serf__replay_range(svn_ra_session_t *ra_session, /* Run the serf loop. */ done = FALSE; - SVN_ERR(svn_ra_serf__context_run_wait(&done, session, scratch_pool)); + { + svn_error_t *err = svn_ra_serf__context_run_wait(&done, session, + subpool); + + if (err) + { + svn_pool_destroy(subpool); /* Unregister all requests! */ + return svn_error_trace(err); + } + } /* The done handler of reports decrements active_reports when a report is done. This same handler reports (fatal) report errors, so we can just loop here. */ } + svn_pool_destroy(subpool); return SVN_NO_ERROR; } #undef MAX_OUTSTANDING_REQUESTS diff --git a/subversion/libsvn_ra_serf/request_body.c b/subversion/libsvn_ra_serf/request_body.c new file mode 100644 index 000000000000..eb3b9fc1c10c --- /dev/null +++ b/subversion/libsvn_ra_serf/request_body.c @@ -0,0 +1,232 @@ +/* + * request_body.c : svn_ra_serf__request_body_t implementation + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#include + +#include "ra_serf.h" + +struct svn_ra_serf__request_body_t +{ + svn_stream_t *stream; + apr_size_t in_memory_size; + apr_size_t total_bytes; + serf_bucket_alloc_t *alloc; + serf_bucket_t *collect_bucket; + const void *all_data; + apr_file_t *file; + apr_pool_t *result_pool; + apr_pool_t *scratch_pool; +}; + +/* Fold all previously collected data in a single buffer allocated in + RESULT_POOL and clear all intermediate state. */ +static const char * +allocate_all(svn_ra_serf__request_body_t *body, + apr_pool_t *result_pool) +{ + char *buffer = apr_pcalloc(result_pool, body->total_bytes); + const char *data; + apr_size_t sz; + apr_status_t s; + apr_size_t remaining = body->total_bytes; + char *next = buffer; + + while (!(s = serf_bucket_read(body->collect_bucket, remaining, &data, &sz))) + { + memcpy(next, data, sz); + remaining -= sz; + next += sz; + + if (! remaining) + break; + } + + if (!SERF_BUCKET_READ_ERROR(s)) + { + memcpy(next, data, sz); + } + + serf_bucket_destroy(body->collect_bucket); + body->collect_bucket = NULL; + + return (s != APR_EOF) ? NULL : buffer; +} + +/* Noop function. Make serf take care of freeing in error situations. */ +static void serf_free_no_error(void *unfreed_baton, void *block) {} + +/* Stream write function for body creation. */ +static svn_error_t * +request_body_stream_write(void *baton, + const char *data, + apr_size_t *len) +{ + svn_ra_serf__request_body_t *b = baton; + + if (!b->scratch_pool) + b->scratch_pool = svn_pool_create(b->result_pool); + + if (b->file) + { + SVN_ERR(svn_io_file_write_full(b->file, data, *len, NULL, + b->scratch_pool)); + svn_pool_clear(b->scratch_pool); + + b->total_bytes += *len; + } + else if (*len + b->total_bytes > b->in_memory_size) + { + SVN_ERR(svn_io_open_unique_file3(&b->file, NULL, NULL, + svn_io_file_del_on_pool_cleanup, + b->result_pool, b->scratch_pool)); + + if (b->total_bytes) + { + const char *all = allocate_all(b, b->scratch_pool); + + SVN_ERR(svn_io_file_write_full(b->file, all, b->total_bytes, + NULL, b->scratch_pool)); + } + + SVN_ERR(svn_io_file_write_full(b->file, data, *len, NULL, + b->scratch_pool)); + b->total_bytes += *len; + } + else + { + if (!b->alloc) + b->alloc = serf_bucket_allocator_create(b->scratch_pool, + serf_free_no_error, NULL); + + if (!b->collect_bucket) + b->collect_bucket = serf_bucket_aggregate_create(b->alloc); + + serf_bucket_aggregate_append(b->collect_bucket, + serf_bucket_simple_copy_create(data, *len, + b->alloc)); + + b->total_bytes += *len; + } + + return SVN_NO_ERROR; +} + +/* Stream close function for collecting body. */ +static svn_error_t * +request_body_stream_close(void *baton) +{ + svn_ra_serf__request_body_t *b = baton; + + if (b->file) + { + /* We need to flush the file, make it unbuffered (so that it can be + * zero-copied via mmap), and reset the position before attempting + * to deliver the file. + * + * N.B. If we have APR 1.3+, we can unbuffer the file to let us use + * mmap and zero-copy the PUT body. However, on older APR versions, + * we can't check the buffer status; but serf will fall through and + * create a file bucket for us on the buffered handle. + */ + + SVN_ERR(svn_io_file_flush(b->file, b->scratch_pool)); + apr_file_buffer_set(b->file, NULL, 0); + } + else if (b->collect_bucket) + b->all_data = allocate_all(b, b->result_pool); + + if (b->scratch_pool) + svn_pool_destroy(b->scratch_pool); + + return SVN_NO_ERROR; +} + +/* Implements svn_ra_serf__request_body_delegate_t. */ +static svn_error_t * +request_body_delegate(serf_bucket_t **body_bkt, + void *baton, + serf_bucket_alloc_t *alloc, + apr_pool_t *request_pool, + apr_pool_t *scratch_pool) +{ + svn_ra_serf__request_body_t *b = baton; + + if (b->file) + { + apr_off_t offset; + + offset = 0; + SVN_ERR(svn_io_file_seek(b->file, APR_SET, &offset, scratch_pool)); + + *body_bkt = serf_bucket_file_create(b->file, alloc); + } + else + { + *body_bkt = serf_bucket_simple_create(b->all_data, + b->total_bytes, + NULL, NULL, alloc); + } + + return SVN_NO_ERROR; +} + +svn_ra_serf__request_body_t * +svn_ra_serf__request_body_create(apr_size_t in_memory_size, + apr_pool_t *result_pool) +{ + svn_ra_serf__request_body_t *body = apr_pcalloc(result_pool, sizeof(*body)); + + body->in_memory_size = in_memory_size; + body->result_pool = result_pool; + body->stream = svn_stream_create(body, result_pool); + + svn_stream_set_write(body->stream, request_body_stream_write); + svn_stream_set_close(body->stream, request_body_stream_close); + + return body; +} + +svn_stream_t * +svn_ra_serf__request_body_get_stream(svn_ra_serf__request_body_t *body) +{ + return body->stream; +} + +void +svn_ra_serf__request_body_get_delegate(svn_ra_serf__request_body_delegate_t *del, + void **baton, + svn_ra_serf__request_body_t *body) +{ + *del = request_body_delegate; + *baton = body; +} + +svn_error_t * +svn_ra_serf__request_body_cleanup(svn_ra_serf__request_body_t *body, + apr_pool_t *scratch_pool) +{ + if (body->file) + SVN_ERR(svn_io_file_close(body->file, scratch_pool)); + + return SVN_NO_ERROR; +} diff --git a/subversion/libsvn_ra_serf/sb_bucket.c b/subversion/libsvn_ra_serf/sb_bucket.c index df0541f75eb3..b88dba53d8a2 100644 --- a/subversion/libsvn_ra_serf/sb_bucket.c +++ b/subversion/libsvn_ra_serf/sb_bucket.c @@ -117,7 +117,7 @@ sb_bucket_read(serf_bucket_t *bucket, apr_size_t requested, return *data == NULL ? APR_EOF : APR_SUCCESS; } - +#if !SERF_VERSION_AT_LEAST(1, 4, 0) static apr_status_t sb_bucket_readline(serf_bucket_t *bucket, int acceptable, int *found, @@ -128,6 +128,7 @@ sb_bucket_readline(serf_bucket_t *bucket, int acceptable, "Not implemented.")); return APR_ENOTIMPL; } +#endif static apr_status_t @@ -159,7 +160,11 @@ sb_bucket_peek(serf_bucket_t *bucket, static const serf_bucket_type_t sb_bucket_vtable = { "SPILLBUF", sb_bucket_read, +#if SERF_VERSION_AT_LEAST(1, 4, 0) + serf_default_readline, +#else sb_bucket_readline, +#endif serf_default_read_iovec, serf_default_read_for_sendfile, serf_default_read_bucket, diff --git a/subversion/libsvn_ra_serf/serf.c b/subversion/libsvn_ra_serf/serf.c index 3c47d5eae900..830e5cad532e 100644 --- a/subversion/libsvn_ra_serf/serf.c +++ b/subversion/libsvn_ra_serf/serf.c @@ -153,7 +153,8 @@ load_http_auth_types(apr_pool_t *pool, svn_config_t *config, static svn_error_t * load_config(svn_ra_serf__session_t *session, apr_hash_t *config_hash, - apr_pool_t *pool) + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { svn_config_t *config, *config_client; const char *server_group; @@ -179,9 +180,10 @@ load_config(svn_ra_serf__session_t *session, config_client = NULL; } - SVN_ERR(svn_config_get_bool(config, &session->using_compression, - SVN_CONFIG_SECTION_GLOBAL, - SVN_CONFIG_OPTION_HTTP_COMPRESSION, TRUE)); + SVN_ERR(svn_config_get_tristate(config, &session->using_compression, + SVN_CONFIG_SECTION_GLOBAL, + SVN_CONFIG_OPTION_HTTP_COMPRESSION, + "auto", svn_tristate_unknown)); svn_config_get(config, &timeout_str, SVN_CONFIG_SECTION_GLOBAL, SVN_CONFIG_OPTION_HTTP_TIMEOUT, NULL); @@ -207,7 +209,7 @@ load_config(svn_ra_serf__session_t *session, SVN_CONFIG_OPTION_HTTP_PROXY_EXCEPTIONS, ""); if (! svn_cstring_match_glob_list(session->session_url.hostname, svn_cstring_split(exceptions, ",", - TRUE, pool))) + TRUE, scratch_pool))) { svn_config_get(config, &proxy_host, SVN_CONFIG_SECTION_GLOBAL, SVN_CONFIG_OPTION_HTTP_PROXY_HOST, NULL); @@ -265,10 +267,10 @@ load_config(svn_ra_serf__session_t *session, if (server_group) { - SVN_ERR(svn_config_get_bool(config, &session->using_compression, - server_group, - SVN_CONFIG_OPTION_HTTP_COMPRESSION, - session->using_compression)); + SVN_ERR(svn_config_get_tristate(config, &session->using_compression, + server_group, + SVN_CONFIG_OPTION_HTTP_COMPRESSION, + "auto", session->using_compression)); svn_config_get(config, &timeout_str, server_group, SVN_CONFIG_OPTION_HTTP_TIMEOUT, timeout_str); @@ -340,7 +342,7 @@ load_config(svn_ra_serf__session_t *session, (apr_uint32_t)log_components, SERF_LOG_DEFAULT_LAYOUT, stderr, - pool); + result_pool); if (!status) serf_logging_add_output(session->context, output); @@ -359,19 +361,16 @@ load_config(svn_ra_serf__session_t *session, session->timeout = apr_time_from_sec(DEFAULT_HTTP_TIMEOUT); if (timeout_str) { - char *endstr; - const long int timeout = strtol(timeout_str, &endstr, 10); - - if (*endstr) - return svn_error_create(SVN_ERR_BAD_CONFIG_VALUE, NULL, - _("Invalid config: illegal character in " - "timeout value")); - if (timeout < 0) - return svn_error_create(SVN_ERR_BAD_CONFIG_VALUE, NULL, - _("Invalid config: negative timeout value")); + apr_int64_t timeout; + svn_error_t *err; + + err = svn_cstring_strtoi64(&timeout, timeout_str, 0, APR_INT64_MAX, 10); + if (err) + return svn_error_createf(SVN_ERR_BAD_CONFIG_VALUE, err, + _("invalid config: bad value for '%s' option"), + SVN_CONFIG_OPTION_HTTP_TIMEOUT); session->timeout = apr_time_from_sec(timeout); } - SVN_ERR_ASSERT(session->timeout >= 0); /* Convert the proxy port value, if any. */ if (port_str) @@ -438,7 +437,7 @@ load_config(svn_ra_serf__session_t *session, } /* Setup authentication. */ - SVN_ERR(load_http_auth_types(pool, config, server_group, + SVN_ERR(load_http_auth_types(result_pool, config, server_group, &session->authn_types)); serf_config_authn_types(session->context, session->authn_types); serf_config_credentials_callback(session->context, @@ -449,12 +448,13 @@ load_config(svn_ra_serf__session_t *session, #undef DEFAULT_HTTP_TIMEOUT static void -svn_ra_serf__progress(void *progress_baton, apr_off_t read, apr_off_t written) +svn_ra_serf__progress(void *progress_baton, apr_off_t bytes_read, + apr_off_t bytes_written) { const svn_ra_serf__session_t *serf_sess = progress_baton; if (serf_sess->progress_func) { - serf_sess->progress_func(read + written, -1, + serf_sess->progress_func(bytes_read + bytes_written, -1, serf_sess->progress_baton, serf_sess->pool); } @@ -531,12 +531,13 @@ svn_ra_serf__open(svn_ra_session_t *session, /* We have to assume that the server only supports HTTP/1.0. Once it's clear HTTP/1.1 is supported, we can upgrade. */ serf_sess->http10 = TRUE; + serf_sess->http20 = FALSE; /* If we switch to HTTP/1.1, then we will use chunked requests. We may disable this, if we find an intervening proxy does not support chunked requests. */ serf_sess->using_chunked_requests = TRUE; - SVN_ERR(load_config(serf_sess, config, serf_sess->pool)); + SVN_ERR(load_config(serf_sess, config, serf_sess->pool, scratch_pool)); serf_sess->conns[0] = apr_pcalloc(serf_sess->pool, sizeof(*serf_sess->conns[0])); @@ -593,8 +594,12 @@ svn_ra_serf__open(svn_ra_session_t *session, && apr_pool_is_ancestor(serf_sess->pool, scratch_pool)); #endif + /* The actual latency will be determined as a part of the initial + OPTIONS request. */ + serf_sess->conn_latency = -1; + err = svn_ra_serf__exchange_capabilities(serf_sess, corrected_url, - result_pool, scratch_pool); + result_pool, scratch_pool); /* serf should produce a usable error code instead of APR_EGENERAL */ if (err && err->apr_err == APR_EGENERAL) @@ -637,6 +642,7 @@ ra_serf_dup_session(svn_ra_session_t *new_session, /* using_ssl */ /* using_compression */ /* http10 */ + /* http20 */ /* using_chunked_requests */ /* detect_chunking */ @@ -685,7 +691,7 @@ ra_serf_dup_session(svn_ra_session_t *new_session, if (new_sess->proxy_password) { - new_sess->proxy_username + new_sess->proxy_password = apr_pstrdup(result_pool, new_sess->proxy_password); } @@ -733,11 +739,14 @@ ra_serf_dup_session(svn_ra_session_t *new_session, new_sess->server_allows_bulk = apr_pstrdup(result_pool, new_sess->server_allows_bulk); - new_sess->repos_root_str = apr_pstrdup(result_pool, - new_sess->repos_root_str); - SVN_ERR(svn_ra_serf__uri_parse(&new_sess->repos_root, - new_sess->repos_root_str, - result_pool)); + if (new_sess->repos_root_str) + { + new_sess->repos_root_str = apr_pstrdup(result_pool, + new_sess->repos_root_str); + SVN_ERR(svn_ra_serf__uri_parse(&new_sess->repos_root, + new_sess->repos_root_str, + result_pool)); + } new_sess->session_url_str = apr_pstrdup(result_pool, new_session_url); @@ -747,10 +756,15 @@ ra_serf_dup_session(svn_ra_session_t *new_session, /* svn_boolean_t supports_inline_props */ /* supports_rev_rsrc_replay */ + /* supports_svndiff1 */ + /* supports_svndiff2 */ + /* supports_put_result_checksum */ + /* conn_latency */ new_sess->context = serf_context_create(result_pool); - SVN_ERR(load_config(new_sess, old_sess->config, result_pool)); + SVN_ERR(load_config(new_sess, old_sess->config, + result_pool, scratch_pool)); new_sess->conns[0] = apr_pcalloc(result_pool, sizeof(*new_sess->conns[0])); @@ -1047,8 +1061,12 @@ static const svn_ra__vtable_t serf_vtable = { svn_ra_serf__has_capability, svn_ra_serf__replay_range, svn_ra_serf__get_deleted_rev, + svn_ra_serf__get_inherited_props, + NULL /* set_svn_ra_open */, + svn_ra_serf__list, svn_ra_serf__register_editor_shim_callbacks, - svn_ra_serf__get_inherited_props + NULL /* commit_ev2 */, + NULL /* replay_range_ev2 */ }; svn_error_t * diff --git a/subversion/libsvn_ra_serf/stat.c b/subversion/libsvn_ra_serf/stat.c index b6d10c51f29d..be5ae5a010f0 100644 --- a/subversion/libsvn_ra_serf/stat.c +++ b/subversion/libsvn_ra_serf/stat.c @@ -193,6 +193,9 @@ fill_dirent_propfunc(void *baton, { if (*val->data) { + /* Note: 1.8.x and earlier servers send the count proper; 1.9.0 + * and newer send "1" if there are properties and "0" otherwise. + */ apr_int64_t deadprop_count; SVN_ERR(svn_cstring_atoi64(&deadprop_count, val->data)); fdb->entry->has_props = deadprop_count > 0; @@ -213,64 +216,8 @@ get_dirent_props(apr_uint32_t dirent_fields, apr_pool_t *pool) { svn_ra_serf__dav_props_t *prop; - apr_array_header_t *props = apr_array_make - (pool, 7, sizeof(svn_ra_serf__dav_props_t)); - - if (session->supports_deadprop_count != svn_tristate_false - || ! (dirent_fields & SVN_DIRENT_HAS_PROPS)) - { - if (dirent_fields & SVN_DIRENT_KIND) - { - prop = apr_array_push(props); - prop->xmlns = "DAV:"; - prop->name = "resourcetype"; - } - - if (dirent_fields & SVN_DIRENT_SIZE) - { - prop = apr_array_push(props); - prop->xmlns = "DAV:"; - prop->name = "getcontentlength"; - } - - if (dirent_fields & SVN_DIRENT_HAS_PROPS) - { - prop = apr_array_push(props); - prop->xmlns = SVN_DAV_PROP_NS_DAV; - prop->name = "deadprop-count"; - } - - if (dirent_fields & SVN_DIRENT_CREATED_REV) - { - svn_ra_serf__dav_props_t *p = apr_array_push(props); - p->xmlns = "DAV:"; - p->name = SVN_DAV__VERSION_NAME; - } - - if (dirent_fields & SVN_DIRENT_TIME) - { - prop = apr_array_push(props); - prop->xmlns = "DAV:"; - prop->name = SVN_DAV__CREATIONDATE; - } - - if (dirent_fields & SVN_DIRENT_LAST_AUTHOR) - { - prop = apr_array_push(props); - prop->xmlns = "DAV:"; - prop->name = "creator-displayname"; - } - } - else - { - /* We found an old subversion server that can't handle - the deadprop-count property in the way we expect. - - The neon behavior is to retrieve all properties in this case */ - prop = apr_array_push(props); - prop->xmlns = "DAV:"; - prop->name = "allprop"; - } + apr_array_header_t *props = svn_ra_serf__get_dirent_props(dirent_fields, + session, pool); prop = apr_array_push(props); prop->xmlns = NULL; diff --git a/subversion/libsvn_ra_serf/stream_bucket.c b/subversion/libsvn_ra_serf/stream_bucket.c new file mode 100644 index 000000000000..79de7bfe8451 --- /dev/null +++ b/subversion/libsvn_ra_serf/stream_bucket.c @@ -0,0 +1,120 @@ +/* + * stream_bucket.c : a serf bucket that wraps a readable svn_stream_t + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#include +#include + +#include "ra_serf.h" + +typedef struct stream_bucket_ctx_t +{ + svn_stream_t *stream; + svn_ra_serf__stream_bucket_errfunc_t errfunc; + void *errfunc_baton; + serf_databuf_t databuf; +} stream_bucket_ctx_t; + +static apr_status_t +stream_reader(void *baton, apr_size_t bufsize, char *buf, apr_size_t *len) +{ + stream_bucket_ctx_t *ctx = baton; + svn_error_t *err; + + *len = bufsize; + + err = svn_stream_read_full(ctx->stream, buf, len); + if (err) + { + if (ctx->errfunc) + ctx->errfunc(ctx->errfunc_baton, err); + svn_error_clear(err); + + return SVN_ERR_RA_SERF_STREAM_BUCKET_READ_ERROR; + } + + if (*len == bufsize) + { + return APR_SUCCESS; + } + else + { + svn_error_clear(svn_stream_close(ctx->stream)); + return APR_EOF; + } +} + +static apr_status_t +stream_bucket_read(serf_bucket_t *bucket, apr_size_t requested, + const char **data, apr_size_t *len) +{ + stream_bucket_ctx_t *ctx = bucket->data; + + return serf_databuf_read(&ctx->databuf, requested, data, len); +} + +static apr_status_t +stream_bucket_readline(serf_bucket_t *bucket, int acceptable, + int *found, const char **data, apr_size_t *len) +{ + stream_bucket_ctx_t *ctx = bucket->data; + + return serf_databuf_readline(&ctx->databuf, acceptable, found, data, len); +} + +static apr_status_t +stream_bucket_peek(serf_bucket_t *bucket, const char **data, apr_size_t *len) +{ + stream_bucket_ctx_t *ctx = bucket->data; + + return serf_databuf_peek(&ctx->databuf, data, len); +} + +static const serf_bucket_type_t stream_bucket_vtable = { + "SVNSTREAM", + stream_bucket_read, + stream_bucket_readline, + serf_default_read_iovec, + serf_default_read_for_sendfile, + serf_default_read_bucket, + stream_bucket_peek, + serf_default_destroy_and_data +}; + +serf_bucket_t * +svn_ra_serf__create_stream_bucket(svn_stream_t *stream, + serf_bucket_alloc_t *allocator, + svn_ra_serf__stream_bucket_errfunc_t errfunc, + void *errfunc_baton) +{ + stream_bucket_ctx_t *ctx; + + ctx = serf_bucket_mem_calloc(allocator, sizeof(*ctx)); + ctx->stream = stream; + ctx->errfunc = errfunc; + ctx->errfunc_baton = errfunc_baton; + serf_databuf_init(&ctx->databuf); + ctx->databuf.read = stream_reader; + ctx->databuf.read_baton = ctx; + + return serf_bucket_create(&stream_bucket_vtable, allocator, ctx); +} diff --git a/subversion/libsvn_ra_serf/update.c b/subversion/libsvn_ra_serf/update.c index 8313af019ecc..63091f2ebd21 100644 --- a/subversion/libsvn_ra_serf/update.c +++ b/subversion/libsvn_ra_serf/update.c @@ -365,7 +365,7 @@ typedef struct fetch_ctx_t { /* The handler representing this particular fetch. */ svn_ra_serf__handler_t *handler; - svn_boolean_t using_compression; + svn_ra_serf__session_t *session; /* Stores the information for the file we want to fetch. */ file_baton_t *file; @@ -433,13 +433,11 @@ struct report_context_t { const svn_delta_editor_t *editor; void *editor_baton; - /* The file holding request body for the REPORT. - * - * ### todo: It will be better for performance to store small - * request bodies (like 4k) in memory and bigger bodies on disk. - */ + /* Stream for collecting the request body. */ svn_stream_t *body_template; - body_create_baton_t *body; + + /* Buffer holding request body for the REPORT (can spill to disk). */ + svn_ra_serf__request_body_t *body; /* number of pending GET requests */ unsigned int num_active_fetches; @@ -457,148 +455,6 @@ struct report_context_t { svn_boolean_t closed_root; }; -/* Baton for collecting REPORT body. Depending on the size this - work is backed by a memory buffer (via serf buckets) or by - a file */ -struct body_create_baton_t -{ - apr_pool_t *result_pool; - apr_size_t total_bytes; - - apr_pool_t *scratch_pool; - - serf_bucket_alloc_t *alloc; - serf_bucket_t *collect_bucket; - - const void *all_data; - apr_file_t *file; -}; - - -#define MAX_BODY_IN_RAM (256*1024) - -/* Fold all previously collected data in a single buffer allocated in - RESULT_POOL and clear all intermediate state */ -static const char * -body_allocate_all(body_create_baton_t *body, - apr_pool_t *result_pool) -{ - char *buffer = apr_pcalloc(result_pool, body->total_bytes); - const char *data; - apr_size_t sz; - apr_status_t s; - apr_size_t remaining = body->total_bytes; - char *next = buffer; - - while (!(s = serf_bucket_read(body->collect_bucket, remaining, &data, &sz))) - { - memcpy(next, data, sz); - remaining -= sz; - next += sz; - - if (! remaining) - break; - } - - if (!SERF_BUCKET_READ_ERROR(s)) - { - memcpy(next, data, sz); - } - - serf_bucket_destroy(body->collect_bucket); - body->collect_bucket = NULL; - - return (s != APR_EOF) ? NULL : buffer; -} - -/* Noop function. Make serf take care of freeing in error situations */ -static void serf_free_no_error(void *unfreed_baton, void *block) {} - -/* Stream write function for body creation */ -static svn_error_t * -body_write_fn(void *baton, - const char *data, - apr_size_t *len) -{ - body_create_baton_t *bcb = baton; - - if (!bcb->scratch_pool) - bcb->scratch_pool = svn_pool_create(bcb->result_pool); - - if (bcb->file) - { - SVN_ERR(svn_io_file_write_full(bcb->file, data, *len, NULL, - bcb->scratch_pool)); - svn_pool_clear(bcb->scratch_pool); - - bcb->total_bytes += *len; - } - else if (*len + bcb->total_bytes > MAX_BODY_IN_RAM) - { - SVN_ERR(svn_io_open_unique_file3(&bcb->file, NULL, NULL, - svn_io_file_del_on_pool_cleanup, - bcb->result_pool, bcb->scratch_pool)); - - if (bcb->total_bytes) - { - const char *all = body_allocate_all(bcb, bcb->scratch_pool); - - SVN_ERR(svn_io_file_write_full(bcb->file, all, bcb->total_bytes, - NULL, bcb->scratch_pool)); - } - - SVN_ERR(svn_io_file_write_full(bcb->file, data, *len, NULL, - bcb->scratch_pool)); - bcb->total_bytes += *len; - } - else - { - if (!bcb->alloc) - bcb->alloc = serf_bucket_allocator_create(bcb->scratch_pool, - serf_free_no_error, NULL); - - if (!bcb->collect_bucket) - bcb->collect_bucket = serf_bucket_aggregate_create(bcb->alloc); - - serf_bucket_aggregate_append(bcb->collect_bucket, - serf_bucket_simple_copy_create(data, *len, - bcb->alloc)); - - bcb->total_bytes += *len; - } - - return SVN_NO_ERROR; -} - -/* Stream close function for collecting body */ -static svn_error_t * -body_done_fn(void *baton) -{ - body_create_baton_t *bcb = baton; - if (bcb->file) - { - /* We need to flush the file, make it unbuffered (so that it can be - * zero-copied via mmap), and reset the position before attempting - * to deliver the file. - * - * N.B. If we have APR 1.3+, we can unbuffer the file to let us use - * mmap and zero-copy the PUT body. However, on older APR versions, - * we can't check the buffer status; but serf will fall through and - * create a file bucket for us on the buffered handle. - */ - - SVN_ERR(svn_io_file_flush(bcb->file, bcb->scratch_pool)); - apr_file_buffer_set(bcb->file, NULL, 0); - } - else if (bcb->collect_bucket) - bcb->all_data = body_allocate_all(bcb, bcb->result_pool); - - if (bcb->scratch_pool) - svn_pool_destroy(bcb->scratch_pool); - - return SVN_NO_ERROR; -} - static svn_error_t * create_dir_baton(dir_baton_t **new_dir, report_context_t *ctx, @@ -941,10 +797,9 @@ headers_fetch(serf_bucket_t *headers, { serf_bucket_headers_setn(headers, SVN_DAV_DELTA_BASE_HEADER, fetch_ctx->delta_base); - serf_bucket_headers_setn(headers, "Accept-Encoding", - "svndiff1;q=0.9,svndiff;q=0.8"); + svn_ra_serf__setup_svndiff_accept_encoding(headers, fetch_ctx->session); } - else if (fetch_ctx->using_compression) + else if (fetch_ctx->session->using_compression != svn_tristate_false) { serf_bucket_headers_setn(headers, "Accept-Encoding", "gzip"); } @@ -1422,7 +1277,7 @@ fetch_for_file(file_baton_t *file, fetch_ctx = apr_pcalloc(file->pool, sizeof(*fetch_ctx)); fetch_ctx->file = file; - fetch_ctx->using_compression = ctx->sess->using_compression; + fetch_ctx->session = ctx->sess; /* Can we somehow get away with just obtaining a DIFF? */ if (SVN_RA_SERF__HAVE_HTTPV2_SUPPORT(ctx->sess)) @@ -2304,37 +2159,6 @@ link_path(void *report_baton, return APR_SUCCESS; } -/* Serf callback to create update request body bucket. - Implements svn_ra_serf__request_body_delegate_t */ -static svn_error_t * -create_update_report_body(serf_bucket_t **body_bkt, - void *baton, - serf_bucket_alloc_t *alloc, - apr_pool_t *pool /* request pool */, - apr_pool_t *scratch_pool) -{ - report_context_t *report = baton; - body_create_baton_t *body = report->body; - - if (body->file) - { - apr_off_t offset; - - offset = 0; - SVN_ERR(svn_io_file_seek(body->file, APR_SET, &offset, pool)); - - *body_bkt = serf_bucket_file_create(report->body->file, alloc); - } - else - { - *body_bkt = serf_bucket_simple_create(body->all_data, - body->total_bytes, - NULL, NULL, alloc); - } - - return SVN_NO_ERROR; -} - /* Serf callback to setup update request headers. */ static svn_error_t * setup_update_report_headers(serf_bucket_t *headers, @@ -2344,16 +2168,7 @@ setup_update_report_headers(serf_bucket_t *headers, { report_context_t *report = baton; - if (report->sess->using_compression) - { - serf_bucket_headers_setn(headers, "Accept-Encoding", - "gzip,svndiff1;q=0.9,svndiff;q=0.8"); - } - else - { - serf_bucket_headers_setn(headers, "Accept-Encoding", - "svndiff1;q=0.9,svndiff;q=0.8"); - } + svn_ra_serf__setup_svndiff_accept_encoding(headers, report->sess); return SVN_NO_ERROR; } @@ -2674,10 +2489,11 @@ finish_report(void *report_baton, handler = svn_ra_serf__create_expat_handler(sess, xmlctx, NULL, scratch_pool); + svn_ra_serf__request_body_get_delegate(&handler->body_delegate, + &handler->body_delegate_baton, + report->body); handler->method = "REPORT"; handler->path = report_target; - handler->body_delegate = create_update_report_body; - handler->body_delegate_baton = report; handler->body_type = "text/xml"; handler->custom_accept_encoding = TRUE; handler->header_delegate = setup_update_report_headers; @@ -2792,11 +2608,10 @@ make_update_reporter(svn_ra_session_t *ra_session, *reporter = &ra_serf_reporter; *report_baton = report; - report->body = apr_pcalloc(report->pool, sizeof(*report->body)); - report->body->result_pool = report->pool; - report->body_template = svn_stream_create(report->body, report->pool); - svn_stream_set_write(report->body_template, body_write_fn); - svn_stream_set_close(report->body_template, body_done_fn); + report->body = + svn_ra_serf__request_body_create(SVN_RA_SERF__REQUEST_BODY_IN_MEM_SIZE, + report->pool); + report->body_template = svn_ra_serf__request_body_get_stream(report->body); if (sess->bulk_updates == svn_tristate_true) { diff --git a/subversion/libsvn_ra_serf/util.c b/subversion/libsvn_ra_serf/util.c index 5490ddea8a59..52bf93b3a9b1 100644 --- a/subversion/libsvn_ra_serf/util.c +++ b/subversion/libsvn_ra_serf/util.c @@ -65,7 +65,9 @@ ssl_convert_serf_failures(int failures) apr_uint32_t svn_failures = 0; apr_size_t i; - for (i = 0; i < sizeof(serf_failure_map) / (2 * sizeof(apr_uint32_t)); ++i) + for (i = 0; + i < sizeof(serf_failure_map) / (sizeof(serf_failure_map[0])); + ++i) { if (failures & serf_failure_map[i][0]) { @@ -478,6 +480,38 @@ load_authorities(svn_ra_serf__connection_t *conn, const char *authorities, return SVN_NO_ERROR; } +#if SERF_VERSION_AT_LEAST(1, 4, 0) && defined(SVN__SERF_TEST_HTTP2) +/* Implements serf_ssl_protocol_result_cb_t */ +static apr_status_t +conn_negotiate_protocol(void *data, + const char *protocol) +{ + svn_ra_serf__connection_t *conn = data; + + if (!strcmp(protocol, "h2")) + { + serf_connection_set_framing_type( + conn->conn, + SERF_CONNECTION_FRAMING_TYPE_HTTP2); + + /* Disable generating content-length headers. */ + conn->session->http10 = FALSE; + conn->session->http20 = TRUE; + conn->session->using_chunked_requests = TRUE; + conn->session->detect_chunking = FALSE; + } + else + { + /* protocol should be "" or "http/1.1" */ + serf_connection_set_framing_type( + conn->conn, + SERF_CONNECTION_FRAMING_TYPE_HTTP1); + } + + return APR_SUCCESS; +} +#endif + static svn_error_t * conn_setup(apr_socket_t *sock, serf_bucket_t **read_bkt, @@ -523,6 +557,16 @@ conn_setup(apr_socket_t *sock, SVN_ERR(load_authorities(conn, conn->session->ssl_authorities, conn->session->pool)); } +#if SERF_VERSION_AT_LEAST(1, 4, 0) && defined(SVN__SERF_TEST_HTTP2) + if (APR_SUCCESS == + serf_ssl_negotiate_protocol(conn->ssl_context, "h2,http/1.1", + conn_negotiate_protocol, conn)) + { + serf_connection_set_framing_type( + conn->conn, + SERF_CONNECTION_FRAMING_TYPE_NONE); + } +#endif } if (write_bkt) @@ -957,7 +1001,7 @@ svn_ra_serf__context_run_wait(svn_boolean_t *done, will cancel all outstanding requests and prepare the connection for re-use. */ -static void +void svn_ra_serf__unschedule_handler(svn_ra_serf__handler_t *handler) { serf_connection_reset(handler->conn->conn); @@ -1293,6 +1337,10 @@ handle_response(serf_request_t *request, /* HTTP/1.1? (or later) */ if (sl.version != SERF_HTTP_10) handler->session->http10 = FALSE; + + if (sl.version >= SERF_HTTP_VERSION(2, 0)) { + handler->session->http20 = TRUE; + } } /* Keep reading from the network until we've read all the headers. */ @@ -1523,7 +1571,7 @@ setup_request(serf_request_t *request, { accept_encoding = NULL; } - else if (handler->session->using_compression) + else if (handler->session->using_compression != svn_tristate_false) { /* Accept gzip compression if enabled. */ accept_encoding = "gzip"; @@ -1975,3 +2023,114 @@ svn_ra_serf__uri_parse(apr_uri_t *uri, return SVN_NO_ERROR; } + +void +svn_ra_serf__setup_svndiff_accept_encoding(serf_bucket_t *headers, + svn_ra_serf__session_t *session) +{ + if (session->using_compression == svn_tristate_false) + { + /* Don't advertise support for compressed svndiff formats if + compression is disabled. */ + serf_bucket_headers_setn( + headers, "Accept-Encoding", "svndiff"); + } + else if (session->using_compression == svn_tristate_unknown && + svn_ra_serf__is_low_latency_connection(session)) + { + /* With http-compression=auto, advertise that we prefer svndiff2 + to svndiff1 with a low latency connection (assuming the underlying + network has high bandwidth), as it is faster and in this case, we + don't care about worse compression ratio. */ + serf_bucket_headers_setn( + headers, "Accept-Encoding", + "gzip,svndiff2;q=0.9,svndiff1;q=0.8,svndiff;q=0.7"); + } + else + { + /* Otherwise, advertise that we prefer svndiff1 over svndiff2. + svndiff2 is not a reasonable substitute for svndiff1 with default + compression level, because, while it is faster, it also gives worse + compression ratio. While we can use svndiff2 in some cases (see + above), we can't do this generally. */ + serf_bucket_headers_setn( + headers, "Accept-Encoding", + "gzip,svndiff1;q=0.9,svndiff2;q=0.8,svndiff;q=0.7"); + } +} + +svn_boolean_t +svn_ra_serf__is_low_latency_connection(svn_ra_serf__session_t *session) +{ + return session->conn_latency >= 0 && + session->conn_latency < apr_time_from_msec(5); +} + +apr_array_header_t * +svn_ra_serf__get_dirent_props(apr_uint32_t dirent_fields, + svn_ra_serf__session_t *session, + apr_pool_t *result_pool) +{ + svn_ra_serf__dav_props_t *prop; + apr_array_header_t *props = apr_array_make + (result_pool, 7, sizeof(svn_ra_serf__dav_props_t)); + + if (session->supports_deadprop_count != svn_tristate_false + || ! (dirent_fields & SVN_DIRENT_HAS_PROPS)) + { + if (dirent_fields & SVN_DIRENT_KIND) + { + prop = apr_array_push(props); + prop->xmlns = "DAV:"; + prop->name = "resourcetype"; + } + + if (dirent_fields & SVN_DIRENT_SIZE) + { + prop = apr_array_push(props); + prop->xmlns = "DAV:"; + prop->name = "getcontentlength"; + } + + if (dirent_fields & SVN_DIRENT_HAS_PROPS) + { + prop = apr_array_push(props); + prop->xmlns = SVN_DAV_PROP_NS_DAV; + prop->name = "deadprop-count"; + } + + if (dirent_fields & SVN_DIRENT_CREATED_REV) + { + svn_ra_serf__dav_props_t *p = apr_array_push(props); + p->xmlns = "DAV:"; + p->name = SVN_DAV__VERSION_NAME; + } + + if (dirent_fields & SVN_DIRENT_TIME) + { + prop = apr_array_push(props); + prop->xmlns = "DAV:"; + prop->name = SVN_DAV__CREATIONDATE; + } + + if (dirent_fields & SVN_DIRENT_LAST_AUTHOR) + { + prop = apr_array_push(props); + prop->xmlns = "DAV:"; + prop->name = "creator-displayname"; + } + } + else + { + /* We found an old subversion server that can't handle + the deadprop-count property in the way we expect. + + The neon behavior is to retrieve all properties in this case */ + prop = apr_array_push(props); + prop->xmlns = "DAV:"; + prop->name = "allprop"; + } + + return props; +} + diff --git a/subversion/libsvn_ra_serf/xml.c b/subversion/libsvn_ra_serf/xml.c index 1a988572b841..cc6948cd607a 100644 --- a/subversion/libsvn_ra_serf/xml.c +++ b/subversion/libsvn_ra_serf/xml.c @@ -24,7 +24,6 @@ #include -#include #include #include "svn_hash.h" @@ -43,22 +42,6 @@ #include "ra_serf.h" -/* Fix for older expat 1.95.x's that do not define - * XML_STATUS_OK/XML_STATUS_ERROR - */ -#ifndef XML_STATUS_OK -#define XML_STATUS_OK 1 -#define XML_STATUS_ERROR 0 -#endif - -#ifndef XML_VERSION_AT_LEAST -#define XML_VERSION_AT_LEAST(major,minor,patch) \ -(((major) < XML_MAJOR_VERSION) \ - || ((major) == XML_MAJOR_VERSION && (minor) < XML_MINOR_VERSION) \ - || ((major) == XML_MAJOR_VERSION && (minor) == XML_MINOR_VERSION && \ - (patch) <= XML_MICRO_VERSION)) -#endif /* XML_VERSION_AT_LEAST */ - /* Read/write chunks of this size into the spillbuf. */ #define PARSE_CHUNK_SIZE 8000 @@ -149,12 +132,10 @@ struct svn_ra_serf__xml_estate_t { struct expat_ctx_t { svn_ra_serf__xml_context_t *xmlctx; - XML_Parser parser; + svn_xml_parser_t *parser; svn_ra_serf__handler_t *handler; const int *expected_status; - svn_error_t *inner_error; - /* Do not use this pool for allocation. It is merely recorded for running the cleanup handler. */ apr_pool_t *cleanup_pool; @@ -886,132 +867,60 @@ xml_cb_cdata(svn_ra_serf__xml_context_t *xmlctx, return SVN_NO_ERROR; } -/* svn_error_t * wrapper around XML_Parse */ +/* Wrapper around svn_xml_parse */ static APR_INLINE svn_error_t * parse_xml(struct expat_ctx_t *ectx, const char *data, apr_size_t len, svn_boolean_t is_final) { - int xml_status = XML_Parse(ectx->parser, data, (int)len, is_final); - const char *msg; - int xml_code; + svn_error_t *err = svn_xml_parse(ectx->parser, data, len, is_final); - if (xml_status == XML_STATUS_OK) - return ectx->inner_error; + if (err && err->apr_err == SVN_ERR_XML_MALFORMED) + err = svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, err, + _("The XML response contains invalid XML")); - xml_code = XML_GetErrorCode(ectx->parser); - -#if XML_VERSION_AT_LEAST(1, 95, 8) - /* If we called XML_StopParser() expat will return an abort error. If we - have a better error stored we should ignore it as it will not help - the end-user to store it in the error chain. */ - if (xml_code == XML_ERROR_ABORTED && ectx->inner_error) - return ectx->inner_error; -#endif - - msg = XML_ErrorString(xml_code); - - return svn_error_compose_create( - ectx->inner_error, - svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, - svn_error_createf(SVN_ERR_XML_MALFORMED, NULL, - _("Malformed XML: %s"), - msg), - _("The XML response contains invalid XML"))); + return err; } -/* Apr pool cleanup handler to release an XML_Parser in success and error - conditions */ -static apr_status_t -xml_parser_cleanup(void *baton) -{ - XML_Parser *xmlp = baton; - - if (*xmlp) - { - (void) XML_ParserFree(*xmlp); - *xmlp = NULL; - } - - return APR_SUCCESS; -} - -/* Conforms to Expat's XML_StartElementHandler */ +/* Implements svn_xml_start_elem callback */ static void -expat_start(void *userData, const char *raw_name, const char **attrs) +expat_start(void *baton, const char *raw_name, const char **attrs) { - struct expat_ctx_t *ectx = userData; + struct expat_ctx_t *ectx = baton; + svn_error_t *err; - if (ectx->inner_error != NULL) - return; + err = svn_error_trace(xml_cb_start(ectx->xmlctx, raw_name, attrs)); - ectx->inner_error = svn_error_trace(xml_cb_start(ectx->xmlctx, - raw_name, attrs)); - -#if XML_VERSION_AT_LEAST(1, 95, 8) - if (ectx->inner_error) - (void) XML_StopParser(ectx->parser, 0 /* resumable */); -#endif + if (err) + svn_xml_signal_bailout(err, ectx->parser); } -/* Conforms to Expat's XML_EndElementHandler */ +/* Implements svn_xml_end_elem callback */ static void -expat_end(void *userData, const char *raw_name) +expat_end(void *baton, const char *raw_name) { - struct expat_ctx_t *ectx = userData; + struct expat_ctx_t *ectx = baton; + svn_error_t *err; - if (ectx->inner_error != NULL) - return; + err = svn_error_trace(xml_cb_end(ectx->xmlctx, raw_name)); - ectx->inner_error = svn_error_trace(xml_cb_end(ectx->xmlctx, raw_name)); - -#if XML_VERSION_AT_LEAST(1, 95, 8) - if (ectx->inner_error) - (void) XML_StopParser(ectx->parser, 0 /* resumable */); -#endif + if (err) + svn_xml_signal_bailout(err, ectx->parser); } -/* Conforms to Expat's XML_CharacterDataHandler */ +/* Implements svn_xml_char_data callback */ static void -expat_cdata(void *userData, const char *data, int len) +expat_cdata(void *baton, const char *data, apr_size_t len) { - struct expat_ctx_t *ectx = userData; + struct expat_ctx_t *ectx = baton; + svn_error_t *err; - if (ectx->inner_error != NULL) - return; + err = svn_error_trace(xml_cb_cdata(ectx->xmlctx, data, len)); - ectx->inner_error = svn_error_trace(xml_cb_cdata(ectx->xmlctx, data, len)); - -#if XML_VERSION_AT_LEAST(1, 95, 8) - if (ectx->inner_error) - (void) XML_StopParser(ectx->parser, 0 /* resumable */); -#endif + if (err) + svn_xml_signal_bailout(err, ectx->parser); } -#if XML_VERSION_AT_LEAST(1, 95, 8) -static void -expat_entity_declaration(void *userData, - const XML_Char *entityName, - int is_parameter_entity, - const XML_Char *value, - int value_length, - const XML_Char *base, - const XML_Char *systemId, - const XML_Char *publicId, - const XML_Char *notationName) -{ - struct expat_ctx_t *ectx = userData; - - /* Stop the parser if an entity declaration is hit. */ - XML_StopParser(ectx->parser, 0 /* resumable */); -} -#else -/* A noop default_handler. */ -static void -expat_default_handler(void *userData, const XML_Char *s, int len) -{ -} -#endif /* Implements svn_ra_serf__response_handler_t */ static svn_error_t * @@ -1060,18 +969,8 @@ expat_response_handler(serf_request_t *request, if (!ectx->parser) { - ectx->parser = XML_ParserCreate(NULL); - apr_pool_cleanup_register(ectx->cleanup_pool, &ectx->parser, - xml_parser_cleanup, apr_pool_cleanup_null); - XML_SetUserData(ectx->parser, ectx); - XML_SetElementHandler(ectx->parser, expat_start, expat_end); - XML_SetCharacterDataHandler(ectx->parser, expat_cdata); - -#if XML_VERSION_AT_LEAST(1, 95, 8) - XML_SetEntityDeclHandler(ectx->parser, expat_entity_declaration); -#else - XML_SetDefaultHandler(ectx->parser, expat_default_handler); -#endif + ectx->parser = svn_xml_make_parser(ectx, expat_start, expat_end, + expat_cdata, ectx->cleanup_pool); } while (1) @@ -1079,7 +978,6 @@ expat_response_handler(serf_request_t *request, apr_status_t status; const char *data; apr_size_t len; - svn_error_t *err; svn_boolean_t at_eof = FALSE; status = serf_bucket_read(response, PARSE_CHUNK_SIZE, &data, &len); @@ -1088,16 +986,7 @@ expat_response_handler(serf_request_t *request, else if (APR_STATUS_IS_EOF(status)) at_eof = TRUE; - err = parse_xml(ectx, data, len, at_eof /* isFinal */); - - if (at_eof || err) - { - /* Release xml parser state/tables. */ - apr_pool_cleanup_run(ectx->cleanup_pool, &ectx->parser, - xml_parser_cleanup); - } - - SVN_ERR(err); + SVN_ERR(parse_xml(ectx, data, len, at_eof /* isFinal */)); /* The parsing went fine. What has the bucket told us? */ if (at_eof) diff --git a/subversion/libsvn_ra_svn/client.c b/subversion/libsvn_ra_svn/client.c index a4939ab2ad53..ab1aa58cdc48 100644 --- a/subversion/libsvn_ra_svn/client.c +++ b/subversion/libsvn_ra_svn/client.c @@ -51,6 +51,7 @@ #include "svn_private_config.h" #include "private/svn_fspath.h" +#include "private/svn_string_private.h" #include "private/svn_subr_private.h" #include "../libsvn_ra/ra_loader.h" @@ -188,7 +189,7 @@ static svn_error_t *make_connection(const char *hostname, unsigned short port, /* Set *DIFFS to an array of svn_prop_t, allocated in POOL, based on the property diffs in LIST, received from the server. */ -static svn_error_t *parse_prop_diffs(const apr_array_header_t *list, +static svn_error_t *parse_prop_diffs(const svn_ra_svn__list_t *list, apr_pool_t *pool, apr_array_header_t **diffs) { @@ -199,26 +200,27 @@ static svn_error_t *parse_prop_diffs(const apr_array_header_t *list, for (i = 0; i < list->nelts; i++) { svn_prop_t *prop; - svn_ra_svn_item_t *elt = &APR_ARRAY_IDX(list, i, svn_ra_svn_item_t); + svn_ra_svn__item_t *elt = &SVN_RA_SVN__LIST_ITEM(list, i); if (elt->kind != SVN_RA_SVN_LIST) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Prop diffs element not a list")); prop = apr_array_push(*diffs); - SVN_ERR(svn_ra_svn__parse_tuple(elt->u.list, pool, "c(?s)", &prop->name, - &prop->value)); + SVN_ERR(svn_ra_svn__parse_tuple(&elt->u.list, "c(?s)", + &prop->name, &prop->value)); } return SVN_NO_ERROR; } /* Parse a lockdesc, provided in LIST as specified by the protocol into LOCK, allocated in POOL. */ -static svn_error_t *parse_lock(const apr_array_header_t *list, apr_pool_t *pool, +static svn_error_t *parse_lock(const svn_ra_svn__list_t *list, + apr_pool_t *pool, svn_lock_t **lock) { const char *cdate, *edate; *lock = svn_lock_create(pool); - SVN_ERR(svn_ra_svn__parse_tuple(list, pool, "ccc(?c)c(?c)", &(*lock)->path, + SVN_ERR(svn_ra_svn__parse_tuple(list, "ccc(?c)c(?c)", &(*lock)->path, &(*lock)->token, &(*lock)->owner, &(*lock)->comment, &cdate, &edate)); (*lock)->path = svn_fspath__canonicalize((*lock)->path, pool); @@ -241,7 +243,7 @@ static svn_error_t *handle_auth_request(svn_ra_svn__session_baton_t *sess, apr_pool_t *pool) { svn_ra_svn_conn_t *conn = sess->conn; - apr_array_header_t *mechlist; + svn_ra_svn__list_t *mechlist; const char *realm; SVN_ERR(svn_ra_svn__read_cmd_response(conn, pool, "lc", &mechlist, &realm)); @@ -470,9 +472,9 @@ static void handle_child_process_error(apr_pool_t *pool, apr_status_t status, in_stream = svn_stream_from_aprfile2(in_file, FALSE, pool); out_stream = svn_stream_from_aprfile2(out_file, FALSE, pool); - conn = svn_ra_svn_create_conn4(NULL, in_stream, out_stream, + conn = svn_ra_svn_create_conn5(NULL, in_stream, out_stream, SVN_DELTA_COMPRESSION_LEVEL_DEFAULT, 0, - 0, pool); + 0, 0, 0, pool); err = svn_error_wrap_apr(status, _("Error in child process: %s"), desc); svn_error_clear(svn_ra_svn__write_cmd_failure(conn, pool, err)); svn_error_clear(err); @@ -541,13 +543,13 @@ static svn_error_t *make_tunnel(const char **args, svn_ra_svn_conn_t **conn, apr_file_inherit_unset(proc->out); /* Guard against dotfile output to stdout on the server. */ - *conn = svn_ra_svn_create_conn4(NULL, + *conn = svn_ra_svn_create_conn5(NULL, svn_stream_from_aprfile2(proc->out, FALSE, pool), svn_stream_from_aprfile2(proc->in, FALSE, pool), SVN_DELTA_COMPRESSION_LEVEL_DEFAULT, - 0, 0, pool); + 0, 0, 0, 0, pool); err = svn_ra_svn__skip_leading_garbage(*conn, pool); if (err) return svn_error_quick_wrap( @@ -625,14 +627,20 @@ static svn_error_t *open_session(svn_ra_svn__session_baton_t **sess_p, svn_ra_svn_conn_t *conn; apr_socket_t *sock; apr_uint64_t minver, maxver; - apr_array_header_t *mechlist, *server_caplist, *repos_caplist; + svn_ra_svn__list_t *mechlist, *server_caplist, *repos_caplist; const char *client_string = NULL; apr_pool_t *pool = result_pool; + svn_ra_svn__parent_t *parent; + + parent = apr_pcalloc(pool, sizeof(*parent)); + parent->client_url = svn_stringbuf_create(url, pool); + parent->server_url = svn_stringbuf_create(url, pool); + parent->path = svn_stringbuf_create_empty(pool); sess = apr_palloc(pool, sizeof(*sess)); sess->pool = pool; sess->is_tunneled = (tunnel_name != NULL); - sess->url = apr_pstrdup(pool, url); + sess->parent = parent; sess->user = uri->user; sess->hostname = uri->hostname; sess->tunnel_name = tunnel_name; @@ -673,9 +681,9 @@ static svn_error_t *open_session(svn_ra_svn__session_baton_t **sess_p, apr_pool_cleanup_register(pool, td, close_tunnel_cleanup, apr_pool_cleanup_null); - conn = svn_ra_svn_create_conn4(NULL, td->response, td->request, + conn = svn_ra_svn_create_conn5(NULL, td->response, td->request, SVN_DELTA_COMPRESSION_LEVEL_DEFAULT, - 0, 0, pool); + 0, 0, 0, 0, pool); SVN_ERR(svn_ra_svn__skip_leading_garbage(conn, pool)); } } @@ -687,9 +695,9 @@ static svn_error_t *open_session(svn_ra_svn__session_baton_t **sess_p, SVN_ERR(make_connection(uri->hostname, uri->port ? uri->port : SVN_RA_SVN_PORT, &sock, pool)); - conn = svn_ra_svn_create_conn4(sock, NULL, NULL, + conn = svn_ra_svn_create_conn5(sock, NULL, NULL, SVN_DELTA_COMPRESSION_LEVEL_DEFAULT, - 0, 0, pool); + 0, 0, 0, 0, pool); } /* Build the useragent string, querying the client for any @@ -727,7 +735,7 @@ static svn_error_t *open_session(svn_ra_svn__session_baton_t **sess_p, return svn_error_createf(SVN_ERR_RA_SVN_BAD_VERSION, NULL, _("Server only supports versions up to %d"), (int) maxver); - SVN_ERR(svn_ra_svn_set_capabilities(conn, server_caplist)); + SVN_ERR(svn_ra_svn__set_capabilities(conn, server_caplist)); /* All released versions of Subversion support edit-pipeline, * so we do not support servers that do not. */ @@ -739,10 +747,11 @@ static svn_error_t *open_session(svn_ra_svn__session_baton_t **sess_p, * capability list, and the URL, and subsequently there is an auth * request. */ /* Client-side capabilities list: */ - SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "n(wwwwww)cc(?c)", + SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "n(wwwwwww)cc(?c)", (apr_uint64_t) 2, SVN_RA_SVN_CAP_EDIT_PIPELINE, SVN_RA_SVN_CAP_SVNDIFF1, + SVN_RA_SVN_CAP_SVNDIFF2_ACCEPTED, SVN_RA_SVN_CAP_ABSENT_ENTRIES, SVN_RA_SVN_CAP_DEPTH, SVN_RA_SVN_CAP_MERGEINFO, @@ -760,7 +769,7 @@ static svn_error_t *open_session(svn_ra_svn__session_baton_t **sess_p, SVN_ERR(svn_ra_svn__read_cmd_response(conn, pool, "c?c?l", &conn->uuid, &conn->repos_root, &repos_caplist)); if (repos_caplist) - SVN_ERR(svn_ra_svn_set_capabilities(conn, repos_caplist)); + SVN_ERR(svn_ra_svn__set_capabilities(conn, repos_caplist)); if (conn->repos_root) { @@ -912,23 +921,29 @@ static svn_error_t *ra_svn_dup_session(svn_ra_session_t *new_session, return SVN_NO_ERROR; } -static svn_error_t *ra_svn_reparent(svn_ra_session_t *ra_session, - const char *url, - apr_pool_t *pool) +/* Send the "reparent to URL" command to the server for RA_SESSION and + update the session state. Use SCRATCH_POOL for tempoaries. + */ +static svn_error_t * +reparent_server(svn_ra_session_t *ra_session, + const char *url, + apr_pool_t *scratch_pool) { svn_ra_svn__session_baton_t *sess = ra_session->priv; + svn_ra_svn__parent_t *parent = sess->parent; svn_ra_svn_conn_t *conn = sess->conn; svn_error_t *err; apr_pool_t *sess_pool; svn_ra_svn__session_baton_t *new_sess; apr_uri_t uri; - SVN_ERR(svn_ra_svn__write_cmd_reparent(conn, pool, url)); - err = handle_auth_request(sess, pool); + /* Send the request to the server. */ + SVN_ERR(svn_ra_svn__write_cmd_reparent(conn, scratch_pool, url)); + err = handle_auth_request(sess, scratch_pool); if (! err) { - SVN_ERR(svn_ra_svn__read_cmd_response(conn, pool, "")); - sess->url = apr_pstrdup(sess->pool, url); + SVN_ERR(svn_ra_svn__read_cmd_response(conn, scratch_pool, "")); + svn_stringbuf_set(parent->server_url, url); return SVN_NO_ERROR; } else if (err->apr_err != SVN_ERR_RA_SVN_UNKNOWN_CMD) @@ -959,11 +974,143 @@ static svn_error_t *ra_svn_reparent(svn_ra_session_t *ra_session, return SVN_NO_ERROR; } +/* Make sure that RA_SESSION's client and server-side parent infp are in + sync. Use SCRATCH_POOL for temporary allocations. */ +static svn_error_t * +ensure_exact_server_parent(svn_ra_session_t *ra_session, + apr_pool_t *scratch_pool) +{ + svn_ra_svn__session_baton_t *sess = ra_session->priv; + svn_ra_svn__parent_t *parent = sess->parent; + + /* During e.g. a checkout operation, many requests will be sent for the + same URL that was used to create the session. So, both sides are + often already in sync. */ + if (svn_stringbuf_compare(parent->client_url, parent->server_url)) + return SVN_NO_ERROR; + + /* Actually reparent the server to the session URL. */ + SVN_ERR(reparent_server(ra_session, parent->client_url->data, + scratch_pool)); + svn_stringbuf_setempty(parent->path); + + return SVN_NO_ERROR; +} + +/* Return a copy of PATH, adjusted to the RA_SESSION's server parent URL. + Allocate the result in RESULT_POOL. */ +static const char * +reparent_path(svn_ra_session_t *ra_session, + const char *path, + apr_pool_t *result_pool) +{ + svn_ra_svn__session_baton_t *sess = ra_session->priv; + svn_ra_svn__parent_t *parent = sess->parent; + + return svn_relpath_join(parent->path->data, path, result_pool); +} + +/* Return a copy of PATHS, containing the same const char * paths but + adjusted to the RA_SESSION's server parent URL. Returns NULL if + PATHS is NULL. Allocate the result in RESULT_POOL. */ +static apr_array_header_t * +reparent_path_array(svn_ra_session_t *ra_session, + const apr_array_header_t *paths, + apr_pool_t *result_pool) +{ + int i; + apr_array_header_t *result; + + if (!paths) + return NULL; + + result = apr_array_copy(result_pool, paths); + for (i = 0; i < result->nelts; ++i) + { + const char **path = &APR_ARRAY_IDX(result, i, const char *); + *path = reparent_path(ra_session, *path, result_pool); + } + + return result; +} + +/* Return a copy of PATHS, containing the same paths for keys but adjusted + to the RA_SESSION's server parent URL. Keeps the values as-are and + returns NULL if PATHS is NULL. Allocate the result in RESULT_POOL. */ +static apr_hash_t * +reparent_path_hash(svn_ra_session_t *ra_session, + apr_hash_t *paths, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + apr_hash_t *result; + apr_hash_index_t *hi; + + if (!paths) + return NULL; + + result = svn_hash__make(result_pool); + for (hi = apr_hash_first(scratch_pool, paths); hi; hi = apr_hash_next(hi)) + { + const char *path = apr_hash_this_key(hi); + svn_hash_sets(result, + reparent_path(ra_session, path, result_pool), + apr_hash_this_val(hi)); + } + + return result; +} + +static svn_error_t *ra_svn_reparent(svn_ra_session_t *ra_session, + const char *url, + apr_pool_t *pool) +{ + svn_ra_svn__session_baton_t *sess = ra_session->priv; + svn_ra_svn__parent_t *parent = sess->parent; + svn_ra_svn_conn_t *conn = sess->conn; + const char *path; + + /* Eliminate reparent requests if they are to a sub-path of the + server's current parent path. */ + path = svn_uri_skip_ancestor(parent->server_url->data, url, pool); + if (!path) + { + /* Send the request to the server. + + If within the same repository, reparent to the repo root + because this will maximize the chance to turn future reparent + requests into a client-side update of the rel path. */ + path = conn->repos_root + ? svn_uri_skip_ancestor(conn->repos_root, url, pool) + : NULL; + + if (path) + SVN_ERR(reparent_server(ra_session, conn->repos_root, pool)); + else + SVN_ERR(reparent_server(ra_session, url, pool)); + } + + /* Update the local PARENT information. + PARENT.SERVER_BASE_URL is already up-to-date. */ + svn_stringbuf_set(parent->client_url, url); + if (path) + svn_stringbuf_set(parent->path, path); + else + svn_stringbuf_setempty(parent->path); + + return SVN_NO_ERROR; +} + static svn_error_t *ra_svn_get_session_url(svn_ra_session_t *session, - const char **url, apr_pool_t *pool) + const char **url, + apr_pool_t *pool) { svn_ra_svn__session_baton_t *sess = session->priv; - *url = apr_pstrdup(pool, sess->url); + svn_ra_svn__parent_t *parent = sess->parent; + + *url = apr_pstrmemdup(pool, parent->client_url->data, + parent->client_url->len); + return SVN_NO_ERROR; } @@ -1069,7 +1216,7 @@ static svn_error_t *ra_svn_rev_proplist(svn_ra_session_t *session, svn_revnum_t { svn_ra_svn__session_baton_t *sess_baton = session->priv; svn_ra_svn_conn_t *conn = sess_baton->conn; - apr_array_header_t *proplist; + svn_ra_svn__list_t *proplist; SVN_ERR(svn_ra_svn__write_cmd_rev_proplist(conn, pool, rev)); SVN_ERR(handle_auth_request(sess_baton, pool)); @@ -1172,6 +1319,9 @@ static svn_error_t *ra_svn_commit(svn_ra_session_t *session, svn_string_create(sess_baton->useragent, pool)); } + /* Callbacks may assume that all data is relative the sessions's URL. */ + SVN_ERR(ensure_exact_server_parent(session, pool)); + /* Tell the server we're starting the commit. Send log message here for backwards compatibility with servers before 1.5. */ @@ -1216,12 +1366,12 @@ static svn_error_t *ra_svn_commit(svn_ra_session_t *session, return SVN_NO_ERROR; } -/* Parse IPROPLIST, an array of svn_ra_svn_item_t structures, as a list of +/* Parse IPROPLIST, an array of svn_ra_svn__item_t structures, as a list of const char * repos relative paths and properties for those paths, storing the result as an array of svn_prop_inherited_item_t *items. */ static svn_error_t * parse_iproplist(apr_array_header_t **inherited_props, - const apr_array_header_t *iproplist, + const svn_ra_svn__list_t *iproplist, svn_ra_session_t *session, apr_pool_t *result_pool, apr_pool_t *scratch_pool) @@ -1247,14 +1397,13 @@ parse_iproplist(apr_array_header_t **inherited_props, for (i = 0; i < iproplist->nelts; i++) { - apr_array_header_t *iprop_list; + svn_ra_svn__list_t *iprop_list; char *parent_rel_path; apr_hash_t *iprops; apr_hash_index_t *hi; svn_prop_inherited_item_t *new_iprop = apr_palloc(result_pool, sizeof(*new_iprop)); - svn_ra_svn_item_t *elt = &APR_ARRAY_IDX(iproplist, i, - svn_ra_svn_item_t); + svn_ra_svn__item_t *elt = &SVN_RA_SVN__LIST_ITEM(iproplist, i); if (elt->kind != SVN_RA_SVN_LIST) return svn_error_create( SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, @@ -1262,7 +1411,7 @@ parse_iproplist(apr_array_header_t **inherited_props, svn_pool_clear(iterpool); - SVN_ERR(svn_ra_svn__parse_tuple(elt->u.list, iterpool, "cl", + SVN_ERR(svn_ra_svn__parse_tuple(&elt->u.list, "cl", &parent_rel_path, &iprop_list)); SVN_ERR(svn_ra_svn__parse_proplist(iprop_list, iterpool, &iprops)); new_iprop->path_or_url = apr_pstrdup(result_pool, parent_rel_path); @@ -1292,12 +1441,13 @@ static svn_error_t *ra_svn_get_file(svn_ra_session_t *session, const char *path, { svn_ra_svn__session_baton_t *sess_baton = session->priv; svn_ra_svn_conn_t *conn = sess_baton->conn; - apr_array_header_t *proplist; + svn_ra_svn__list_t *proplist; const char *expected_digest; svn_checksum_t *expected_checksum = NULL; svn_checksum_ctx_t *checksum_ctx; apr_pool_t *iterpool; + path = reparent_path(session, path, pool); SVN_ERR(svn_ra_svn__write_cmd_get_file(conn, pool, path, rev, (props != NULL), (stream != NULL))); SVN_ERR(handle_auth_request(sess_baton, pool)); @@ -1325,22 +1475,22 @@ static svn_error_t *ra_svn_get_file(svn_ra_session_t *session, const char *path, iterpool = svn_pool_create(pool); while (1) { - svn_ra_svn_item_t *item; + svn_ra_svn__item_t *item; svn_pool_clear(iterpool); SVN_ERR(svn_ra_svn__read_item(conn, iterpool, &item)); if (item->kind != SVN_RA_SVN_STRING) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Non-string as part of file contents")); - if (item->u.string->len == 0) + if (item->u.string.len == 0) break; if (expected_checksum) - SVN_ERR(svn_checksum_update(checksum_ctx, item->u.string->data, - item->u.string->len)); + SVN_ERR(svn_checksum_update(checksum_ctx, item->u.string.data, + item->u.string.len)); - SVN_ERR(svn_stream_write(stream, item->u.string->data, - &item->u.string->len)); + SVN_ERR(svn_stream_write(stream, item->u.string.data, + &item->u.string.len)); } svn_pool_destroy(iterpool); @@ -1360,6 +1510,35 @@ static svn_error_t *ra_svn_get_file(svn_ra_session_t *session, const char *path, return SVN_NO_ERROR; } +/* Write the protocol words that correspond to DIRENT_FIELDS to CONN + * and use SCRATCH_POOL for temporary allocations. */ +static svn_error_t * +send_dirent_fields(svn_ra_svn_conn_t *conn, + apr_uint32_t dirent_fields, + apr_pool_t *scratch_pool) +{ + if (dirent_fields & SVN_DIRENT_KIND) + SVN_ERR(svn_ra_svn__write_word(conn, scratch_pool, + SVN_RA_SVN_DIRENT_KIND)); + if (dirent_fields & SVN_DIRENT_SIZE) + SVN_ERR(svn_ra_svn__write_word(conn, scratch_pool, + SVN_RA_SVN_DIRENT_SIZE)); + if (dirent_fields & SVN_DIRENT_HAS_PROPS) + SVN_ERR(svn_ra_svn__write_word(conn, scratch_pool, + SVN_RA_SVN_DIRENT_HAS_PROPS)); + if (dirent_fields & SVN_DIRENT_CREATED_REV) + SVN_ERR(svn_ra_svn__write_word(conn, scratch_pool, + SVN_RA_SVN_DIRENT_CREATED_REV)); + if (dirent_fields & SVN_DIRENT_TIME) + SVN_ERR(svn_ra_svn__write_word(conn, scratch_pool, + SVN_RA_SVN_DIRENT_TIME)); + if (dirent_fields & SVN_DIRENT_LAST_AUTHOR) + SVN_ERR(svn_ra_svn__write_word(conn, scratch_pool, + SVN_RA_SVN_DIRENT_LAST_AUTHOR)); + + return SVN_NO_ERROR; +} + static svn_error_t *ra_svn_get_dir(svn_ra_session_t *session, apr_hash_t **dirents, svn_revnum_t *fetched_rev, @@ -1371,23 +1550,13 @@ static svn_error_t *ra_svn_get_dir(svn_ra_session_t *session, { svn_ra_svn__session_baton_t *sess_baton = session->priv; svn_ra_svn_conn_t *conn = sess_baton->conn; - apr_array_header_t *proplist, *dirlist; + svn_ra_svn__list_t *proplist, *dirlist; int i; + path = reparent_path(session, path, pool); SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w(c(?r)bb(!", "get-dir", path, rev, (props != NULL), (dirents != NULL))); - if (dirent_fields & SVN_DIRENT_KIND) - SVN_ERR(svn_ra_svn__write_word(conn, pool, SVN_RA_SVN_DIRENT_KIND)); - if (dirent_fields & SVN_DIRENT_SIZE) - SVN_ERR(svn_ra_svn__write_word(conn, pool, SVN_RA_SVN_DIRENT_SIZE)); - if (dirent_fields & SVN_DIRENT_HAS_PROPS) - SVN_ERR(svn_ra_svn__write_word(conn, pool, SVN_RA_SVN_DIRENT_HAS_PROPS)); - if (dirent_fields & SVN_DIRENT_CREATED_REV) - SVN_ERR(svn_ra_svn__write_word(conn, pool, SVN_RA_SVN_DIRENT_CREATED_REV)); - if (dirent_fields & SVN_DIRENT_TIME) - SVN_ERR(svn_ra_svn__write_word(conn, pool, SVN_RA_SVN_DIRENT_TIME)); - if (dirent_fields & SVN_DIRENT_LAST_AUTHOR) - SVN_ERR(svn_ra_svn__write_word(conn, pool, SVN_RA_SVN_DIRENT_LAST_AUTHOR)); + SVN_ERR(send_dirent_fields(conn, dirent_fields, pool)); /* Always send the, nominally optional, want-iprops as "false" to workaround a bug in svnserve 1.8.0-1.8.8 that causes the server @@ -1416,12 +1585,12 @@ static svn_error_t *ra_svn_get_dir(svn_ra_session_t *session, svn_dirent_t *dirent; apr_uint64_t size; svn_revnum_t crev; - svn_ra_svn_item_t *elt = &APR_ARRAY_IDX(dirlist, i, svn_ra_svn_item_t); + svn_ra_svn__item_t *elt = &SVN_RA_SVN__LIST_ITEM(dirlist, i); if (elt->kind != SVN_RA_SVN_LIST) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Dirlist element not a list")); - SVN_ERR(svn_ra_svn__parse_tuple(elt->u.list, pool, "cwnbr(?c)(?c)", + SVN_ERR(svn_ra_svn__parse_tuple(&elt->u.list, "cwnbr(?c)(?c)", &name, &kind, &size, &has_props, &crev, &cdate, &cauthor)); @@ -1481,12 +1650,14 @@ static svn_error_t *ra_svn_get_mergeinfo(svn_ra_session_t *session, apr_pool_t *pool) { svn_ra_svn__session_baton_t *sess_baton = session->priv; + svn_ra_svn__parent_t *parent = sess_baton->parent; svn_ra_svn_conn_t *conn = sess_baton->conn; int i; - apr_array_header_t *mergeinfo_tuple; - svn_ra_svn_item_t *elt; + svn_ra_svn__list_t *mergeinfo_tuple; + svn_ra_svn__item_t *elt; const char *path; + paths = reparent_path_array(session, paths, pool); SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w((!", "get-mergeinfo")); for (i = 0; i < paths->nelts; i++) { @@ -1509,16 +1680,23 @@ static svn_error_t *ra_svn_get_mergeinfo(svn_ra_session_t *session, svn_mergeinfo_t for_path; const char *to_parse; - elt = &((svn_ra_svn_item_t *) mergeinfo_tuple->elts)[i]; + elt = &SVN_RA_SVN__LIST_ITEM(mergeinfo_tuple, i); if (elt->kind != SVN_RA_SVN_LIST) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Mergeinfo element is not a list")); - SVN_ERR(svn_ra_svn__parse_tuple(elt->u.list, pool, "cc", + SVN_ERR(svn_ra_svn__parse_tuple(&elt->u.list, "cc", &path, &to_parse)); SVN_ERR(svn_mergeinfo_parse(&for_path, to_parse, pool)); + /* Correct for naughty servers that send "relative" paths with leading slashes! */ - svn_hash_sets(*catalog, path[0] == '/' ? path + 1 :path, for_path); + if (path[0] == '/') + ++path; + + /* Correct for the (potential) difference between client and + server-side session parent paths. */ + path = svn_relpath_skip_ancestor(parent->path->data, path); + svn_hash_sets(*catalog, path, for_path); } } @@ -1540,6 +1718,9 @@ static svn_error_t *ra_svn_update(svn_ra_session_t *session, svn_ra_svn_conn_t *conn = sess_baton->conn; svn_boolean_t recurse = DEPTH_TO_RECURSE(depth); + /* Callbacks may assume that all data is relative the sessions's URL. */ + SVN_ERR(ensure_exact_server_parent(session, scratch_pool)); + /* Tell the server we want to start an update. */ SVN_ERR(svn_ra_svn__write_cmd_update(conn, pool, rev, target, recurse, depth, send_copyfrom_args, @@ -1571,6 +1752,9 @@ ra_svn_switch(svn_ra_session_t *session, svn_ra_svn_conn_t *conn = sess_baton->conn; svn_boolean_t recurse = DEPTH_TO_RECURSE(depth); + /* Callbacks may assume that all data is relative the sessions's URL. */ + SVN_ERR(ensure_exact_server_parent(session, scratch_pool)); + /* Tell the server we want to start a switch. */ SVN_ERR(svn_ra_svn__write_cmd_switch(conn, pool, rev, target, recurse, switch_url, depth, @@ -1596,6 +1780,9 @@ static svn_error_t *ra_svn_status(svn_ra_session_t *session, svn_ra_svn_conn_t *conn = sess_baton->conn; svn_boolean_t recurse = DEPTH_TO_RECURSE(depth); + /* Callbacks may assume that all data is relative the sessions's URL. */ + SVN_ERR(ensure_exact_server_parent(session, pool)); + /* Tell the server we want to start a status operation. */ SVN_ERR(svn_ra_svn__write_cmd_status(conn, pool, target, recurse, rev, depth)); @@ -1623,6 +1810,9 @@ static svn_error_t *ra_svn_diff(svn_ra_session_t *session, svn_ra_svn_conn_t *conn = sess_baton->conn; svn_boolean_t recurse = DEPTH_TO_RECURSE(depth); + /* Callbacks may assume that all data is relative the sessions's URL. */ + SVN_ERR(ensure_exact_server_parent(session, pool)); + /* Tell the server we want to start a diff. */ SVN_ERR(svn_ra_svn__write_cmd_diff(conn, pool, rev, target, recurse, ignore_ancestry, versus_url, @@ -1636,6 +1826,16 @@ static svn_error_t *ra_svn_diff(svn_ra_session_t *session, return SVN_NO_ERROR; } +/* Return TRUE if ITEM matches the word "done". */ +static svn_boolean_t +is_done_response(const svn_ra_svn__item_t *item) +{ + static const svn_string_t str_done = SVN__STATIC_STRING("done"); + + return ( item->kind == SVN_RA_SVN_WORD + && svn_string_compare(&item->u.word, &str_done)); +} + static svn_error_t * perform_ra_svn_log(svn_error_t **outer_error, @@ -1716,23 +1916,23 @@ perform_ra_svn_log(svn_error_t **outer_error, apr_uint64_t has_children_param, invalid_revnum_param; apr_uint64_t has_subtractive_merge_param; svn_string_t *author, *date, *message; - apr_array_header_t *cplist, *rplist; + svn_ra_svn__list_t *cplist, *rplist; svn_log_entry_t *log_entry; svn_boolean_t has_children; svn_boolean_t subtractive_merge = FALSE; apr_uint64_t revprop_count; - svn_ra_svn_item_t *item; + svn_ra_svn__item_t *item; apr_hash_t *cphash; svn_revnum_t rev; svn_pool_clear(iterpool); SVN_ERR(svn_ra_svn__read_item(conn, iterpool, &item)); - if (item->kind == SVN_RA_SVN_WORD && strcmp(item->u.word, "done") == 0) + if (is_done_response(item)) break; if (item->kind != SVN_RA_SVN_LIST) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Log entry not a list")); - SVN_ERR(svn_ra_svn__parse_tuple(item->u.list, iterpool, + SVN_ERR(svn_ra_svn__parse_tuple(&item->u.list, "lr(?s)(?s)(?s)?BBnl?B", &cplist, &rev, &author, &date, &message, &has_children_param, @@ -1774,13 +1974,12 @@ perform_ra_svn_log(svn_error_t **outer_error, const char *copy_path, *action, *kind_str; apr_uint64_t text_mods, prop_mods; svn_revnum_t copy_rev; - svn_ra_svn_item_t *elt = &APR_ARRAY_IDX(cplist, i, - svn_ra_svn_item_t); + svn_ra_svn__item_t *elt = &SVN_RA_SVN__LIST_ITEM(cplist, i); if (elt->kind != SVN_RA_SVN_LIST) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Changed-path entry not a list")); - SVN_ERR(svn_ra_svn__read_data_log_changed_entry(elt->u.list, + SVN_ERR(svn_ra_svn__read_data_log_changed_entry(&elt->u.list, &cpath, &action, ©_path, ©_rev, &kind_str, &text_mods, &prop_mods)); @@ -1810,7 +2009,7 @@ perform_ra_svn_log(svn_error_t **outer_error, - Except if the server sends more than a >= 1 limit top level items - Or when the callback reported a SVN_ERR_CEASE_INVOCATION in an earlier invocation. */ - if (! (limit && (nest_level == 0) && (++nreceived > limit)) + if (! ((limit > 0) && (nest_level == 0) && (++nreceived > limit)) && ! *outer_error) { svn_error_t *err; @@ -1838,7 +2037,7 @@ perform_ra_svn_log(svn_error_t **outer_error, SVN_PROP_REVISION_LOG, message); err = receiver(receiver_baton, log_entry, iterpool); - if (err && err->apr_err == SVN_ERR_CEASE_INVOCATION) + if (svn_error_find_cause(err, SVN_ERR_CEASE_INVOCATION)) { *outer_error = svn_error_trace( svn_error_compose_create(*outer_error, err)); @@ -1878,6 +2077,16 @@ ra_svn_log(svn_ra_session_t *session, svn_error_t *outer_error = NULL; svn_error_t *err; + /* If we don't specify paths, the session's URL is implied. + + Because the paths passed to callbacks are always relative the repos + root, there is no need *always* sync the parent URLs despite invoking + user-provided callbacks. */ + if (paths) + paths = reparent_path_array(session, paths, pool); + else + SVN_ERR(ensure_exact_server_parent(session, pool)); + err = svn_error_trace(perform_ra_svn_log(&outer_error, session, paths, start, end, @@ -1903,6 +2112,7 @@ static svn_error_t *ra_svn_check_path(svn_ra_session_t *session, svn_ra_svn_conn_t *conn = sess_baton->conn; const char *kind_word; + path = reparent_path(session, path, pool); SVN_ERR(svn_ra_svn__write_cmd_check_path(conn, pool, path, rev)); SVN_ERR(handle_auth_request(sess_baton, pool)); SVN_ERR(svn_ra_svn__read_cmd_response(conn, pool, "w", &kind_word)); @@ -1929,9 +2139,10 @@ static svn_error_t *ra_svn_stat(svn_ra_session_t *session, { svn_ra_svn__session_baton_t *sess_baton = session->priv; svn_ra_svn_conn_t *conn = sess_baton->conn; - apr_array_header_t *list = NULL; + svn_ra_svn__list_t *list = NULL; svn_dirent_t *the_dirent; + path = reparent_path(session, path, pool); SVN_ERR(svn_ra_svn__write_cmd_stat(conn, pool, path, rev)); SVN_ERR(handle_unsupported_cmd(handle_auth_request(sess_baton, pool), N_("'stat' not implemented"))); @@ -1948,7 +2159,7 @@ static svn_error_t *ra_svn_stat(svn_ra_session_t *session, svn_revnum_t crev; apr_uint64_t size; - SVN_ERR(svn_ra_svn__parse_tuple(list, pool, "wnbr(?c)(?c)", + SVN_ERR(svn_ra_svn__parse_tuple(list, "wnbr(?c)(?c)", &kind, &size, &has_props, &crev, &cdate, &cauthor)); @@ -1978,8 +2189,11 @@ static svn_error_t *ra_svn_get_locations(svn_ra_session_t *session, svn_ra_svn_conn_t *conn = sess_baton->conn; svn_revnum_t revision; svn_boolean_t is_done; + apr_pool_t *iterpool; int i; + path = reparent_path(session, path, pool); + /* Transmit the parameters. */ SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w(cr(!", "get-locations", path, peg_revision)); @@ -1998,21 +2212,25 @@ static svn_error_t *ra_svn_get_locations(svn_ra_session_t *session, /* Read the hash items. */ is_done = FALSE; *locations = apr_hash_make(pool); + iterpool = svn_pool_create(pool); while (!is_done) { - svn_ra_svn_item_t *item; + svn_ra_svn__item_t *item; const char *ret_path; - SVN_ERR(svn_ra_svn__read_item(conn, pool, &item)); - if (item->kind == SVN_RA_SVN_WORD && strcmp(item->u.word, "done") == 0) + svn_pool_clear(iterpool); + SVN_ERR(svn_ra_svn__read_item(conn, iterpool, &item)); + if (is_done_response(item)) is_done = 1; else if (item->kind != SVN_RA_SVN_LIST) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Location entry not a list")); else { - SVN_ERR(svn_ra_svn__parse_tuple(item->u.list, pool, "rc", + SVN_ERR(svn_ra_svn__parse_tuple(&item->u.list, "rc", &revision, &ret_path)); + + /* This also makes RET_PATH live in POOL rather than ITERPOOL. */ ret_path = svn_fspath__canonicalize(ret_path, pool); apr_hash_set(*locations, apr_pmemdup(pool, &revision, sizeof(revision)), @@ -2020,20 +2238,23 @@ static svn_error_t *ra_svn_get_locations(svn_ra_session_t *session, } } + svn_pool_destroy(iterpool); + /* Read the response. This is so the server would have a chance to * report an error. */ return svn_error_trace(svn_ra_svn__read_cmd_response(conn, pool, "")); } static svn_error_t * -ra_svn_get_location_segments(svn_ra_session_t *session, - const char *path, - svn_revnum_t peg_revision, - svn_revnum_t start_rev, - svn_revnum_t end_rev, - svn_location_segment_receiver_t receiver, - void *receiver_baton, - apr_pool_t *pool) +perform_get_location_segments(svn_error_t **outer_error, + svn_ra_session_t *session, + const char *path, + svn_revnum_t peg_revision, + svn_revnum_t start_rev, + svn_revnum_t end_rev, + svn_location_segment_receiver_t receiver, + void *receiver_baton, + apr_pool_t *pool) { svn_ra_svn__session_baton_t *sess_baton = session->priv; svn_ra_svn_conn_t *conn = sess_baton->conn; @@ -2055,12 +2276,12 @@ ra_svn_get_location_segments(svn_ra_session_t *session, while (!is_done) { svn_revnum_t range_start, range_end; - svn_ra_svn_item_t *item; + svn_ra_svn__item_t *item; const char *ret_path; svn_pool_clear(iterpool); SVN_ERR(svn_ra_svn__read_item(conn, iterpool, &item)); - if (item->kind == SVN_RA_SVN_WORD && strcmp(item->u.word, "done") == 0) + if (is_done_response(item)) is_done = 1; else if (item->kind != SVN_RA_SVN_LIST) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, @@ -2069,7 +2290,7 @@ ra_svn_get_location_segments(svn_ra_session_t *session, { svn_location_segment_t *segment = apr_pcalloc(iterpool, sizeof(*segment)); - SVN_ERR(svn_ra_svn__parse_tuple(item->u.list, iterpool, "rr(?c)", + SVN_ERR(svn_ra_svn__parse_tuple(&item->u.list, "rr(?c)", &range_start, &range_end, &ret_path)); if (! (SVN_IS_VALID_REVNUM(range_start) && SVN_IS_VALID_REVNUM(range_end))) @@ -2080,7 +2301,17 @@ ra_svn_get_location_segments(svn_ra_session_t *session, segment->path = ret_path; segment->range_start = range_start; segment->range_end = range_end; - SVN_ERR(receiver(segment, receiver_baton, iterpool)); + + if (!*outer_error) + { + svn_error_t *err = svn_error_trace(receiver(segment, receiver_baton, + iterpool)); + + if (svn_error_find_cause(err, SVN_ERR_CEASE_INVOCATION)) + *outer_error = err; + else + SVN_ERR(err); + } } } svn_pool_destroy(iterpool); @@ -2092,6 +2323,27 @@ ra_svn_get_location_segments(svn_ra_session_t *session, return SVN_NO_ERROR; } +static svn_error_t * +ra_svn_get_location_segments(svn_ra_session_t *session, + const char *path, + svn_revnum_t peg_revision, + svn_revnum_t start_rev, + svn_revnum_t end_rev, + svn_location_segment_receiver_t receiver, + void *receiver_baton, + apr_pool_t *pool) +{ + svn_error_t *outer_err = SVN_NO_ERROR; + svn_error_t *err; + + path = reparent_path(session, path, pool); + err = svn_error_trace( + perform_get_location_segments(&outer_err, session, path, + peg_revision, start_rev, end_rev, + receiver, receiver_baton, pool)); + return svn_error_compose_create(outer_err, err); +} + static svn_error_t *ra_svn_get_file_revs(svn_ra_session_t *session, const char *path, svn_revnum_t start, svn_revnum_t end, @@ -2109,6 +2361,7 @@ static svn_error_t *ra_svn_get_file_revs(svn_ra_session_t *session, rev_pool = svn_pool_create(pool); chunk_pool = svn_pool_create(pool); + path = reparent_path(session, path, pool); SVN_ERR(svn_ra_svn__write_cmd_get_file_revs(sess_baton->conn, pool, path, start, end, include_merged_revisions)); @@ -2119,10 +2372,10 @@ static svn_error_t *ra_svn_get_file_revs(svn_ra_session_t *session, while (1) { - apr_array_header_t *rev_proplist, *proplist; + svn_ra_svn__list_t *rev_proplist, *proplist; apr_uint64_t merged_rev_param; apr_array_header_t *props; - svn_ra_svn_item_t *item; + svn_ra_svn__item_t *item; apr_hash_t *rev_props; svn_revnum_t rev; const char *p; @@ -2133,7 +2386,7 @@ static svn_error_t *ra_svn_get_file_revs(svn_ra_session_t *session, svn_pool_clear(rev_pool); svn_pool_clear(chunk_pool); SVN_ERR(svn_ra_svn__read_item(sess_baton->conn, rev_pool, &item)); - if (item->kind == SVN_RA_SVN_WORD && strcmp(item->u.word, "done") == 0) + if (is_done_response(item)) break; /* Either we've got a correct revision or we will error out below. */ had_revision = TRUE; @@ -2141,7 +2394,7 @@ static svn_error_t *ra_svn_get_file_revs(svn_ra_session_t *session, return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Revision entry not a list")); - SVN_ERR(svn_ra_svn__parse_tuple(item->u.list, rev_pool, + SVN_ERR(svn_ra_svn__parse_tuple(&item->u.list, "crll?B", &p, &rev, &rev_proplist, &proplist, &merged_rev_param)); p = svn_fspath__canonicalize(p, rev_pool); @@ -2157,7 +2410,7 @@ static svn_error_t *ra_svn_get_file_revs(svn_ra_session_t *session, if (item->kind != SVN_RA_SVN_STRING) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Text delta chunk not a string")); - has_txdelta = item->u.string->len > 0; + has_txdelta = item->u.string.len > 0; SVN_ERR(handler(handler_baton, p, rev, rev_props, merged_rev, has_txdelta ? &d_handler : NULL, &d_baton, @@ -2173,13 +2426,13 @@ static svn_error_t *ra_svn_get_file_revs(svn_ra_session_t *session, rev_pool); else stream = NULL; - while (item->u.string->len > 0) + while (item->u.string.len > 0) { apr_size_t size; - size = item->u.string->len; + size = item->u.string.len; if (stream) - SVN_ERR(svn_stream_write(stream, item->u.string->data, &size)); + SVN_ERR(svn_stream_write(stream, item->u.string.data, &size)); svn_pool_clear(chunk_pool); SVN_ERR(svn_ra_svn__read_item(sess_baton->conn, chunk_pool, @@ -2221,7 +2474,7 @@ static svn_error_t *ra_svn_lock_compat(svn_ra_session_t *session, { svn_ra_svn__session_baton_t *sess = session->priv; svn_ra_svn_conn_t* conn = sess->conn; - apr_array_header_t *list; + svn_ra_svn__list_t *list; apr_hash_index_t *hi; apr_pool_t *iterpool = svn_pool_create(pool); @@ -2292,7 +2545,7 @@ static svn_error_t *ra_svn_unlock_compat(svn_ra_session_t *session, const void *key; const char *path; void *val; - const char *token; + const svn_string_t *token; svn_error_t *err, *callback_err = NULL; svn_pool_clear(iterpool); @@ -2300,7 +2553,7 @@ static svn_error_t *ra_svn_unlock_compat(svn_ra_session_t *session, apr_hash_this(hi, &key, NULL, &val); path = key; if (strcmp(val, "") != 0) - token = val; + token = svn_string_create(val, iterpool); else token = NULL; @@ -2347,6 +2600,7 @@ static svn_error_t *ra_svn_lock(svn_ra_session_t *session, svn_error_t *err; apr_pool_t *iterpool = svn_pool_create(pool); + path_revs = reparent_path_hash(session, path_revs, pool, pool); SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w((?c)b(!", "lock-many", comment, steal_lock)); @@ -2384,13 +2638,13 @@ static svn_error_t *ra_svn_lock(svn_ra_session_t *session, /* Loop over responses to get lock information. */ for (hi = apr_hash_first(pool, path_revs); hi; hi = apr_hash_next(hi)) { - svn_ra_svn_item_t *elt; + svn_ra_svn__item_t *elt; const void *key; const char *path; svn_error_t *callback_err; const char *status; svn_lock_t *lock; - apr_array_header_t *list; + svn_ra_svn__list_t *list; apr_hash_this(hi, &key, NULL, NULL); path = key; @@ -2402,18 +2656,17 @@ static svn_error_t *ra_svn_lock(svn_ra_session_t *session, the middle of the request list. If this happens, it will transmit "done" to end the lock-info early, and then the overall command response will talk about the fatal error. */ - if (elt->kind == SVN_RA_SVN_WORD && strcmp(elt->u.word, "done") == 0) + if (is_done_response(elt)) break; if (elt->kind != SVN_RA_SVN_LIST) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Lock response not a list")); - SVN_ERR(svn_ra_svn__parse_tuple(elt->u.list, iterpool, "wl", &status, - &list)); + SVN_ERR(svn_ra_svn__parse_tuple(&elt->u.list, "wl", &status, &list)); if (strcmp(status, "failure") == 0) - err = svn_ra_svn__handle_failure_status(list, iterpool); + err = svn_ra_svn__handle_failure_status(list); else if (strcmp(status, "success") == 0) { SVN_ERR(parse_lock(list, iterpool, &lock)); @@ -2440,10 +2693,10 @@ static svn_error_t *ra_svn_lock(svn_ra_session_t *session, read the final "done" from the server. */ if (!hi) { - svn_ra_svn_item_t *elt; + svn_ra_svn__item_t *elt; SVN_ERR(svn_ra_svn__read_item(conn, pool, &elt)); - if (elt->kind != SVN_RA_SVN_WORD || strcmp(elt->u.word, "done") != 0) + if (!is_done_response(elt)) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Didn't receive end marker for lock " "responses")); @@ -2472,6 +2725,7 @@ static svn_error_t *ra_svn_unlock(svn_ra_session_t *session, svn_error_t *err; const char *path; + path_tokens = reparent_path_hash(session, path_tokens, pool, pool); SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w(b(!", "unlock-many", break_lock)); @@ -2513,11 +2767,11 @@ static svn_error_t *ra_svn_unlock(svn_ra_session_t *session, /* Loop over responses to unlock files. */ for (hi = apr_hash_first(pool, path_tokens); hi; hi = apr_hash_next(hi)) { - svn_ra_svn_item_t *elt; + svn_ra_svn__item_t *elt; const void *key; svn_error_t *callback_err; const char *status; - apr_array_header_t *list; + svn_ra_svn__list_t *list; svn_pool_clear(iterpool); @@ -2527,7 +2781,7 @@ static svn_error_t *ra_svn_unlock(svn_ra_session_t *session, the middle of the request list. If this happens, it will transmit "done" to end the lock-info early, and then the overall command response will talk about the fatal error. */ - if (elt->kind == SVN_RA_SVN_WORD && (strcmp(elt->u.word, "done") == 0)) + if (is_done_response(elt)) break; apr_hash_this(hi, &key, NULL, NULL); @@ -2537,14 +2791,13 @@ static svn_error_t *ra_svn_unlock(svn_ra_session_t *session, return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Unlock response not a list")); - SVN_ERR(svn_ra_svn__parse_tuple(elt->u.list, iterpool, "wl", &status, - &list)); + SVN_ERR(svn_ra_svn__parse_tuple(&elt->u.list, "wl", &status, &list)); if (strcmp(status, "failure") == 0) - err = svn_ra_svn__handle_failure_status(list, iterpool); + err = svn_ra_svn__handle_failure_status(list); else if (strcmp(status, "success") == 0) { - SVN_ERR(svn_ra_svn__parse_tuple(list, iterpool, "c", &path)); + SVN_ERR(svn_ra_svn__parse_tuple(list, "c", &path)); err = SVN_NO_ERROR; } else @@ -2567,10 +2820,10 @@ static svn_error_t *ra_svn_unlock(svn_ra_session_t *session, read the final "done" from the server. */ if (!hi) { - svn_ra_svn_item_t *elt; + svn_ra_svn__item_t *elt; SVN_ERR(svn_ra_svn__read_item(conn, pool, &elt)); - if (elt->kind != SVN_RA_SVN_WORD || strcmp(elt->u.word, "done") != 0) + if (! is_done_response(elt)) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Didn't receive end marker for unlock " "responses")); @@ -2590,8 +2843,9 @@ static svn_error_t *ra_svn_get_lock(svn_ra_session_t *session, { svn_ra_svn__session_baton_t *sess = session->priv; svn_ra_svn_conn_t* conn = sess->conn; - apr_array_header_t *list; + svn_ra_svn__list_t *list; + path = reparent_path(session, path, pool); SVN_ERR(svn_ra_svn__write_cmd_get_lock(conn, pool, path)); /* Servers before 1.2 doesn't support locking. Check this here. */ @@ -2635,12 +2889,13 @@ static svn_error_t *ra_svn_get_locks(svn_ra_session_t *session, { svn_ra_svn__session_baton_t *sess = session->priv; svn_ra_svn_conn_t* conn = sess->conn; - apr_array_header_t *list; + svn_ra_svn__list_t *list; const char *full_url, *abs_path; int i; /* Figure out the repository abspath from PATH. */ - full_url = svn_path_url_add_component2(sess->url, path, pool); + full_url = svn_path_url_add_component2(sess->parent->client_url->data, + path, pool); SVN_ERR(path_relative_to_root(session, &abs_path, full_url, pool)); abs_path = svn_fspath__canonicalize(abs_path, pool); @@ -2658,12 +2913,12 @@ static svn_error_t *ra_svn_get_locks(svn_ra_session_t *session, for (i = 0; i < list->nelts; ++i) { svn_lock_t *lock; - svn_ra_svn_item_t *elt = &APR_ARRAY_IDX(list, i, svn_ra_svn_item_t); + svn_ra_svn__item_t *elt = &SVN_RA_SVN__LIST_ITEM(list, i); if (elt->kind != SVN_RA_SVN_LIST) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Lock element not a list")); - SVN_ERR(parse_lock(elt->u.list, pool, &lock)); + SVN_ERR(parse_lock(&elt->u.list, pool, &lock)); /* Filter out unwanted paths. Since Subversion only allows locks on files, we can treat depth=immediates the same as @@ -2701,6 +2956,9 @@ static svn_error_t *ra_svn_replay(svn_ra_session_t *session, { svn_ra_svn__session_baton_t *sess = session->priv; + /* Complex EDITOR callbacks may rely on client and server parent path + being in sync. */ + SVN_ERR(ensure_exact_server_parent(session, pool)); SVN_ERR(svn_ra_svn__write_cmd_replay(sess->conn, pool, revision, low_water_mark, send_deltas)); @@ -2731,6 +2989,9 @@ ra_svn_replay_range(svn_ra_session_t *session, svn_revnum_t rev; svn_boolean_t drive_aborted = FALSE; + /* Complex EDITOR callbacks may rely on client and server parent path + being in sync. */ + SVN_ERR(ensure_exact_server_parent(session, pool)); SVN_ERR(svn_ra_svn__write_cmd_replay_range(sess->conn, pool, start_revision, end_revision, low_water_mark, send_deltas)); @@ -2746,16 +3007,22 @@ ra_svn_replay_range(svn_ra_session_t *session, void *edit_baton; apr_hash_t *rev_props; const char *word; - apr_array_header_t *list; + svn_ra_svn__list_t *list; svn_pool_clear(iterpool); SVN_ERR(svn_ra_svn__read_tuple(sess->conn, iterpool, "wl", &word, &list)); + if (strcmp(word, "revprops") != 0) - return svn_error_createf(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, - _("Expected 'revprops', found '%s'"), - word); + { + if (strcmp(word, "failure") == 0) + SVN_ERR(svn_ra_svn__handle_failure_status(list)); + + return svn_error_createf(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, + _("Expected 'revprops', found '%s'"), + word); + } SVN_ERR(svn_ra_svn__parse_proplist(list, iterpool, &rev_props)); @@ -2805,6 +3072,7 @@ ra_svn_has_capability(svn_ra_session_t *session, SVN_RA_SVN_CAP_EPHEMERAL_TXNPROPS}, {SVN_RA_CAPABILITY_GET_FILE_REVS_REVERSE, SVN_RA_SVN_CAP_GET_FILE_REVS_REVERSE}, + {SVN_RA_CAPABILITY_LIST, SVN_RA_SVN_CAP_LIST}, {NULL, NULL} /* End of list marker */ }; @@ -2838,6 +3106,8 @@ ra_svn_get_deleted_rev(svn_ra_session_t *session, svn_ra_svn__session_baton_t *sess_baton = session->priv; svn_ra_svn_conn_t *conn = sess_baton->conn; + path = reparent_path(session, path, pool); + /* Transmit the parameters. */ SVN_ERR(svn_ra_svn__write_cmd_get_deleted_rev(conn, pool, path, peg_revision, end_revision)); @@ -2872,9 +3142,10 @@ ra_svn_get_inherited_props(svn_ra_session_t *session, { svn_ra_svn__session_baton_t *sess_baton = session->priv; svn_ra_svn_conn_t *conn = sess_baton->conn; - apr_array_header_t *iproplist; + svn_ra_svn__list_t *iproplist; svn_boolean_t iprop_capable; + path = reparent_path(session, path, scratch_pool); SVN_ERR(ra_svn_has_capability(session, &iprop_capable, SVN_RA_CAPABILITY_INHERITED_PROPS, scratch_pool)); @@ -2894,6 +3165,83 @@ ra_svn_get_inherited_props(svn_ra_session_t *session, return SVN_NO_ERROR; } +static svn_error_t * +ra_svn_list(svn_ra_session_t *session, + const char *path, + svn_revnum_t revision, + const apr_array_header_t *patterns, + svn_depth_t depth, + apr_uint32_t dirent_fields, + svn_ra_dirent_receiver_t receiver, + void *receiver_baton, + apr_pool_t *scratch_pool) +{ + svn_ra_svn__session_baton_t *sess_baton = session->priv; + svn_ra_svn_conn_t *conn = sess_baton->conn; + int i; + apr_pool_t *iterpool = svn_pool_create(scratch_pool); + + path = reparent_path(session, path, scratch_pool); + + /* Send the list request. */ + SVN_ERR(svn_ra_svn__write_tuple(conn, scratch_pool, "w(c(?r)w(!", "list", + path, revision, svn_depth_to_word(depth))); + SVN_ERR(send_dirent_fields(conn, dirent_fields, scratch_pool)); + + if (patterns) + { + SVN_ERR(svn_ra_svn__write_tuple(conn, scratch_pool, "!)(!")); + + for (i = 0; i < patterns->nelts; ++i) + { + const char *pattern = APR_ARRAY_IDX(patterns, i, const char *); + SVN_ERR(svn_ra_svn__write_cstring(conn, scratch_pool, pattern)); + } + } + + SVN_ERR(svn_ra_svn__write_tuple(conn, scratch_pool, "!))")); + + /* Handle auth request by server */ + SVN_ERR(handle_auth_request(sess_baton, scratch_pool)); + + /* Read and process list response. */ + while (1) + { + svn_ra_svn__item_t *item; + const char *dirent_path; + const char *kind_word, *date; + svn_dirent_t dirent = { 0 }; + + svn_pool_clear(iterpool); + + /* Read the next dirent or bail out on "done", respectively */ + SVN_ERR(svn_ra_svn__read_item(conn, iterpool, &item)); + if (is_done_response(item)) + break; + if (item->kind != SVN_RA_SVN_LIST) + return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, + _("List entry not a list")); + SVN_ERR(svn_ra_svn__parse_tuple(&item->u.list, + "cw?(?n)(?b)(?r)(?c)(?c)", + &dirent_path, &kind_word, &dirent.size, + &dirent.has_props, &dirent.created_rev, + &date, &dirent.last_author)); + + /* Convert data. */ + dirent.kind = svn_node_kind_from_word(kind_word); + if (date) + SVN_ERR(svn_time_from_cstring(&dirent.time, date, iterpool)); + + /* Invoke RECEIVER */ + SVN_ERR(receiver(dirent_path, &dirent, receiver_baton, iterpool)); + } + svn_pool_destroy(iterpool); + + /* Read the actual command response. */ + SVN_ERR(svn_ra_svn__read_cmd_response(conn, scratch_pool, "")); + return SVN_NO_ERROR; +} + static const svn_ra__vtable_t ra_svn_vtable = { svn_ra_svn_version, ra_svn_get_description, @@ -2931,8 +3279,12 @@ static const svn_ra__vtable_t ra_svn_vtable = { ra_svn_has_capability, ra_svn_replay_range, ra_svn_get_deleted_rev, + ra_svn_get_inherited_props, + NULL /* ra_set_svn_ra_open */, + ra_svn_list, ra_svn_register_editor_shim_callbacks, - ra_svn_get_inherited_props + NULL /* commit_ev2 */, + NULL /* replay_range_ev2 */ }; svn_error_t * diff --git a/subversion/libsvn_ra_svn/cram.c b/subversion/libsvn_ra_svn/cram.c index b92f37b4a172..0a694b46d027 100644 --- a/subversion/libsvn_ra_svn/cram.c +++ b/subversion/libsvn_ra_svn/cram.c @@ -140,7 +140,7 @@ svn_error_t *svn_ra_svn_cram_server(svn_ra_svn_conn_t *conn, apr_pool_t *pool, char hostbuf[APRMAXHOSTLEN + 1]; unsigned char cdigest[APR_MD5_DIGESTSIZE], sdigest[APR_MD5_DIGESTSIZE]; const char *challenge, *sep, *password; - svn_ra_svn_item_t *item; + svn_ra_svn__item_t *item; svn_string_t *resp; *success = FALSE; @@ -160,7 +160,7 @@ svn_error_t *svn_ra_svn_cram_server(svn_ra_svn_conn_t *conn, apr_pool_t *pool, SVN_ERR(svn_ra_svn__read_item(conn, pool, &item)); if (item->kind != SVN_RA_SVN_STRING) /* Very wrong; don't report failure */ return SVN_NO_ERROR; - resp = item->u.string; + resp = &item->u.string; sep = strrchr(resp->data, ' '); if (!sep || resp->len - (sep + 1 - resp->data) != APR_MD5_DIGESTSIZE * 2 || !hex_decode(cdigest, sep + 1)) diff --git a/subversion/libsvn_ra_svn/cyrus_auth.c b/subversion/libsvn_ra_svn/cyrus_auth.c index ac94a485a44f..66cefa66cc41 100644 --- a/subversion/libsvn_ra_svn/cyrus_auth.c +++ b/subversion/libsvn_ra_svn/cyrus_auth.c @@ -68,7 +68,7 @@ static apr_status_t sasl_done_cb(void *data) apr_initialize()/apr_terminate() more than once. */ svn_ra_svn__sasl_status = 0; if (svn_atomic_dec(&sasl_ctx_count) == 0) - sasl_done(); + svn_sasl__done(); return APR_SUCCESS; } @@ -174,10 +174,10 @@ svn_ra_svn__sasl_common_init(apr_pool_t *pool) apr_pool_cleanup_register(sasl_pool, NULL, sasl_done_cb, apr_pool_cleanup_null); #if APR_HAS_THREADS - sasl_set_mutex(sasl_mutex_alloc_cb, - sasl_mutex_lock_cb, - sasl_mutex_unlock_cb, - sasl_mutex_free_cb); + svn_sasl__set_mutex(sasl_mutex_alloc_cb, + sasl_mutex_lock_cb, + sasl_mutex_unlock_cb, + sasl_mutex_free_cb); free_mutexes = apr_array_make(sasl_pool, 0, sizeof(svn_mutex__t *)); SVN_ERR(svn_mutex__init(&array_mutex, TRUE, sasl_pool)); @@ -223,7 +223,7 @@ get_sasl_error(sasl_conn_t *sasl_ctx, int result, apr_pool_t *result_pool) return apr_psprintf(result_pool, _("SASL authentication error: %s%s"), - sasl_errdetail(sasl_ctx), sasl_errno_msg); + svn_sasl__errdetail(sasl_ctx), sasl_errno_msg); } static svn_error_t *sasl_init_cb(void *baton, apr_pool_t *pool) @@ -232,7 +232,7 @@ static svn_error_t *sasl_init_cb(void *baton, apr_pool_t *pool) SVN_ERR(svn_ra_svn__sasl_common_init(pool)); clear_sasl_errno(); - result = sasl_client_init(NULL); + result = svn_sasl__client_init(NULL); if (result != SASL_OK) { const char *sasl_errno_msg = get_sasl_errno_msg(result, pool); @@ -240,7 +240,7 @@ static svn_error_t *sasl_init_cb(void *baton, apr_pool_t *pool) return svn_error_createf (SVN_ERR_RA_NOT_AUTHORIZED, NULL, _("Could not initialized the SASL library: %s%s"), - sasl_errstring(result, NULL, NULL), + svn_sasl__errstring(result, NULL, NULL), sasl_errno_msg); } @@ -257,9 +257,9 @@ svn_error_t *svn_ra_svn__sasl_init(void) static apr_status_t sasl_dispose_cb(void *data) { sasl_conn_t *sasl_ctx = data; - sasl_dispose(&sasl_ctx); + svn_sasl__dispose(&sasl_ctx); if (svn_atomic_dec(&sasl_ctx_count) == 0) - sasl_done(); + svn_sasl__done(); return APR_SUCCESS; } @@ -403,17 +403,17 @@ static svn_error_t *new_sasl_ctx(sasl_conn_t **sasl_ctx, int result; clear_sasl_errno(); - result = sasl_client_new(SVN_RA_SVN_SASL_NAME, - hostname, local_addrport, remote_addrport, - callbacks, SASL_SUCCESS_DATA, - sasl_ctx); + result = svn_sasl__client_new(SVN_RA_SVN_SASL_NAME, + hostname, local_addrport, remote_addrport, + callbacks, SASL_SUCCESS_DATA, + sasl_ctx); if (result != SASL_OK) { const char *sasl_errno_msg = get_sasl_errno_msg(result, pool); return svn_error_createf(SVN_ERR_RA_NOT_AUTHORIZED, NULL, _("Could not create SASL context: %s%s"), - sasl_errstring(result, NULL, NULL), + svn_sasl__errstring(result, NULL, NULL), sasl_errno_msg); } svn_atomic_inc(&sasl_ctx_count); @@ -427,8 +427,8 @@ static svn_error_t *new_sasl_ctx(sasl_conn_t **sasl_ctx, should be the username, but since SASL doesn't seem to use it on the client side, any non-empty string will do. */ clear_sasl_errno(); - result = sasl_setprop(*sasl_ctx, - SASL_AUTH_EXTERNAL, " "); + result = svn_sasl__setprop(*sasl_ctx, + SASL_AUTH_EXTERNAL, " "); if (result != SASL_OK) return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL, get_sasl_error(*sasl_ctx, result, pool)); @@ -436,7 +436,7 @@ static svn_error_t *new_sasl_ctx(sasl_conn_t **sasl_ctx, /* Set security properties. */ svn_ra_svn__default_secprops(&secprops); - sasl_setprop(*sasl_ctx, SASL_SEC_PROPS, &secprops); + svn_sasl__setprop(*sasl_ctx, SASL_SEC_PROPS, &secprops); return SVN_NO_ERROR; } @@ -460,12 +460,12 @@ static svn_error_t *try_auth(svn_ra_svn__session_baton_t *sess, { again = FALSE; clear_sasl_errno(); - result = sasl_client_start(sasl_ctx, - mechstring, - &client_interact, - &out, - &outlen, - &mech); + result = svn_sasl__client_start(sasl_ctx, + mechstring, + &client_interact, + &out, + &outlen, + &mech); switch (result) { case SASL_OK: @@ -531,12 +531,12 @@ static svn_error_t *try_auth(svn_ra_svn__session_baton_t *sess, in = svn_base64_decode_string(in, pool); clear_sasl_errno(); - result = sasl_client_step(sasl_ctx, - in->data, - (const unsigned int) in->len, - &client_interact, - &out, /* Filled in by SASL. */ - &outlen); + result = svn_sasl__client_step(sasl_ctx, + in->data, + (const unsigned int) in->len, + &client_interact, + &out, /* Filled in by SASL. */ + &outlen); if (result != SASL_OK && result != SASL_CONTINUE) return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL, @@ -620,9 +620,9 @@ static svn_error_t *sasl_read_cb(void *baton, char *buffer, apr_size_t *len) return SVN_NO_ERROR; } clear_sasl_errno(); - result = sasl_decode(sasl_baton->ctx, buffer, (unsigned int) len2, - &sasl_baton->read_buf, - &sasl_baton->read_len); + result = svn_sasl__decode(sasl_baton->ctx, buffer, (unsigned int) len2, + &sasl_baton->read_buf, + &sasl_baton->read_len); if (result != SASL_OK) return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL, get_sasl_error(sasl_baton->ctx, result, @@ -662,9 +662,9 @@ sasl_write_cb(void *baton, const char *buffer, apr_size_t *len) /* Make sure we don't write too much. */ *len = (*len > sasl_baton->maxsize) ? sasl_baton->maxsize : *len; clear_sasl_errno(); - result = sasl_encode(sasl_baton->ctx, buffer, (unsigned int) *len, - &sasl_baton->write_buf, - &sasl_baton->write_len); + result = svn_sasl__encode(sasl_baton->ctx, buffer, (unsigned int) *len, + &sasl_baton->write_buf, + &sasl_baton->write_len); if (result != SASL_OK) return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL, @@ -725,7 +725,7 @@ svn_error_t *svn_ra_svn__enable_sasl_encryption(svn_ra_svn_conn_t *conn, /* Get the strength of the security layer. */ clear_sasl_errno(); - result = sasl_getprop(sasl_ctx, SASL_SSF, (void*) &ssfp); + result = svn_sasl__getprop(sasl_ctx, SASL_SSF, (void*) &ssfp); if (result != SASL_OK) return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL, get_sasl_error(sasl_ctx, result, pool)); @@ -745,7 +745,7 @@ svn_error_t *svn_ra_svn__enable_sasl_encryption(svn_ra_svn_conn_t *conn, /* Find out the maximum input size for sasl_encode. */ clear_sasl_errno(); - result = sasl_getprop(sasl_ctx, SASL_MAXOUTBUF, &maxsize); + result = svn_sasl__getprop(sasl_ctx, SASL_MAXOUTBUF, &maxsize); if (result != SASL_OK) return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL, get_sasl_error(sasl_ctx, result, pool)); @@ -756,9 +756,10 @@ svn_error_t *svn_ra_svn__enable_sasl_encryption(svn_ra_svn_conn_t *conn, if (conn->read_end > conn->read_ptr) { clear_sasl_errno(); - result = sasl_decode(sasl_ctx, conn->read_ptr, - (unsigned int) (conn->read_end - conn->read_ptr), - &sasl_baton->read_buf, &sasl_baton->read_len); + result = svn_sasl__decode( + sasl_ctx, conn->read_ptr, + (unsigned int) (conn->read_end - conn->read_ptr), + &sasl_baton->read_buf, &sasl_baton->read_len); if (result != SASL_OK) return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL, get_sasl_error(sasl_ctx, result, pool)); @@ -828,7 +829,7 @@ svn_error_t *svn_ra_svn__get_addresses(const char **local_addrport, svn_error_t * svn_ra_svn__do_cyrus_auth(svn_ra_svn__session_baton_t *sess, - const apr_array_header_t *mechlist, + const svn_ra_svn__list_t *mechlist, const char *realm, apr_pool_t *pool) { apr_pool_t *subpool; @@ -856,11 +857,11 @@ svn_ra_svn__do_cyrus_auth(svn_ra_svn__session_baton_t *sess, /* Create a string containing the list of mechanisms, separated by spaces. */ for (i = 0; i < mechlist->nelts; i++) { - svn_ra_svn_item_t *elt = &APR_ARRAY_IDX(mechlist, i, svn_ra_svn_item_t); + svn_ra_svn__item_t *elt = &SVN_RA_SVN__LIST_ITEM(mechlist, i); mechstring = apr_pstrcat(pool, mechstring, i == 0 ? "" : " ", - elt->u.word, SVN_VA_NULL); + elt->u.word.data, SVN_VA_NULL); } } diff --git a/subversion/libsvn_ra_svn/deprecated.c b/subversion/libsvn_ra_svn/deprecated.c index 7f0c8fde2edc..a4ff18e180e1 100644 --- a/subversion/libsvn_ra_svn/deprecated.c +++ b/subversion/libsvn_ra_svn/deprecated.c @@ -110,7 +110,12 @@ svn_ra_svn_read_item(svn_ra_svn_conn_t *conn, apr_pool_t *pool, svn_ra_svn_item_t **item) { - return svn_error_trace(svn_ra_svn__read_item(conn, pool, item)); + svn_ra_svn__item_t *temp; + SVN_ERR(svn_ra_svn__read_item(conn, pool, &temp)); + *item = apr_pcalloc(pool, sizeof(**item)); + svn_ra_svn__to_public_item(*item, temp, pool); + + return SVN_NO_ERROR; } svn_error_t * @@ -127,9 +132,10 @@ svn_ra_svn_parse_tuple(const apr_array_header_t *list, { va_list va; svn_error_t *err; + svn_ra_svn__list_t *internal = svn_ra_svn__to_private_array(list, pool); va_start(va, fmt); - err = svn_ra_svn__parse_tuple(list, pool, fmt, va); + err = svn_ra_svn__parse_tuple(internal, fmt, va); va_end(va); return svn_error_trace(err); @@ -155,7 +161,9 @@ svn_ra_svn_parse_proplist(const apr_array_header_t *list, apr_pool_t *pool, apr_hash_t **props) { - return svn_error_trace(svn_ra_svn__parse_proplist(list, pool, props)); + svn_ra_svn__list_t *internal + = svn_ra_svn__to_private_array(list, pool); + return svn_error_trace(svn_ra_svn__parse_proplist(internal, pool, props)); } svn_error_t * @@ -180,8 +188,23 @@ svn_ra_svn_handle_commands2(svn_ra_svn_conn_t *conn, void *baton, svn_boolean_t error_on_disconnect) { + apr_size_t i, count = 0; + svn_ra_svn__cmd_entry_t *internal; + + while (commands[count].cmdname) + count++; + + internal = apr_pcalloc(pool, count * sizeof(*internal)); + for (i = 0; i < count; ++i) + { + internal[i].cmdname = commands[i].cmdname; + internal[i].handler = NULL; + internal[i].deprecated_handler = commands[i].handler; + internal[i].terminate = commands[i].terminate; + } + return svn_error_trace(svn_ra_svn__handle_commands2(conn, pool, - commands, baton, + internal, baton, error_on_disconnect)); } @@ -191,9 +214,9 @@ svn_ra_svn_handle_commands(svn_ra_svn_conn_t *conn, const svn_ra_svn_cmd_entry_t *commands, void *baton) { - return svn_error_trace(svn_ra_svn__handle_commands2(conn, pool, - commands, baton, - FALSE)); + return svn_error_trace(svn_ra_svn_handle_commands2(conn, pool, + commands, baton, + FALSE)); } svn_error_t * @@ -238,6 +261,20 @@ svn_ra_svn_write_cmd_failure(svn_ra_svn_conn_t *conn, } /* From marshal.c */ +svn_ra_svn_conn_t * +svn_ra_svn_create_conn4(apr_socket_t *sock, + svn_stream_t *in_stream, + svn_stream_t *out_stream, + int compression_level, + apr_size_t zero_copy_limit, + apr_size_t error_check_interval, + apr_pool_t *pool) +{ + return svn_ra_svn_create_conn5(sock, in_stream, out_stream, + compression_level, zero_copy_limit, + error_check_interval, 0, 0, pool); +} + svn_ra_svn_conn_t * svn_ra_svn_create_conn3(apr_socket_t *sock, apr_file_t *in_file, diff --git a/subversion/libsvn_ra_svn/editorp.c b/subversion/libsvn_ra_svn/editorp.c index 88af89859fc4..10c8a2b04a63 100644 --- a/subversion/libsvn_ra_svn/editorp.c +++ b/subversion/libsvn_ra_svn/editorp.c @@ -39,8 +39,11 @@ #include "svn_pools.h" #include "svn_private_config.h" +#include "private/svn_atomic.h" #include "private/svn_fspath.h" #include "private/svn_editor.h" +#include "private/svn_string_private.h" +#include "private/svn_subr_private.h" #include "ra_svn.h" @@ -57,7 +60,7 @@ typedef struct ra_svn_edit_baton_t { svn_ra_svn_conn_t *conn; svn_ra_svn_edit_callback callback; /* Called on successful completion. */ void *callback_baton; - int next_token; + apr_uint64_t next_token; svn_boolean_t got_status; } ra_svn_edit_baton_t; @@ -66,13 +69,19 @@ typedef struct ra_svn_baton_t { svn_ra_svn_conn_t *conn; apr_pool_t *pool; ra_svn_edit_baton_t *eb; - const char *token; + svn_string_t *token; } ra_svn_baton_t; +/* Forward declaration. */ +typedef struct ra_svn_token_entry_t ra_svn_token_entry_t; + typedef struct ra_svn_driver_state_t { const svn_delta_editor_t *editor; void *edit_baton; apr_hash_t *tokens; + + /* Entry for the last token seen. May be NULL. */ + ra_svn_token_entry_t *last_token; svn_boolean_t *aborted; svn_boolean_t done; apr_pool_t *pool; @@ -90,26 +99,33 @@ typedef struct ra_svn_driver_state_t { field in this structure is vestigial for files, and we use it for a different purpose instead: at apply-textdelta time, we set it to a subpool of the file pool, which is destroyed in textdelta-end. */ -typedef struct ra_svn_token_entry_t { +struct ra_svn_token_entry_t { svn_string_t *token; void *baton; svn_boolean_t is_file; svn_stream_t *dstream; /* svndiff stream for apply_textdelta */ apr_pool_t *pool; -} ra_svn_token_entry_t; +}; /* --- CONSUMING AN EDITOR BY PASSING EDIT OPERATIONS OVER THE NET --- */ -static const char *make_token(char type, ra_svn_edit_baton_t *eb, - apr_pool_t *pool) +static svn_string_t * +make_token(char type, + ra_svn_edit_baton_t *eb, + apr_pool_t *pool) { - return apr_psprintf(pool, "%c%d", type, eb->next_token++); + apr_size_t len; + char buffer[1 + SVN_INT64_BUFFER_SIZE]; + buffer[0] = type; + len = 1 + svn__ui64toa(&buffer[1], eb->next_token++); + + return svn_string_ncreate(buffer, len, pool); } static ra_svn_baton_t *ra_svn_make_baton(svn_ra_svn_conn_t *conn, apr_pool_t *pool, ra_svn_edit_baton_t *eb, - const char *token) + svn_string_t *token) { ra_svn_baton_t *b; @@ -171,7 +187,7 @@ static svn_error_t *ra_svn_open_root(void *edit_baton, svn_revnum_t rev, apr_pool_t *pool, void **root_baton) { ra_svn_edit_baton_t *eb = edit_baton; - const char *token = make_token('d', eb, pool); + svn_string_t *token = make_token('d', eb, pool); SVN_ERR(check_for_error(eb, pool)); SVN_ERR(svn_ra_svn__write_cmd_open_root(eb->conn, pool, rev, token)); @@ -196,7 +212,7 @@ static svn_error_t *ra_svn_add_dir(const char *path, void *parent_baton, apr_pool_t *pool, void **child_baton) { ra_svn_baton_t *b = parent_baton; - const char *token = make_token('d', b->eb, pool); + svn_string_t *token = make_token('d', b->eb, pool); SVN_ERR_ASSERT((copy_path && SVN_IS_VALID_REVNUM(copy_rev)) || (!copy_path && !SVN_IS_VALID_REVNUM(copy_rev))); @@ -212,7 +228,7 @@ static svn_error_t *ra_svn_open_dir(const char *path, void *parent_baton, void **child_baton) { ra_svn_baton_t *b = parent_baton; - const char *token = make_token('d', b->eb, pool); + svn_string_t *token = make_token('d', b->eb, pool); SVN_ERR(check_for_error(b->eb, pool)); SVN_ERR(svn_ra_svn__write_cmd_open_dir(b->conn, pool, path, b->token, @@ -265,7 +281,7 @@ static svn_error_t *ra_svn_add_file(const char *path, void **file_baton) { ra_svn_baton_t *b = parent_baton; - const char *token = make_token('c', b->eb, pool); + svn_string_t *token = make_token('c', b->eb, pool); SVN_ERR_ASSERT((copy_path && SVN_IS_VALID_REVNUM(copy_rev)) || (!copy_path && !SVN_IS_VALID_REVNUM(copy_rev))); @@ -283,7 +299,7 @@ static svn_error_t *ra_svn_open_file(const char *path, void **file_baton) { ra_svn_baton_t *b = parent_baton; - const char *token = make_token('c', b->eb, pool); + svn_string_t *token = make_token('c', b->eb, pool); SVN_ERR(check_for_error(b->eb, b->pool)); SVN_ERR(svn_ra_svn__write_cmd_open_file(b->conn, pool, path, b->token, @@ -335,15 +351,9 @@ static svn_error_t *ra_svn_apply_textdelta(void *file_baton, svn_stream_set_write(diff_stream, ra_svn_svndiff_handler); svn_stream_set_close(diff_stream, ra_svn_svndiff_close_handler); - /* If the connection does not support SVNDIFF1 or if we don't want to use - * compression, use the non-compressing "version 0" implementation */ - if ( svn_ra_svn_compression_level(b->conn) > 0 - && svn_ra_svn_has_capability(b->conn, SVN_RA_SVN_CAP_SVNDIFF1)) - svn_txdelta_to_svndiff3(wh, wh_baton, diff_stream, 1, - b->conn->compression_level, pool); - else - svn_txdelta_to_svndiff3(wh, wh_baton, diff_stream, 0, - b->conn->compression_level, pool); + svn_txdelta_to_svndiff3(wh, wh_baton, diff_stream, + svn_ra_svn__svndiff_version(b->conn), + b->conn->compression_level, pool); return SVN_NO_ERROR; } @@ -480,6 +490,7 @@ static ra_svn_token_entry_t *store_token(ra_svn_driver_state_t *ds, entry->pool = pool; apr_hash_set(ds->tokens, entry->token->data, entry->token->len, entry); + ds->last_token = entry; return entry; } @@ -489,36 +500,59 @@ static svn_error_t *lookup_token(ra_svn_driver_state_t *ds, svn_boolean_t is_file, ra_svn_token_entry_t **entry) { - *entry = apr_hash_get(ds->tokens, token->data, token->len); + if (ds->last_token && svn_string_compare(ds->last_token->token, token)) + { + *entry = ds->last_token; + } + else + { + *entry = apr_hash_get(ds->tokens, token->data, token->len); + ds->last_token = *entry; + } + if (!*entry || (*entry)->is_file != is_file) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Invalid file or dir token during edit")); return SVN_NO_ERROR; } -static svn_error_t *ra_svn_handle_target_rev(svn_ra_svn_conn_t *conn, - apr_pool_t *pool, - const apr_array_header_t *params, - ra_svn_driver_state_t *ds) +/* Remove a TOKEN entry from DS. */ +static void remove_token(ra_svn_driver_state_t *ds, + svn_string_t *token) +{ + apr_hash_set(ds->tokens, token->data, token->len, NULL); + + /* Reset this unconditionally. In most cases, LAST_TOKEN->TOKEN will + match TOKEN anyway and if it doesn't, lookup_token() will suffer only + a minor performance hit. */ + ds->last_token = NULL; +} + +static svn_error_t * +ra_svn_handle_target_rev(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + const svn_ra_svn__list_t *params, + ra_svn_driver_state_t *ds) { svn_revnum_t rev; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "r", &rev)); + SVN_ERR(svn_ra_svn__parse_tuple(params, "r", &rev)); SVN_CMD_ERR(ds->editor->set_target_revision(ds->edit_baton, rev, pool)); return SVN_NO_ERROR; } -static svn_error_t *ra_svn_handle_open_root(svn_ra_svn_conn_t *conn, - apr_pool_t *pool, - const apr_array_header_t *params, - ra_svn_driver_state_t *ds) +static svn_error_t * +ra_svn_handle_open_root(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + const svn_ra_svn__list_t *params, + ra_svn_driver_state_t *ds) { svn_revnum_t rev; apr_pool_t *subpool; svn_string_t *token; void *root_baton; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "(?r)s", &rev, &token)); + SVN_ERR(svn_ra_svn__parse_tuple(params, "(?r)s", &rev, &token)); subpool = svn_pool_create(ds->pool); SVN_CMD_ERR(ds->editor->open_root(ds->edit_baton, rev, subpool, &root_baton)); @@ -526,17 +560,18 @@ static svn_error_t *ra_svn_handle_open_root(svn_ra_svn_conn_t *conn, return SVN_NO_ERROR; } -static svn_error_t *ra_svn_handle_delete_entry(svn_ra_svn_conn_t *conn, - apr_pool_t *pool, - const apr_array_header_t *params, - ra_svn_driver_state_t *ds) +static svn_error_t * +ra_svn_handle_delete_entry(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + const svn_ra_svn__list_t *params, + ra_svn_driver_state_t *ds) { const char *path; svn_string_t *token; svn_revnum_t rev; ra_svn_token_entry_t *entry; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c(?r)s", + SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)s", &path, &rev, &token)); SVN_ERR(lookup_token(ds, token, FALSE, &entry)); path = svn_relpath_canonicalize(path, pool); @@ -544,10 +579,11 @@ static svn_error_t *ra_svn_handle_delete_entry(svn_ra_svn_conn_t *conn, return SVN_NO_ERROR; } -static svn_error_t *ra_svn_handle_add_dir(svn_ra_svn_conn_t *conn, - apr_pool_t *pool, - const apr_array_header_t *params, - ra_svn_driver_state_t *ds) +static svn_error_t * +ra_svn_handle_add_dir(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + const svn_ra_svn__list_t *params, + ra_svn_driver_state_t *ds) { const char *path, *copy_path; svn_string_t *token, *child_token; @@ -556,7 +592,7 @@ static svn_error_t *ra_svn_handle_add_dir(svn_ra_svn_conn_t *conn, apr_pool_t *subpool; void *child_baton; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "css(?cr)", &path, &token, + SVN_ERR(svn_ra_svn__parse_tuple(params, "css(?cr)", &path, &token, &child_token, ©_path, ©_rev)); SVN_ERR(lookup_token(ds, token, FALSE, &entry)); subpool = svn_pool_create(entry->pool); @@ -578,10 +614,11 @@ static svn_error_t *ra_svn_handle_add_dir(svn_ra_svn_conn_t *conn, return SVN_NO_ERROR; } -static svn_error_t *ra_svn_handle_open_dir(svn_ra_svn_conn_t *conn, - apr_pool_t *pool, - const apr_array_header_t *params, - ra_svn_driver_state_t *ds) +static svn_error_t * +ra_svn_handle_open_dir(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + const svn_ra_svn__list_t *params, + ra_svn_driver_state_t *ds) { const char *path; svn_string_t *token, *child_token; @@ -590,7 +627,7 @@ static svn_error_t *ra_svn_handle_open_dir(svn_ra_svn_conn_t *conn, apr_pool_t *subpool; void *child_baton; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "css(?r)", &path, &token, + SVN_ERR(svn_ra_svn__parse_tuple(params, "css(?r)", &path, &token, &child_token, &rev)); SVN_ERR(lookup_token(ds, token, FALSE, &entry)); subpool = svn_pool_create(entry->pool); @@ -601,17 +638,18 @@ static svn_error_t *ra_svn_handle_open_dir(svn_ra_svn_conn_t *conn, return SVN_NO_ERROR; } -static svn_error_t *ra_svn_handle_change_dir_prop(svn_ra_svn_conn_t *conn, - apr_pool_t *pool, - const apr_array_header_t *params, - ra_svn_driver_state_t *ds) +static svn_error_t * +ra_svn_handle_change_dir_prop(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + const svn_ra_svn__list_t *params, + ra_svn_driver_state_t *ds) { svn_string_t *token; const char *name; svn_string_t *value; ra_svn_token_entry_t *entry; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "sc(?s)", &token, &name, + SVN_ERR(svn_ra_svn__parse_tuple(params, "sc(?s)", &token, &name, &value)); SVN_ERR(lookup_token(ds, token, FALSE, &entry)); SVN_CMD_ERR(ds->editor->change_dir_prop(entry->baton, name, value, @@ -619,36 +657,38 @@ static svn_error_t *ra_svn_handle_change_dir_prop(svn_ra_svn_conn_t *conn, return SVN_NO_ERROR; } -static svn_error_t *ra_svn_handle_close_dir(svn_ra_svn_conn_t *conn, - apr_pool_t *pool, - const apr_array_header_t *params, - ra_svn_driver_state_t *ds) +static svn_error_t * +ra_svn_handle_close_dir(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + const svn_ra_svn__list_t *params, + ra_svn_driver_state_t *ds) { svn_string_t *token; ra_svn_token_entry_t *entry; /* Parse and look up the directory token. */ - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "s", &token)); + SVN_ERR(svn_ra_svn__parse_tuple(params, "s", &token)); SVN_ERR(lookup_token(ds, token, FALSE, &entry)); /* Close the directory and destroy the baton. */ SVN_CMD_ERR(ds->editor->close_directory(entry->baton, pool)); - apr_hash_set(ds->tokens, token->data, token->len, NULL); + remove_token(ds, token); svn_pool_destroy(entry->pool); return SVN_NO_ERROR; } -static svn_error_t *ra_svn_handle_absent_dir(svn_ra_svn_conn_t *conn, - apr_pool_t *pool, - const apr_array_header_t *params, - ra_svn_driver_state_t *ds) +static svn_error_t * +ra_svn_handle_absent_dir(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + const svn_ra_svn__list_t *params, + ra_svn_driver_state_t *ds) { const char *path; svn_string_t *token; ra_svn_token_entry_t *entry; /* Parse parameters and look up the directory token. */ - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "cs", &path, &token)); + SVN_ERR(svn_ra_svn__parse_tuple(params, "cs", &path, &token)); SVN_ERR(lookup_token(ds, token, FALSE, &entry)); /* Call the editor. */ @@ -656,17 +696,18 @@ static svn_error_t *ra_svn_handle_absent_dir(svn_ra_svn_conn_t *conn, return SVN_NO_ERROR; } -static svn_error_t *ra_svn_handle_add_file(svn_ra_svn_conn_t *conn, - apr_pool_t *pool, - const apr_array_header_t *params, - ra_svn_driver_state_t *ds) +static svn_error_t * +ra_svn_handle_add_file(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + const svn_ra_svn__list_t *params, + ra_svn_driver_state_t *ds) { const char *path, *copy_path; svn_string_t *token, *file_token; svn_revnum_t copy_rev; ra_svn_token_entry_t *entry, *file_entry; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "css(?cr)", &path, &token, + SVN_ERR(svn_ra_svn__parse_tuple(params, "css(?cr)", &path, &token, &file_token, ©_path, ©_rev)); SVN_ERR(lookup_token(ds, token, FALSE, &entry)); ds->file_refs++; @@ -691,17 +732,18 @@ static svn_error_t *ra_svn_handle_add_file(svn_ra_svn_conn_t *conn, return SVN_NO_ERROR; } -static svn_error_t *ra_svn_handle_open_file(svn_ra_svn_conn_t *conn, - apr_pool_t *pool, - const apr_array_header_t *params, - ra_svn_driver_state_t *ds) +static svn_error_t * +ra_svn_handle_open_file(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + const svn_ra_svn__list_t *params, + ra_svn_driver_state_t *ds) { const char *path; svn_string_t *token, *file_token; svn_revnum_t rev; ra_svn_token_entry_t *entry, *file_entry; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "css(?r)", &path, &token, + SVN_ERR(svn_ra_svn__parse_tuple(params, "css(?r)", &path, &token, &file_token, &rev)); SVN_ERR(lookup_token(ds, token, FALSE, &entry)); ds->file_refs++; @@ -716,10 +758,11 @@ static svn_error_t *ra_svn_handle_open_file(svn_ra_svn_conn_t *conn, return SVN_NO_ERROR; } -static svn_error_t *ra_svn_handle_apply_textdelta(svn_ra_svn_conn_t *conn, - apr_pool_t *pool, - const apr_array_header_t *params, - ra_svn_driver_state_t *ds) +static svn_error_t * +ra_svn_handle_apply_textdelta(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + const svn_ra_svn__list_t *params, + ra_svn_driver_state_t *ds) { svn_string_t *token; ra_svn_token_entry_t *entry; @@ -728,7 +771,7 @@ static svn_error_t *ra_svn_handle_apply_textdelta(svn_ra_svn_conn_t *conn, char *base_checksum; /* Parse arguments and look up the token. */ - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "s(?c)", + SVN_ERR(svn_ra_svn__parse_tuple(params, "s(?c)", &token, &base_checksum)); SVN_ERR(lookup_token(ds, token, TRUE, &entry)); if (entry->dstream) @@ -741,17 +784,18 @@ static svn_error_t *ra_svn_handle_apply_textdelta(svn_ra_svn_conn_t *conn, return SVN_NO_ERROR; } -static svn_error_t *ra_svn_handle_textdelta_chunk(svn_ra_svn_conn_t *conn, - apr_pool_t *pool, - const apr_array_header_t *params, - ra_svn_driver_state_t *ds) +static svn_error_t * +ra_svn_handle_textdelta_chunk(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + const svn_ra_svn__list_t *params, + ra_svn_driver_state_t *ds) { svn_string_t *token; ra_svn_token_entry_t *entry; svn_string_t *str; /* Parse arguments and look up the token. */ - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "ss", &token, &str)); + SVN_ERR(svn_ra_svn__parse_tuple(params, "ss", &token, &str)); SVN_ERR(lookup_token(ds, token, TRUE, &entry)); if (!entry->dstream) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, @@ -760,16 +804,17 @@ static svn_error_t *ra_svn_handle_textdelta_chunk(svn_ra_svn_conn_t *conn, return SVN_NO_ERROR; } -static svn_error_t *ra_svn_handle_textdelta_end(svn_ra_svn_conn_t *conn, - apr_pool_t *pool, - const apr_array_header_t *params, - ra_svn_driver_state_t *ds) +static svn_error_t * +ra_svn_handle_textdelta_end(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + const svn_ra_svn__list_t *params, + ra_svn_driver_state_t *ds) { svn_string_t *token; ra_svn_token_entry_t *entry; /* Parse arguments and look up the token. */ - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "s", &token)); + SVN_ERR(svn_ra_svn__parse_tuple(params, "s", &token)); SVN_ERR(lookup_token(ds, token, TRUE, &entry)); if (!entry->dstream) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, @@ -780,55 +825,58 @@ static svn_error_t *ra_svn_handle_textdelta_end(svn_ra_svn_conn_t *conn, return SVN_NO_ERROR; } -static svn_error_t *ra_svn_handle_change_file_prop(svn_ra_svn_conn_t *conn, - apr_pool_t *pool, - const apr_array_header_t *params, - ra_svn_driver_state_t *ds) +static svn_error_t * +ra_svn_handle_change_file_prop(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + const svn_ra_svn__list_t *params, + ra_svn_driver_state_t *ds) { const char *name; svn_string_t *token, *value; ra_svn_token_entry_t *entry; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "sc(?s)", &token, &name, + SVN_ERR(svn_ra_svn__parse_tuple(params, "sc(?s)", &token, &name, &value)); SVN_ERR(lookup_token(ds, token, TRUE, &entry)); SVN_CMD_ERR(ds->editor->change_file_prop(entry->baton, name, value, pool)); return SVN_NO_ERROR; } -static svn_error_t *ra_svn_handle_close_file(svn_ra_svn_conn_t *conn, - apr_pool_t *pool, - const apr_array_header_t *params, - ra_svn_driver_state_t *ds) +static svn_error_t * +ra_svn_handle_close_file(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + const svn_ra_svn__list_t *params, + ra_svn_driver_state_t *ds) { svn_string_t *token; ra_svn_token_entry_t *entry; const char *text_checksum; /* Parse arguments and look up the file token. */ - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "s(?c)", + SVN_ERR(svn_ra_svn__parse_tuple(params, "s(?c)", &token, &text_checksum)); SVN_ERR(lookup_token(ds, token, TRUE, &entry)); /* Close the file and destroy the baton. */ SVN_CMD_ERR(ds->editor->close_file(entry->baton, text_checksum, pool)); - apr_hash_set(ds->tokens, token->data, token->len, NULL); + remove_token(ds, token); if (--ds->file_refs == 0) svn_pool_clear(ds->file_pool); return SVN_NO_ERROR; } -static svn_error_t *ra_svn_handle_absent_file(svn_ra_svn_conn_t *conn, - apr_pool_t *pool, - const apr_array_header_t *params, - ra_svn_driver_state_t *ds) +static svn_error_t * +ra_svn_handle_absent_file(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + const svn_ra_svn__list_t *params, + ra_svn_driver_state_t *ds) { const char *path; svn_string_t *token; ra_svn_token_entry_t *entry; /* Parse parameters and look up the parent directory token. */ - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "cs", &path, &token)); + SVN_ERR(svn_ra_svn__parse_tuple(params, "cs", &path, &token)); SVN_ERR(lookup_token(ds, token, FALSE, &entry)); /* Call the editor. */ @@ -836,22 +884,32 @@ static svn_error_t *ra_svn_handle_absent_file(svn_ra_svn_conn_t *conn, return SVN_NO_ERROR; } -static svn_error_t *ra_svn_handle_close_edit(svn_ra_svn_conn_t *conn, - apr_pool_t *pool, - const apr_array_header_t *params, - ra_svn_driver_state_t *ds) +static svn_error_t * +ra_svn_handle_close_edit(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + const svn_ra_svn__list_t *params, + ra_svn_driver_state_t *ds) { SVN_CMD_ERR(ds->editor->close_edit(ds->edit_baton, pool)); ds->done = TRUE; +#ifdef SVN_DEBUG + /* Before enabling this in non-maintainer mode: + * Note that this code is used on both client *and* server */ + if (apr_hash_count(ds->tokens) != 0) + return svn_error_create( + SVN_ERR_FS_INCORRECT_EDITOR_COMPLETION, NULL, + _("Closing editor with directories or files open")); +#endif if (ds->aborted) *ds->aborted = FALSE; return svn_ra_svn__write_cmd_response(conn, pool, ""); } -static svn_error_t *ra_svn_handle_abort_edit(svn_ra_svn_conn_t *conn, - apr_pool_t *pool, - const apr_array_header_t *params, - ra_svn_driver_state_t *ds) +static svn_error_t * +ra_svn_handle_abort_edit(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + const svn_ra_svn__list_t *params, + ra_svn_driver_state_t *ds) { ds->done = TRUE; if (ds->aborted) @@ -860,10 +918,11 @@ static svn_error_t *ra_svn_handle_abort_edit(svn_ra_svn_conn_t *conn, return svn_ra_svn__write_cmd_response(conn, pool, ""); } -static svn_error_t *ra_svn_handle_finish_replay(svn_ra_svn_conn_t *conn, - apr_pool_t *pool, - const apr_array_header_t *params, - ra_svn_driver_state_t *ds) +static svn_error_t * +ra_svn_handle_finish_replay(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + const svn_ra_svn__list_t *params, + ra_svn_driver_state_t *ds) { if (!ds->for_replay) return svn_error_createf @@ -875,11 +934,15 @@ static svn_error_t *ra_svn_handle_finish_replay(svn_ra_svn_conn_t *conn, return SVN_NO_ERROR; } +/* Common function signature for all editor command handlers. */ +typedef svn_error_t *(*cmd_handler_t)(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + const svn_ra_svn__list_t *params, + ra_svn_driver_state_t *ds); + static const struct { const char *cmd; - svn_error_t *(*handler)(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - const apr_array_header_t *params, - ra_svn_driver_state_t *ds); + cmd_handler_t handler; } ra_svn_edit_cmds[] = { { "change-file-prop", ra_svn_handle_change_file_prop }, { "open-file", ra_svn_handle_open_file }, @@ -903,12 +966,98 @@ static const struct { { NULL } }; +/* All editor commands are kept in a collision-free hash table. */ + +/* Hash table entry. + It is similar to ra_svn_edit_cmds but uses our SVN string type. */ +typedef struct cmd_t { + svn_string_t cmd; + cmd_handler_t handler; +} cmd_t; + +/* The actual hash table. It will be filled once before first usage. + + If you add more commands, you may have to tweak the table size to + eliminate collisions. Alternatively, you may modify the hash function. + + Be sure to initialize all elements with 0 as the has conflict detection + will rely on it (see init_cmd_hash). + */ +#define CMD_HASH_SIZE 67 +static cmd_t cmd_hash[CMD_HASH_SIZE] = { { { NULL } } }; + +/* Init flag that controls CMD_HASH's atomic initialization. */ +static volatile svn_atomic_t cmd_hash_initialized = FALSE; + +/* Super-fast hash function that works very well with the structure of our + command words. It produces no conflicts for them. + + Return the index within CMD_HASH that a command NAME of LEN chars would + be found. LEN > 0. + */ +static apr_size_t +cmd_hash_func(const char *name, + apr_size_t len) +{ + apr_size_t value = (apr_byte_t)(name[0] - 'a') % 8 + + 1 * (apr_byte_t)(name[len - 1] - 'a') % 8 + + 10 * (len - 7); + return value % CMD_HASH_SIZE; +} + +/* svn_atomic__init_once callback that fills the CMD_HASH table. It will + error out on hash collisions. BATON and POOL are not used. */ +static svn_error_t * +init_cmd_hash(void *baton, + apr_pool_t *pool) +{ + int i; + for (i = 0; ra_svn_edit_cmds[i].cmd; i++) + { + apr_size_t len = strlen(ra_svn_edit_cmds[i].cmd); + apr_size_t value = cmd_hash_func(ra_svn_edit_cmds[i].cmd, len); + SVN_ERR_ASSERT(cmd_hash[value].cmd.data == NULL); + + cmd_hash[value].cmd.data = ra_svn_edit_cmds[i].cmd; + cmd_hash[value].cmd.len = len; + cmd_hash[value].handler = ra_svn_edit_cmds[i].handler; + } + + return SVN_NO_ERROR; +} + +/* Return the command handler function for the command name CMD. + Return NULL if no such handler exists */ +static cmd_handler_t +cmd_lookup(const char *cmd) +{ + apr_size_t value; + apr_size_t len = strlen(cmd); + + /* Malicious data that our hash function may not like? */ + if (len == 0) + return NULL; + + /* Hash lookup. */ + value = cmd_hash_func(cmd, len); + + /* Hit? */ + if (cmd_hash[value].cmd.len != len) + return NULL; + + if (memcmp(cmd_hash[value].cmd.data, cmd, len)) + return NULL; + + /* Yes! */ + return cmd_hash[value].handler; +} + static svn_error_t *blocked_write(svn_ra_svn_conn_t *conn, apr_pool_t *pool, void *baton) { ra_svn_driver_state_t *ds = baton; const char *cmd; - apr_array_header_t *params; + svn_ra_svn__list_t *params; /* We blocked trying to send an error. Read and discard an editing * command in order to avoid deadlock. */ @@ -931,13 +1080,16 @@ svn_error_t *svn_ra_svn_drive_editor2(svn_ra_svn_conn_t *conn, ra_svn_driver_state_t state; apr_pool_t *subpool = svn_pool_create(pool); const char *cmd; - int i; svn_error_t *err, *write_err; - apr_array_header_t *params; + svn_ra_svn__list_t *params; + + SVN_ERR(svn_atomic__init_once(&cmd_hash_initialized, init_cmd_hash, NULL, + pool)); state.editor = editor; state.edit_baton = edit_baton; - state.tokens = apr_hash_make(pool); + state.tokens = svn_hash__make(pool); + state.last_token = NULL; state.aborted = aborted; state.done = FALSE; state.pool = pool; @@ -948,15 +1100,18 @@ svn_error_t *svn_ra_svn_drive_editor2(svn_ra_svn_conn_t *conn, while (!state.done) { svn_pool_clear(subpool); + + /* WRT to applying I/O limits, treat each editor command as a separate + * protocol command. */ + svn_ra_svn__reset_command_io_counters(conn); if (editor) { + cmd_handler_t handler; SVN_ERR(svn_ra_svn__read_tuple(conn, subpool, "wl", &cmd, ¶ms)); - for (i = 0; ra_svn_edit_cmds[i].cmd; i++) - if (strcmp(cmd, ra_svn_edit_cmds[i].cmd) == 0) - break; + handler = cmd_lookup(cmd); - if (ra_svn_edit_cmds[i].cmd) - err = (*ra_svn_edit_cmds[i].handler)(conn, subpool, params, &state); + if (handler) + err = (*handler)(conn, subpool, params, &state); else if (strcmp(cmd, "failure") == 0) { /* While not really an editor command this can occur when @@ -964,7 +1119,7 @@ svn_error_t *svn_ra_svn_drive_editor2(svn_ra_svn_conn_t *conn, command */ if (aborted) *aborted = TRUE; - err = svn_ra_svn__handle_failure_status(params, pool); + err = svn_ra_svn__handle_failure_status(params); return svn_error_compose_create( err, editor->abort_edit(edit_baton, subpool)); diff --git a/subversion/libsvn_ra_svn/internal_auth.c b/subversion/libsvn_ra_svn/internal_auth.c index 8e63ab5b5fc3..7f84c7bfdaad 100644 --- a/subversion/libsvn_ra_svn/internal_auth.c +++ b/subversion/libsvn_ra_svn/internal_auth.c @@ -37,16 +37,16 @@ #include "ra_svn.h" -svn_boolean_t svn_ra_svn__find_mech(const apr_array_header_t *mechlist, +svn_boolean_t svn_ra_svn__find_mech(const svn_ra_svn__list_t *mechlist, const char *mech) { int i; - svn_ra_svn_item_t *elt; + svn_ra_svn__item_t *elt; for (i = 0; i < mechlist->nelts; i++) { - elt = &APR_ARRAY_IDX(mechlist, i, svn_ra_svn_item_t); - if (elt->kind == SVN_RA_SVN_WORD && strcmp(elt->u.word, mech) == 0) + elt = &SVN_RA_SVN__LIST_ITEM(mechlist, i); + if (elt->kind == SVN_RA_SVN_WORD && strcmp(elt->u.word.data, mech) == 0) return TRUE; } return FALSE; @@ -69,7 +69,7 @@ static svn_error_t *read_success(svn_ra_svn_conn_t *conn, apr_pool_t *pool) svn_error_t * svn_ra_svn__do_internal_auth(svn_ra_svn__session_baton_t *sess, - const apr_array_header_t *mechlist, + const svn_ra_svn__list_t *mechlist, const char *realm, apr_pool_t *pool) { svn_ra_svn_conn_t *conn = sess->conn; diff --git a/subversion/libsvn_ra_svn/marshal.c b/subversion/libsvn_ra_svn/marshal.c index 0778269fa404..41caaa51a553 100644 --- a/subversion/libsvn_ra_svn/marshal.c +++ b/subversion/libsvn_ra_svn/marshal.c @@ -60,9 +60,10 @@ /* We don't use "words" longer than this in our protocol. The longest word * we are currently using is only about 16 chars long but we leave room for - * longer future capability and command names. + * longer future capability and command names. See read_item() to understand + * why MAX_WORD_LENGTH - 1 should be a multiple of 8. */ -#define MAX_WORD_LENGTH 31 +#define MAX_WORD_LENGTH 25 /* The generic parsers will use the following value to limit the recursion * depth to some reasonable value. The current protocol implementation @@ -71,6 +72,10 @@ */ #define ITEM_NESTING_LIMIT 64 +/* The protocol words for booleans. */ +static const svn_string_t str_true = SVN__STATIC_STRING("true"); +static const svn_string_t str_false = SVN__STATIC_STRING("false"); + /* Return the APR socket timeout to be used for the connection depending * on whether there is a blockage handler or zero copy has been activated. */ static apr_interval_time_t @@ -79,14 +84,109 @@ get_timeout(svn_ra_svn_conn_t *conn) return conn->block_handler ? 0 : -1; } +/* --- Public / private API data conversion --- */ + +void +svn_ra_svn__to_public_item(svn_ra_svn_item_t *target, + const svn_ra_svn__item_t *source, + apr_pool_t *result_pool) +{ + target->kind = source->kind; + switch (source->kind) + { + case SVN_RA_SVN_STRING: + target->u.string = svn_string_dup(&source->u.string, result_pool); + break; + case SVN_RA_SVN_NUMBER: + target->u.number = source->u.number; + break; + case SVN_RA_SVN_WORD: + target->u.word = source->u.word.data; + break; + case SVN_RA_SVN_LIST: + target->u.list = svn_ra_svn__to_public_array(&source->u.list, + result_pool); + break; + } +} + +apr_array_header_t * +svn_ra_svn__to_public_array(const svn_ra_svn__list_t *source, + apr_pool_t *result_pool) +{ + apr_array_header_t *result = apr_array_make(result_pool, source->nelts, + sizeof(svn_ra_svn_item_t)); + + int i; + for (i = 0; i < source->nelts; ++i) + { + svn_ra_svn_item_t *sub_target = apr_array_push(result); + svn_ra_svn__item_t *sub_source = &SVN_RA_SVN__LIST_ITEM(source, i); + + svn_ra_svn__to_public_item(sub_target, sub_source, result_pool); + } + + return result; +} + +void +svn_ra_svn__to_private_item(svn_ra_svn__item_t *target, + const svn_ra_svn_item_t *source, + apr_pool_t *result_pool) +{ + target->kind = source->kind; + switch (source->kind) + { + case SVN_RA_SVN_STRING: + target->u.string = *source->u.string; + break; + case SVN_RA_SVN_NUMBER: + target->u.number = source->u.number; + break; + case SVN_RA_SVN_WORD: + target->u.word.data = source->u.word; + target->u.word.len = strlen(source->u.word); + break; + case SVN_RA_SVN_LIST: + target->u.list = *svn_ra_svn__to_private_array(source->u.list, + result_pool); + break; + } +} + +svn_ra_svn__list_t * +svn_ra_svn__to_private_array(const apr_array_header_t *source, + apr_pool_t *result_pool) +{ + int i; + + svn_ra_svn__list_t *result = apr_pcalloc(result_pool, sizeof(*result)); + result->nelts = source->nelts; + result->items = apr_palloc(result_pool, + source->nelts * sizeof(*result->items)); + + for (i = 0; i < source->nelts; ++i) + { + svn_ra_svn__item_t *sub_target = &result->items[i]; + svn_ra_svn_item_t *sub_source = &APR_ARRAY_IDX(source, i, + svn_ra_svn_item_t); + + svn_ra_svn__to_private_item(sub_target, sub_source, result_pool); + } + + return result; +} + /* --- CONNECTION INITIALIZATION --- */ -svn_ra_svn_conn_t *svn_ra_svn_create_conn4(apr_socket_t *sock, +svn_ra_svn_conn_t *svn_ra_svn_create_conn5(apr_socket_t *sock, svn_stream_t *in_stream, svn_stream_t *out_stream, int compression_level, apr_size_t zero_copy_limit, apr_size_t error_check_interval, + apr_uint64_t max_in, + apr_uint64_t max_out, apr_pool_t *result_pool) { svn_ra_svn_conn_t *conn; @@ -106,6 +206,10 @@ svn_ra_svn_conn_t *svn_ra_svn_create_conn4(apr_socket_t *sock, conn->written_since_error_check = 0; conn->error_check_interval = error_check_interval; conn->may_check_for_error = error_check_interval == 0; + conn->max_in = max_in; + conn->current_in = 0; + conn->max_out = max_out; + conn->current_out = 0; conn->block_handler = NULL; conn->block_baton = NULL; conn->capabilities = apr_hash_make(result_pool); @@ -132,25 +236,53 @@ svn_ra_svn_conn_t *svn_ra_svn_create_conn4(apr_socket_t *sock, return conn; } -svn_error_t *svn_ra_svn_set_capabilities(svn_ra_svn_conn_t *conn, - const apr_array_header_t *list) +svn_error_t * +svn_ra_svn_set_capabilities(svn_ra_svn_conn_t *conn, + const apr_array_header_t *list) +{ + svn_ra_svn__list_t *internal + = svn_ra_svn__to_private_array(list, list->pool); + return svn_error_trace(svn_ra_svn__set_capabilities(conn, internal)); +} + +svn_error_t * +svn_ra_svn__set_capabilities(svn_ra_svn_conn_t *conn, + const svn_ra_svn__list_t *list) { int i; - svn_ra_svn_item_t *item; + svn_ra_svn__item_t *item; const char *word; for (i = 0; i < list->nelts; i++) { - item = &APR_ARRAY_IDX(list, i, svn_ra_svn_item_t); + item = &SVN_RA_SVN__LIST_ITEM(list, i); if (item->kind != SVN_RA_SVN_WORD) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Capability entry is not a word")); - word = apr_pstrdup(conn->pool, item->u.word); - svn_hash_sets(conn->capabilities, word, word); + word = apr_pstrmemdup(conn->pool, item->u.word.data, item->u.word.len); + apr_hash_set(conn->capabilities, word, item->u.word.len, word); } return SVN_NO_ERROR; } +int +svn_ra_svn__svndiff_version(svn_ra_svn_conn_t *conn) +{ + /* If we don't want to use compression, use the non-compressing + * "version 0" implementation. */ + if (svn_ra_svn_compression_level(conn) <= 0) + return 0; + + /* Prefer SVNDIFF2 over SVNDIFF1. */ + if (svn_ra_svn_has_capability(conn, SVN_RA_SVN_CAP_SVNDIFF2_ACCEPTED)) + return 2; + if (svn_ra_svn_has_capability(conn, SVN_RA_SVN_CAP_SVNDIFF1)) + return 1; + + /* The connection does not support SVNDIFF1/2; default to "version 0". */ + return 0; +} + apr_pool_t * svn_ra_svn__get_pool(svn_ra_svn_conn_t *conn) { @@ -204,8 +336,33 @@ svn_error_t *svn_ra_svn__data_available(svn_ra_svn_conn_t *conn, return svn_ra_svn__stream_data_available(conn->stream, data_available); } +void +svn_ra_svn__reset_command_io_counters(svn_ra_svn_conn_t *conn) +{ + conn->current_in = 0; + conn->current_out = 0; +} + + /* --- WRITE BUFFER MANAGEMENT --- */ +/* Return an error object if CONN exceeded its send or receive limits. */ +static svn_error_t * +check_io_limits(svn_ra_svn_conn_t *conn) +{ + if (conn->max_in && (conn->current_in > conn->max_in)) + return svn_error_create(SVN_ERR_RA_SVN_REQUEST_SIZE, NULL, + "The client request size exceeds the " + "configured limit"); + + if (conn->max_out && (conn->current_out > conn->max_out)) + return svn_error_create(SVN_ERR_RA_SVN_RESPONSE_SIZE, NULL, + "The server response size exceeds the " + "configured limit"); + + return SVN_NO_ERROR; +} + /* Write data to socket or output file as appropriate. */ static svn_error_t *writebuf_output(svn_ra_svn_conn_t *conn, apr_pool_t *pool, const char *data, apr_size_t len) @@ -215,6 +372,12 @@ static svn_error_t *writebuf_output(svn_ra_svn_conn_t *conn, apr_pool_t *pool, apr_pool_t *subpool = NULL; svn_ra_svn__session_baton_t *session = conn->session; + /* Limit the size of the response, if a limit has been configured. + * This is to limit the server load in case users e.g. accidentally ran + * an export on the root folder. */ + conn->current_out += len; + SVN_ERR(check_io_limits(conn)); + while (data < end) { count = end - data; @@ -333,12 +496,19 @@ static svn_error_t *readbuf_input(svn_ra_svn_conn_t *conn, char *data, { svn_ra_svn__session_baton_t *session = conn->session; + /* First, give the user a chance to cancel the request before we do. */ if (session && session->callbacks && session->callbacks->cancel_func) SVN_ERR((session->callbacks->cancel_func)(session->callbacks_baton)); + /* Limit our memory usage, if a limit has been configured. Note that + * we first read the whole request into memory before process it. */ + SVN_ERR(check_io_limits(conn)); + + /* Actually fill the buffer. */ SVN_ERR(svn_ra_svn__stream_read(conn->stream, data, len)); if (*len == 0) return svn_error_create(SVN_ERR_RA_SVN_CONNECTION_CLOSED, NULL, NULL); + conn->current_in += *len; if (session) { @@ -384,9 +554,13 @@ static svn_error_t *readbuf_fill(svn_ra_svn_conn_t *conn, apr_pool_t *pool) apr_size_t len; SVN_ERR_ASSERT(conn->read_ptr == conn->read_end); + + /* Make sure we tell the other side everything we have to say before + * reading / waiting for an answer. */ if (conn->write_pos) SVN_ERR(writebuf_flush(conn, pool)); + /* Fill (some of the) buffer. */ len = sizeof(conn->read_buf); SVN_ERR(readbuf_input(conn, conn->read_buf, &len, pool)); conn->read_ptr = conn->read_buf; @@ -512,22 +686,69 @@ svn_ra_svn__write_number(svn_ra_svn_conn_t *conn, return write_number(conn, pool, number, ' '); } +/* Write string S of length LEN to TARGET and return the first position + after the written data. + + NOTE: This function assumes that TARGET has enough room for S, the LEN + prefix and the required separators. The available buffer size + should be SVN_INT64_BUFFER_SIZE + LEN + 1 to avoid any chance of + overflow. + */ +static char * +write_ncstring_quick(char *target, + const char *s, + apr_size_t len) +{ + /* Write string length. */ + if (len < 10) + { + *target = (char)(len + '0'); + target++; + } + else + { + target += svn__ui64toa(target, len); + } + + /* Separator & contents. */ + target[0] = ':'; + memcpy(target + 1, s, len); + target[len + 1] = ' '; + + /* First location after the string. */ + return target + len + 2; +} + + static svn_error_t * svn_ra_svn__write_ncstring(svn_ra_svn_conn_t *conn, apr_pool_t *pool, const char *s, apr_size_t len) { - if (len < 10) + /* Apart from LEN bytes of string contents, we need room for a number, + a colon and a space. */ + apr_size_t max_fill = sizeof(conn->write_buf) - SVN_INT64_BUFFER_SIZE - 2; + + /* In most cases, there is enough left room in the WRITE_BUF + the we can serialize directly into it. On platforms with + segmented memory, LEN might actually be close to APR_SIZE_MAX. + Blindly doing arithmetic on it might cause an overflow. */ + if ((len <= max_fill) && (conn->write_pos <= max_fill - len)) { - SVN_ERR(writebuf_writechar(conn, pool, (char)(len + '0'))); - SVN_ERR(writebuf_writechar(conn, pool, ':')); + /* Quick path. */ + conn->write_pos = write_ncstring_quick(conn->write_buf + + conn->write_pos, s, len) + - conn->write_buf; } else - SVN_ERR(write_number(conn, pool, len, ':')); + { + /* Slower fallback code. */ + SVN_ERR(write_number(conn, pool, len, ':')); - SVN_ERR(writebuf_write(conn, pool, s, len)); - SVN_ERR(writebuf_writechar(conn, pool, ' ')); + SVN_ERR(writebuf_write(conn, pool, s, len)); + SVN_ERR(writebuf_writechar(conn, pool, ' ')); + } return SVN_NO_ERROR; } @@ -755,6 +976,55 @@ write_tuple_string_opt(svn_ra_svn_conn_t *conn, return str ? svn_ra_svn__write_string(conn, pool, str) : SVN_NO_ERROR; } +/* Optimized sending code for the "(s?)" pattern. */ +static svn_error_t * +write_tuple_string_opt_list(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + const svn_string_t *str) +{ + apr_size_t max_fill; + + /* Special case. */ + if (!str) + return writebuf_write(conn, pool, "( ) ", 4); + + /* If this how far we can fill the WRITE_BUF with string data and still + guarantee that the length info will fit in as well. */ + max_fill = sizeof(conn->write_buf) + - 2 /* open list */ + - SVN_INT64_BUFFER_SIZE /* string length + separator */ + - 2; /* close list */ + + /* On platforms with segmented memory, STR->LEN might actually be + close to APR_SIZE_MAX. Blindly doing arithmetic on it might + cause an overflow. */ + if ((str->len <= max_fill) && (conn->write_pos <= max_fill - str->len)) + { + /* Quick path. */ + /* Open list. */ + char *p = conn->write_buf + conn->write_pos; + p[0] = '('; + p[1] = ' '; + + /* Write string. */ + p = write_ncstring_quick(p + 2, str->data, str->len); + + /* Close list. */ + p[0] = ')'; + p[1] = ' '; + conn->write_pos = p + 2 - conn->write_buf; + } + else + { + /* Standard code path (fallback). */ + SVN_ERR(svn_ra_svn__start_list(conn, pool)); + SVN_ERR(svn_ra_svn__write_string(conn, pool, str)); + SVN_ERR(svn_ra_svn__end_list(conn, pool)); + } + + return SVN_NO_ERROR; +} + static svn_error_t * write_tuple_start_list(svn_ra_svn_conn_t *conn, apr_pool_t *pool) @@ -809,14 +1079,14 @@ static svn_error_t * write_cmd_add_node(svn_ra_svn_conn_t *conn, apr_pool_t *pool, const char *path, - const char *parent_token, - const char *token, + const svn_string_t *parent_token, + const svn_string_t *token, const char *copy_path, svn_revnum_t copy_rev) { SVN_ERR(write_tuple_cstring(conn, pool, path)); - SVN_ERR(write_tuple_cstring(conn, pool, parent_token)); - SVN_ERR(write_tuple_cstring(conn, pool, token)); + SVN_ERR(write_tuple_string(conn, pool, parent_token)); + SVN_ERR(write_tuple_string(conn, pool, token)); SVN_ERR(write_tuple_start_list(conn, pool)); SVN_ERR(write_tuple_cstring_opt(conn, pool, copy_path)); SVN_ERR(write_tuple_revision_opt(conn, pool, copy_rev)); @@ -829,13 +1099,13 @@ static svn_error_t * write_cmd_open_node(svn_ra_svn_conn_t *conn, apr_pool_t *pool, const char *path, - const char *parent_token, - const char *token, + const svn_string_t *parent_token, + const svn_string_t *token, svn_revnum_t rev) { SVN_ERR(write_tuple_cstring(conn, pool, path)); - SVN_ERR(write_tuple_cstring(conn, pool, parent_token)); - SVN_ERR(write_tuple_cstring(conn, pool, token)); + SVN_ERR(write_tuple_string(conn, pool, parent_token)); + SVN_ERR(write_tuple_string(conn, pool, token)); SVN_ERR(write_tuple_start_list(conn, pool)); SVN_ERR(write_tuple_revision_opt(conn, pool, rev)); SVN_ERR(write_tuple_end_list(conn, pool)); @@ -846,15 +1116,13 @@ write_cmd_open_node(svn_ra_svn_conn_t *conn, static svn_error_t * write_cmd_change_node_prop(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - const char *token, + const svn_string_t *token, const char *name, const svn_string_t *value) { - SVN_ERR(write_tuple_cstring(conn, pool, token)); + SVN_ERR(write_tuple_string(conn, pool, token)); SVN_ERR(write_tuple_cstring(conn, pool, name)); - SVN_ERR(write_tuple_start_list(conn, pool)); - SVN_ERR(write_tuple_string_opt(conn, pool, value)); - SVN_ERR(write_tuple_end_list(conn, pool)); + SVN_ERR(write_tuple_string_opt_list(conn, pool, value)); return SVN_NO_ERROR; } @@ -863,10 +1131,10 @@ static svn_error_t * write_cmd_absent_node(svn_ra_svn_conn_t *conn, apr_pool_t *pool, const char *path, - const char *token) + const svn_string_t *token) { SVN_ERR(write_tuple_cstring(conn, pool, path)); - SVN_ERR(write_tuple_cstring(conn, pool, token)); + SVN_ERR(write_tuple_string(conn, pool, token)); return SVN_NO_ERROR; } @@ -892,10 +1160,17 @@ static svn_error_t *vwrite_tuple(svn_ra_svn_conn_t *conn, apr_pool_t *pool, SVN_ERR(opt ? vwrite_tuple_string_opt(conn, pool, ap) : vwrite_tuple_string(conn, pool, ap)); else if (*fmt == '(' && !opt) - SVN_ERR(write_tuple_start_list(conn, pool)); + { + /* Optional sub-tuples are not supported. + * If OPT was set, we would fall through to the malfunction call. */ + SVN_ERR(write_tuple_start_list(conn, pool)); + } else if (*fmt == ')') { SVN_ERR(write_tuple_end_list(conn, pool)); + + /* OPT could not have been set when opening the list (see above), + * hence this is correct and handles nested tuples just fine. */ opt = FALSE; } else if (*fmt == '?') @@ -939,7 +1214,7 @@ svn_ra_svn__write_tuple(svn_ra_svn_conn_t *conn, * Afterwards, *ITEM is of type 'SVN_RA_SVN_STRING', and its string * data is allocated in POOL. */ static svn_error_t *read_string(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - svn_ra_svn_item_t *item, apr_uint64_t len64) + svn_ra_svn__item_t *item, apr_uint64_t len64) { apr_size_t len = (apr_size_t)len64; apr_size_t readbuf_len; @@ -947,7 +1222,7 @@ static svn_error_t *read_string(svn_ra_svn_conn_t *conn, apr_pool_t *pool, apr_size_t buflen; /* We can't store strings longer than the maximum size of apr_size_t, - * so check for wrapping */ + * so check before using the truncated value. */ if (len64 > APR_SIZE_MAX) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("String length larger than maximum")); @@ -957,11 +1232,22 @@ static svn_error_t *read_string(svn_ra_svn_conn_t *conn, apr_pool_t *pool, if (len <= buflen) { item->kind = SVN_RA_SVN_STRING; - item->u.string = svn_string_ncreate(conn->read_ptr, len, pool); + item->u.string.data = apr_pstrmemdup(pool, conn->read_ptr, len); + item->u.string.len = len; conn->read_ptr += len; } else { + svn_stringbuf_t *stringbuf; + + /* Don't even attempt to read anything that exceeds the I/O limit. + * So, we can terminate the transfer at an early point, saving + * everybody's time and resources. */ + if (conn->max_in && (conn->max_in < len64)) + return svn_error_create(SVN_ERR_RA_SVN_REQUEST_SIZE, NULL, + "The client request size exceeds the " + "configured limit"); + /* Read the string in chunks. The chunk size is large enough to avoid * re-allocation in typical cases, and small enough to ensure we do * not pre-allocate an unreasonable amount of memory if (perhaps due @@ -970,7 +1256,7 @@ static svn_error_t *read_string(svn_ra_svn_conn_t *conn, apr_pool_t *pool, * start small and wait for all that data to actually show up. This * does not fully prevent DOS attacks but makes them harder (you have * to actually send gigabytes of data). */ - svn_stringbuf_t *stringbuf = svn_stringbuf_create_empty(pool); + stringbuf = svn_stringbuf_create_empty(pool); /* Read string data directly into the string structure. * Do it iteratively. */ @@ -998,7 +1284,8 @@ static svn_error_t *read_string(svn_ra_svn_conn_t *conn, apr_pool_t *pool, /* Return the string properly wrapped into an RA_SVN item. */ item->kind = SVN_RA_SVN_STRING; - item->u.string = svn_stringbuf__morph_into_string(stringbuf); + item->u.string.data = stringbuf->data; + item->u.string.len = stringbuf->len; } return SVN_NO_ERROR; @@ -1009,12 +1296,12 @@ static svn_error_t *read_string(svn_ra_svn_conn_t *conn, apr_pool_t *pool, * to 0 for the first call and is used to enforce a recursion limit * on the parser. */ static svn_error_t *read_item(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - svn_ra_svn_item_t *item, char first_char, + svn_ra_svn__item_t *item, char first_char, int level) { char c = first_char; apr_uint64_t val; - svn_ra_svn_item_t *listitem; + svn_ra_svn__item_t *listitem; if (++level >= ITEM_NESTING_LIMIT) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, @@ -1062,36 +1349,108 @@ static svn_error_t *read_item(svn_ra_svn_conn_t *conn, apr_pool_t *pool, char *p = buffer + 1; buffer[0] = c; - while (1) + if (conn->read_ptr + MAX_WORD_LENGTH <= conn->read_end) { - SVN_ERR(readbuf_getchar(conn, pool, p)); - if (!svn_ctype_isalnum(*p) && *p != '-') - break; + /* Fast path: we can simply take a chunk from the read + * buffer and inspect it with no overflow checks etc. + * + * Copying these 24 bytes unconditionally is also faster + * than a variable-sized memcpy. Note that P is at BUFFER[1]. + */ + memcpy(p, conn->read_ptr, MAX_WORD_LENGTH - 1); + *end = 0; - if (++p == end) - return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, - _("Word is too long")); + /* This will terminate at P == END because of *END == NUL. */ + while (svn_ctype_isalnum(*p) || *p == '-') + ++p; + + /* Only now do we mark data as actually read. */ + conn->read_ptr += p - buffer; } + else + { + /* Slow path. Byte-by-byte copying and checking for + * input and output buffer boundaries. */ + for (p = buffer + 1; p != end; ++p) + { + SVN_ERR(readbuf_getchar(conn, pool, p)); + if (!svn_ctype_isalnum(*p) && *p != '-') + break; + } + } + + if (p == end) + return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, + _("Word is too long")); c = *p; *p = '\0'; + /* Store the word in ITEM. */ item->kind = SVN_RA_SVN_WORD; - item->u.word = buffer; + item->u.word.data = buffer; + item->u.word.len = p - buffer; } else if (c == '(') { + /* The largest struct that the protocol currently defines has 10 + * elements (log-entry) and add some headroom for future extensions. + * At a maximum nesting level of 64 this use <= 18kB of stack. + * + * All system-defined data structures will fit into this and will be + * copied into ITEM after a single apr_palloc with no over-provision. + * Unbounded lists with more than 12 but less than 25 entries will + * also see only a single allocation from POOL. However, there will + * be some over-provision. Longer lists will see log N resizes and + * O(N) total cost. + */ + svn_ra_svn__item_t stack_items[12]; + svn_ra_svn__item_t *items = stack_items; + int capacity = sizeof(stack_items) / sizeof(stack_items[0]); + int count = 0; + /* Read in the list items. */ item->kind = SVN_RA_SVN_LIST; - item->u.list = apr_array_make(pool, 4, sizeof(svn_ra_svn_item_t)); while (1) { SVN_ERR(readbuf_getchar_skip_whitespace(conn, pool, &c)); if (c == ')') break; - listitem = apr_array_push(item->u.list); + + /* Auto-expand the list. */ + if (count == capacity) + { + svn_ra_svn__item_t *new_items + = apr_palloc(pool, 2 * capacity * sizeof(*new_items)); + memcpy(new_items, items, capacity * sizeof(*new_items)); + items = new_items; + capacity = 2 * capacity; + } + + listitem = &items[count]; + ++count; + SVN_ERR(read_item(conn, pool, listitem, c, level)); } + + /* Store the list in ITEM - if not empty (= default). */ + if (count) + { + item->u.list.nelts = count; + + /* If we haven't allocated from POOL, yet, do it now. */ + if (items == stack_items) + item->u.list.items = apr_pmemdup(pool, items, + count * sizeof(*items)); + else + item->u.list.items = items; + } + else + { + item->u.list.items = NULL; + item->u.list.nelts = 0; + } + SVN_ERR(readbuf_getchar(conn, pool, &c)); } @@ -1193,7 +1552,7 @@ read_command_only(svn_ra_svn_conn_t *conn, apr_pool_t *pool, svn_error_t * svn_ra_svn__read_item(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - svn_ra_svn_item_t **item) + svn_ra_svn__item_t **item) { char c; @@ -1243,36 +1602,38 @@ svn_ra_svn__skip_leading_garbage(svn_ra_svn_conn_t *conn, /* --- READING AND PARSING TUPLES --- */ -/* Parse a tuple of svn_ra_svn_item_t *'s. Advance *FMT to the end of the +/* Parse a tuple of svn_ra_svn__item_t *'s. Advance *FMT to the end of the * tuple specification and advance AP by the corresponding arguments. */ -static svn_error_t *vparse_tuple(const apr_array_header_t *items, apr_pool_t *pool, - const char **fmt, va_list *ap) +static svn_error_t * +vparse_tuple(const svn_ra_svn__list_t *items, + const char **fmt, + va_list *ap) { int count, nesting_level; - svn_ra_svn_item_t *elt; + svn_ra_svn__item_t *elt; for (count = 0; **fmt && count < items->nelts; (*fmt)++, count++) { /* '?' just means the tuple may stop; skip past it. */ if (**fmt == '?') (*fmt)++; - elt = &APR_ARRAY_IDX(items, count, svn_ra_svn_item_t); + elt = &SVN_RA_SVN__LIST_ITEM(items, count); if (**fmt == '(' && elt->kind == SVN_RA_SVN_LIST) { (*fmt)++; - SVN_ERR(vparse_tuple(elt->u.list, pool, fmt, ap)); + SVN_ERR(vparse_tuple(&elt->u.list, fmt, ap)); } else if (**fmt == 'c' && elt->kind == SVN_RA_SVN_STRING) - *va_arg(*ap, const char **) = elt->u.string->data; + *va_arg(*ap, const char **) = elt->u.string.data; else if (**fmt == 's' && elt->kind == SVN_RA_SVN_STRING) - *va_arg(*ap, svn_string_t **) = elt->u.string; + *va_arg(*ap, svn_string_t **) = &elt->u.string; else if (**fmt == 'w' && elt->kind == SVN_RA_SVN_WORD) - *va_arg(*ap, const char **) = elt->u.word; + *va_arg(*ap, const char **) = elt->u.word.data; else if (**fmt == 'b' && elt->kind == SVN_RA_SVN_WORD) { - if (strcmp(elt->u.word, "true") == 0) + if (svn_string_compare(&elt->u.word, &str_true)) *va_arg(*ap, svn_boolean_t *) = TRUE; - else if (strcmp(elt->u.word, "false") == 0) + else if (svn_string_compare(&elt->u.word, &str_false)) *va_arg(*ap, svn_boolean_t *) = FALSE; else break; @@ -1283,24 +1644,24 @@ static svn_error_t *vparse_tuple(const apr_array_header_t *items, apr_pool_t *po *va_arg(*ap, svn_revnum_t *) = (svn_revnum_t) elt->u.number; else if (**fmt == 'B' && elt->kind == SVN_RA_SVN_WORD) { - if (strcmp(elt->u.word, "true") == 0) + if (svn_string_compare(&elt->u.word, &str_true)) *va_arg(*ap, apr_uint64_t *) = TRUE; - else if (strcmp(elt->u.word, "false") == 0) + else if (svn_string_compare(&elt->u.word, &str_false)) *va_arg(*ap, apr_uint64_t *) = FALSE; else break; } else if (**fmt == '3' && elt->kind == SVN_RA_SVN_WORD) { - if (strcmp(elt->u.word, "true") == 0) + if (svn_string_compare(&elt->u.word, &str_true)) *va_arg(*ap, svn_tristate_t *) = svn_tristate_true; - else if (strcmp(elt->u.word, "false") == 0) + else if (svn_string_compare(&elt->u.word, &str_false)) *va_arg(*ap, svn_tristate_t *) = svn_tristate_false; else break; } else if (**fmt == 'l' && elt->kind == SVN_RA_SVN_LIST) - *va_arg(*ap, apr_array_header_t **) = elt->u.list; + *va_arg(*ap, svn_ra_svn__list_t **) = &elt->u.list; else if (**fmt == ')') return SVN_NO_ERROR; else @@ -1326,7 +1687,7 @@ static svn_error_t *vparse_tuple(const apr_array_header_t *items, apr_pool_t *po *va_arg(*ap, const char **) = NULL; break; case 'l': - *va_arg(*ap, apr_array_header_t **) = NULL; + *va_arg(*ap, svn_ra_svn__list_t **) = NULL; break; case 'B': case 'n': @@ -1335,6 +1696,9 @@ static svn_error_t *vparse_tuple(const apr_array_header_t *items, apr_pool_t *po case '3': *va_arg(*ap, svn_tristate_t *) = svn_tristate_unknown; break; + case 'b': + *va_arg(*ap, svn_boolean_t *) = FALSE; + break; case '(': nesting_level++; break; @@ -1354,15 +1718,14 @@ static svn_error_t *vparse_tuple(const apr_array_header_t *items, apr_pool_t *po } svn_error_t * -svn_ra_svn__parse_tuple(const apr_array_header_t *list, - apr_pool_t *pool, +svn_ra_svn__parse_tuple(const svn_ra_svn__list_t *list, const char *fmt, ...) { svn_error_t *err; va_list ap; va_start(ap, fmt); - err = vparse_tuple(list, pool, &fmt, &ap); + err = vparse_tuple(list, &fmt, &ap); va_end(ap); return err; } @@ -1373,7 +1736,7 @@ svn_ra_svn__read_tuple(svn_ra_svn_conn_t *conn, const char *fmt, ...) { va_list ap; - svn_ra_svn_item_t *item; + svn_ra_svn__item_t *item; svn_error_t *err; SVN_ERR(svn_ra_svn__read_item(conn, pool, &item)); @@ -1381,7 +1744,7 @@ svn_ra_svn__read_tuple(svn_ra_svn_conn_t *conn, return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Malformed network data")); va_start(ap, fmt); - err = vparse_tuple(item->u.list, pool, &fmt, &ap); + err = vparse_tuple(&item->u.list, &fmt, &ap); va_end(ap); return err; } @@ -1400,24 +1763,23 @@ svn_ra_svn__read_command_only(svn_ra_svn_conn_t *conn, svn_error_t * -svn_ra_svn__parse_proplist(const apr_array_header_t *list, +svn_ra_svn__parse_proplist(const svn_ra_svn__list_t *list, apr_pool_t *pool, apr_hash_t **props) { svn_string_t *name; svn_string_t *value; - svn_ra_svn_item_t *elt; + svn_ra_svn__item_t *elt; int i; *props = svn_hash__make(pool); for (i = 0; i < list->nelts; i++) { - elt = &APR_ARRAY_IDX(list, i, svn_ra_svn_item_t); + elt = &SVN_RA_SVN__LIST_ITEM(list, i); if (elt->kind != SVN_RA_SVN_LIST) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Proplist element not a list")); - SVN_ERR(svn_ra_svn__parse_tuple(elt->u.list, pool, "ss", - &name, &value)); + SVN_ERR(svn_ra_svn__parse_tuple(&elt->u.list, "ss", &name, &value)); apr_hash_set(*props, name->data, name->len, value); } @@ -1442,15 +1804,14 @@ svn_error_t *svn_ra_svn__locate_real_error_child(svn_error_t *err) return this_link; } -svn_error_t *svn_ra_svn__handle_failure_status(const apr_array_header_t *params, - apr_pool_t *pool) +svn_error_t * +svn_ra_svn__handle_failure_status(const svn_ra_svn__list_t *params) { const char *message, *file; svn_error_t *err = NULL; - svn_ra_svn_item_t *elt; + svn_ra_svn__item_t *elt; int i; apr_uint64_t apr_err, line; - apr_pool_t *subpool = svn_pool_create(pool); if (params->nelts == 0) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, @@ -1459,12 +1820,11 @@ svn_error_t *svn_ra_svn__handle_failure_status(const apr_array_header_t *params, /* Rebuild the error list from the end, to avoid reversing the order. */ for (i = params->nelts - 1; i >= 0; i--) { - svn_pool_clear(subpool); - elt = &APR_ARRAY_IDX(params, i, svn_ra_svn_item_t); + elt = &SVN_RA_SVN__LIST_ITEM(params, i); if (elt->kind != SVN_RA_SVN_LIST) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Malformed error list")); - SVN_ERR(svn_ra_svn__parse_tuple(elt->u.list, subpool, "nccn", + SVN_ERR(svn_ra_svn__parse_tuple(&elt->u.list, "nccn", &apr_err, &message, &file, &line)); /* The message field should have been optional, but we can't easily change that, so "" means a nonexistent message. */ @@ -1483,8 +1843,6 @@ svn_error_t *svn_ra_svn__handle_failure_status(const apr_array_header_t *params, } } - svn_pool_destroy(subpool); - /* If we get here, then we failed to find a real error in the error chain that the server proported to be sending us. That's bad. */ if (! err) @@ -1501,20 +1859,20 @@ svn_ra_svn__read_cmd_response(svn_ra_svn_conn_t *conn, { va_list ap; const char *status; - apr_array_header_t *params; + svn_ra_svn__list_t *params; svn_error_t *err; SVN_ERR(svn_ra_svn__read_tuple(conn, pool, "wl", &status, ¶ms)); if (strcmp(status, "success") == 0) { va_start(ap, fmt); - err = vparse_tuple(params, pool, &fmt, &ap); + err = vparse_tuple(params, &fmt, &ap); va_end(ap); return err; } else if (strcmp(status, "failure") == 0) { - return svn_error_trace(svn_ra_svn__handle_failure_status(params, pool)); + return svn_error_trace(svn_ra_svn__handle_failure_status(params)); } return svn_error_createf(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, @@ -1528,7 +1886,12 @@ svn_ra_svn__has_command(svn_boolean_t *has_command, svn_ra_svn_conn_t *conn, apr_pool_t *pool) { - svn_error_t *err = svn_ra_svn__has_item(has_command, conn, pool); + svn_error_t *err; + + /* Don't make whitespace between commands trigger I/O limitiations. */ + svn_ra_svn__reset_command_io_counters(conn); + + err = svn_ra_svn__has_item(has_command, conn, pool); if (err && err->apr_err == SVN_ERR_RA_SVN_CONNECTION_CLOSED) { *terminated = TRUE; @@ -1550,10 +1913,14 @@ svn_ra_svn__handle_command(svn_boolean_t *terminate, { const char *cmdname; svn_error_t *err, *write_err; - apr_array_header_t *params; - const svn_ra_svn_cmd_entry_t *command; + svn_ra_svn__list_t *params; + const svn_ra_svn__cmd_entry_t *command; *terminate = FALSE; + + /* Limit I/O for every command separately. */ + svn_ra_svn__reset_command_io_counters(conn); + err = svn_ra_svn__read_tuple(conn, pool, "wl", &cmdname, ¶ms); if (err) { @@ -1570,7 +1937,28 @@ svn_ra_svn__handle_command(svn_boolean_t *terminate, command = svn_hash_gets(cmd_hash, cmdname); if (command) { - err = (*command->handler)(conn, pool, params, baton); + /* Call the standard command handler. + * If that is not set, then this is a lecagy API call and we invoke + * the legacy command handler. */ + if (command->handler) + { + err = (*command->handler)(conn, pool, params, baton); + } + else + { + apr_array_header_t *deprecated_params + = svn_ra_svn__to_public_array(params, pool); + err = (*command->deprecated_handler)(conn, pool, deprecated_params, + baton); + } + + /* The command implementation may have swallowed or wrapped the I/O + * error not knowing that we may no longer be able to send data. + * + * So, check again for the limit violations and exit the command + * processing quickly if we may have truncated data. */ + err = svn_error_compose_create(check_io_limits(conn), err); + *terminate = command->terminate; } else @@ -1595,13 +1983,13 @@ svn_ra_svn__handle_command(svn_boolean_t *terminate, svn_error_t * svn_ra_svn__handle_commands2(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - const svn_ra_svn_cmd_entry_t *commands, + const svn_ra_svn__cmd_entry_t *commands, void *baton, svn_boolean_t error_on_disconnect) { apr_pool_t *subpool = svn_pool_create(pool); apr_pool_t *iterpool = svn_pool_create(subpool); - const svn_ra_svn_cmd_entry_t *command; + const svn_ra_svn__cmd_entry_t *command; apr_hash_t *cmd_hash = apr_hash_make(subpool); for (command = commands; command->cmdname; command++) @@ -1644,13 +2032,13 @@ svn_error_t * svn_ra_svn__write_cmd_open_root(svn_ra_svn_conn_t *conn, apr_pool_t *pool, svn_revnum_t rev, - const char *token) + const svn_string_t *token) { SVN_ERR(writebuf_write_literal(conn, pool, "( open-root ( ")); SVN_ERR(write_tuple_start_list(conn, pool)); SVN_ERR(write_tuple_revision_opt(conn, pool, rev)); SVN_ERR(write_tuple_end_list(conn, pool)); - SVN_ERR(write_tuple_cstring(conn, pool, token)); + SVN_ERR(write_tuple_string(conn, pool, token)); SVN_ERR(writebuf_write_literal(conn, pool, ") ) ")); return SVN_NO_ERROR; @@ -1661,14 +2049,14 @@ svn_ra_svn__write_cmd_delete_entry(svn_ra_svn_conn_t *conn, apr_pool_t *pool, const char *path, svn_revnum_t rev, - const char *token) + const svn_string_t *token) { SVN_ERR(writebuf_write_literal(conn, pool, "( delete-entry ( ")); SVN_ERR(write_tuple_cstring(conn, pool, path)); SVN_ERR(write_tuple_start_list(conn, pool)); SVN_ERR(write_tuple_revision_opt(conn, pool, rev)); SVN_ERR(write_tuple_end_list(conn, pool)); - SVN_ERR(write_tuple_cstring(conn, pool, token)); + SVN_ERR(write_tuple_string(conn, pool, token)); SVN_ERR(writebuf_write_literal(conn, pool, ") ) ")); return SVN_NO_ERROR; @@ -1678,8 +2066,8 @@ svn_error_t * svn_ra_svn__write_cmd_add_dir(svn_ra_svn_conn_t *conn, apr_pool_t *pool, const char *path, - const char *parent_token, - const char *token, + const svn_string_t *parent_token, + const svn_string_t *token, const char *copy_path, svn_revnum_t copy_rev) { @@ -1695,8 +2083,8 @@ svn_error_t * svn_ra_svn__write_cmd_open_dir(svn_ra_svn_conn_t *conn, apr_pool_t *pool, const char *path, - const char *parent_token, - const char *token, + const svn_string_t *parent_token, + const svn_string_t *token, svn_revnum_t rev) { SVN_ERR(writebuf_write_literal(conn, pool, "( open-dir ( ")); @@ -1709,7 +2097,7 @@ svn_ra_svn__write_cmd_open_dir(svn_ra_svn_conn_t *conn, svn_error_t * svn_ra_svn__write_cmd_change_dir_prop(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - const char *token, + const svn_string_t *token, const char *name, const svn_string_t *value) { @@ -1723,10 +2111,10 @@ svn_ra_svn__write_cmd_change_dir_prop(svn_ra_svn_conn_t *conn, svn_error_t * svn_ra_svn__write_cmd_close_dir(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - const char *token) + const svn_string_t *token) { SVN_ERR(writebuf_write_literal(conn, pool, "( close-dir ( ")); - SVN_ERR(write_tuple_cstring(conn, pool, token)); + SVN_ERR(write_tuple_string(conn, pool, token)); SVN_ERR(writebuf_write_literal(conn, pool, ") ) ")); return SVN_NO_ERROR; @@ -1736,7 +2124,7 @@ svn_error_t * svn_ra_svn__write_cmd_absent_dir(svn_ra_svn_conn_t *conn, apr_pool_t *pool, const char *path, - const char *parent_token) + const svn_string_t *parent_token) { SVN_ERR(writebuf_write_literal(conn, pool, "( absent-dir ( ")); SVN_ERR(write_cmd_absent_node(conn, pool, path, parent_token)); @@ -1749,8 +2137,8 @@ svn_error_t * svn_ra_svn__write_cmd_add_file(svn_ra_svn_conn_t *conn, apr_pool_t *pool, const char *path, - const char *parent_token, - const char *token, + const svn_string_t *parent_token, + const svn_string_t *token, const char *copy_path, svn_revnum_t copy_rev) { @@ -1766,8 +2154,8 @@ svn_error_t * svn_ra_svn__write_cmd_open_file(svn_ra_svn_conn_t *conn, apr_pool_t *pool, const char *path, - const char *parent_token, - const char *token, + const svn_string_t *parent_token, + const svn_string_t *token, svn_revnum_t rev) { SVN_ERR(writebuf_write_literal(conn, pool, "( open-file ( ")); @@ -1780,7 +2168,7 @@ svn_ra_svn__write_cmd_open_file(svn_ra_svn_conn_t *conn, svn_error_t * svn_ra_svn__write_cmd_change_file_prop(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - const char *token, + const svn_string_t *token, const char *name, const svn_string_t *value) { @@ -1794,11 +2182,11 @@ svn_ra_svn__write_cmd_change_file_prop(svn_ra_svn_conn_t *conn, svn_error_t * svn_ra_svn__write_cmd_close_file(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - const char *token, + const svn_string_t *token, const char *text_checksum) { SVN_ERR(writebuf_write_literal(conn, pool, "( close-file ( ")); - SVN_ERR(write_tuple_cstring(conn, pool, token)); + SVN_ERR(write_tuple_string(conn, pool, token)); SVN_ERR(write_tuple_start_list(conn, pool)); SVN_ERR(write_tuple_cstring_opt(conn, pool, text_checksum)); SVN_ERR(write_tuple_end_list(conn, pool)); @@ -1811,7 +2199,7 @@ svn_error_t * svn_ra_svn__write_cmd_absent_file(svn_ra_svn_conn_t *conn, apr_pool_t *pool, const char *path, - const char *parent_token) + const svn_string_t *parent_token) { SVN_ERR(writebuf_write_literal(conn, pool, "( absent-file ( ")); SVN_ERR(write_cmd_absent_node(conn, pool, path, parent_token)); @@ -1823,11 +2211,11 @@ svn_ra_svn__write_cmd_absent_file(svn_ra_svn_conn_t *conn, svn_error_t * svn_ra_svn__write_cmd_textdelta_chunk(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - const char *token, + const svn_string_t *token, const svn_string_t *chunk) { SVN_ERR(writebuf_write_literal(conn, pool, "( textdelta-chunk ( ")); - SVN_ERR(write_tuple_cstring(conn, pool, token)); + SVN_ERR(write_tuple_string(conn, pool, token)); SVN_ERR(write_tuple_string(conn, pool, chunk)); SVN_ERR(writebuf_write_literal(conn, pool, ") ) ")); @@ -1837,10 +2225,10 @@ svn_ra_svn__write_cmd_textdelta_chunk(svn_ra_svn_conn_t *conn, svn_error_t * svn_ra_svn__write_cmd_textdelta_end(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - const char *token) + const svn_string_t *token) { SVN_ERR(writebuf_write_literal(conn, pool, "( textdelta-end ( ")); - SVN_ERR(write_tuple_cstring(conn, pool, token)); + SVN_ERR(write_tuple_string(conn, pool, token)); SVN_ERR(writebuf_write_literal(conn, pool, ") ) ")); return SVN_NO_ERROR; @@ -1849,11 +2237,11 @@ svn_ra_svn__write_cmd_textdelta_end(svn_ra_svn_conn_t *conn, svn_error_t * svn_ra_svn__write_cmd_apply_textdelta(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - const char *token, + const svn_string_t *token, const char *base_checksum) { SVN_ERR(writebuf_write_literal(conn, pool, "( apply-textdelta ( ")); - SVN_ERR(write_tuple_cstring(conn, pool, token)); + SVN_ERR(write_tuple_string(conn, pool, token)); SVN_ERR(write_tuple_start_list(conn, pool)); SVN_ERR(write_tuple_cstring_opt(conn, pool, base_checksum)); SVN_ERR(write_tuple_end_list(conn, pool)); @@ -1991,9 +2379,7 @@ svn_ra_svn__write_cmd_change_rev_prop2(svn_ra_svn_conn_t *conn, SVN_ERR(writebuf_write_literal(conn, pool, "( change-rev-prop2 ( ")); SVN_ERR(write_tuple_revision(conn, pool, rev)); SVN_ERR(write_tuple_cstring(conn, pool, name)); - SVN_ERR(write_tuple_start_list(conn, pool)); - SVN_ERR(write_tuple_string_opt(conn, pool, value)); - SVN_ERR(write_tuple_end_list(conn, pool)); + SVN_ERR(write_tuple_string_opt_list(conn, pool, value)); SVN_ERR(write_tuple_start_list(conn, pool)); SVN_ERR(write_tuple_boolean(conn, pool, dont_care)); SVN_ERR(write_tuple_string_opt(conn, pool, old_value)); @@ -2245,14 +2631,12 @@ svn_error_t * svn_ra_svn__write_cmd_unlock(svn_ra_svn_conn_t *conn, apr_pool_t *pool, const char *path, - const char *token, + const svn_string_t *token, svn_boolean_t break_lock) { SVN_ERR(writebuf_write_literal(conn, pool, "( unlock ( ")); SVN_ERR(write_tuple_cstring(conn, pool, path)); - SVN_ERR(write_tuple_start_list(conn, pool)); - SVN_ERR(write_tuple_cstring_opt(conn, pool, token)); - SVN_ERR(write_tuple_end_list(conn, pool)); + SVN_ERR(write_tuple_string_opt_list(conn, pool, token)); SVN_ERR(write_tuple_boolean(conn, pool, break_lock)); SVN_ERR(writebuf_write_literal(conn, pool, ") ) ")); @@ -2402,10 +2786,53 @@ svn_error_t *svn_ra_svn__write_cmd_failure(svn_ra_svn_conn_t *conn, return writebuf_write_literal(conn, pool, ") ) "); } +/* Initializer for static svn_string_t . */ +#define STATIC_SVN_STRING(x) { x, sizeof(x) - 1 } + +/* Return a pre-cooked serialized representation for the changed path + flags NODE_KIND, TEXT_MODIFIED and PROPS_MODIFIED. If we don't + have a suitable pre-cooked string, return an empty string. */ +static const svn_string_t * +changed_path_flags(svn_node_kind_t node_kind, + svn_boolean_t text_modified, + svn_boolean_t props_modified) +{ + static const svn_string_t file_flags[4] + = { STATIC_SVN_STRING(" ) ( 4:file false false ) ) "), + STATIC_SVN_STRING(" ) ( 4:file false true ) ) "), + STATIC_SVN_STRING(" ) ( 4:file true false ) ) "), + STATIC_SVN_STRING(" ) ( 4:file true true ) ) ") }; + + static const svn_string_t dir_flags[4] + = { STATIC_SVN_STRING(" ) ( 3:dir false false ) ) "), + STATIC_SVN_STRING(" ) ( 3:dir false true ) ) "), + STATIC_SVN_STRING(" ) ( 3:dir true false ) ) "), + STATIC_SVN_STRING(" ) ( 3:dir true true ) ) ") }; + + static const svn_string_t no_flags = STATIC_SVN_STRING(""); + + /* Select the array based on the NODE_KIND. */ + const svn_string_t *flags; + if (node_kind == svn_node_file) + flags = file_flags; + else if (node_kind == svn_node_dir) + flags = dir_flags; + else + return &no_flags; + + /* Select the correct array entry. */ + if (text_modified) + flags += 2; + if (props_modified) + flags++; + + return flags; +} + svn_error_t * svn_ra_svn__write_data_log_changed_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - const char *path, + const svn_string_t *path, char action, const char *copyfrom_path, svn_revnum_t copyfrom_rev, @@ -2413,21 +2840,83 @@ svn_ra_svn__write_data_log_changed_path(svn_ra_svn_conn_t *conn, svn_boolean_t text_modified, svn_boolean_t props_modified) { - SVN_ERR(write_tuple_start_list(conn, pool)); + apr_size_t path_len = path->len; + apr_size_t copyfrom_len = copyfrom_path ? strlen(copyfrom_path) : 0; + const svn_string_t *flags_str = changed_path_flags(node_kind, + text_modified, + props_modified); + apr_size_t flags_len = flags_str->len; - SVN_ERR(write_tuple_cstring(conn, pool, path)); - SVN_ERR(writebuf_writechar(conn, pool, action)); - SVN_ERR(writebuf_writechar(conn, pool, ' ')); - SVN_ERR(write_tuple_start_list(conn, pool)); - SVN_ERR(write_tuple_cstring_opt(conn, pool, copyfrom_path)); - SVN_ERR(write_tuple_revision_opt(conn, pool, copyfrom_rev)); - SVN_ERR(write_tuple_end_list(conn, pool)); - SVN_ERR(write_tuple_start_list(conn, pool)); - SVN_ERR(write_tuple_cstring(conn, pool, svn_node_kind_to_word(node_kind))); - SVN_ERR(write_tuple_boolean(conn, pool, text_modified)); - SVN_ERR(write_tuple_boolean(conn, pool, props_modified)); + /* How much buffer space can we use for non-string data (worst case)? */ + apr_size_t max_fill = sizeof(conn->write_buf) + - 2 /* list start */ + - 2 - SVN_INT64_BUFFER_SIZE /* path */ + - 2 /* action */ + - 2 /* list start */ + - 2 - SVN_INT64_BUFFER_SIZE /* copy-from path */ + - 1 - SVN_INT64_BUFFER_SIZE; /* copy-from rev */ - return writebuf_write_literal(conn, pool, ") ) "); + /* If the remaining buffer is big enough and we've got all parts, + directly copy into the buffer. On platforms with segmented memory, + PATH_LEN + COPYFROM_LEN might actually be close to APR_SIZE_MAX. + Blindly doing arithmetic on them might cause an overflow. + The sum in here cannot overflow because WRITE_BUF is small, i.e. + MAX_FILL and WRITE_POS are much smaller than APR_SIZE_MAX. */ + if ( (path_len <= max_fill) && (copyfrom_len <= max_fill) + && (conn->write_pos + path_len + copyfrom_len + flags_len <= max_fill) + && (flags_len > 0)) + { + /* Quick path. */ + /* Open list. */ + char *p = conn->write_buf + conn->write_pos; + p[0] = '('; + p[1] = ' '; + + /* Write path. */ + p = write_ncstring_quick(p + 2, path->data, path_len); + + /* Action */ + p[0] = action; + p[1] = ' '; + p[2] = '('; + + /* Copy-from info (if given) */ + if (copyfrom_path) + { + p[3] = ' '; + p = write_ncstring_quick(p + 4, copyfrom_path, copyfrom_len); + p += svn__ui64toa(p, copyfrom_rev); + } + else + { + p += 3; + } + + /* Close with flags. */ + memcpy(p, flags_str->data, flags_str->len); + conn->write_pos = p + flags_str->len - conn->write_buf; + } + else + { + /* Standard code path (fallback). */ + SVN_ERR(write_tuple_start_list(conn, pool)); + + SVN_ERR(svn_ra_svn__write_ncstring(conn, pool, path->data, path_len)); + SVN_ERR(writebuf_writechar(conn, pool, action)); + SVN_ERR(writebuf_writechar(conn, pool, ' ')); + SVN_ERR(write_tuple_start_list(conn, pool)); + SVN_ERR(write_tuple_cstring_opt(conn, pool, copyfrom_path)); + SVN_ERR(write_tuple_revision_opt(conn, pool, copyfrom_rev)); + SVN_ERR(write_tuple_end_list(conn, pool)); + SVN_ERR(write_tuple_start_list(conn, pool)); + SVN_ERR(write_tuple_cstring(conn, pool, svn_node_kind_to_word(node_kind))); + SVN_ERR(write_tuple_boolean(conn, pool, text_modified)); + SVN_ERR(write_tuple_boolean(conn, pool, props_modified)); + + SVN_ERR(writebuf_write_literal(conn, pool, ") ) ")); + } + + return SVN_NO_ERROR; } svn_error_t * @@ -2442,15 +2931,9 @@ svn_ra_svn__write_data_log_entry(svn_ra_svn_conn_t *conn, unsigned revprop_count) { SVN_ERR(write_tuple_revision(conn, pool, revision)); - SVN_ERR(write_tuple_start_list(conn, pool)); - SVN_ERR(write_tuple_string_opt(conn, pool, author)); - SVN_ERR(write_tuple_end_list(conn, pool)); - SVN_ERR(write_tuple_start_list(conn, pool)); - SVN_ERR(write_tuple_string_opt(conn, pool, date)); - SVN_ERR(write_tuple_end_list(conn, pool)); - SVN_ERR(write_tuple_start_list(conn, pool)); - SVN_ERR(write_tuple_string_opt(conn, pool, message)); - SVN_ERR(write_tuple_end_list(conn, pool)); + SVN_ERR(write_tuple_string_opt_list(conn, pool, author)); + SVN_ERR(write_tuple_string_opt_list(conn, pool, date)); + SVN_ERR(write_tuple_string_opt_list(conn, pool, message)); SVN_ERR(write_tuple_boolean(conn, pool, has_children)); SVN_ERR(write_tuple_boolean(conn, pool, invalid_revnum)); SVN_ERR(svn_ra_svn__write_number(conn, pool, revprop_count)); @@ -2458,6 +2941,57 @@ svn_ra_svn__write_data_log_entry(svn_ra_svn_conn_t *conn, return SVN_NO_ERROR; } +svn_error_t * +svn_ra_svn__write_dirent(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + const char *path, + svn_dirent_t *dirent, + apr_uint32_t dirent_fields) +{ + const char *kind = (dirent_fields & SVN_DIRENT_KIND) + ? svn_node_kind_to_word(dirent->kind) + : "unknown"; + + if (dirent_fields & ~SVN_DIRENT_KIND) + { + SVN_ERR(write_tuple_start_list(conn, pool)); + SVN_ERR(write_tuple_cstring(conn, pool, path)); + SVN_ERR(writebuf_write(conn, pool, kind, strlen(kind))); + + SVN_ERR(writebuf_write_literal(conn, pool, " ( ")); + if (dirent_fields & SVN_DIRENT_SIZE) + SVN_ERR(svn_ra_svn__write_number(conn, pool, dirent->size)); + + SVN_ERR(writebuf_write_literal(conn, pool, ") ( ")); + if (dirent_fields & SVN_DIRENT_HAS_PROPS) + SVN_ERR(write_tuple_boolean(conn, pool, dirent->has_props)); + + SVN_ERR(writebuf_write_literal(conn, pool, ") ( ")); + if (dirent_fields & SVN_DIRENT_CREATED_REV) + SVN_ERR(write_tuple_revision(conn, pool, dirent->created_rev)); + + SVN_ERR(writebuf_write_literal(conn, pool, ") ( ")); + if (dirent_fields & SVN_DIRENT_TIME) + SVN_ERR(write_tuple_cstring_opt(conn, pool, + svn_time_to_cstring(dirent->time, pool))); + + SVN_ERR(writebuf_write_literal(conn, pool, ") ( ")); + if (dirent_fields & SVN_DIRENT_LAST_AUTHOR) + SVN_ERR(write_tuple_cstring_opt(conn, pool, dirent->last_author)); + + SVN_ERR(writebuf_write_literal(conn, pool, ") ) ")); + } + else + { + SVN_ERR(write_tuple_start_list(conn, pool)); + SVN_ERR(write_tuple_cstring(conn, pool, path)); + SVN_ERR(writebuf_write(conn, pool, kind, strlen(kind))); + SVN_ERR(writebuf_write_literal(conn, pool, " ) ")); + } + + return SVN_NO_ERROR; +} + /* If condition COND is not met, return a "malformed network data" error. */ #define CHECK_PROTOCOL_COND(cond)\ @@ -2468,13 +3002,13 @@ svn_ra_svn__write_data_log_entry(svn_ra_svn_conn_t *conn, /* In *RESULT, return the SVN-style string at index IDX in tuple ITEMS. */ static svn_error_t * -svn_ra_svn__read_string(const apr_array_header_t *items, +svn_ra_svn__read_string(const svn_ra_svn__list_t *items, int idx, svn_string_t **result) { - svn_ra_svn_item_t *elt = &APR_ARRAY_IDX(items, idx, svn_ra_svn_item_t); + svn_ra_svn__item_t *elt = &SVN_RA_SVN__LIST_ITEM(items, idx); CHECK_PROTOCOL_COND(elt->kind == SVN_RA_SVN_STRING); - *result = elt->u.string; + *result = &elt->u.string; return SVN_NO_ERROR; } @@ -2482,13 +3016,13 @@ svn_ra_svn__read_string(const apr_array_header_t *items, /* In *RESULT, return the C-style string at index IDX in tuple ITEMS. */ static svn_error_t * -svn_ra_svn__read_cstring(const apr_array_header_t *items, +svn_ra_svn__read_cstring(const svn_ra_svn__list_t *items, int idx, const char **result) { - svn_ra_svn_item_t *elt = &APR_ARRAY_IDX(items, idx, svn_ra_svn_item_t); + svn_ra_svn__item_t *elt = &SVN_RA_SVN__LIST_ITEM(items, idx); CHECK_PROTOCOL_COND(elt->kind == SVN_RA_SVN_STRING); - *result = elt->u.string->data; + *result = elt->u.string.data; return SVN_NO_ERROR; } @@ -2496,13 +3030,13 @@ svn_ra_svn__read_cstring(const apr_array_header_t *items, /* In *RESULT, return the word at index IDX in tuple ITEMS. */ static svn_error_t * -svn_ra_svn__read_word(const apr_array_header_t *items, +svn_ra_svn__read_word(const svn_ra_svn__list_t *items, int idx, const char **result) { - svn_ra_svn_item_t *elt = &APR_ARRAY_IDX(items, idx, svn_ra_svn_item_t); + svn_ra_svn__item_t *elt = &SVN_RA_SVN__LIST_ITEM(items, idx); CHECK_PROTOCOL_COND(elt->kind == SVN_RA_SVN_WORD); - *result = elt->u.word; + *result = elt->u.word.data; return SVN_NO_ERROR; } @@ -2510,11 +3044,11 @@ svn_ra_svn__read_word(const apr_array_header_t *items, /* In *RESULT, return the revision at index IDX in tuple ITEMS. */ static svn_error_t * -svn_ra_svn__read_revision(const apr_array_header_t *items, +svn_ra_svn__read_revision(const svn_ra_svn__list_t *items, int idx, svn_revnum_t *result) { - svn_ra_svn_item_t *elt = &APR_ARRAY_IDX(items, idx, svn_ra_svn_item_t); + svn_ra_svn__item_t *elt = &SVN_RA_SVN__LIST_ITEM(items, idx); CHECK_PROTOCOL_COND(elt->kind == SVN_RA_SVN_NUMBER); *result = (svn_revnum_t)elt->u.number; @@ -2524,15 +3058,15 @@ svn_ra_svn__read_revision(const apr_array_header_t *items, /* In *RESULT, return the boolean at index IDX in tuple ITEMS. */ static svn_error_t * -svn_ra_svn__read_boolean(const apr_array_header_t *items, +svn_ra_svn__read_boolean(const svn_ra_svn__list_t *items, int idx, apr_uint64_t *result) { - svn_ra_svn_item_t *elt = &APR_ARRAY_IDX(items, idx, svn_ra_svn_item_t); + svn_ra_svn__item_t *elt = &SVN_RA_SVN__LIST_ITEM(items, idx); CHECK_PROTOCOL_COND(elt->kind == SVN_RA_SVN_WORD); - if (elt->u.word[0] == 't' && strcmp(elt->u.word, "true") == 0) + if (svn_string_compare(&elt->u.word, &str_true)) *result = TRUE; - else if (strcmp(elt->u.word, "false") == 0) + else if (svn_string_compare(&elt->u.word, &str_false)) *result = FALSE; else CHECK_PROTOCOL_COND(FALSE); @@ -2543,21 +3077,21 @@ svn_ra_svn__read_boolean(const apr_array_header_t *items, /* In *RESULT, return the tuple at index IDX in tuple ITEMS. */ static svn_error_t * -svn_ra_svn__read_list(const apr_array_header_t *items, +svn_ra_svn__read_list(const svn_ra_svn__list_t *items, int idx, - const apr_array_header_t **result) + const svn_ra_svn__list_t **result) { - svn_ra_svn_item_t *elt = &APR_ARRAY_IDX(items, idx, svn_ra_svn_item_t); + svn_ra_svn__item_t *elt = &SVN_RA_SVN__LIST_ITEM(items, idx); CHECK_PROTOCOL_COND(elt->kind == SVN_RA_SVN_LIST); - *result = elt->u.list; + *result = &elt->u.list; return SVN_NO_ERROR; } /* Verify the tuple ITEMS contains at least MIN and at most MAX elements. */ static svn_error_t * -svn_ra_svn__read_check_array_size(const apr_array_header_t *items, +svn_ra_svn__read_check_array_size(const svn_ra_svn__list_t *items, int min, int max) { @@ -2566,7 +3100,7 @@ svn_ra_svn__read_check_array_size(const apr_array_header_t *items, } svn_error_t * -svn_ra_svn__read_data_log_changed_entry(const apr_array_header_t *items, +svn_ra_svn__read_data_log_changed_entry(const svn_ra_svn__list_t *items, svn_string_t **cpath, const char **action, const char **copy_path, @@ -2575,7 +3109,7 @@ svn_ra_svn__read_data_log_changed_entry(const apr_array_header_t *items, apr_uint64_t *text_mods, apr_uint64_t *prop_mods) { - const apr_array_header_t *sub_items; + const svn_ra_svn__list_t *sub_items; /* initialize optional values */ *copy_path = NULL; diff --git a/subversion/libsvn_ra_svn/protocol b/subversion/libsvn_ra_svn/protocol index dfc1f3dc1659..dfa7bc4585ac 100644 --- a/subversion/libsvn_ra_svn/protocol +++ b/subversion/libsvn_ra_svn/protocol @@ -188,6 +188,10 @@ capability and C indicates a client capability): [CS] svndiff1 If both the client and server support svndiff version 1, this will be used as the on-the-wire format for svndiff instead of svndiff version 0. +[CS] accepts-svndiff2 This capability advertises support for accepting + svndiff2 deltas. The sender of a delta (= the editor + driver) may send it in any svndiff version the receiver + has announced it can accept. [CS] absent-entries If the remote end announces support for this capability, it will accept the absent-dir and absent-file editor commands. @@ -206,6 +210,8 @@ capability and C indicates a client capability): retrieval of inherited properties via the get-dir and get-file commands and also supports the get-iprops command (see section 3.1.1). +[S] list If the server presents this capability, it supports the + list command (see section 3.1.1). 3. Commands ----------- @@ -487,6 +493,21 @@ second place for auth-request point as noted below. response: ( inherited-props:iproplist ) New in svn 1.8. If rev is not specified, the youngest revision is used. + list + params: ( path:string [ rev:number ] depth:word + ( field:dirent-field ... ) ? ( pattern:string ... ) ) + Before sending response, server sends dirents, ending with "done". + dirent: ( rel-path:string kind:node-kind + ? [ size:number ] [ has-props:bool ] [ created-rev:number ] + [ created-date:string ] [ last-author:string ] ) + | done + dirent-field: kind | size | has-props | created-rev | time | last-author + | word + response: ( ) + New in svn 1.10. If rev is not specified, the youngest revision is used. + If the dirent-fields don't contain "kind", "unknown" will be returned + in the kind field. + 3.1.2. Editor Command Set An edit operation produces only one response, at close-edit or diff --git a/subversion/libsvn_ra_svn/ra_svn.h b/subversion/libsvn_ra_svn/ra_svn.h index d9fe1b2758c9..012d455b1359 100644 --- a/subversion/libsvn_ra_svn/ra_svn.h +++ b/subversion/libsvn_ra_svn/ra_svn.h @@ -96,6 +96,12 @@ struct svn_ra_svn_conn_st { apr_size_t error_check_interval; svn_boolean_t may_check_for_error; + /* I/O limits and tracking */ + apr_uint64_t max_in; + apr_uint64_t current_in; + apr_uint64_t max_out; + apr_uint64_t current_out; + /* repository info */ const char *uuid; const char *repos_root; @@ -119,12 +125,30 @@ struct svn_ra_svn_conn_st { apr_pool_t *pool; }; +/* The session's URL state for client and server side. + * + * This keeps track of the respective client-side and server-side "parent" + * URLs. It tells us whether we may have to send reparent commands to the + * server and how to tweak path parameters when we decided to handle + * reparent requests on the client side only. */ +typedef struct svn_ra_svn__parent_t { + /* Client-side session base URL, i.e. client's parent path. */ + svn_stringbuf_t *client_url; + + /* Server-side base URL, i.e. server's parent path. */ + svn_stringbuf_t *server_url; + + /* Relative path to add to a client-side parameter to translate it for the + * server-side. I.e. the relative path from SERVER_URL to CLIENT_URL. */ + svn_stringbuf_t *path; +} svn_ra_svn__parent_t; + struct svn_ra_svn__session_baton_t { apr_pool_t *pool; svn_ra_svn_conn_t *conn; svn_boolean_t is_tunneled; svn_auth_baton_t *auth_baton; - const char *url; + svn_ra_svn__parent_t *parent; const char *user; const char *hostname; /* The remote hostname. */ const char *realm_prefix; @@ -151,6 +175,12 @@ void svn_ra_svn__set_block_handler(svn_ra_svn_conn_t *conn, svn_error_t *svn_ra_svn__data_available(svn_ra_svn_conn_t *conn, svn_boolean_t *data_available); +/* Signal a new request / response pair on CONN. That resets the I/O + * counters we use to limit the size of individual requests / response pairs. + */ +void +svn_ra_svn__reset_command_io_counters(svn_ra_svn_conn_t *conn); + /* CRAM-MD5 client implementation. */ svn_error_t *svn_ra_svn__cram_client(svn_ra_svn_conn_t *conn, apr_pool_t *pool, const char *user, const char *password, @@ -163,10 +193,9 @@ svn_error_t *svn_ra_svn__locate_real_error_child(svn_error_t *err); /* Return an error chain based on @a params (which contains a * command response indicating failure). The error chain will be - * in the same order as the errors indicated in @a params. Use - * @a pool for temporary allocations. */ -svn_error_t *svn_ra_svn__handle_failure_status(const apr_array_header_t *params, - apr_pool_t *pool); + * in the same order as the errors indicated in @a params. */ +svn_error_t * +svn_ra_svn__handle_failure_status(const svn_ra_svn__list_t *params); /* Returns a stream that reads/writes from/to SOCK. */ svn_ra_svn__stream_t *svn_ra_svn__stream_from_sock(apr_socket_t *sock, @@ -220,7 +249,7 @@ svn_ra_svn__stream_data_available(svn_ra_svn__stream_t *stream, * tokens. */ svn_error_t * svn_ra_svn__do_cyrus_auth(svn_ra_svn__session_baton_t *sess, - const apr_array_header_t *mechlist, + const svn_ra_svn__list_t *mechlist, const char *realm, apr_pool_t *pool); /* Same as svn_ra_svn__do_cyrus_auth, but uses the built-in implementation of @@ -229,7 +258,7 @@ svn_ra_svn__do_cyrus_auth(svn_ra_svn__session_baton_t *sess, * mechanism with the server. */ svn_error_t * svn_ra_svn__do_internal_auth(svn_ra_svn__session_baton_t *sess, - const apr_array_header_t *mechlist, + const svn_ra_svn__list_t *mechlist, const char *realm, apr_pool_t *pool); /* Having picked a mechanism, start authentication by writing out an @@ -239,8 +268,8 @@ svn_error_t *svn_ra_svn__auth_response(svn_ra_svn_conn_t *conn, apr_pool_t *pool, const char *mech, const char *mech_arg); -/* Looks for MECH as a word in MECHLIST (an array of svn_ra_svn_item_t). */ -svn_boolean_t svn_ra_svn__find_mech(const apr_array_header_t *mechlist, +/* Looks for MECH as a word in MECHLIST. */ +svn_boolean_t svn_ra_svn__find_mech(const svn_ra_svn__list_t *mechlist, const char *mech); /* Initialize the SASL library. */ diff --git a/subversion/libsvn_ra_svn/wrapped_sasl.c b/subversion/libsvn_ra_svn/wrapped_sasl.c new file mode 100644 index 000000000000..e20fc98689a9 --- /dev/null +++ b/subversion/libsvn_ra_svn/wrapped_sasl.c @@ -0,0 +1,197 @@ +/* + * wrapped_sasl.c : wrapped SASL API + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#include "svn_private_config.h" +#ifdef SVN_HAVE_SASL + +#include "private/ra_svn_wrapped_sasl.h" + +/* See the comment at the top of svn_wrapped_sasl.h */ +#ifdef __APPLE__ +# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2) +# pragma GCC diagnostic ignored "-Wdeprecated-declarations" +# endif +#endif /* __APPLE__ */ + +void +svn_sasl__set_mutex(sasl_mutex_alloc_t *alloc, + sasl_mutex_lock_t *lock, + sasl_mutex_unlock_t *unlock, + sasl_mutex_free_t *free) +{ + sasl_set_mutex(alloc, lock, unlock, free); +} + +void +svn_sasl__done(void) +{ + sasl_done(); +} + +void +svn_sasl__dispose(sasl_conn_t **pconn) +{ + sasl_dispose(pconn); +} + +const char * +svn_sasl__errstring(int saslerr, const char *langlist, const char **outlang) +{ + return sasl_errstring(saslerr, langlist, outlang); +} + +const char * +svn_sasl__errdetail(sasl_conn_t *conn) +{ + return sasl_errdetail(conn); +} + +int +svn_sasl__getprop(sasl_conn_t *conn, int propnum, const void **pvalue) +{ + return sasl_getprop(conn, propnum, pvalue); +} + +int +svn_sasl__setprop(sasl_conn_t *conn, int propnum, const void *value) +{ + return sasl_setprop(conn, propnum, value); +} + +int +svn_sasl__client_init(const sasl_callback_t *callbacks) +{ + return sasl_client_init(callbacks); +} + +int +svn_sasl__client_new(const char *service, + const char *serverFQDN, + const char *iplocalport, + const char *ipremoteport, + const sasl_callback_t *prompt_supp, + unsigned flags, + sasl_conn_t **pconn) +{ + return sasl_client_new(service, serverFQDN, iplocalport, ipremoteport, + prompt_supp, flags, pconn); +} + +int +svn_sasl__client_start(sasl_conn_t *conn, + const char *mechlist, + sasl_interact_t **prompt_need, + const char **clientout, + unsigned *clientoutlen, + const char **mech) +{ + return sasl_client_start(conn, mechlist, prompt_need, + clientout, clientoutlen, mech); +} + +int +svn_sasl__client_step(sasl_conn_t *conn, + const char *serverin, + unsigned serverinlen, + sasl_interact_t **prompt_need, + const char **clientout, + unsigned *clientoutlen) +{ + return sasl_client_step(conn, serverin, serverinlen, prompt_need, + clientout, clientoutlen); +} + +int +svn_sasl__server_init(const sasl_callback_t *callbacks, + const char *appname) +{ + return sasl_server_init(callbacks, appname); +} + +int +svn_sasl__server_new(const char *service, + const char *serverFQDN, + const char *user_realm, + const char *iplocalport, + const char *ipremoteport, + const sasl_callback_t *callbacks, + unsigned flags, + sasl_conn_t **pconn) +{ + return sasl_server_new(service, serverFQDN, user_realm, + iplocalport, ipremoteport, callbacks, flags, pconn); +} + +int +svn_sasl__listmech(sasl_conn_t *conn, + const char *user, + const char *prefix, + const char *sep, + const char *suffix, + const char **result, + unsigned *plen, + int *pcount) +{ + return sasl_listmech(conn, user, prefix, sep, suffix, result, plen, pcount); +} + +int +svn_sasl__server_start(sasl_conn_t *conn, + const char *mech, + const char *clientin, + unsigned clientinlen, + const char **serverout, + unsigned *serveroutlen) +{ + return sasl_server_start(conn, mech, clientin, clientinlen, + serverout, serveroutlen); +} + +int +svn_sasl__server_step(sasl_conn_t *conn, + const char *clientin, + unsigned clientinlen, + const char **serverout, + unsigned *serveroutlen) +{ + return sasl_server_step(conn, clientin, clientinlen, + serverout, serveroutlen); +} + +int +svn_sasl__encode(sasl_conn_t *conn, + const char *input, unsigned inputlen, + const char **output, unsigned *outputlen) +{ + return sasl_encode(conn, input, inputlen, output, outputlen); +} + +int +svn_sasl__decode(sasl_conn_t *conn, + const char *input, unsigned inputlen, + const char **output, unsigned *outputlen) +{ + return sasl_decode(conn, input, inputlen, output, outputlen); +} + +#endif /* SVN_HAVE_SASL */ diff --git a/subversion/libsvn_repos/authz.c b/subversion/libsvn_repos/authz.c index 20f9231dc22a..668d78dd5993 100644 --- a/subversion/libsvn_repos/authz.c +++ b/subversion/libsvn_repos/authz.c @@ -25,6 +25,7 @@ #include #include +#include #include "svn_hash.h" #include "svn_pools.h" @@ -34,946 +35,1592 @@ #include "svn_repos.h" #include "svn_config.h" #include "svn_ctype.h" +#include "private/svn_atomic.h" #include "private/svn_fspath.h" #include "private/svn_repos_private.h" +#include "private/svn_sorts_private.h" +#include "private/svn_subr_private.h" #include "repos.h" +#include "authz.h" +#include "config_file.h" -/*** Structures. ***/ +/*** Access rights. ***/ -/* Information for the config enumerators called during authz - lookup. */ -struct authz_lookup_baton { - /* The authz configuration. */ - svn_config_t *config; +/* This structure describes the access rights given to a specific user by + * a path rule (actually the rule set specified for a path). I.e. there is + * one instance of this per path rule. + */ +typedef struct path_access_t +{ + /* Sequence number of the path rule that this struct was derived from. + * If multiple rules apply to the same path (only possible with wildcard + * matching), the one with the highest SEQUENCE_NUMBER wins, i.e. the latest + * one defined in the authz file. + * + * A value of 0 denotes the default rule at the repository root denying + * access to everybody. User-defined path rules start with ID 1. + */ + int sequence_number; - /* The user to authorize. */ + /* Access rights of the respective user as defined by the rule set. */ + authz_access_t rights; +} path_access_t; + +/* Use this to indicate that no sequence ID has been assigned. + * It will automatically be inferior to (less than) any other sequence ID. */ +#define NO_SEQUENCE_NUMBER (-1) + +/* Convenience structure combining the node-local access rights with the + * min and max rights granted within the sub-tree. */ +typedef struct limited_rights_t +{ + /* Access granted to the current user. If the SEQUENCE_NUMBER member is + * NO_SEQUENCE_NUMBER, there has been no specific path rule for this PATH + * but only for some sub-path(s). There is always a rule at the root node. + */ + path_access_t access; + + /* Minimal access rights that the user has on this or any other node in + * the sub-tree. This does not take inherited rights into account. */ + authz_access_t min_rights; + + /* Maximal access rights that the user has on this or any other node in + * the sub-tree. This does not take inherited rights into account. */ + authz_access_t max_rights; + +} limited_rights_t; + +/* Return TRUE, if RIGHTS has local rights defined in the ACCESS member. */ +static svn_boolean_t +has_local_rule(const limited_rights_t *rights) +{ + return rights->access.sequence_number != NO_SEQUENCE_NUMBER; +} + +/* Aggregate the ACCESS spec of TARGET and RIGHTS into TARGET. I.e. if both + * are specified, pick one in accordance to the precedence rules. */ +static void +combine_access(limited_rights_t *target, + const limited_rights_t *rights) +{ + /* This implies the check for NO_SEQUENCE_NUMBER, i.e no rights being + * specified. */ + if (target->access.sequence_number < rights->access.sequence_number) + target->access = rights->access; +} + +/* Aggregate the min / max access rights of TARGET and RIGHTS into TARGET. */ +static void +combine_right_limits(limited_rights_t *target, + const limited_rights_t *rights) +{ + target->max_rights |= rights->max_rights; + target->min_rights &= rights->min_rights; +} + + + +/*** Authz cache access. ***/ + +/* All authz instances currently in use as well as all filtered authz + * instances in use will be cached here. + * Both caches will be instantiated at most once. */ +static svn_object_pool__t *authz_pool = NULL; +static svn_object_pool__t *filtered_pool = NULL; +static svn_atomic_t authz_pool_initialized = FALSE; + +/* Implements svn_atomic__err_init_func_t. */ +static svn_error_t * +synchronized_authz_initialize(void *baton, apr_pool_t *pool) +{ +#if APR_HAS_THREADS + svn_boolean_t multi_threaded = TRUE; +#else + svn_boolean_t multi_threaded = FALSE; +#endif + + SVN_ERR(svn_object_pool__create(&authz_pool, multi_threaded, pool)); + SVN_ERR(svn_object_pool__create(&filtered_pool, multi_threaded, pool)); + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_repos_authz_initialize(apr_pool_t *pool) +{ + /* Protect against multiple calls. */ + return svn_error_trace(svn_atomic__init_once(&authz_pool_initialized, + synchronized_authz_initialize, + NULL, pool)); +} + +/* Return a combination of AUTHZ_KEY and GROUPS_KEY, allocated in RESULT_POOL. + * GROUPS_KEY may be NULL. This is the key for the AUTHZ_POOL. + */ +static svn_membuf_t * +construct_authz_key(const svn_checksum_t *authz_key, + const svn_checksum_t *groups_key, + apr_pool_t *result_pool) +{ + svn_membuf_t *result = apr_pcalloc(result_pool, sizeof(*result)); + if (groups_key) + { + apr_size_t authz_size = svn_checksum_size(authz_key); + apr_size_t groups_size = svn_checksum_size(groups_key); + + svn_membuf__create(result, authz_size + groups_size, result_pool); + result->size = authz_size + groups_size; /* exact length is required! */ + + memcpy(result->data, authz_key->digest, authz_size); + memcpy((char *)result->data + authz_size, + groups_key->digest, groups_size); + } + else + { + apr_size_t size = svn_checksum_size(authz_key); + svn_membuf__create(result, size, result_pool); + result->size = size; /* exact length is required! */ + memcpy(result->data, authz_key->digest, size); + } + + return result; +} + +/* Return a combination of REPOS_NAME, USER and AUTHZ_ID, allocated in + * RESULT_POOL. USER may be NULL. This is the key for the FILTERED_POOL. + */ +static svn_membuf_t * +construct_filtered_key(const char *repos_name, + const char *user, + const svn_membuf_t *authz_id, + apr_pool_t *result_pool) +{ + svn_membuf_t *result = apr_pcalloc(result_pool, sizeof(*result)); + size_t repos_len = strlen(repos_name); + size_t user_len = user ? strlen(user) : 1; + const char *nullable_user = user ? user : "\0"; + size_t size = authz_id->size + repos_len + 1 + user_len + 1; + + svn_membuf__create(result, size, result_pool); + result->size = size; + + memcpy(result->data, repos_name, repos_len + 1); + size = repos_len + 1; + memcpy((char *)result->data + size, nullable_user, user_len + 1); + size += user_len + 1; + memcpy((char *)result->data + size, authz_id->data, authz_id->size); + + return result; +} + + +/*** Constructing the prefix tree. ***/ + +/* Since prefix arrays may have more than one hit, we need to link them + * for fast lookup. */ +typedef struct sorted_pattern_t +{ + /* The filtered tree node carrying the prefix. */ + struct node_t *node; + + /* Entry that is a prefix to this one or NULL. */ + struct sorted_pattern_t *next; +} sorted_pattern_t; + +/* Substructure of node_t. It contains all sub-node that use patterns + * in the next segment level. We keep it separate to save a bit of memory + * and to be able to check for pattern presence in a single operation. + */ +typedef struct node_pattern_t +{ + /* If not NULL, this represents the "*" follow-segment. */ + struct node_t *any; + + /* If not NULL, this represents the "**" follow-segment. */ + struct node_t *any_var; + + /* If not NULL, the segments of all sorted_pattern_t in this array are the + * prefix part of "prefix*" patterns. Sorted by segment prefix. */ + apr_array_header_t *prefixes; + + /* If not NULL, the segments of all sorted_pattern_t in this array are the + * reversed suffix part of "*suffix" patterns. Sorted by reversed + * segment suffix. */ + apr_array_header_t *suffixes; + + /* If not NULL, the segments of all sorted_pattern_t in this array contain + * wildcards and don't fit into any of the above categories. + * The NEXT members of the elements will not be used. */ + apr_array_header_t *complex; + + /* This node itself is a "**" segment and must therefore itself be added + * to the matching node list for the next level. */ + svn_boolean_t repeat; +} node_pattern_t; + +/* The pattern tree. All relevant path rules are being folded into this + * prefix tree, with a single, whole segment stored at each node. The whole + * tree applies to a single user only. + */ +typedef struct node_t +{ + /* The segment as specified in the path rule. During the lookup tree walk, + * this will compared to the respective segment of the path to check. */ + svn_string_t segment; + + /* Immediate access rights granted by rules on this node and the min / + * max rights on any path in this sub-tree. */ + limited_rights_t rights; + + /* Map of sub-segment(const char *) to respective node (node_t) for all + * sub-segments that have rules on themselves or their respective subtrees. + * NULL, if there are no rules for sub-paths relevant to the user. */ + apr_hash_t *sub_nodes; + + /* If not NULL, this contains the pattern-based segment sub-nodes. */ + node_pattern_t *pattern_sub_nodes; +} node_t; + +/* Create a new tree node for SEGMENT. + Note: SEGMENT->pattern is always interned and therefore does not + have to be copied into the result pool. */ +static node_t * +create_node(authz_rule_segment_t *segment, + apr_pool_t *result_pool) +{ + node_t *result = apr_pcalloc(result_pool, sizeof(*result)); + if (segment) + result->segment = segment->pattern; + else + { + result->segment.data = ""; + result->segment.len = 0; + } + result->rights.access.sequence_number = NO_SEQUENCE_NUMBER; + return result; +} + +/* Auto-create a node in *NODE, make it apply to SEGMENT and return it. */ +static node_t * +ensure_node(node_t **node, + authz_rule_segment_t *segment, + apr_pool_t *result_pool) +{ + if (!*node) + *node = create_node(segment, result_pool); + + return *node; +} + +/* compare_func comparing segment names. It takes a sorted_pattern_t* as + * VOID_LHS and a const authz_rule_segment_t * as VOID_RHS. + */ +static int +compare_node_rule_segment(const void *void_lhs, + const void *void_rhs) +{ + const sorted_pattern_t *element = void_lhs; + const authz_rule_segment_t *segment = void_rhs; + + return strcmp(element->node->segment.data, segment->pattern.data); +} + +/* compare_func comparing segment names. It takes a sorted_pattern_t* as + * VOID_LHS and a const char * as VOID_RHS. + */ +static int +compare_node_path_segment(const void *void_lhs, + const void *void_rhs) +{ + const sorted_pattern_t *element = void_lhs; + const char *segment = void_rhs; + + return strcmp(element->node->segment.data, segment); +} + +/* Make sure a node_t* for SEGMENT exists in *ARRAY and return it. + * Auto-create either if they don't exist. Entries in *ARRAY are + * sorted by their segment strings. + */ +static node_t * +ensure_node_in_array(apr_array_header_t **array, + authz_rule_segment_t *segment, + apr_pool_t *result_pool) +{ + int idx; + sorted_pattern_t entry; + sorted_pattern_t *entry_ptr; + + /* Auto-create the array. */ + if (!*array) + *array = apr_array_make(result_pool, 4, sizeof(sorted_pattern_t)); + + /* Find the node in ARRAY and the IDX at which it were to be inserted. + * Initialize IDX such that we won't attempt a hinted lookup (likely + * to fail and therefore pure overhead). */ + idx = (*array)->nelts; + entry_ptr = svn_sort__array_lookup(*array, segment, &idx, + compare_node_rule_segment); + if (entry_ptr) + return entry_ptr->node; + + /* There is no such node, yet. + * Create one and insert it into the sorted array. */ + entry.node = create_node(segment, result_pool); + entry.next = NULL; + svn_sort__array_insert(*array, &entry, idx); + + return entry.node; +} + +/* Auto-create the PATTERN_SUB_NODES sub-structure in *NODE and return it. */ +static node_pattern_t * +ensure_pattern_sub_nodes(node_t *node, + apr_pool_t *result_pool) +{ + if (node->pattern_sub_nodes == NULL) + node->pattern_sub_nodes = apr_pcalloc(result_pool, + sizeof(*node->pattern_sub_nodes)); + + return node->pattern_sub_nodes; +} + +/* Combine an ACL rule segment with the corresponding node in our filtered + * data model. */ +typedef struct node_segment_pair_t +{ + authz_rule_segment_t *segment; + node_t *node; +} node_segment_pair_t; + +/* Context object to be used with process_acl. It allows us to re-use + * information from previous insertions. */ +typedef struct construction_context_t +{ + /* Array of node_segment_pair_t. It contains all segments already + * processed of the current insertion together with the respective + * nodes in our filtered tree. Before the next lookup, the tree + * walk for the common prefix can be skipped. */ + apr_array_header_t *path; +} construction_context_t; + +/* Return a new context object allocated in RESULT_POOL. */ +static construction_context_t * +create_construction_context(apr_pool_t *result_pool) +{ + construction_context_t *result = apr_pcalloc(result_pool, sizeof(*result)); + + /* Array will be auto-extended but this initial size will make it rarely + * ever necessary. */ + result->path = apr_array_make(result_pool, 32, sizeof(node_segment_pair_t)); + + return result; +} + +/* Constructor utility: Below NODE, recursively insert sub-nodes for the + * path given as *SEGMENTS of length SEGMENT_COUNT. If matching nodes + * already exist, use those instead of creating new ones. Set the leave + * node's access rights spec to PATH_ACCESS. Update the context info in CTX. + */ +static void +insert_path(construction_context_t *ctx, + node_t *node, + path_access_t *path_access, + int segment_count, + authz_rule_segment_t *segment, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + node_t *sub_node; + node_segment_pair_t *node_segment; + + /* End of path? */ + if (segment_count == 0) + { + /* Set access rights. Note that there might be multiple rules for + * the same path due to non-repo-specific rules vs. repo-specific + * ones. Whichever gets defined last wins. + */ + limited_rights_t rights; + rights.access = *path_access; + rights.max_rights = path_access->rights; + rights.min_rights = path_access->rights; + combine_access(&node->rights, &rights); + return; + } + + /* Any wildcards? They will go into a separate sub-structure. */ + if (segment->kind != authz_rule_literal) + ensure_pattern_sub_nodes(node, result_pool); + + switch (segment->kind) + { + /* A full wildcard segment? */ + case authz_rule_any_segment: + sub_node = ensure_node(&node->pattern_sub_nodes->any, + segment, result_pool); + break; + + /* One or more full wildcard segments? */ + case authz_rule_any_recursive: + sub_node = ensure_node(&node->pattern_sub_nodes->any_var, + segment, result_pool); + ensure_pattern_sub_nodes(sub_node, result_pool)->repeat = TRUE; + break; + + /* A single wildcard at the end of the segment? */ + case authz_rule_prefix: + sub_node = ensure_node_in_array(&node->pattern_sub_nodes->prefixes, + segment, result_pool); + break; + + /* A single wildcard at the start of segments? */ + case authz_rule_suffix: + sub_node = ensure_node_in_array(&node->pattern_sub_nodes->suffixes, + segment, result_pool); + break; + + /* General pattern? */ + case authz_rule_fnmatch: + sub_node = ensure_node_in_array(&node->pattern_sub_nodes->complex, + segment, result_pool); + break; + + /* Then it must be a literal. */ + default: + SVN_ERR_ASSERT_NO_RETURN(segment->kind == authz_rule_literal); + + if (!node->sub_nodes) + { + node->sub_nodes = svn_hash__make(result_pool); + sub_node = NULL; + } + else + { + sub_node = svn_hash_gets(node->sub_nodes, segment->pattern.data); + } + + /* Auto-insert a sub-node for the current segment. */ + if (!sub_node) + { + sub_node = create_node(segment, result_pool); + apr_hash_set(node->sub_nodes, + sub_node->segment.data, + sub_node->segment.len, + sub_node); + } + } + + /* Update context. */ + node_segment = apr_array_push(ctx->path); + node_segment->segment = segment; + node_segment->node = sub_node; + + /* Continue at the sub-node with the next segment. */ + insert_path(ctx, sub_node, path_access, segment_count - 1, segment + 1, + result_pool, scratch_pool); +} + + +/* If the ACL is relevant to the REPOSITORY and user (given as MEMBERSHIPS + * plus ANONYMOUS flag), insert the respective nodes into tree starting + * at ROOT. Use the context info of the previous call in CTX to eliminate + * repeated lookups. Allocate new nodes in RESULT_POOL and use SCRATCH_POOL + * for temporary allocations. + */ +static void +process_acl(construction_context_t *ctx, + const authz_acl_t *acl, + node_t *root, + const char *repository, + const char *user, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + path_access_t path_access; + int i; + node_t *node; + + /* Skip ACLs that don't say anything about the current user + and/or repository. */ + if (!svn_authz__get_acl_access(&path_access.rights, acl, user, repository)) + return; + + /* Insert the rule into the filtered tree. */ + path_access.sequence_number = acl->sequence_number; + + /* Try to reuse results from previous runs. + * Basically, skip the common prefix. */ + node = root; + for (i = 0; i < ctx->path->nelts; ++i) + { + const node_segment_pair_t *step + = &APR_ARRAY_IDX(ctx->path, i, const node_segment_pair_t); + + /* Exploit the fact that all strings in the authz model are unique / + * internized and can be identified by address alone. */ + if ( !step->node + || i >= acl->rule.len + || step->segment->kind != acl->rule.path[i].kind + || step->segment->pattern.data != acl->rule.path[i].pattern.data) + { + ctx->path->nelts = i; + break; + } + else + { + node = step->node; + } + } + + /* Insert the path rule into the filtered tree. */ + insert_path(ctx, node, &path_access, + acl->rule.len - i, acl->rule.path + i, + result_pool, scratch_pool); +} + +/* Forward declaration ... */ +static svn_boolean_t +trim_tree(node_t *node, + int latest_any_var, + apr_pool_t *scratch_pool); + +/* Call trim_tree() with LATEST_ANY_VAR on all elements in the *HASH of + * node_t * and remove empty nodes from. *HASH may be NULL. If all nodes + * could be removed, set *HASH to NULL and return TRUE. Allocate temporary + * data in SCRATCH_POOL. + */ +static svn_boolean_t +trim_subnode_hash(apr_hash_t **hash, + int latest_any_var, + apr_pool_t *scratch_pool) +{ + if (*hash) + { + apr_array_header_t *to_remove = apr_array_make(scratch_pool, 0, + sizeof(node_t *)); + + apr_hash_index_t *hi; + for (hi = apr_hash_first(scratch_pool, *hash); + hi; + hi = apr_hash_next(hi)) + { + node_t *node = apr_hash_this_val(hi); + if (trim_tree(node, latest_any_var, scratch_pool)) + APR_ARRAY_PUSH(to_remove, node_t *) = node; + } + + /* Are some nodes left? */ + if (to_remove->nelts < apr_hash_count(*hash)) + { + /* Remove empty nodes (if any). */ + int i; + for (i = 0; i < to_remove->nelts; ++i) + { + node_t *node = APR_ARRAY_IDX(to_remove, i, node_t *); + apr_hash_set(*hash, node->segment.data, node->segment.len, + NULL); + } + + return FALSE; + } + + /* No nodes left. A NULL hash is more efficient than an empty one. */ + *hash = NULL; + } + + return TRUE; +} + +/* Call trim_tree() with LATEST_ANY_VAR on all elements in the *ARRAY of + * node_t * and remove empty nodes from. *ARRAY may be NULL. If all nodes + * could be removed, set *ARRAY to NULL and return TRUE. Allocate + * temporary data in SCRATCH_POOL. + */ +static svn_boolean_t +trim_subnode_array(apr_array_header_t **array, + int latest_any_var, + apr_pool_t *scratch_pool) +{ + if (*array) + { + int i, dest; + for (i = 0, dest = 0; i < (*array)->nelts; ++i) + { + node_t *node = APR_ARRAY_IDX(*array, i, sorted_pattern_t).node; + if (!trim_tree(node, latest_any_var, scratch_pool)) + { + if (i != dest) + APR_ARRAY_IDX(*array, dest, sorted_pattern_t) + = APR_ARRAY_IDX(*array, i, sorted_pattern_t); + ++dest; + } + } + + /* Are some nodes left? */ + if (dest) + { + /* Trim it to the number of valid entries. */ + (*array)->nelts = dest; + return FALSE; + } + + /* No nodes left. A NULL array is more efficient than an empty one. */ + *array = NULL; + } + + return TRUE; +} + +/* Remove all rules and sub-nodes from NODE that are fully eclipsed by the + * "any-var" rule with sequence number LATEST_ANY_VAR. Return TRUE, if + * there are no rules left in the sub-tree, including NODE. + * Allocate temporary data in SCRATCH_POOL. + */ +static svn_boolean_t +trim_tree(node_t *node, + int latest_any_var, + apr_pool_t *scratch_pool) +{ + svn_boolean_t removed_all = TRUE; + + /* For convenience, we allow NODE to be NULL: */ + if (!node) + return TRUE; + + /* Do we have a later "any_var" rule at this node. */ + if ( node->pattern_sub_nodes + && node->pattern_sub_nodes->any_var + && node->pattern_sub_nodes->any_var->rights.access.sequence_number + > latest_any_var) + { + latest_any_var + = node->pattern_sub_nodes->any_var->rights.access.sequence_number; + } + + /* Is there a local rule at this node that is not eclipsed by any_var? */ + if (has_local_rule(&node->rights)) + { + /* Remove the local rule, if it got eclipsed. + * Note that for the latest any_var node, the sequence number is equal. */ + if (node->rights.access.sequence_number >= latest_any_var) + removed_all = FALSE; + else + node->rights.access.sequence_number = NO_SEQUENCE_NUMBER; + } + + /* Process all sub-nodes. */ + removed_all &= trim_subnode_hash(&node->sub_nodes, latest_any_var, + scratch_pool); + + if (node->pattern_sub_nodes) + { + if (trim_tree(node->pattern_sub_nodes->any, latest_any_var, + scratch_pool)) + node->pattern_sub_nodes->any = NULL; + else + removed_all = FALSE; + + if (trim_tree(node->pattern_sub_nodes->any_var, latest_any_var, + scratch_pool)) + node->pattern_sub_nodes->any_var = NULL; + else + removed_all = FALSE; + + removed_all &= trim_subnode_array(&node->pattern_sub_nodes->prefixes, + latest_any_var, scratch_pool); + removed_all &= trim_subnode_array(&node->pattern_sub_nodes->suffixes, + latest_any_var, scratch_pool); + removed_all &= trim_subnode_array(&node->pattern_sub_nodes->complex, + latest_any_var, scratch_pool); + + /* Trim the tree as much as possible to speed up lookup(). */ + if (removed_all) + node->pattern_sub_nodes = NULL; + } + + return removed_all; +} + +/* Forward declaration ... */ +static void +finalize_tree(node_t *node, + limited_rights_t *sum, + apr_pool_t *scratch_pool); + +/* Call finalize_tree() on all elements in the HASH of node_t *, passing + * SUM along. HASH may be NULL. Use SCRATCH_POOL for temporary allocations. + */ +static void +finalize_subnode_hash(apr_hash_t *hash, + limited_rights_t *sum, + apr_pool_t *scratch_pool) +{ + if (hash) + { + apr_hash_index_t *hi; + for (hi = apr_hash_first(scratch_pool, hash); + hi; + hi = apr_hash_next(hi)) + finalize_tree(apr_hash_this_val(hi), sum, scratch_pool); + } +} + +/* Call finalize_up_tree() on all elements in the ARRAY of node_t *, + * passing SUM along. ARRAY may be NULL. Use SCRATCH_POOL for temporary + * allocations. + */ +static void +finalize_subnode_array(apr_array_header_t *array, + limited_rights_t *sum, + apr_pool_t *scratch_pool) +{ + if (array) + { + int i; + for (i = 0; i < array->nelts; ++i) + finalize_tree(APR_ARRAY_IDX(array, i, sorted_pattern_t).node, sum, + scratch_pool); + } +} + +/* Link prefixes within the sorted ARRAY. */ +static void +link_prefix_patterns(apr_array_header_t *array) +{ + int i; + if (!array) + return; + + for (i = 1; i < array->nelts; ++i) + { + sorted_pattern_t *prev + = &APR_ARRAY_IDX(array, i - 1, sorted_pattern_t); + sorted_pattern_t *pattern + = &APR_ARRAY_IDX(array, i, sorted_pattern_t); + + /* Does PATTERN potentially have a prefix in ARRAY? + * If so, at least the first char must match with the predecessor's + * because the array is sorted by that string. */ + if (prev->node->segment.data[0] != pattern->node->segment.data[0]) + continue; + + /* Only the predecessor or any of its prefixes can be the closest + * prefix to PATTERN. */ + for ( ; prev; prev = prev->next) + if ( prev->node->segment.len < pattern->node->segment.len + && !memcmp(prev->node->segment.data, + pattern->node->segment.data, + prev->node->segment.len)) + { + pattern->next = prev; + break; + } + } +} + +/* Recursively finalization the tree node properties for NODE. Update SUM + * (of NODE's parent) by combining it with the recursive access rights info + * on NODE. Use SCRATCH_POOL for temporary allocations. + */ +static void +finalize_tree(node_t *node, + limited_rights_t *sum, + apr_pool_t *scratch_pool) +{ + limited_rights_t *local_sum = &node->rights; + + /* For convenience, we allow NODE to be NULL: */ + if (!node) + return; + + /* Sum of rights at NODE - so far. */ + if (has_local_rule(local_sum)) + { + local_sum->max_rights = local_sum->access.rights; + local_sum->min_rights = local_sum->access.rights; + } + else + { + local_sum->min_rights = authz_access_write; + local_sum->max_rights = authz_access_none; + } + + /* Process all sub-nodes. */ + finalize_subnode_hash(node->sub_nodes, local_sum, scratch_pool); + + if (node->pattern_sub_nodes) + { + finalize_tree(node->pattern_sub_nodes->any, local_sum, scratch_pool); + finalize_tree(node->pattern_sub_nodes->any_var, local_sum, scratch_pool); + + finalize_subnode_array(node->pattern_sub_nodes->prefixes, local_sum, + scratch_pool); + finalize_subnode_array(node->pattern_sub_nodes->suffixes, local_sum, + scratch_pool); + finalize_subnode_array(node->pattern_sub_nodes->complex, local_sum, + scratch_pool); + + /* Link up the prefixes / suffixes. */ + link_prefix_patterns(node->pattern_sub_nodes->prefixes); + link_prefix_patterns(node->pattern_sub_nodes->suffixes); + } + + /* Add our min / max info to the parent's info. + * Idempotent for parent == node (happens at root). */ + combine_right_limits(sum, local_sum); +} + +/* From the authz CONFIG, extract the parts relevant to USER and REPOSITORY. + * Return the filtered rule tree. + */ +static node_t * +create_user_authz(authz_full_t *authz, + const char *repository, + const char *user, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + int i; + node_t *root = create_node(NULL, result_pool); + construction_context_t *ctx = create_construction_context(scratch_pool); + + /* Use a separate sub-pool to keep memory usage tight. */ + apr_pool_t *subpool = svn_pool_create(scratch_pool); + + /* Find all ACLs for REPOSITORY. + * Note that repo-specific rules replace global rules, + * even if they don't apply to the current user. */ + apr_array_header_t *acls = apr_array_make(subpool, authz->acls->nelts, + sizeof(authz_acl_t *)); + for (i = 0; i < authz->acls->nelts; ++i) + { + const authz_acl_t *acl = &APR_ARRAY_IDX(authz->acls, i, authz_acl_t); + if (svn_authz__acl_applies_to_repo(acl, repository)) + { + /* ACLs in the AUTHZ are sorted by path and repository. + * So, if there is a rule for the repo and a global rule for the + * same path, we will detect them here. */ + if (acls->nelts) + { + const authz_acl_t *prev_acl + = APR_ARRAY_IDX(acls, acls->nelts - 1, const authz_acl_t *); + if (svn_authz__compare_paths(&prev_acl->rule, &acl->rule) == 0) + { + SVN_ERR_ASSERT_NO_RETURN(!strcmp(prev_acl->rule.repos, + AUTHZ_ANY_REPOSITORY)); + SVN_ERR_ASSERT_NO_RETURN(strcmp(acl->rule.repos, + AUTHZ_ANY_REPOSITORY)); + apr_array_pop(acls); + } + } + + APR_ARRAY_PUSH(acls, const authz_acl_t *) = acl; + } + } + + /* Filtering and tree construction. */ + for (i = 0; i < acls->nelts; ++i) + process_acl(ctx, APR_ARRAY_IDX(acls, i, const authz_acl_t *), + root, repository, user, result_pool, subpool); + + /* If there is no relevant rule at the root node, the "no access" default + * applies. Give it a SEQUENCE_NUMBER that will never overrule others. */ + if (!has_local_rule(&root->rights)) + { + root->rights.access.sequence_number = 0; + root->rights.access.rights = authz_access_none; + } + + /* Trim the tree. + * + * We can't do pattern comparison, so for most pattern rules we cannot + * say that a set of rules "eclipses" / overrides a given other set of + * rules for all possible paths. That limits the accuracy of our check + * for recursive access in similar ways than for non-pattern rules. + * + * However, the user expects a rule ending with "**" to eclipse any older + * rule in that sub-tree recursively. So, this trim function removes + * eclipsed nodes from the tree. + */ + svn_pool_clear(subpool); + trim_tree(root, NO_SEQUENCE_NUMBER, subpool); + + /* Calculate recursive rights. + * + * This is a bottom-up calculation of the range of access rights + * specified anywhere in the respective sub-tree, including the base + * node itself. + * + * To prevent additional finalization passes, we piggy-back the addition + * of the ordering links of the prefix and suffix sub-node rules. + */ + svn_pool_clear(subpool); + finalize_tree(root, &root->rights, subpool); + + /* Done. */ + svn_pool_destroy(subpool); + return root; +} + + +/*** Lookup. ***/ + +/* Reusable lookup state object. It is easy to pass to functions and + * recycling it between lookups saves significant setup costs. */ +typedef struct lookup_state_t +{ + /* Rights immediately applying to this node and limits to the rights to + * any sub-path. */ + limited_rights_t rights; + + /* Nodes applying to the path followed so far. */ + apr_array_header_t *current; + + /* Temporary array containing the nodes applying to the next path + * segment (used to build up the next contents of CURRENT). */ + apr_array_header_t *next; + + /* Scratch pad for path operations. */ + svn_stringbuf_t *scratch_pad; + + /* After each lookup iteration, CURRENT and PARENT_RIGHTS will + * apply to this path. */ + svn_stringbuf_t *parent_path; + + /* Rights that apply at PARENT_PATH, if PARENT_PATH is not empty. */ + limited_rights_t parent_rights; + +} lookup_state_t; + +/* Constructor for lookup_state_t. */ +static lookup_state_t * +create_lookup_state(apr_pool_t *result_pool) +{ + lookup_state_t *state = apr_pcalloc(result_pool, sizeof(*state)); + + state->next = apr_array_make(result_pool, 4, sizeof(node_t *)); + state->current = apr_array_make(result_pool, 4, sizeof(node_t *)); + + /* Virtually all path segments should fit into this buffer. If they + * don't, the buffer gets automatically reallocated. + * + * Using a smaller initial size would be fine as well but does not + * buy us much for the increased risk of being expanded anyway - at + * some extra cost. */ + state->scratch_pad = svn_stringbuf_create_ensure(200, result_pool); + + /* Most paths should fit into this buffer. The same rationale as + * above applies. */ + state->parent_path = svn_stringbuf_create_ensure(200, result_pool); + + return state; +} + +/* Clear the current contents of STATE and re-initialize it for ROOT. + * Check whether we can reuse a previous parent path lookup to shorten + * the current PATH walk. Return the full or remaining portion of + * PATH, respectively. PATH must not be NULL. */ +static const char * +init_lockup_state(lookup_state_t *state, + node_t *root, + const char *path) +{ + apr_size_t len = strlen(path); + if ( (len > state->parent_path->len) + && state->parent_path->len + && (path[state->parent_path->len] == '/') + && !memcmp(path, state->parent_path->data, state->parent_path->len)) + { + /* The PARENT_PATH of the previous lookup is actually a parent path + * of PATH. The CURRENT node list already matches the parent path + * and we only have to set the correct rights info. */ + state->rights = state->parent_rights; + + /* Tell the caller where to proceed. */ + return path + state->parent_path->len; + } + + /* Start lookup at ROOT for the full PATH. */ + state->rights = root->rights; + state->parent_rights = root->rights; + + apr_array_clear(state->next); + apr_array_clear(state->current); + APR_ARRAY_PUSH(state->current, node_t *) = root; + + /* Var-segment rules match empty segments as well */ + if (root->pattern_sub_nodes && root->pattern_sub_nodes->any_var) + { + node_t *node = root->pattern_sub_nodes->any_var; + + /* This is non-recursive due to ACL normalization. */ + combine_access(&state->rights, &node->rights); + combine_right_limits(&state->rights, &node->rights); + APR_ARRAY_PUSH(state->current, node_t *) = node; + } + + svn_stringbuf_setempty(state->parent_path); + svn_stringbuf_setempty(state->scratch_pad); + + return path; +} + +/* Add NODE to the list of NEXT nodes in STATE. NODE may be NULL in which + * case this is a no-op. Also update and aggregate the access rights data + * for the next path segment. + */ +static void +add_next_node(lookup_state_t *state, + node_t *node) +{ + /* Allowing NULL nodes simplifies the caller. */ + if (node) + { + /* The rule with the highest sequence number is the one that applies. + * Not all nodes that we are following have rules that apply directly + * to this path but are mere intermediates that may only have some + * matching deep sub-node. */ + combine_access(&state->rights, &node->rights); + + /* The rule tree node can be seen as an overlay of all the nodes that + * we are following. Any of them _may_ match eventually, so the min/ + * max possible access rights are a combination of all these sub-trees. + */ + combine_right_limits(&state->rights, &node->rights); + + /* NODE is now enlisted as a (potential) match for the next segment. */ + APR_ARRAY_PUSH(state->next, node_t *) = node; + + /* Variable length sub-segment sequences apply to the same node as + * they match empty sequences as well. */ + if (node->pattern_sub_nodes && node->pattern_sub_nodes->any_var) + { + node = node->pattern_sub_nodes->any_var; + + /* This is non-recursive due to ACL normalization. */ + combine_access(&state->rights, &node->rights); + combine_right_limits(&state->rights, &node->rights); + APR_ARRAY_PUSH(state->next, node_t *) = node; + } + } +} + +/* If PREFIX is indeed a prefix (or exact match) or SEGMENT, add the + * node in PREFIX to STATE. */ +static void +add_if_prefix_matches(lookup_state_t *state, + const sorted_pattern_t *prefix, + const svn_stringbuf_t *segment) +{ + node_t *node = prefix->node; + if ( node->segment.len <= segment->len + && !memcmp(node->segment.data, segment->data, node->segment.len)) + add_next_node(state, node); +} + +/* Scan the PREFIXES array of node_t* for all entries whose SEGMENT members + * are prefixes of SEGMENT. Add these to STATE for the next tree level. */ +static void +add_prefix_matches(lookup_state_t *state, + const svn_stringbuf_t *segment, + apr_array_header_t *prefixes) +{ + /* Index of the first node that might be a match. All matches will + * be at this and the immediately following indexes. */ + int i = svn_sort__bsearch_lower_bound(prefixes, segment->data, + compare_node_path_segment); + + /* The entry we found may be an exact match (but not a true prefix). + * The prefix matching test will still work. */ + if (i < prefixes->nelts) + add_if_prefix_matches(state, + &APR_ARRAY_IDX(prefixes, i, sorted_pattern_t), + segment); + + /* The immediate predecessor may be a true prefix and all potential + * prefixes can be found following the NEXT links between the array + * indexes. */ + if (i > 0) + { + sorted_pattern_t *pattern; + for (pattern = &APR_ARRAY_IDX(prefixes, i - 1, sorted_pattern_t); + pattern; + pattern = pattern->next) + { + add_if_prefix_matches(state, pattern, segment); + } + } +} + +/* Scan the PATTERNS array of node_t* for all entries whose SEGMENT members + * (usually containing wildcards) match SEGMENT. Add these to STATE for the + * next tree level. */ +static void +add_complex_matches(lookup_state_t *state, + const svn_stringbuf_t *segment, + apr_array_header_t *patterns) +{ + int i; + for (i = 0; i < patterns->nelts; ++i) + { + node_t *node = APR_ARRAY_IDX(patterns, i, sorted_pattern_t).node; + if (0 == apr_fnmatch(node->segment.data, segment->data, 0)) + add_next_node(state, node); + } +} + +/* Extract the next segment from PATH and copy it into SEGMENT, whose current + * contents get overwritten. Empty paths ("") are supported and leading '/' + * segment separators will be interpreted as an empty segment (""). Non- + * normalizes parts, i.e. sequences of '/', will be treated as a single '/'. + * + * Return the start of the next segment within PATH, skipping the '/' + * separator(s). Return NULL, if there are no further segments. + * + * The caller (only called by lookup(), ATM) must ensure that SEGMENT has + * enough room to store all of PATH. + */ +static const char * +next_segment(svn_stringbuf_t *segment, + const char *path) +{ + apr_size_t len; + char c; + + /* Read and scan PATH for NUL and '/' -- whichever comes first. */ + for (len = 0, c = *path; c; c = path[++len]) + if (c == '/') + { + /* End of segment. */ + segment->data[len] = 0; + segment->len = len; + + /* If PATH is not normalized, this is where we skip whole sequences + * of separators. */ + while (path[++len] == '/') + ; + + /* Continue behind the last separator in the sequence. We will + * treat trailing '/' as indicating an empty trailing segment. + * Therefore, we never have to return NULL here. */ + return path + len; + } + else + { + /* Copy segment contents directly into the result buffer. + * On many architectures, this is almost or entirely for free. */ + segment->data[len] = c; + } + + /* No separator found, so all of PATH has been the last segment. */ + segment->data[len] = 0; + segment->len = len; + + /* Tell the caller that this has been the last segment. */ + return NULL; +} + +/* Starting at the respective user's authz root node provided with STATE, + * follow PATH and return TRUE, iff the REQUIRED access has been granted to + * that user for this PATH. REQUIRED must not contain svn_authz_recursive. + * If RECURSIVE is set, all paths in the sub-tree at and below PATH must + * have REQUIRED access. PATH does not need to be normalized, may be empty + * but must not be NULL. + */ +static svn_boolean_t +lookup(lookup_state_t *state, + const char *path, + authz_access_t required, + svn_boolean_t recursive, + apr_pool_t *scratch_pool) +{ + /* Create a scratch pad large enough to hold any of PATH's segments. */ + apr_size_t path_len = strlen(path); + svn_stringbuf_ensure(state->scratch_pad, path_len); + + /* Normalize start and end of PATH. Most paths will be fully normalized, + * so keep the overhead as low as possible. */ + if (path_len && path[path_len-1] == '/') + { + do + { + --path_len; + } + while (path_len && path[path_len-1] == '/'); + path = apr_pstrmemdup(scratch_pool, path, path_len); + } + + while (path[0] == '/') + ++path; /* Don't update PATH_LEN as we won't need it anymore. */ + + /* Actually walk the path rule tree following PATH until we run out of + * either tree or PATH. */ + while (state->current->nelts && path) + { + apr_array_header_t *temp; + int i; + svn_stringbuf_t *segment = state->scratch_pad; + + /* Shortcut 1: We could nowhere find enough rights in this sub-tree. */ + if ((state->rights.max_rights & required) != required) + return FALSE; + + /* Shortcut 2: We will find enough rights everywhere in this sub-tree. */ + if ((state->rights.min_rights & required) == required) + return TRUE; + + /* Extract the next segment. */ + path = next_segment(segment, path); + + /* Initial state for this segment. */ + apr_array_clear(state->next); + state->rights.access.sequence_number = NO_SEQUENCE_NUMBER; + state->rights.access.rights = authz_access_none; + + /* These init values ensure that the first node's value will be used + * when combined with them. If there is no first node, + * state->access.sequence_number remains unchanged and we will use + * the parent's (i.e. inherited) access rights. */ + state->rights.min_rights = authz_access_write; + state->rights.max_rights = authz_access_none; + + /* Update the PARENT_PATH member in STATE to match the nodes in + * CURRENT at the end of this iteration, i.e. if and when NEXT + * has become CURRENT. */ + if (path) + { + svn_stringbuf_appendbyte(state->parent_path, '/'); + svn_stringbuf_appendbytes(state->parent_path, segment->data, + segment->len); + } + + /* Scan follow all alternative routes to the next level. */ + for (i = 0; i < state->current->nelts; ++i) + { + node_t *node = APR_ARRAY_IDX(state->current, i, node_t *); + if (node->sub_nodes) + add_next_node(state, apr_hash_get(node->sub_nodes, segment->data, + segment->len)); + + /* Process alternative, wildcard-based sub-nodes. */ + if (node->pattern_sub_nodes) + { + add_next_node(state, node->pattern_sub_nodes->any); + + /* If the current node represents a "**" pattern, it matches + * to all levels. So, add it to the list for the NEXT level. */ + if (node->pattern_sub_nodes->repeat) + add_next_node(state, node); + + /* Find all prefix pattern matches. */ + if (node->pattern_sub_nodes->prefixes) + add_prefix_matches(state, segment, + node->pattern_sub_nodes->prefixes); + + if (node->pattern_sub_nodes->complex) + add_complex_matches(state, segment, + node->pattern_sub_nodes->complex); + + /* Find all suffux pattern matches. + * This must be the last check as it destroys SEGMENT. */ + if (node->pattern_sub_nodes->suffixes) + { + /* Suffixes behave like reversed prefixes. */ + svn_authz__reverse_string(segment->data, segment->len); + add_prefix_matches(state, segment, + node->pattern_sub_nodes->suffixes); + } + } + } + + /* If no rule applied to this SEGMENT directly, the parent rights + * will apply to at least the SEGMENT node itself and possibly + * other parts deeper in it's subtree. */ + if (!has_local_rule(&state->rights)) + { + state->rights.access = state->parent_rights.access; + state->rights.min_rights &= state->parent_rights.access.rights; + state->rights.max_rights |= state->parent_rights.access.rights; + } + + /* The list of nodes for SEGMENT is now complete. If we need to + * continue, make it the current and put the old one into the recycler. + * + * If this is the end of the path, keep the parent path and rights in + * STATE as are such that sibling lookups will benefit from it. + */ + if (path) + { + temp = state->current; + state->current = state->next; + state->next = temp; + + /* In STATE, PARENT_PATH, PARENT_RIGHTS and CURRENT are now in sync. */ + state->parent_rights = state->rights; + } + } + + /* If we check recursively, none of the (potential) sub-paths must have + * less than the REQUIRED access rights. "Potential" because we don't + * verify that the respective paths actually exist in the repository. + */ + if (recursive) + return (state->rights.min_rights & required) == required; + + /* Return whether the access rights on PATH fully include REQUIRED. */ + return (state->rights.access.rights & required) == required; +} + + + +/*** The authz data structure. ***/ + +/* An entry in svn_authz_t's USER_RULES cache. All members must be + * allocated in the POOL and the latter has to be cleared / destroyed + * before overwriting the entries' contents. + */ +struct authz_user_rules_t +{ + /* User name for which we filtered the rules. + * User NULL for the anonymous user. */ const char *user; - /* Explicitly granted rights. */ - svn_repos_authz_access_t allow; - /* Explicitly denied rights. */ - svn_repos_authz_access_t deny; + /* Repository name for which we filtered the rules. + * May be empty but never NULL for used entries. */ + const char *repository; - /* The rights required by the caller of the lookup. */ - svn_repos_authz_access_t required_access; + /* The combined min/max rights USER has on REPOSITORY. */ + authz_rights_t global_rights; - /* The following are used exclusively in recursive lookups. */ + /* Root of the filtered path rule tree. + * Will remain NULL until the first usage. */ + node_t *root; - /* The path in the repository (an fspath) to authorize. */ - const char *repos_path; - /* repos_path prefixed by the repository name and a colon. */ - const char *qualified_repos_path; + /* Reusable lookup state instance. */ + lookup_state_t *lookup_state; - /* Whether, at the end of a recursive lookup, access is granted. */ - svn_boolean_t access; + /* Pool from which all data within this struct got allocated. + * Can be destroyed or cleaned up with no further side-effects. */ + apr_pool_t *pool; }; -/* Information for the config enumeration functions called during the - validation process. */ -struct authz_validate_baton { - svn_config_t *config; /* The configuration file being validated. */ - svn_error_t *err; /* The error being thrown out of the - enumerator, if any. */ -}; - -/* Currently this structure is just a wrapper around a svn_config_t. - Please update authz_pool if you modify this structure. */ -struct svn_authz_t -{ - svn_config_t *cfg; -}; - - - -/*** Checking access. ***/ - -/* Determine whether the REQUIRED access is granted given what authz - * to ALLOW or DENY. Return TRUE if the REQUIRED access is - * granted. - * - * Access is granted either when no required access is explicitly - * denied (implicit grant), or when the required access is explicitly - * granted, overriding any denials. +/* Return TRUE, iff AUTHZ matches the pair of REPOS_NAME and USER. + * Note that USER may be NULL. */ static svn_boolean_t -authz_access_is_granted(svn_repos_authz_access_t allow, - svn_repos_authz_access_t deny, - svn_repos_authz_access_t required) +matches_filtered_tree(const authz_user_rules_t *authz, + const char *repos_name, + const char *user) { - svn_repos_authz_access_t stripped_req = - required & (svn_authz_read | svn_authz_write); - - if ((deny & required) == svn_authz_none) - return TRUE; - else if ((allow & required) == stripped_req) - return TRUE; - else - return FALSE; -} - - -/* Decide whether the REQUIRED access has been conclusively - * determined. Return TRUE if the given ALLOW/DENY authz are - * conclusive regarding the REQUIRED authz. - * - * Conclusive determination occurs when any of the REQUIRED authz are - * granted or denied by ALLOW/DENY. - */ -static svn_boolean_t -authz_access_is_determined(svn_repos_authz_access_t allow, - svn_repos_authz_access_t deny, - svn_repos_authz_access_t required) -{ - if ((deny & required) || (allow & required)) - return TRUE; - else - return FALSE; -} - -/* Return TRUE is USER equals ALIAS. The alias definitions are in the - "aliases" sections of CFG. Use POOL for temporary allocations during - the lookup. */ -static svn_boolean_t -authz_alias_is_user(svn_config_t *cfg, - const char *alias, - const char *user, - apr_pool_t *pool) -{ - const char *value; - - svn_config_get(cfg, &value, "aliases", alias, NULL); - if (!value) - return FALSE; - - if (strcmp(value, user) == 0) - return TRUE; - - return FALSE; -} - - -/* Return TRUE if USER is in GROUP. The group definitions are in the - "groups" section of CFG. Use POOL for temporary allocations during - the lookup. */ -static svn_boolean_t -authz_group_contains_user(svn_config_t *cfg, - const char *group, - const char *user, - apr_pool_t *pool) -{ - const char *value; - apr_array_header_t *list; - int i; - - svn_config_get(cfg, &value, "groups", group, NULL); - - list = svn_cstring_split(value, ",", TRUE, pool); - - for (i = 0; i < list->nelts; i++) + /* Does the user match? */ + if (user) { - const char *group_user = APR_ARRAY_IDX(list, i, char *); + if (authz->user == NULL || strcmp(user, authz->user)) + return FALSE; + } + else if (authz->user != NULL) + return FALSE; - /* If the 'user' is a subgroup, recurse into it. */ - if (*group_user == '@') - { - if (authz_group_contains_user(cfg, &group_user[1], - user, pool)) - return TRUE; - } + /* Does the repository match as well? */ + return strcmp(repos_name, authz->repository) == 0; +} - /* If the 'user' is an alias, verify it. */ - else if (*group_user == '&') - { - if (authz_alias_is_user(cfg, &group_user[1], - user, pool)) - return TRUE; - } +/* Check if AUTHZ's already contains a path rule tree filtered for this + * USER, REPOS_NAME combination. If that does not exist, yet, create one + * but don't construct the actual filtered tree, yet. + */ +static authz_user_rules_t * +get_user_rules(svn_authz_t *authz, + const char *repos_name, + const char *user) +{ + apr_pool_t *pool; - /* If the user matches, stop. */ - else if (strcmp(user, group_user) == 0) - return TRUE; + /* Search our cache for a suitable previously filtered tree. */ + if (authz->filtered) + { + /* Is this a suitable filtered tree? */ + if (matches_filtered_tree(authz->filtered, repos_name, user)) + return authz->filtered; + + /* Drop the old filtered tree before creating a new one. */ + svn_pool_destroy(authz->filtered->pool); + authz->filtered = NULL; } - return FALSE; + /* Global cache lookup. Filter the full model only if necessary. */ + pool = svn_pool_create(authz->pool); + + /* Write a new entry. */ + authz->filtered = apr_palloc(pool, sizeof(*authz->filtered)); + authz->filtered->pool = pool; + authz->filtered->repository = apr_pstrdup(pool, repos_name); + authz->filtered->user = user ? apr_pstrdup(pool, user) : NULL; + authz->filtered->lookup_state = create_lookup_state(pool); + authz->filtered->root = NULL; + + svn_authz__get_global_rights(&authz->filtered->global_rights, + authz->full, user, repos_name); + + return authz->filtered; } - -/* Determines whether an authz rule applies to the current - * user, given the name part of the rule's name-value pair - * in RULE_MATCH_STRING and the authz_lookup_baton object - * B with the username in question. - */ -static svn_boolean_t -authz_line_applies_to_user(const char *rule_match_string, - struct authz_lookup_baton *b, - apr_pool_t *pool) -{ - /* If the rule has an inversion, recurse and invert the result. */ - if (rule_match_string[0] == '~') - return !authz_line_applies_to_user(&rule_match_string[1], b, pool); - - /* Check for special tokens. */ - if (strcmp(rule_match_string, "$anonymous") == 0) - return (b->user == NULL); - if (strcmp(rule_match_string, "$authenticated") == 0) - return (b->user != NULL); - - /* Check for a wildcard rule. */ - if (strcmp(rule_match_string, "*") == 0) - return TRUE; - - /* If we get here, then the rule is: - * - Not an inversion rule. - * - Not an authz token rule. - * - Not a wildcard rule. - * - * All that's left over is regular user or group specifications. - */ - - /* If the session is anonymous, then a user/group - * rule definitely won't match. - */ - if (b->user == NULL) - return FALSE; - - /* Process the rule depending on whether it is - * a user, alias or group rule. - */ - if (rule_match_string[0] == '@') - return authz_group_contains_user( - b->config, &rule_match_string[1], b->user, pool); - else if (rule_match_string[0] == '&') - return authz_alias_is_user( - b->config, &rule_match_string[1], b->user, pool); - else - return (strcmp(b->user, rule_match_string) == 0); -} - - -/* Callback to parse one line of an authz file and update the - * authz_baton accordingly. - */ -static svn_boolean_t -authz_parse_line(const char *name, const char *value, - void *baton, apr_pool_t *pool) -{ - struct authz_lookup_baton *b = baton; - - /* Stop if the rule doesn't apply to this user. */ - if (!authz_line_applies_to_user(name, b, pool)) - return TRUE; - - /* Set the access grants for the rule. */ - if (strchr(value, 'r')) - b->allow |= svn_authz_read; - else - b->deny |= svn_authz_read; - - if (strchr(value, 'w')) - b->allow |= svn_authz_write; - else - b->deny |= svn_authz_write; - - return TRUE; -} - - -/* Return TRUE iff the access rules in SECTION_NAME apply to PATH_SPEC - * (which is a repository name, colon, and repository fspath, such as - * "myrepos:/trunk/foo"). - */ -static svn_boolean_t -is_applicable_section(const char *path_spec, - const char *section_name) -{ - apr_size_t path_spec_len = strlen(path_spec); - - return ((strncmp(path_spec, section_name, path_spec_len) == 0) - && (path_spec[path_spec_len - 1] == '/' - || section_name[path_spec_len] == '/' - || section_name[path_spec_len] == '\0')); -} - - -/* Callback to parse a section and update the authz_baton if the - * section denies access to the subtree the baton describes. - */ -static svn_boolean_t -authz_parse_section(const char *section_name, void *baton, apr_pool_t *pool) -{ - struct authz_lookup_baton *b = baton; - svn_boolean_t conclusive; - - /* Does the section apply to us? */ - if (!is_applicable_section(b->qualified_repos_path, section_name) - && !is_applicable_section(b->repos_path, section_name)) - return TRUE; - - /* Work out what this section grants. */ - b->allow = b->deny = 0; - svn_config_enumerate2(b->config, section_name, - authz_parse_line, b, pool); - - /* Has the section explicitly determined an access? */ - conclusive = authz_access_is_determined(b->allow, b->deny, - b->required_access); - - /* Is access granted OR inconclusive? */ - b->access = authz_access_is_granted(b->allow, b->deny, - b->required_access) - || !conclusive; - - /* As long as access isn't conclusively denied, carry on. */ - return b->access; -} - - -/* Validate access to the given user for the given path. This - * function checks rules for exactly the given path, and first tries - * to access a section specific to the given repository before falling - * back to pan-repository rules. - * - * Update *access_granted to inform the caller of the outcome of the - * lookup. Return a boolean indicating whether the access rights were - * successfully determined. - */ -static svn_boolean_t -authz_get_path_access(svn_config_t *cfg, const char *repos_name, - const char *path, const char *user, - svn_repos_authz_access_t required_access, - svn_boolean_t *access_granted, - apr_pool_t *pool) -{ - const char *qualified_path; - struct authz_lookup_baton baton = { 0 }; - - baton.config = cfg; - baton.user = user; - - /* Try to locate a repository-specific block first. */ - qualified_path = apr_pstrcat(pool, repos_name, ":", path, SVN_VA_NULL); - svn_config_enumerate2(cfg, qualified_path, - authz_parse_line, &baton, pool); - - *access_granted = authz_access_is_granted(baton.allow, baton.deny, - required_access); - - /* If the first test has determined access, stop now. */ - if (authz_access_is_determined(baton.allow, baton.deny, - required_access)) - return TRUE; - - /* No repository specific rule, try pan-repository rules. */ - svn_config_enumerate2(cfg, path, authz_parse_line, &baton, pool); - - *access_granted = authz_access_is_granted(baton.allow, baton.deny, - required_access); - return authz_access_is_determined(baton.allow, baton.deny, - required_access); -} - - -/* Validate access to the given user for the subtree starting at the - * given path. This function walks the whole authz file in search of - * rules applying to paths in the requested subtree which deny the - * requested access. - * - * As soon as one is found, or else when the whole ACL file has been - * searched, return the updated authorization status. - */ -static svn_boolean_t -authz_get_tree_access(svn_config_t *cfg, const char *repos_name, - const char *path, const char *user, - svn_repos_authz_access_t required_access, - apr_pool_t *pool) -{ - struct authz_lookup_baton baton = { 0 }; - - baton.config = cfg; - baton.user = user; - baton.required_access = required_access; - baton.repos_path = path; - baton.qualified_repos_path = apr_pstrcat(pool, repos_name, - ":", path, SVN_VA_NULL); - /* Default to access granted if no rules say otherwise. */ - baton.access = TRUE; - - svn_config_enumerate_sections2(cfg, authz_parse_section, - &baton, pool); - - return baton.access; -} - - -/* Callback to parse sections of the configuration file, looking for - any kind of granted access. Implements the - svn_config_section_enumerator2_t interface. */ -static svn_boolean_t -authz_get_any_access_parser_cb(const char *section_name, void *baton, - apr_pool_t *pool) -{ - struct authz_lookup_baton *b = baton; - - /* Does the section apply to the query? */ - if (section_name[0] == '/' - || strncmp(section_name, b->qualified_repos_path, - strlen(b->qualified_repos_path)) == 0) - { - b->allow = b->deny = svn_authz_none; - - svn_config_enumerate2(b->config, section_name, - authz_parse_line, baton, pool); - b->access = authz_access_is_granted(b->allow, b->deny, - b->required_access); - - /* Continue as long as we don't find a determined, granted access. */ - return !(b->access - && authz_access_is_determined(b->allow, b->deny, - b->required_access)); - } - - return TRUE; -} - - -/* Walk through the authz CFG to check if USER has the REQUIRED_ACCESS - * to any path within the REPOSITORY. Return TRUE if so. Use POOL - * for temporary allocations. */ -static svn_boolean_t -authz_get_any_access(svn_config_t *cfg, const char *repos_name, - const char *user, - svn_repos_authz_access_t required_access, - apr_pool_t *pool) -{ - struct authz_lookup_baton baton = { 0 }; - - baton.config = cfg; - baton.user = user; - baton.required_access = required_access; - baton.access = FALSE; /* Deny access by default. */ - baton.repos_path = "/"; - baton.qualified_repos_path = apr_pstrcat(pool, repos_name, - ":/", SVN_VA_NULL); - - /* We could have used svn_config_enumerate2 for "repos_name:/". - * However, this requires access for root explicitly (which the user - * may not always have). So we end up enumerating the sections in - * the authz CFG and stop on the first match with some access for - * this user. */ - svn_config_enumerate_sections2(cfg, authz_get_any_access_parser_cb, - &baton, pool); - - /* If walking the configuration was inconclusive, deny access. */ - if (!authz_access_is_determined(baton.allow, - baton.deny, baton.required_access)) - return FALSE; - - return baton.access; -} - - - -/*** Validating the authz file. ***/ - -/* Check for errors in GROUP's definition of CFG. The errors - * detected are references to non-existent groups and circular - * dependencies between groups. If an error is found, return - * SVN_ERR_AUTHZ_INVALID_CONFIG. Use POOL for temporary - * allocations only. - * - * CHECKED_GROUPS should be an empty (it is used for recursive calls). +/* In AUTHZ's user rules, construct the actual filtered tree. + * Use SCRATCH_POOL for temporary allocations. */ static svn_error_t * -authz_group_walk(svn_config_t *cfg, - const char *group, - apr_hash_t *checked_groups, - apr_pool_t *pool) +filter_tree(svn_authz_t *authz, + apr_pool_t *scratch_pool) { - const char *value; - apr_array_header_t *list; - int i; + apr_pool_t *pool = authz->filtered->pool; + const char *repos_name = authz->filtered->repository; + const char *user = authz->filtered->user; + node_t *root; - svn_config_get(cfg, &value, "groups", group, NULL); - /* Having a non-existent group in the ACL configuration might be the - sign of a typo. Refuse to perform authz on uncertain rules. */ - if (!value) - return svn_error_createf(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, - "An authz rule refers to group '%s', " - "which is undefined", - group); - - list = svn_cstring_split(value, ",", TRUE, pool); - - for (i = 0; i < list->nelts; i++) + if (filtered_pool) { - const char *group_user = APR_ARRAY_IDX(list, i, char *); + svn_membuf_t *key = construct_filtered_key(repos_name, user, + authz->authz_id, + scratch_pool); - /* If the 'user' is a subgroup, recurse into it. */ - if (*group_user == '@') + /* Cache lookup. */ + SVN_ERR(svn_object_pool__lookup((void **)&root, filtered_pool, key, + pool)); + + if (!root) { - /* A circular dependency between groups is a Bad Thing. We - don't do authz with invalid ACL files. */ - if (svn_hash_gets(checked_groups, &group_user[1])) - return svn_error_createf(SVN_ERR_AUTHZ_INVALID_CONFIG, - NULL, - "Circular dependency between " - "groups '%s' and '%s'", - &group_user[1], group); + apr_pool_t *item_pool = svn_object_pool__new_item_pool(authz_pool); + authz_full_t *add_ref = NULL; - /* Add group to hash of checked groups. */ - svn_hash_sets(checked_groups, &group_user[1], ""); + /* Make sure the underlying full authz object lives as long as the + * filtered one that we are about to create. We do this by adding + * a reference to it in ITEM_POOL (which may live longer than AUTHZ). + * + * Note that we already have a reference to that full authz in + * AUTHZ->FULL. Assert that we actually don't created multiple + * instances of the same full model. + */ + svn_error_clear(svn_object_pool__lookup((void **)&add_ref, + authz_pool, authz->authz_id, + item_pool)); + SVN_ERR_ASSERT(add_ref == authz->full); - /* Recurse on that group. */ - SVN_ERR(authz_group_walk(cfg, &group_user[1], - checked_groups, pool)); - - /* Remove group from hash of checked groups, so that we don't - incorrectly report an error if we see it again as part of - another group. */ - svn_hash_sets(checked_groups, &group_user[1], NULL); - } - else if (*group_user == '&') - { - const char *alias; - - svn_config_get(cfg, &alias, "aliases", &group_user[1], NULL); - /* Having a non-existent alias in the ACL configuration might be the - sign of a typo. Refuse to perform authz on uncertain rules. */ - if (!alias) - return svn_error_createf(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, - "An authz rule refers to alias '%s', " - "which is undefined", - &group_user[1]); - } - } - - return SVN_NO_ERROR; -} - - -/* Callback to perform some simple sanity checks on an authz rule. - * - * - If RULE_MATCH_STRING references a group or an alias, verify that - * the group or alias definition exists. - * - If RULE_MATCH_STRING specifies a token (starts with $), verify - * that the token name is valid. - * - If RULE_MATCH_STRING is using inversion, verify that it isn't - * doing it more than once within the one rule, and that it isn't - * "~*", as that would never match. - * - Check that VALUE part of the rule specifies only allowed rule - * flag characters ('r' and 'w'). - * - * Return TRUE if the rule has no errors. Use BATON for context and - * error reporting. - */ -static svn_boolean_t authz_validate_rule(const char *rule_match_string, - const char *value, - void *baton, - apr_pool_t *pool) -{ - const char *val; - const char *match = rule_match_string; - struct authz_validate_baton *b = baton; - - /* Make sure the user isn't using double-negatives. */ - if (match[0] == '~') - { - /* Bump the pointer past the inversion for the other checks. */ - match++; - - /* Another inversion is a double negative; we can't not stop. */ - if (match[0] == '~') - { - b->err = svn_error_createf(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, - "Rule '%s' has more than one " - "inversion; double negatives are " - "not permitted.", - rule_match_string); - return FALSE; - } - - /* Make sure that the rule isn't "~*", which won't ever match. */ - if (strcmp(match, "*") == 0) - { - b->err = svn_error_create(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, - "Authz rules with match string '~*' " - "are not allowed, because they never " - "match anyone."); - return FALSE; - } - } - - /* If the rule applies to a group, check its existence. */ - if (match[0] == '@') - { - const char *group = &match[1]; - - svn_config_get(b->config, &val, "groups", group, NULL); - - /* Having a non-existent group in the ACL configuration might be - the sign of a typo. Refuse to perform authz on uncertain - rules. */ - if (!val) - { - b->err = svn_error_createf(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, - "An authz rule refers to group " - "'%s', which is undefined", - rule_match_string); - return FALSE; - } - } - - /* If the rule applies to an alias, check its existence. */ - if (match[0] == '&') - { - const char *alias = &match[1]; - - svn_config_get(b->config, &val, "aliases", alias, NULL); - - if (!val) - { - b->err = svn_error_createf(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, - "An authz rule refers to alias " - "'%s', which is undefined", - rule_match_string); - return FALSE; + /* Now construct the new filtered tree and cache it. */ + root = create_user_authz(authz->full, repos_name, user, item_pool, + scratch_pool); + svn_error_clear(svn_object_pool__insert((void **)&root, + filtered_pool, key, root, + item_pool, pool)); } } - - /* If the rule specifies a token, check its validity. */ - if (match[0] == '$') - { - const char *token_name = &match[1]; - - if ((strcmp(token_name, "anonymous") != 0) - && (strcmp(token_name, "authenticated") != 0)) - { - b->err = svn_error_createf(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, - "Unrecognized authz token '%s'.", - rule_match_string); - return FALSE; - } - } - - val = value; - - while (*val) - { - if (*val != 'r' && *val != 'w' && ! svn_ctype_isspace(*val)) - { - b->err = svn_error_createf(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, - "The character '%c' in rule '%s' is not " - "allowed in authz rules", *val, - rule_match_string); - return FALSE; - } - - ++val; - } - - return TRUE; -} - -/* Callback to check ALIAS's definition for validity. Use - BATON for context and error reporting. */ -static svn_boolean_t authz_validate_alias(const char *alias, - const char *value, - void *baton, - apr_pool_t *pool) -{ - /* No checking at the moment, every alias is valid */ - return TRUE; -} - - -/* Callback to check GROUP's definition for cyclic dependancies. Use - BATON for context and error reporting. */ -static svn_boolean_t authz_validate_group(const char *group, - const char *value, - void *baton, - apr_pool_t *pool) -{ - struct authz_validate_baton *b = baton; - - b->err = authz_group_walk(b->config, group, apr_hash_make(pool), pool); - if (b->err) - return FALSE; - - return TRUE; -} - - -/* Callback to check the contents of the configuration section given - by NAME. Use BATON for context and error reporting. */ -static svn_boolean_t authz_validate_section(const char *name, - void *baton, - apr_pool_t *pool) -{ - struct authz_validate_baton *b = baton; - - /* Use the group checking callback for the "groups" section... */ - if (strcmp(name, "groups") == 0) - svn_config_enumerate2(b->config, name, authz_validate_group, - baton, pool); - /* ...and the alias checking callback for "aliases"... */ - else if (strcmp(name, "aliases") == 0) - svn_config_enumerate2(b->config, name, authz_validate_alias, - baton, pool); - /* ...but for everything else use the rule checking callback. */ else { - /* Validate the section's name. Skip the optional REPOS_NAME. */ - const char *fspath = strchr(name, ':'); - if (fspath) - fspath++; - else - fspath = name; - if (! svn_fspath__is_canonical(fspath)) - { - b->err = svn_error_createf(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, - "Section name '%s' contains non-canonical " - "fspath '%s'", - name, fspath); - return FALSE; - } - - svn_config_enumerate2(b->config, name, authz_validate_rule, - baton, pool); + root = create_user_authz(authz->full, repos_name, user, pool, + scratch_pool); } - if (b->err) - return FALSE; - - return TRUE; -} - - -svn_error_t * -svn_repos__authz_validate(svn_authz_t *authz, apr_pool_t *pool) -{ - struct authz_validate_baton baton = { 0 }; - - baton.err = SVN_NO_ERROR; - baton.config = authz->cfg; - - /* Step through the entire rule file stopping on error. */ - svn_config_enumerate_sections2(authz->cfg, authz_validate_section, - &baton, pool); - SVN_ERR(baton.err); + /* Write a new entry. */ + authz->filtered->root = root; return SVN_NO_ERROR; } + -/* Retrieve the file at DIRENT (contained in a repo) then parse it as a config - * file placing the result into CFG_P allocated in POOL. - * - * If DIRENT cannot be parsed as a config file then an error is returned. The - * contents of CFG_P is then undefined. If MUST_EXIST is TRUE, a missing - * authz file is also an error. The CASE_SENSITIVE controls the lookup - * behavior for section and option names alike. - * - * SCRATCH_POOL will be used for temporary allocations. */ +/* Read authz configuration data from PATH into *AUTHZ_P, allocated in + RESULT_POOL. Return the cache key in *AUTHZ_ID. If GROUPS_PATH is set, + use the global groups parsed from it. Use SCRATCH_POOL for temporary + allocations. + + PATH and GROUPS_PATH may be a dirent or an absolute file url. REPOS_HINT + may be specified to speed up access to in-repo authz files. + + If PATH or GROUPS_PATH is not a valid authz rule file, then return + SVN_AUTHZ_INVALID_CONFIG. The contents of *AUTHZ_P is then + undefined. If MUST_EXIST is TRUE, a missing authz or global groups file + is also an error. */ static svn_error_t * -authz_retrieve_config_repo(svn_config_t **cfg_p, - const char *dirent, - svn_boolean_t must_exist, - svn_boolean_t case_sensitive, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) +authz_read(authz_full_t **authz_p, + svn_membuf_t **authz_id, + const char *path, + const char *groups_path, + svn_boolean_t must_exist, + svn_repos_t *repos_hint, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { - svn_error_t *err; - svn_repos_t *repos; - const char *repos_root_dirent; - const char *fs_path; - svn_fs_t *fs; - svn_fs_root_t *root; - svn_revnum_t youngest_rev; - svn_node_kind_t node_kind; - svn_stream_t *contents; + svn_error_t* err = NULL; + svn_stream_t *rules_stream = NULL; + svn_stream_t *groups_stream = NULL; + svn_checksum_t *rules_checksum = NULL; + svn_checksum_t *groups_checksum = NULL; - /* Search for a repository in the full path. */ - repos_root_dirent = svn_repos_find_root_path(dirent, scratch_pool); - if (!repos_root_dirent) - return svn_error_createf(SVN_ERR_RA_LOCAL_REPOS_NOT_FOUND, NULL, - "Unable to find repository at '%s'", dirent); + config_access_t *config_access = + svn_repos__create_config_access(repos_hint, scratch_pool); - /* Attempt to open a repository at repos_root_dirent. */ - SVN_ERR(svn_repos_open3(&repos, repos_root_dirent, NULL, scratch_pool, - scratch_pool)); - - fs_path = &dirent[strlen(repos_root_dirent)]; - - /* Root path is always a directory so no reason to go any further */ - if (*fs_path == '\0') - return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL, - "'/' is not a file in repo '%s'", - repos_root_dirent); - - /* We skip some things that are non-important for how we're going to use - * this repo connection. We do not set any capabilities since none of - * the current ones are important for what we're doing. We also do not - * setup the environment that repos hooks would run under since we won't - * be triggering any. */ - - /* Get the filesystem. */ - fs = svn_repos_fs(repos); - - /* Find HEAD and the revision root */ - SVN_ERR(svn_fs_youngest_rev(&youngest_rev, fs, scratch_pool)); - SVN_ERR(svn_fs_revision_root(&root, fs, youngest_rev, scratch_pool)); - - SVN_ERR(svn_fs_check_path(&node_kind, root, fs_path, scratch_pool)); - if (node_kind == svn_node_none) - { - if (!must_exist) - { - SVN_ERR(svn_config_create2(cfg_p, case_sensitive, case_sensitive, - result_pool)); - return SVN_NO_ERROR; - } - else - { - return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL, - "'%s' path not found in repo '%s'", fs_path, - repos_root_dirent); - } - } - else if (node_kind != svn_node_file) - { - return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL, - "'%s' is not a file in repo '%s'", fs_path, - repos_root_dirent); - } - - SVN_ERR(svn_fs_file_contents(&contents, root, fs_path, scratch_pool)); - err = svn_config_parse(cfg_p, contents, case_sensitive, case_sensitive, - result_pool); - - /* Add the URL to the error stack since the parser doesn't have it. */ - if (err != SVN_NO_ERROR) - return svn_error_createf(err->apr_err, err, - "Error while parsing config file: '%s' in repo '%s':", - fs_path, repos_root_dirent); - - return SVN_NO_ERROR; -} - -svn_error_t * -svn_repos__retrieve_config(svn_config_t **cfg_p, - const char *path, - svn_boolean_t must_exist, - svn_boolean_t case_sensitive, - apr_pool_t *pool) -{ - if (svn_path_is_url(path)) - { - const char *dirent; - svn_error_t *err; - apr_pool_t *scratch_pool = svn_pool_create(pool); - - err = svn_uri_get_dirent_from_file_url(&dirent, path, scratch_pool); - - if (err == SVN_NO_ERROR) - err = authz_retrieve_config_repo(cfg_p, dirent, must_exist, - case_sensitive, pool, scratch_pool); - - /* Close the repos and streams we opened. */ - svn_pool_destroy(scratch_pool); - - return err; - } - else - { - /* Outside of repo file or Windows registry*/ - SVN_ERR(svn_config_read3(cfg_p, path, must_exist, case_sensitive, - case_sensitive, pool)); - } - - return SVN_NO_ERROR; -} - - -/* Callback to copy (name, value) group into the "groups" section - of another configuration. */ -static svn_boolean_t -authz_copy_group(const char *name, const char *value, - void *baton, apr_pool_t *pool) -{ - svn_config_t *authz_cfg = baton; - - svn_config_set(authz_cfg, SVN_CONFIG_SECTION_GROUPS, name, value); - - return TRUE; -} - -/* Copy group definitions from GROUPS_CFG to the resulting AUTHZ. - * If AUTHZ already contains any group definition, report an error. - * Use POOL for temporary allocations. */ -static svn_error_t * -authz_copy_groups(svn_authz_t *authz, svn_config_t *groups_cfg, - apr_pool_t *pool) -{ - /* Easy out: we prohibit local groups in the authz file when global - groups are being used. */ - if (svn_config_has_section(authz->cfg, SVN_CONFIG_SECTION_GROUPS)) - { - return svn_error_create(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, - "Authz file cannot contain any groups " - "when global groups are being used."); - } - - svn_config_enumerate2(groups_cfg, SVN_CONFIG_SECTION_GROUPS, - authz_copy_group, authz->cfg, pool); - - return SVN_NO_ERROR; -} - -svn_error_t * -svn_repos__authz_read(svn_authz_t **authz_p, const char *path, - const char *groups_path, svn_boolean_t must_exist, - svn_boolean_t accept_urls, apr_pool_t *pool) -{ - svn_authz_t *authz = apr_palloc(pool, sizeof(*authz)); - - /* Load the authz file */ - if (accept_urls) - SVN_ERR(svn_repos__retrieve_config(&authz->cfg, path, must_exist, TRUE, - pool)); - else - SVN_ERR(svn_config_read3(&authz->cfg, path, must_exist, TRUE, TRUE, - pool)); + /* Open the main authz file */ + SVN_ERR(svn_repos__get_config(&rules_stream, &rules_checksum, config_access, + path, must_exist, scratch_pool)); + /* Open the optional groups file */ if (groups_path) + SVN_ERR(svn_repos__get_config(&groups_stream, &groups_checksum, + config_access, groups_path, must_exist, + scratch_pool)); + + /* The authz cache is optional. */ + *authz_id = construct_authz_key(rules_checksum, groups_checksum, + result_pool); + if (authz_pool) { - svn_config_t *groups_cfg; - svn_error_t *err; + /* Cache lookup. */ + SVN_ERR(svn_object_pool__lookup((void **)authz_p, authz_pool, + *authz_id, result_pool)); - /* Load the groups file */ - if (accept_urls) - SVN_ERR(svn_repos__retrieve_config(&groups_cfg, groups_path, - must_exist, TRUE, pool)); - else - SVN_ERR(svn_config_read3(&groups_cfg, groups_path, must_exist, - TRUE, TRUE, pool)); + /* If not found, parse and add to cache. */ + if (!*authz_p) + { + apr_pool_t *item_pool = svn_object_pool__new_item_pool(authz_pool); - /* Copy the groups from groups_cfg into authz. */ - err = authz_copy_groups(authz, groups_cfg, pool); + /* Parse the configuration(s) and construct the full authz model + * from it. */ + err = svn_authz__parse(authz_p, rules_stream, groups_stream, + item_pool, scratch_pool); + if (err != SVN_NO_ERROR) + { + /* That pool would otherwise never get destroyed. */ + svn_pool_destroy(item_pool); - /* Add the paths to the error stack since the authz_copy_groups - routine knows nothing about them. */ - if (err != SVN_NO_ERROR) - return svn_error_createf(err->apr_err, err, - "Error reading authz file '%s' with " - "groups file '%s':", path, groups_path); + /* Add the URL / file name to the error stack since the parser + * doesn't have it. */ + err = svn_error_quick_wrapf(err, + "Error while parsing config file: '%s':", + path); + } + else + { + SVN_ERR(svn_object_pool__insert((void **)authz_p, authz_pool, + *authz_id, *authz_p, + item_pool, result_pool)); + } + } + } + else + { + /* Parse the configuration(s) and construct the full authz model from + * it. */ + err = svn_error_quick_wrapf(svn_authz__parse(authz_p, rules_stream, + groups_stream, + result_pool, scratch_pool), + "Error while parsing authz file: '%s':", + path); } - /* Make sure there are no errors in the configuration. */ - SVN_ERR(svn_repos__authz_validate(authz, pool)); + svn_repos__destroy_config_access(config_access); - *authz_p = authz; - return SVN_NO_ERROR; + return err; } @@ -981,12 +1628,22 @@ svn_repos__authz_read(svn_authz_t **authz_p, const char *path, /*** Public functions. ***/ svn_error_t * -svn_repos_authz_read2(svn_authz_t **authz_p, const char *path, - const char *groups_path, svn_boolean_t must_exist, - apr_pool_t *pool) +svn_repos_authz_read3(svn_authz_t **authz_p, + const char *path, + const char *groups_path, + svn_boolean_t must_exist, + svn_repos_t *repos_hint, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { - return svn_repos__authz_read(authz_p, path, groups_path, must_exist, - TRUE, pool); + svn_authz_t *authz = apr_pcalloc(result_pool, sizeof(*authz)); + authz->pool = result_pool; + + SVN_ERR(authz_read(&authz->full, &authz->authz_id, path, groups_path, + must_exist, repos_hint, result_pool, scratch_pool)); + + *authz_p = authz; + return SVN_NO_ERROR; } @@ -994,29 +1651,20 @@ svn_error_t * svn_repos_authz_parse(svn_authz_t **authz_p, svn_stream_t *stream, svn_stream_t *groups_stream, apr_pool_t *pool) { - svn_authz_t *authz = apr_palloc(pool, sizeof(*authz)); + apr_pool_t *scratch_pool = svn_pool_create(pool); + svn_authz_t *authz = apr_pcalloc(pool, sizeof(*authz)); + authz->pool = pool; - /* Parse the authz stream */ - SVN_ERR(svn_config_parse(&authz->cfg, stream, TRUE, TRUE, pool)); + /* Parse the configuration and construct the full authz model from it. */ + SVN_ERR(svn_authz__parse(&authz->full, stream, groups_stream, pool, + scratch_pool)); - if (groups_stream) - { - svn_config_t *groups_cfg; - - /* Parse the groups stream */ - SVN_ERR(svn_config_parse(&groups_cfg, groups_stream, TRUE, TRUE, pool)); - - SVN_ERR(authz_copy_groups(authz, groups_cfg, pool)); - } - - /* Make sure there are no errors in the configuration. */ - SVN_ERR(svn_repos__authz_validate(authz, pool)); + svn_pool_destroy(scratch_pool); *authz_p = authz; return SVN_NO_ERROR; } - svn_error_t * svn_repos_authz_check_access(svn_authz_t *authz, const char *repos_name, const char *path, const char *user, @@ -1024,51 +1672,58 @@ svn_repos_authz_check_access(svn_authz_t *authz, const char *repos_name, svn_boolean_t *access_granted, apr_pool_t *pool) { - const char *current_path; + const authz_access_t required = + ((required_access & svn_authz_read ? authz_access_read_flag : 0) + | (required_access & svn_authz_write ? authz_access_write_flag : 0)); - if (!repos_name) - repos_name = ""; + /* Pick or create the suitable pre-filtered path rule tree. */ + authz_user_rules_t *rules = get_user_rules( + authz, + (repos_name ? repos_name : AUTHZ_ANY_REPOSITORY), + user); - /* If PATH is NULL, check if the user has *any* access. */ - if (!path) + /* In many scenarios, users have uniform access to a repository + * (blanket access or no access at all). + * + * In these cases, don't bother creating or consulting the filtered tree. + */ + if ((rules->global_rights.min_access & required) == required) { - *access_granted = authz_get_any_access(authz->cfg, repos_name, - user, required_access, pool); + *access_granted = TRUE; return SVN_NO_ERROR; } + if ((rules->global_rights.max_access & required) != required) + { + *access_granted = FALSE; + return SVN_NO_ERROR; + } + + /* No specific path given, i.e. looking for anywhere in the tree? */ + if (!path) + { + *access_granted = + ((rules->global_rights.max_access & required) == required); + return SVN_NO_ERROR; + } + + /* Rules tree lookup */ + + /* Did we already filter the data model? */ + if (!rules->root) + SVN_ERR(filter_tree(authz, pool)); + + /* Re-use previous lookup results, if possible. */ + path = init_lockup_state(authz->filtered->lookup_state, + authz->filtered->root, path); + /* Sanity check. */ SVN_ERR_ASSERT(path[0] == '/'); - /* Determine the granted access for the requested path. */ - path = svn_fspath__canonicalize(path, pool); - current_path = path; - - while (!authz_get_path_access(authz->cfg, repos_name, - current_path, user, - required_access, - access_granted, - pool)) - { - /* Stop if the loop hits the repository root with no - results. */ - if (current_path[0] == '/' && current_path[1] == '\0') - { - /* Deny access by default. */ - *access_granted = FALSE; - return SVN_NO_ERROR; - } - - /* Work back to the parent path. */ - current_path = svn_fspath__dirname(current_path, pool); - } - - /* If the caller requested recursive access, we need to walk through - the entire authz config to see whether any child paths are denied - to the requested user. */ - if (*access_granted && (required_access & svn_authz_recursive)) - *access_granted = authz_get_tree_access(authz->cfg, repos_name, path, - user, required_access, pool); + /* Determine the granted access for the requested path. + * PATH does not need to be normalized for lockup(). */ + *access_granted = lookup(rules->lookup_state, path, required, + !!(required_access & svn_authz_recursive), pool); return SVN_NO_ERROR; } diff --git a/subversion/libsvn_repos/authz.h b/subversion/libsvn_repos/authz.h new file mode 100644 index 000000000000..7187335a94fd --- /dev/null +++ b/subversion/libsvn_repos/authz.h @@ -0,0 +1,364 @@ +/* authz.h : authz parsing and searching, private to libsvn_repos + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#ifndef SVN_REPOS_AUTHZ_H +#define SVN_REPOS_AUTHZ_H + +#include +#include +#include + +#include "svn_config.h" +#include "svn_error.h" +#include "svn_io.h" +#include "svn_repos.h" + +#include "private/svn_string_private.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/* + * Authz and global group file parsing + */ + +/* A dictionary of rules that are specific to a particular + (user, repository) combination. */ +typedef struct authz_user_rules_t authz_user_rules_t; + + +/* Access rights in an ACL. + * + * This enum is different from and incompatible with + * svn_repos_authz_access_t, because it has different semantics and + * encodes rights that are not and should never be exposed in the + * public API. + */ +typedef enum authz_access_t +{ + /* + * Individual access flags + */ + + /* TODO: Future extension for lookup/traverse access. + authz_access_lookup_flag = 0x10, */ + + /* Read access allows listing directory entries, reading file + contents and reading properties of files and directories. */ + authz_access_read_flag = 0x20, + + /* Write access allows adding, removing and renaming directory + entries, modifying file contents and adding, removing and + modifying properties of files and directories. */ + authz_access_write_flag = 0x40, + + /* + * Combined access flags + */ + + /* No access. */ + authz_access_none = 0, + + + /* TODO: Lookup access is a synonym for the lookup flag. + authz_access_lookup = authz_access_lookup_flag, */ + + /* Read access (TODO: implies lookup access). */ + authz_access_read = authz_access_read_flag /* TODO: | authz_access_lookup */, + + /* Write access implies read (TODO: and lookup) access. */ + authz_access_write = authz_access_write_flag | authz_access_read +} authz_access_t; + + +/* Accumulated rights for (user, repository). */ +typedef struct authz_rights_t +{ + /* The lowest level of access that the user has to every + path in the repository. */ + authz_access_t min_access; + + /* The highest level of access that the user has to + any path in the repository. */ + authz_access_t max_access; +} authz_rights_t; + + +/* Accumulated global rights for a specific user. */ +typedef struct authz_global_rights_t +{ + /* The user name. */ + const char *user; + + /* Accumulated rights for this user from rules that are not + repository-specific. We use this to avoid a hash lookup for the + "any" repository rights. */ + authz_rights_t any_repos_rights; + + /* Accumulated rights for this user across all repositories. */ + authz_rights_t all_repos_rights; + + /* Accumulated rights for specific repositories. + The key is repository name, the value is an authz_rights_t*. */ + apr_hash_t *per_repos_rights; +} authz_global_rights_t; + + +/* Immutable authorization info */ +typedef struct authz_full_t +{ + /* All ACLs from the authz file, in the order of definition. */ + apr_array_header_t *acls; + + /* Globally accumulated rights for anonymous access. */ + svn_boolean_t has_anon_rights; + authz_global_rights_t anon_rights; + + /* Globally accumulated rights for authenticated users. */ + svn_boolean_t has_authn_rights; + authz_global_rights_t authn_rights; + + /* Globally accumulated rights, for all concrete users mentioned + in the authz file. The key is the user name, the value is + an authz_global_rights_t*. */ + apr_hash_t *user_rights; + + /* The pool from which all the parsed authz data is allocated. + This is the RESULT_POOL passed to svn_authz__tng_parse. + + It's a good idea to dedicate a pool for the authz structure, so + that the whole authz representation can be deallocated by + destroying the pool. */ + apr_pool_t *pool; +} authz_full_t; + + +/* Dynamic authorization info */ +struct svn_authz_t +{ + /* The parsed and pre-processed contents of the authz file. */ + authz_full_t *full; + + /* Identifies the authz model content + * (a hash value that can be used for e.g. cache lookups). */ + svn_membuf_t *authz_id; + + /* Rules filtered for a particular user-repository combination. + * May be NULL. */ + authz_user_rules_t *filtered; + + /* The pool from which all the parsed authz data is allocated. + This is the RESULT_POOL passed to svn_authz__tng_parse. + + It's a good idea to dedicate a pool for the authz structure, so + that the whole authz representation can be deallocated by + destroying the pool. */ + apr_pool_t *pool; +}; + + +/* Rule path segment descriptor. */ +typedef struct authz_rule_segment_t +{ + /* The segment type. */ + enum { + /* A literal string match. + The path segment must exactly match the pattern. + + Note: Make sure this is always the first constant in the + enumeration, otherwise rules that match the repository + root will not sort first in the ACL list and the implicit + default no-access ACE will not be applied correctly. */ + authz_rule_literal, + + /* A prefix match: a literal string followed by '*'. + The path segment must begin with the literal prefix. */ + authz_rule_prefix, + + /* A suffix match: '*' followed by a literal string. + The path segment must end with the literal suffix. + The pattern is stored reversed, so that the matching code can + perform a prefix match on the reversed path segment. */ + authz_rule_suffix, + + /* '*' + Matches any single non-empty path segment. + The pattern will be an empty string. */ + authz_rule_any_segment, + + /* '**' + Matches any sequence of zero or more path segments. + The pattern will be an empty string. */ + authz_rule_any_recursive, + + /* Any other glob/fnmatch pattern. */ + authz_rule_fnmatch + } kind; + + /* The pattern for this path segment. + Any no-op fnmatch escape sequences (i.e., those that do not + escape a wildcard or character class) are stripped from the + string. + + The pattern string will be interned; therefore, two identical + rule patterns will always contain the same pointer value and + equality can therefore be tested by comparing the pointer + values and segment kinds. */ + svn_string_t pattern; +} authz_rule_segment_t; + +/* Rule path descriptor. */ +typedef struct authz_rule_t +{ + /* The repository that this rule applies to. This will be the empty + string string if a the rule did not name a repository. The + repository name is interned. */ + const char *repos; + + /* The number of segments in the rule path. */ + int len; + + /* The array of path segments for this rule. Will be NULL for the + repository root. */ + authz_rule_segment_t *path; +} authz_rule_t; + + +/* An access control list defined by access rules. */ +typedef struct authz_acl_t +{ + /* The sequence number of the ACL stores the order in which access + rules were defined in the authz file. The authz lookup code + selects the highest-numbered ACL from amongst a set of equivalent + matches. */ + int sequence_number; + + /* The parsed rule. */ + authz_rule_t rule; + + /* Access rights for anonymous users */ + svn_boolean_t has_anon_access; + authz_access_t anon_access; + + /* Access rights for authenticated users */ + svn_boolean_t has_authn_access; + authz_access_t authn_access; + + /* All other user- or group-specific access rights. + Aliases are replaced with their definitions, rules for the same + user or group are merged. */ + apr_array_header_t *user_access; +} authz_acl_t; + + +/* An access control entry in authz_acl_t::user_access. */ +typedef struct authz_ace_t +{ + /* The name of the alias, user or group that this ACE applies to. */ + const char *name; + + /* The set of group members, when NAME is the name of a group. + We store this reference in the ACE to save a hash lookup when + resolving access for group ACEs. + */ + apr_hash_t *members; + + /* True if this is an inverse-match rule. */ + svn_boolean_t inverted; + + /* The access rights defined by this ACE. */ + authz_access_t access; +} authz_ace_t; + + +/* Parse authz definitions from RULES and optional global group + * definitions from GROUPS, returning an immutable, in-memory + * representation of all the rules, groups and aliases. + * + * **AUTHZ and its contents will be allocated from RESULT_POOL. + * The function uses SCRATCH_POOL for temporary allocations. + */ +svn_error_t * +svn_authz__parse(authz_full_t **authz, + svn_stream_t *rules, + svn_stream_t *groups, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + + +/* Reverse a STRING of length LEN in place. */ +void +svn_authz__reverse_string(char *string, apr_size_t len); + + +/* Compare two rules in lexical order by path only. */ +int +svn_authz__compare_paths(const authz_rule_t *a, const authz_rule_t *b); + +/* Compare two rules in path lexical order, then repository lexical order. */ +int +svn_authz__compare_rules(const authz_rule_t *a, const authz_rule_t *b); + + +/* + * Authorization lookup + */ + +/* The "anonymous" user for authz queries. */ +#define AUTHZ_ANONYMOUS_USER ((const char*)"") + +/* Rules with this repository name apply to all repositories. */ +#define AUTHZ_ANY_REPOSITORY ((const char*)"") + +/* Check if the ACL applies to the REPOS pair. */ +svn_boolean_t +svn_authz__acl_applies_to_repo(const authz_acl_t *acl, + const char *repos); + +/* Check if the ACL applies to the (USER, REPOS) pair. If it does, + * and ACCESS is not NULL, set *ACCESS to the actual access rights for + * the user in this repository. + */ +svn_boolean_t +svn_authz__get_acl_access(authz_access_t *access, + const authz_acl_t *acl, + const char *user, const char *repos); + + +/* Set *RIGHTS to the accumulated global access rights calculated in + * AUTHZ for (USER, REPOS). + * Return TRUE if the rights are explicit (i.e., an ACL for REPOS + * applies to USER, or REPOS is AUTHZ_ANY_REPOSITORY). + */ +svn_boolean_t +svn_authz__get_global_rights(authz_rights_t *rights, + const authz_full_t *authz, + const char *user, const char *repos); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SVN_REPOS_AUTHZ_H */ diff --git a/subversion/libsvn_repos/authz_info.c b/subversion/libsvn_repos/authz_info.c new file mode 100644 index 000000000000..8f3a8b63b12a --- /dev/null +++ b/subversion/libsvn_repos/authz_info.c @@ -0,0 +1,184 @@ +/* authz_info.c : Information derived from authz settings. + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#include +#include +#include + +#include "svn_hash.h" + +#include "svn_private_config.h" + +#include "authz.h" + + +svn_boolean_t +svn_authz__acl_applies_to_repo(const authz_acl_t *acl, + const char *repos) +{ + /* The repository name must match the one in the rule, iff the rule + was defined for a specific repository. */ + return (0 == strcmp(acl->rule.repos, AUTHZ_ANY_REPOSITORY)) + || (0 == strcmp(repos, acl->rule.repos)); +} + +svn_boolean_t +svn_authz__get_acl_access(authz_access_t *access_p, + const authz_acl_t *acl, + const char *user, const char *repos) +{ + authz_access_t access; + svn_boolean_t has_access; + int i; + + /* The repository name must match the one in the rule, iff the rule + was defined for a specific repository. */ + if (!svn_authz__acl_applies_to_repo(acl, repos)) + return FALSE; + + /* Check anonymous access first. */ + if (!user || 0 == strcmp(user, AUTHZ_ANONYMOUS_USER)) + { + if (!acl->has_anon_access) + return FALSE; + + if (access_p) + *access_p = acl->anon_access; + return TRUE; + } + + /* Get the access rights for all authenticated users. */ + has_access = acl->has_authn_access; + access = (has_access ? acl->authn_access : authz_access_none); + + /* Scan the ACEs in the ACL and merge the access rights. */ + for (i = 0; i < acl->user_access->nelts; ++i) + { + const authz_ace_t *const ace = + &APR_ARRAY_IDX(acl->user_access, i, authz_ace_t); + const svn_boolean_t match = + ((ace->members && svn_hash_gets(ace->members, user)) + || (!ace->members && 0 == strcmp(user, ace->name))); + + if (!match != !ace->inverted) /* match XNOR ace->inverted */ + { + access |= ace->access; + has_access = TRUE; + } + } + + if (access_p) + *access_p = access; + return has_access; +} + +/* Set *RIGHTS_P to the combination of LHS and RHS, i.e. intersect the + * minimal rights and join the maximum rights. + */ +static void +combine_rights(authz_rights_t *rights_p, + const authz_rights_t *lhs, + const authz_rights_t *rhs) +{ + rights_p->min_access = lhs->min_access & rhs->min_access; + rights_p->max_access = lhs->max_access | rhs->max_access; +} + + +/* Given GLOBAL_RIGHTS and a repository name REPOS, set *RIGHTS_P to + * to the actual accumulated rights defined for that repository. + * Return TRUE if these rights were defined explicitly. + */ +static svn_boolean_t +resolve_global_rights(authz_rights_t *rights_p, + const authz_global_rights_t *global_rights, + const char *repos) +{ + if (0 == strcmp(repos, AUTHZ_ANY_REPOSITORY)) + { + /* Return the accumulated rights that are not repository-specific. */ + *rights_p = global_rights->any_repos_rights; + return TRUE; + } + else + { + /* Check if we have explicit rights for this repository. */ + const authz_rights_t *const rights = + svn_hash_gets(global_rights->per_repos_rights, repos); + + if (rights) + { + combine_rights(rights_p, rights, &global_rights->any_repos_rights); + return TRUE; + } + } + + /* Fall-through: return the rights defined for "any" repository + because this user has no specific rules for this specific REPOS. */ + *rights_p = global_rights->any_repos_rights; + return FALSE; +} + + +svn_boolean_t +svn_authz__get_global_rights(authz_rights_t *rights_p, + const authz_full_t *authz, + const char *user, const char *repos) +{ + if (!user || 0 == strcmp(user, AUTHZ_ANONYMOUS_USER)) + { + /* Check if we have explicit rights for anonymous access. */ + if (authz->has_anon_rights) + return resolve_global_rights(rights_p, &authz->anon_rights, repos); + } + else + { + /* Check if we have explicit rights for this user. */ + const authz_global_rights_t *const user_rights = + svn_hash_gets(authz->user_rights, user); + + if (user_rights) + { + svn_boolean_t explicit + = resolve_global_rights(rights_p, user_rights, repos); + + /* Rights given to _any_ authenticated user may apply, too. */ + if (authz->has_authn_rights) + { + authz_rights_t authn; + explicit |= resolve_global_rights(&authn, &authz->authn_rights, + repos); + combine_rights(rights_p, rights_p, &authn); + } + return explicit; + } + + /* Check if we have explicit rights for authenticated access. */ + if (authz->has_authn_rights) + return resolve_global_rights(rights_p, &authz->authn_rights, repos); + } + + /* Fall-through: return the implicit rights, i.e., none. */ + rights_p->min_access = authz_access_none; + rights_p->max_access = authz_access_none; + return FALSE; +} diff --git a/subversion/libsvn_repos/authz_parse.c b/subversion/libsvn_repos/authz_parse.c new file mode 100644 index 000000000000..23612dedd490 --- /dev/null +++ b/subversion/libsvn_repos/authz_parse.c @@ -0,0 +1,1442 @@ +/* authz_parse.c : Parser for path-based access control + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#include +#include + +#include "svn_ctype.h" +#include "svn_error.h" +#include "svn_hash.h" +#include "svn_iter.h" +#include "svn_pools.h" +#include "svn_repos.h" + +#include "private/svn_fspath.h" +#include "private/svn_config_private.h" +#include "private/svn_sorts_private.h" +#include "private/svn_string_private.h" +#include "private/svn_subr_private.h" + +#include "svn_private_config.h" + +#include "authz.h" + + +/* Temporary ACL constructed by the parser. */ +typedef struct parsed_acl_t +{ + /* The global ACL. + The strings in ACL.rule are allocated from the result pool. + ACL.user_access is null during the parsing stage. */ + authz_acl_t acl; + + /* The set of access control entries. In the second pass, aliases in + these entries will be expanded and equivalent entries will be + merged. The entries are allocated from the parser pool. */ + apr_hash_t *aces; + + /* The set of access control entries that use aliases. In the second + pass, aliases in these entries will be expanded and merged into ACES. + The entries are allocated from the parser pool. */ + apr_hash_t *alias_aces; +} parsed_acl_t; + + +/* Temporary group definition constructed by the authz/group parser. + Once all groups and aliases are defined, a second pass over these + data will recursively expand group memberships. */ +typedef struct parsed_group_t +{ + svn_boolean_t local_group; + apr_array_header_t *members; +} parsed_group_t; + + +/* Baton for the parser constructor. */ +typedef struct ctor_baton_t +{ + /* The final output of the parser. */ + authz_full_t *authz; + + /* Interned-string set, allocated in AUTHZ->pool. + Stores singleton instances of user, group and repository names, + which are used by members of the AUTHZ structure. By reusing the + same immutable string multiple times, we reduce the size of the + authz representation in the result pool. + + N.B.: Whilst the strings are allocated from teh result pool, the + hash table itself is not. */ + apr_hash_t *strings; + + /* A set of all the sections that were seen in the authz or global + groups file. Rules, aliases and groups may each only be defined + once in the authz file. The global groups file may only contain a + [groups] section. */ + apr_hash_t *sections; + + /* The name of the section we're currently parsing. */ + const char *section; + + /* TRUE iff we're parsing the global groups file. */ + svn_boolean_t parsing_groups; + + /* TRUE iff we're parsing a [groups] section. */ + svn_boolean_t in_groups; + + /* TRUE iff we're parsing an [aliases] section. */ + svn_boolean_t in_aliases; + + /* A set of all the unique rules we parsed from the section names. */ + apr_hash_t *parsed_rules; + + /* Temporary parsed-groups definitions. */ + apr_hash_t *parsed_groups; + + /* Temporary alias mappings. */ + apr_hash_t *parsed_aliases; + + /* Temporary parsed-acl definitions. */ + apr_array_header_t *parsed_acls; + + /* Temporary expanded groups definitions. */ + apr_hash_t *expanded_groups; + + /* The temporary ACL we're currently constructing. */ + parsed_acl_t *current_acl; + + /* Temporary buffers used to parse a rule into segments. */ + svn_membuf_t rule_path_buffer; + svn_stringbuf_t *rule_string_buffer; + + /* The parser's scratch pool. This may not be the same pool as + passed to the constructor callbacks, that is supposed to be an + iteration pool maintained by the generic parser. + + N.B.: The result pool is AUTHZ->pool. */ + apr_pool_t *parser_pool; +} ctor_baton_t; + + +/* An empty string with a known address. */ +static const char interned_empty_string[] = ""; + +/* The name of the aliases section. */ +static const char aliases_section[] = "aliases"; + +/* The name of the groups section. */ +static const char groups_section[] = "groups"; + +/* The token indicating that an authz rule contains wildcards. */ +static const char glob_rule_token[] = "glob"; + +/* The anonymous access token. */ +static const char anon_access_token[] = "$anonymous"; + +/* The authenticated access token. */ +static const char authn_access_token[] = "$authenticated"; + + +/* Initialize a rights structure. + The minimum rights start with all available access and are later + bitwise-and'ed with actual access rights. The maximum rights begin + empty and are later bitwise-and'ed with actual rights. */ +static void init_rights(authz_rights_t *rights) +{ + rights->min_access = authz_access_write; + rights->max_access = authz_access_none; + } + +/* Initialize a global rights structure. + The USER string must be interned or statically initialized. */ +static void +init_global_rights(authz_global_rights_t *gr, const char *user, + apr_pool_t *result_pool) +{ + gr->user = user; + init_rights(&gr->all_repos_rights); + init_rights(&gr->any_repos_rights); + gr->per_repos_rights = apr_hash_make(result_pool); +} + + +/* Insert the default global ACL into the parsed ACLs. */ +static void +insert_default_acl(ctor_baton_t *cb) +{ + parsed_acl_t *acl = &APR_ARRAY_PUSH(cb->parsed_acls, parsed_acl_t); + acl->acl.sequence_number = 0; + acl->acl.rule.repos = interned_empty_string; + acl->acl.rule.len = 0; + acl->acl.rule.path = NULL; + acl->acl.anon_access = authz_access_none; + acl->acl.has_anon_access = TRUE; + acl->acl.authn_access = authz_access_none; + acl->acl.has_authn_access = TRUE; + acl->acl.user_access = NULL; + acl->aces = svn_hash__make(cb->parser_pool); + acl->alias_aces = svn_hash__make(cb->parser_pool); +} + + +/* Initialize a constuctor baton. */ +static ctor_baton_t * +create_ctor_baton(apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + apr_pool_t *const parser_pool = svn_pool_create(scratch_pool); + ctor_baton_t *const cb = apr_pcalloc(parser_pool, sizeof(*cb)); + + authz_full_t *const authz = apr_pcalloc(result_pool, sizeof(*authz)); + init_global_rights(&authz->anon_rights, anon_access_token, result_pool); + init_global_rights(&authz->authn_rights, authn_access_token, result_pool); + authz->user_rights = svn_hash__make(result_pool); + authz->pool = result_pool; + + cb->authz = authz; + cb->strings = svn_hash__make(parser_pool); + + cb->sections = svn_hash__make(parser_pool); + cb->section = NULL; + cb->parsing_groups = FALSE; + cb->in_groups = FALSE; + cb->in_aliases = FALSE; + + cb->parsed_rules = svn_hash__make(parser_pool); + cb->parsed_groups = svn_hash__make(parser_pool); + cb->parsed_aliases = svn_hash__make(parser_pool); + cb->parsed_acls = apr_array_make(parser_pool, 64, sizeof(parsed_acl_t)); + cb->current_acl = NULL; + + svn_membuf__create(&cb->rule_path_buffer, 0, parser_pool); + cb->rule_string_buffer = svn_stringbuf_create_empty(parser_pool); + + cb->parser_pool = parser_pool; + + insert_default_acl(cb); + + return cb; +} + + +/* Create and store per-user global rights. + The USER string must be interned or statically initialized. */ +static void +prepare_global_rights(ctor_baton_t *cb, const char *user) +{ + authz_global_rights_t *gr = svn_hash_gets(cb->authz->user_rights, user); + if (!gr) + { + gr = apr_palloc(cb->authz->pool, sizeof(*gr)); + init_global_rights(gr, user, cb->authz->pool); + svn_hash_sets(cb->authz->user_rights, gr->user, gr); + } +} + + +/* Internalize a string that will be referenced by the parsed svn_authz_t. + If LEN is (apr_size_t)-1, assume the string is NUL-terminated. */ +static const char * +intern_string(ctor_baton_t *cb, const char *str, apr_size_t len) +{ + const char *interned; + + if (len == (apr_size_t)-1) + len = strlen(str); + + interned = apr_hash_get(cb->strings, str, len); + if (!interned) + { + interned = apr_pstrmemdup(cb->authz->pool, str, len); + apr_hash_set(cb->strings, interned, len, interned); + } + return interned; +} + + +/* Helper for rules_open_section and groups_open_section. */ +static svn_error_t * +check_open_section(ctor_baton_t *cb, svn_stringbuf_t *section) +{ + SVN_ERR_ASSERT(!cb->current_acl && !cb->section); + if (apr_hash_get(cb->sections, section->data, section->len)) + { + if (cb->parsing_groups) + return svn_error_createf( + SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + _("Section appears more than once" + " in the global groups file: [%s]"), + section->data); + else + return svn_error_createf( + SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + _("Section appears more than once" + " in the authz file: [%s]"), + section->data); + } + + cb->section = apr_pstrmemdup(cb->parser_pool, section->data, section->len); + svn_hash_sets(cb->sections, cb->section, interned_empty_string); + return SVN_NO_ERROR; +} + + +/* Constructor callback: Begins the [groups] section. */ +static svn_error_t * +groups_open_section(void *baton, svn_stringbuf_t *section) +{ + ctor_baton_t *const cb = baton; + + if (cb->parsing_groups) + SVN_ERR(check_open_section(cb, section)); + + if (0 == strcmp(section->data, groups_section)) + { + cb->in_groups = TRUE; + return SVN_NO_ERROR; + } + + return svn_error_createf( + SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + (cb->parsing_groups + ? _("Section is not valid in the global group file: [%s]") + : _("Section is not valid in the authz file: [%s]")), + section->data); +} + + +/* Constructor callback: Parses a group declaration. */ +static svn_error_t * +groups_add_value(void *baton, svn_stringbuf_t *section, + svn_stringbuf_t *option, svn_stringbuf_t *value) +{ + ctor_baton_t *const cb = baton; + const char *group; + apr_size_t group_len; + + SVN_ERR_ASSERT(cb->in_groups); + + if (strchr("@$&*~", *option->data)) + { + if (cb->parsing_groups) + return svn_error_createf( + SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + _("Global group name '%s' may not begin with '%c'"), + option->data, *option->data); + else + return svn_error_createf( + SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + _("Group name '%s' may not begin with '%c'"), + option->data, *option->data); + } + + /* Decorate the name to make lookups consistent. */ + group = apr_pstrcat(cb->parser_pool, "@", option->data, SVN_VA_NULL); + group_len = option->len + 1; + if (apr_hash_get(cb->parsed_groups, group, group_len)) + { + if (cb->parsing_groups) + return svn_error_createf(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + _("Can't override definition" + " of global group '%s'"), + group); + else + return svn_error_createf(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + _("Can't override definition" + " of group '%s'"), + group); + } + + /* We store the whole group definition, so that we can use the + temporary groups in the baton hash later to fully expand group + memberships. + At this point, we can finally internalize the group name. */ + apr_hash_set(cb->parsed_groups, + intern_string(cb, group, group_len), group_len, + svn_cstring_split(value->data, ",", TRUE, cb->parser_pool)); + + return SVN_NO_ERROR; +} + + +/* Remove escape sequences in-place. */ +static void +unescape_in_place(svn_stringbuf_t *buf) +{ + char *p = buf->data; + apr_size_t i; + + /* Skip the string up to the first escape sequence. */ + for (i = 0; i < buf->len; ++i) + { + if (*p == '\\') + break; + ++p; + } + + if (i < buf->len) + { + /* Unescape the remainder of the string. */ + svn_boolean_t escape = TRUE; + const char *q; + + for (q = p + 1, ++i; i < buf->len; ++i) + { + if (escape) + { + *p++ = *q++; + escape = FALSE; + } + else if (*q == '\\') + { + ++q; + escape = TRUE; + } + else + *p++ = *q++; + } + + /* A trailing backslash is literal, so make it part of the pattern. */ + if (escape) + *p++ = '\\'; + *p = '\0'; + buf->len = p - buf->data; + } +} + + +/* Internalize a pattern. */ +static void +intern_pattern(ctor_baton_t *cb, + svn_string_t *pattern, + const char *string, + apr_size_t len) +{ + pattern->data = intern_string(cb, string, len); + pattern->len = len; +} + + +/* Parse a rule path PATH up to PATH_LEN into *RULE. + If GLOB is TRUE, treat PATH as possibly containing wildcards. + SECTION is the whole rule in the authz file. + Use pools and buffers from CB to do the obvious thing. */ +static svn_error_t * +parse_rule_path(authz_rule_t *rule, + ctor_baton_t *cb, + svn_boolean_t glob, + const char *path, + apr_size_t path_len, + const char *section) +{ + svn_stringbuf_t *const pattern = cb->rule_string_buffer; + const char *const path_end = path + path_len; + authz_rule_segment_t *segment; + const char *start; + const char *end; + int nseg; + + SVN_ERR_ASSERT(*path == '/'); + + nseg = 0; + for (start = path; start != path_end; start = end) + { + apr_size_t pattern_len; + + /* Skip the leading slash and find the end of the segment. */ + end = memchr(++start, '/', path_len - 1); + if (!end) + end = path_end; + + pattern_len = end - start; + path_len -= pattern_len + 1; + + if (pattern_len == 0) + { + if (nseg == 0) + { + /* This is an empty (root) path. */ + rule->len = 0; + rule->path = NULL; + return SVN_NO_ERROR; + } + + /* A path with two consecutive slashes is not canonical. */ + return svn_error_createf( + SVN_ERR_AUTHZ_INVALID_CONFIG, + svn_error_create(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + _("Found empty name in authz rule path")), + _("Non-canonical path '%s' in authz rule [%s]"), + path, section); + } + + /* A path with . or .. segments is not canonical. */ + if (*start == '.' + && (pattern_len == 1 + || (pattern_len == 2 && start[1] == '.'))) + return svn_error_createf( + SVN_ERR_AUTHZ_INVALID_CONFIG, + (end == start + 1 + ? svn_error_create(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + _("Found '.' in authz rule path")) + : svn_error_create(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + _("Found '..' in authz rule path"))), + _("Non-canonical path '%s' in authz rule [%s]"), + path, section); + + /* Make space for the current segment. */ + ++nseg; + svn_membuf__resize(&cb->rule_path_buffer, nseg * sizeof(*segment)); + segment = cb->rule_path_buffer.data; + segment += (nseg - 1); + + if (!glob) + { + /* Trivial case: this is not a glob rule, so every segment + is a literal match. */ + segment->kind = authz_rule_literal; + intern_pattern(cb, &segment->pattern, start, pattern_len); + continue; + } + + /* Copy the segment into the temporary buffer. */ + svn_stringbuf_setempty(pattern); + svn_stringbuf_appendbytes(pattern, start, pattern_len); + + if (0 == apr_fnmatch_test(pattern->data)) + { + /* It's a literal match after all. */ + segment->kind = authz_rule_literal; + unescape_in_place(pattern); + intern_pattern(cb, &segment->pattern, pattern->data, pattern->len); + continue; + } + + if (*pattern->data == '*') + { + if (pattern->len == 1 + || (pattern->len == 2 && pattern->data[1] == '*')) + { + /* Process * and **, applying normalization as per + https://wiki.apache.org/subversion/AuthzImprovements. */ + + authz_rule_segment_t *const prev = + (nseg > 1 ? segment - 1 : NULL); + + if (pattern_len == 1) + { + /* This is a *. Replace **|* with *|**. */ + if (prev && prev->kind == authz_rule_any_recursive) + { + prev->kind = authz_rule_any_segment; + segment->kind = authz_rule_any_recursive; + } + else + segment->kind = authz_rule_any_segment; + } + else + { + /* This is a **. Replace **|** with a single **. */ + if (prev && prev->kind == authz_rule_any_recursive) + { + /* Simply drop the redundant new segment. */ + --nseg; + continue; + } + else + segment->kind = authz_rule_any_recursive; + } + + segment->pattern.data = interned_empty_string; + segment->pattern.len = 0; + continue; + } + + /* Maybe it's a suffix match? */ + if (0 == apr_fnmatch_test(pattern->data + 1)) + { + svn_stringbuf_leftchop(pattern, 1); + segment->kind = authz_rule_suffix; + unescape_in_place(pattern); + svn_authz__reverse_string(pattern->data, pattern->len); + intern_pattern(cb, &segment->pattern, + pattern->data, pattern->len); + continue; + } + } + + if (pattern->data[pattern->len - 1] == '*') + { + /* Might be a prefix match. Note that because of the + previous test, we already know that the pattern is longer + than one character. */ + if (pattern->data[pattern->len - 2] != '\\') + { + /* OK, the * wasn't escaped. Chop off the wildcard. */ + svn_stringbuf_chop(pattern, 1); + if (0 == apr_fnmatch_test(pattern->data)) + { + segment->kind = authz_rule_prefix; + unescape_in_place(pattern); + intern_pattern(cb, &segment->pattern, + pattern->data, pattern->len); + continue; + } + + /* Restore the wildcard since it was not a prefix match. */ + svn_stringbuf_appendbyte(pattern, '*'); + } + } + + /* It's a generic fnmatch pattern. */ + segment->kind = authz_rule_fnmatch; + intern_pattern(cb, &segment->pattern, pattern->data, pattern->len); + } + + SVN_ERR_ASSERT(nseg > 0); + + /* Copy the temporary segments array into the result pool. */ + { + const apr_size_t path_size = nseg * sizeof(*segment); + SVN_ERR_ASSERT(path_size <= cb->rule_path_buffer.size); + + rule->len = nseg; + rule->path = apr_palloc(cb->authz->pool, path_size); + memcpy(rule->path, cb->rule_path_buffer.data, path_size); + } + + return SVN_NO_ERROR; +} + + +/* Check that the parsed RULE is unique within the authz file. + With the introduction of wildcards, just looking at the SECTION + names is not sufficient to determine uniqueness. + Use pools and buffers from CB to do the obvious thing. */ +static svn_error_t * +check_unique_rule(ctor_baton_t *cb, + const authz_rule_t *rule, + const char *section) +{ + svn_stringbuf_t *const buf = cb->rule_string_buffer; + const char *exists; + int i; + + /* Construct the key for this rule */ + svn_stringbuf_setempty(buf); + svn_stringbuf_appendcstr(buf, rule->repos); + svn_stringbuf_appendbyte(buf, '\n'); + + for (i = 0; i < rule->len; ++i) + { + authz_rule_segment_t *const seg = &rule->path[i]; + svn_stringbuf_appendbyte(buf, '@' + seg->kind); + svn_stringbuf_appendbytes(buf, seg->pattern.data, seg->pattern.len); + svn_stringbuf_appendbyte(buf, '\n'); + } + + /* Check if the section exists. */ + exists = apr_hash_get(cb->parsed_rules, buf->data, buf->len); + if (exists) + return svn_error_createf( + SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + _("Section [%s] describes the same rule as section [%s]"), + section, exists); + + /* Insert the rule into the known rules set. */ + apr_hash_set(cb->parsed_rules, + apr_pstrmemdup(cb->parser_pool, buf->data, buf->len), + buf->len, + apr_pstrdup(cb->parser_pool, section)); + + return SVN_NO_ERROR; +} + + +/* Constructor callback: Starts a rule or [aliases] section. */ +static svn_error_t * +rules_open_section(void *baton, svn_stringbuf_t *section) +{ + ctor_baton_t *const cb = baton; + const char *rule = section->data; + apr_size_t rule_len = section->len; + svn_boolean_t glob; + const char *endp; + parsed_acl_t acl; + + SVN_ERR(check_open_section(cb, section)); + + /* Parse rule property tokens. */ + if (*rule != ':') + glob = FALSE; + else + { + /* This must be a wildcard rule. */ + apr_size_t token_len; + + ++rule; --rule_len; + endp = memchr(rule, ':', rule_len); + if (!endp) + return svn_error_createf( + SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + _("Empty repository name in authz rule [%s]"), + section->data); + + /* Note: the size of glob_rule_token includes the NUL terminator. */ + token_len = endp - rule; + if (token_len != sizeof(glob_rule_token) - 1 + || memcmp(rule, glob_rule_token, token_len)) + return svn_error_createf( + SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + _("Invalid type token '%s' in authz rule [%s]"), + apr_pstrmemdup(cb->parser_pool, rule, token_len), + section->data); + + glob = TRUE; + rule = endp + 1; + rule_len -= token_len + 1; + } + + /* Parse the repository name. */ + endp = (*rule == '/' ? NULL : memchr(rule, ':', rule_len)); + if (!endp) + acl.acl.rule.repos = interned_empty_string; + else + { + const apr_size_t repos_len = endp - rule; + + /* The rule contains a repository name. */ + if (0 == repos_len) + return svn_error_createf( + SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + _("Empty repository name in authz rule [%s]"), + section->data); + + acl.acl.rule.repos = intern_string(cb, rule, repos_len); + rule = endp + 1; + rule_len -= repos_len + 1; + } + + /* Parse the actual rule. */ + if (*rule == '/') + { + SVN_ERR(parse_rule_path(&acl.acl.rule, cb, glob, rule, rule_len, + section->data)); + SVN_ERR(check_unique_rule(cb, &acl.acl.rule, section->data)); + } + else if (0 == strcmp(section->data, aliases_section)) + { + cb->in_aliases = TRUE; + return SVN_NO_ERROR; + } + else + { + /* This must be the [groups] section. */ + return groups_open_section(cb, section); + } + + acl.acl.sequence_number = cb->parsed_acls->nelts; + acl.acl.anon_access = authz_access_none; + acl.acl.has_anon_access = FALSE; + acl.acl.authn_access = authz_access_none; + acl.acl.has_authn_access = FALSE; + acl.acl.user_access = NULL; + + acl.aces = svn_hash__make(cb->parser_pool); + acl.alias_aces = svn_hash__make(cb->parser_pool); + + cb->current_acl = &APR_ARRAY_PUSH(cb->parsed_acls, parsed_acl_t); + *cb->current_acl = acl; + return SVN_NO_ERROR; +} + + +/* Parses an alias declaration. The definition (username) of the + alias will always be interned. */ +static svn_error_t * +add_alias_definition(ctor_baton_t *cb, + svn_stringbuf_t *option, svn_stringbuf_t *value) +{ + const char *alias; + apr_size_t alias_len; + const char *user; + + if (strchr("@$&*~", *option->data)) + return svn_error_createf( + SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + _("Alias name '%s' may not begin with '%c'"), + option->data, *option->data); + + /* Decorate the name to make lookups consistent. */ + alias = apr_pstrcat(cb->parser_pool, "&", option->data, SVN_VA_NULL); + alias_len = option->len + 1; + if (apr_hash_get(cb->parsed_aliases, alias, alias_len)) + return svn_error_createf( + SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + _("Can't override definition of alias '%s'"), + alias); + + user = intern_string(cb, value->data, value->len); + apr_hash_set(cb->parsed_aliases, alias, alias_len, user); + + /* Prepare the global rights struct for this user. */ + prepare_global_rights(cb, user); + return SVN_NO_ERROR; +} + +/* Parses an access entry. Groups and users in access entry names will + always be interned, aliases will never be. */ +static svn_error_t * +add_access_entry(ctor_baton_t *cb, svn_stringbuf_t *section, + svn_stringbuf_t *option, svn_stringbuf_t *value) +{ + parsed_acl_t *const acl = cb->current_acl; + const char *name = option->data; + apr_size_t name_len = option->len; + const svn_boolean_t inverted = (*name == '~'); + svn_boolean_t anonymous = FALSE; + svn_boolean_t authenticated = FALSE; + authz_access_t access = authz_access_none; + authz_ace_t *ace; + int i; + + SVN_ERR_ASSERT(acl != NULL); + + if (inverted) + { + ++name; + --name_len; + } + + /* Determine the access entry type. */ + switch (*name) + { + case '~': + return svn_error_createf( + SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + _("Access entry '%s' has more than one inversion;" + " double negatives are not permitted"), + option->data); + break; + + case '*': + if (name_len != 1) + return svn_error_createf( + SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + _("Access entry '%s' is not valid;" + " it must be a single '*'"), + option->data); + + if (inverted) + return svn_error_createf( + SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + _("Access entry '~*' will never match")); + + anonymous = TRUE; + authenticated = TRUE; + break; + + case '$': + if (0 == strcmp(name, anon_access_token)) + { + if (inverted) + authenticated = TRUE; + else + anonymous = TRUE; + } + else if (0 == strcmp(name, authn_access_token)) + { + if (inverted) + anonymous = TRUE; + else + authenticated = TRUE; + } + else + return svn_error_createf( + SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + _("Access entry token '%s' is not valid;" + " should be '%s' or '%s'"), + option->data, anon_access_token, authn_access_token); + break; + + default: + /* A username, group name or alias. */; + } + + /* Parse the access rights. */ + for (i = 0; i < value->len; ++i) + { + const char access_code = value->data[i]; + switch (access_code) + { + case 'r': + access |= authz_access_read_flag; + break; + + case 'w': + access |= authz_access_write_flag; + break; + + default: + if (!svn_ctype_isspace(access_code)) + return svn_error_createf( + SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + _("The access mode '%c' in access entry '%s'" + " of rule [%s] is not valid"), + access_code, option->data, section->data); + } + } + + /* We do not support write-only access. */ + if ((access & authz_access_write_flag) && !(access & authz_access_read_flag)) + return svn_error_createf( + SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + _("Write-only access entry '%s' of rule [%s] is not valid"), + option->data, section->data); + + /* Update the parsed ACL with this access entry. */ + if (anonymous || authenticated) + { + if (anonymous) + { + acl->acl.has_anon_access = TRUE; + acl->acl.anon_access |= access; + } + if (authenticated) + { + acl->acl.has_authn_access = TRUE; + acl->acl.authn_access |= access; + } + } + else + { + /* The inversion tag must be part of the key in the hash + table, otherwise we can't tell regular and inverted + entries appart. */ + const char *key = (inverted ? name - 1 : name); + const apr_size_t key_len = (inverted ? name_len + 1 : name_len); + const svn_boolean_t aliased = (*name == '&'); + apr_hash_t *aces = (aliased ? acl->alias_aces : acl->aces); + + ace = apr_hash_get(aces, key, key_len); + if (ace) + ace->access |= access; + else + { + ace = apr_palloc(cb->parser_pool, sizeof(*ace)); + ace->name = (aliased + ? apr_pstrmemdup(cb->parser_pool, name, name_len) + : intern_string(cb, name, name_len)); + ace->members = NULL; + ace->inverted = inverted; + ace->access = access; + + key = (inverted + ? apr_pstrmemdup(cb->parser_pool, key, key_len) + : ace->name); + apr_hash_set(aces, key, key_len, ace); + + /* Prepare the global rights struct for this user. */ + if (!aliased && *ace->name != '@') + prepare_global_rights(cb, ace->name); + } + } + + return SVN_NO_ERROR; +} + +/* Constructor callback: Parse a rule, alias or group delcaration. */ +static svn_error_t * +rules_add_value(void *baton, svn_stringbuf_t *section, + svn_stringbuf_t *option, svn_stringbuf_t *value) +{ + ctor_baton_t *const cb = baton; + + if (cb->in_groups) + return groups_add_value(baton, section, option, value); + + if (cb->in_aliases) + return add_alias_definition(cb, option, value); + + return add_access_entry(cb, section, option, value); +} + + +/* Constructor callback: Close a section. */ +static svn_error_t * +close_section(void *baton, svn_stringbuf_t *section) +{ + ctor_baton_t *const cb = baton; + + SVN_ERR_ASSERT(0 == strcmp(cb->section, section->data)); + cb->section = NULL; + cb->current_acl = NULL; + cb->in_groups = FALSE; + cb->in_aliases = FALSE; + return SVN_NO_ERROR; +} + + +/* Add a user to GROUP. + GROUP is never internalized, but USER always is. */ +static void +add_to_group(ctor_baton_t *cb, const char *group, const char *user) +{ + apr_hash_t *members = svn_hash_gets(cb->expanded_groups, group); + if (!members) + { + group = intern_string(cb, group, -1); + members = svn_hash__make(cb->authz->pool); + svn_hash_sets(cb->expanded_groups, group, members); + } + svn_hash_sets(members, user, interned_empty_string); +} + + +/* Hash iterator for expanding group definitions. + WARNING: This function is recursive! */ +static svn_error_t * +expand_group_callback(void *baton, + const void *key, + apr_ssize_t klen, + void *value, + apr_pool_t *scratch_pool) +{ + ctor_baton_t *const cb = baton; + const char *const group = key; + apr_array_header_t *members = value; + + int i; + for (i = 0; i < members->nelts; ++i) + { + const char *member = APR_ARRAY_IDX(members, i, const char*); + if (0 == strcmp(member, group)) + return svn_error_createf(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + _("Recursive definition of group '%s'"), + group); + + if (*member == '&') + { + /* Add expanded alias to the group. + N.B.: the user name is already internalized. */ + const char *user = svn_hash_gets(cb->parsed_aliases, member); + if (!user) + return svn_error_createf( + SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + _("Alias '%s' was never defined"), + member); + + add_to_group(cb, group, user); + } + else if (*member != '@') + { + /* Add the member to the group. */ + const char *user = intern_string(cb, member, -1); + add_to_group(cb, group, user); + + /* Prepare the global rights struct for this user. */ + prepare_global_rights(cb, user); + } + else + { + /* Recursively expand the group membership */ + members = svn_hash_gets(cb->parsed_groups, member); + if (!members) + return svn_error_createf( + SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + _("Undefined group '%s'"), + member); + SVN_ERR(expand_group_callback(cb, key, klen, + members, scratch_pool)); + } + } + return SVN_NO_ERROR; +} + + +/* Hash iteration baton for merge_alias_ace. */ +typedef struct merge_alias_baton_t +{ + apr_hash_t *aces; + ctor_baton_t *cb; +} merge_alias_baton_t; + +/* Hash iterator for expanding and mergina alias-based ACEs + into the user/group-based ACEs. */ +static svn_error_t * +merge_alias_ace(void *baton, + const void *key, + apr_ssize_t klen, + void *value, + apr_pool_t *scratch_pool) +{ + merge_alias_baton_t *const mab = baton; + authz_ace_t *aliased_ace = value; + const char *alias = aliased_ace->name; + const char *unaliased_key; + const char *user; + authz_ace_t *ace; + + user = svn_hash_gets(mab->cb->parsed_aliases, alias); + if (!user) + return svn_error_createf( + SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + _("Alias '%s' was never defined"), + alias); + + /* N.B.: The user name is always internalized, + but the inverted key may not be. */ + if (!aliased_ace->inverted) + unaliased_key = user; + else + { + unaliased_key = apr_pstrcat(mab->cb->parser_pool, + "~", user, SVN_VA_NULL); + unaliased_key = intern_string(mab->cb, unaliased_key, -1); + } + + ace = svn_hash_gets(mab->aces, unaliased_key); + if (!ace) + { + aliased_ace->name = user; + svn_hash_sets(mab->aces, unaliased_key, aliased_ace); + } + else + { + SVN_ERR_ASSERT(!ace->inverted == !aliased_ace->inverted); + ace->access |= aliased_ace->access; + } + + return SVN_NO_ERROR; +} + + +/* Hash iteration baton for array_insert_ace. */ +typedef struct insert_ace_baton_t +{ + apr_array_header_t *ace_array; + ctor_baton_t *cb; +} insert_ace_baton_t; + +/* Hash iterator, inserts an ACE into the ACLs array. */ +static svn_error_t * +array_insert_ace(void *baton, + const void *key, + apr_ssize_t klen, + void *value, + apr_pool_t *scratch_pool) +{ + insert_ace_baton_t *iab = baton; + authz_ace_t *ace = value; + + /* Add group membership info to the ACE. */ + if (*ace->name == '@') + { + SVN_ERR_ASSERT(ace->members == NULL); + ace->members = svn_hash_gets(iab->cb->expanded_groups, ace->name); + if (!ace->members) + return svn_error_createf( + SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + _("Access entry refers to undefined group '%s'"), + ace->name); + } + + APR_ARRAY_PUSH(iab->ace_array, authz_ace_t) = *ace; + return SVN_NO_ERROR; +} + + +/* Update accumulated RIGHTS from ACCESS. */ +static void +update_rights(authz_rights_t *rights, + authz_access_t access) +{ + rights->min_access &= access; + rights->max_access |= access; +} + + +/* Update a global RIGHTS based on REPOS and ACCESS. */ +static void +update_global_rights(authz_global_rights_t *gr, + const char *repos, + authz_access_t access) +{ + update_rights(&gr->all_repos_rights, access); + if (0 == strcmp(repos, AUTHZ_ANY_REPOSITORY)) + update_rights(&gr->any_repos_rights, access); + else + { + authz_rights_t *rights = svn_hash_gets(gr->per_repos_rights, repos); + if (rights) + update_rights(rights, access); + else + { + rights = apr_palloc(apr_hash_pool_get(gr->per_repos_rights), + sizeof(*rights)); + init_rights(rights); + update_rights(rights, access); + svn_hash_sets(gr->per_repos_rights, repos, rights); + } + } +} + + +/* Hash iterator to update global per-user rights from an ACL. */ +static svn_error_t * +update_user_rights(void *baton, + const void *key, + apr_ssize_t klen, + void *value, + apr_pool_t *scratch_pool) +{ + const authz_acl_t *const acl = baton; + const char *const user = key; + authz_global_rights_t *const gr = value; + authz_access_t access; + svn_boolean_t has_access = + svn_authz__get_acl_access(&access, acl, user, acl->rule.repos); + + if (has_access) + update_global_rights(gr, acl->rule.repos, access); + return SVN_NO_ERROR; +} + + +/* List iterator, expands/merges a parsed ACL into its final form and + appends it to the authz info's ACL array. */ +static svn_error_t * +expand_acl_callback(void *baton, + void *item, + apr_pool_t *scratch_pool) +{ + ctor_baton_t *const cb = baton; + parsed_acl_t *const pacl = item; + authz_acl_t *const acl = &pacl->acl; + + /* Expand and merge the aliased ACEs. */ + if (apr_hash_count(pacl->alias_aces)) + { + merge_alias_baton_t mab; + mab.aces = pacl->aces; + mab.cb = cb; + SVN_ERR(svn_iter_apr_hash(NULL, pacl->alias_aces, + merge_alias_ace, &mab, scratch_pool)); + } + + /* Make an array from the merged hashes. */ + acl->user_access = + apr_array_make(cb->authz->pool, apr_hash_count(pacl->aces), + sizeof(authz_ace_t)); + { + insert_ace_baton_t iab; + iab.ace_array = acl->user_access; + iab.cb = cb; + SVN_ERR(svn_iter_apr_hash(NULL, pacl->aces, + array_insert_ace, &iab, scratch_pool)); + } + + /* Store the completed ACL into authz. */ + APR_ARRAY_PUSH(cb->authz->acls, authz_acl_t) = *acl; + + /* Update global access rights for this ACL. */ + if (acl->has_anon_access) + { + cb->authz->has_anon_rights = TRUE; + update_global_rights(&cb->authz->anon_rights, + acl->rule.repos, acl->anon_access); + } + if (acl->has_authn_access) + { + cb->authz->has_authn_rights = TRUE; + update_global_rights(&cb->authz->authn_rights, + acl->rule.repos, acl->authn_access); + } + SVN_ERR(svn_iter_apr_hash(NULL, cb->authz->user_rights, + update_user_rights, acl, scratch_pool)); + return SVN_NO_ERROR; +} + + +/* Compare two ACLs in rule lexical order, then repository order, then + order of definition. This ensures that our default ACL is always + first in the sorted array. */ +static int +compare_parsed_acls(const void *va, const void *vb) +{ + const parsed_acl_t *const a = va; + const parsed_acl_t *const b = vb; + + int cmp = svn_authz__compare_rules(&a->acl.rule, &b->acl.rule); + if (cmp == 0) + cmp = a->acl.sequence_number - b->acl.sequence_number; + return cmp; +} + + +svn_error_t * +svn_authz__parse(authz_full_t **authz, + svn_stream_t *rules, + svn_stream_t *groups, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + ctor_baton_t *const cb = create_ctor_baton(result_pool, scratch_pool); + + /* + * Pass 1: Parse the authz file. + */ + SVN_ERR(svn_config__parse_stream(rules, + svn_config__constructor_create( + rules_open_section, + close_section, + rules_add_value, + cb->parser_pool), + cb, cb->parser_pool)); + + /* + * Pass 1.6487: Parse the global groups file. + */ + if (groups) + { + /* Check that the authz file did not contain any groups. */ + if (0 != apr_hash_count(cb->parsed_groups)) + return svn_error_create(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, + ("Authz file cannot contain any groups" + " when global groups are being used.")); + + apr_hash_clear(cb->sections); + cb->parsing_groups = TRUE; + SVN_ERR(svn_config__parse_stream(groups, + svn_config__constructor_create( + groups_open_section, + close_section, + groups_add_value, + cb->parser_pool), + cb, cb->parser_pool)); + } + + /* + * Pass 2: Expand groups and construct the final svn_authz_t. + */ + cb->expanded_groups = svn_hash__make(cb->parser_pool); + SVN_ERR(svn_iter_apr_hash(NULL, cb->parsed_groups, + expand_group_callback, cb, cb->parser_pool)); + + + /* Sort the parsed ACLs in rule lexical order and pop off the + default global ACL iff an equivalent ACL was defined in the authz + file. */ + if (cb->parsed_acls->nelts > 1) + { + parsed_acl_t *defacl; + parsed_acl_t *nxtacl; + + svn_sort__array(cb->parsed_acls, compare_parsed_acls); + defacl = &APR_ARRAY_IDX(cb->parsed_acls, 0, parsed_acl_t); + nxtacl = &APR_ARRAY_IDX(cb->parsed_acls, 1, parsed_acl_t); + + /* If the first ACL is not our default thingamajig, there's a + bug in our comparator. */ + SVN_ERR_ASSERT( + defacl->acl.sequence_number == 0 && defacl->acl.rule.len == 0 + && 0 == strcmp(defacl->acl.rule.repos, AUTHZ_ANY_REPOSITORY)); + + /* Pop the default ACL off the array if another equivalent + exists, after merging the default rights. */ + if (0 == svn_authz__compare_rules(&defacl->acl.rule, &nxtacl->acl.rule)) + { + nxtacl->acl.has_anon_access = TRUE; + nxtacl->acl.has_authn_access = TRUE; + cb->parsed_acls->elts = (char*)(nxtacl); + --cb->parsed_acls->nelts; + } + } + + cb->authz->acls = apr_array_make(cb->authz->pool, cb->parsed_acls->nelts, + sizeof(authz_acl_t)); + SVN_ERR(svn_iter_apr_array(NULL, cb->parsed_acls, + expand_acl_callback, cb, cb->parser_pool)); + + *authz = cb->authz; + apr_pool_destroy(cb->parser_pool); + return SVN_NO_ERROR; +} + + +void +svn_authz__reverse_string(char *string, apr_size_t len) +{ + char *left = string; + char *right = string + len - 1; + for (; left < right; ++left, --right) + { + char c = *left; + *left = *right; + *right = c; + } +} + + +int +svn_authz__compare_paths(const authz_rule_t *a, const authz_rule_t *b) +{ + const int min_len = (a->len > b->len ? b->len : a->len); + int i; + + for (i = 0; i < min_len; ++i) + { + int cmp = a->path[i].kind - b->path[i].kind; + if (0 == cmp) + { + const char *const aseg = a->path[i].pattern.data; + const char *const bseg = b->path[i].pattern.data; + + /* Exploit the fact that segment patterns are interned. */ + if (aseg != bseg) + cmp = strcmp(aseg, bseg); + else + cmp = 0; + } + if (0 != cmp) + return cmp; + } + + /* Sort shorter rules first. */ + if (a->len != b->len) + return a->len - b->len; + + return 0; +} + +int +svn_authz__compare_rules(const authz_rule_t *a, const authz_rule_t *b) +{ + int diff = svn_authz__compare_paths(a, b); + if (diff) + return diff; + + /* Repository names are interned, too. */ + if (a->repos != b->repos) + return strcmp(a->repos, b->repos); + + return 0; +} diff --git a/subversion/libsvn_repos/authz_pool.c b/subversion/libsvn_repos/authz_pool.c deleted file mode 100644 index f8ac52835876..000000000000 --- a/subversion/libsvn_repos/authz_pool.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * authz_pool.c : pool of authorization objects - * - * ==================================================================== - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * ==================================================================== - */ - - - -#include "svn_checksum.h" -#include "svn_config.h" -#include "svn_error.h" -#include "svn_pools.h" - -#include "private/svn_dep_compat.h" -#include "private/svn_mutex.h" -#include "private/svn_object_pool.h" -#include "private/svn_subr_private.h" -#include "private/svn_repos_private.h" -#include "private/svn_string_private.h" -#include "private/svn_subr_private.h" - -#include "repos.h" - -/* Currently this structure is just a wrapper around a svn_config_t. - */ -struct svn_authz_t -{ - svn_config_t *cfg; -}; - -/* The wrapper object structure that we store in the object pool. It - * combines the authz with the underlying config structures and their - * identifying keys. - */ -typedef struct authz_object_t -{ - /* key = concatenation of AUTHZ_KEY and GROUPS_KEY */ - svn_membuf_t *key; - - /* keys used to identify AUTHZ_CFG and GROUPS_CFG */ - svn_membuf_t *authz_key; - svn_membuf_t *groups_key; - - /* r/o references to configurations from the configuration pool. - GROUPS_CFG may be NULL. */ - svn_config_t *authz_cfg; - svn_config_t *groups_cfg; - - /* Case-sensitive config. */ - svn_authz_t *authz; -} authz_object_t; - -/* Root data structure simply adding the config_pool to the basic object pool. - */ -struct svn_repos__authz_pool_t -{ - /* authz_object_t object storage */ - svn_object_pool__t *object_pool; - - /* factory and storage of (shared) configuration objects */ - svn_repos__config_pool_t *config_pool; -}; - -/* Return a combination of AUTHZ_KEY and GROUPS_KEY, allocated in POOL. - * GROUPS_KEY may be NULL. - */ -static svn_membuf_t * -construct_key(svn_membuf_t *authz_key, - svn_membuf_t *groups_key, - apr_pool_t *pool) -{ - svn_membuf_t *result = apr_pcalloc(pool, sizeof(*result)); - apr_size_t size; - if (groups_key) - { - size = authz_key->size + groups_key->size; - svn_membuf__create(result,size, pool); - memcpy(result->data, authz_key->data, authz_key->size); - memcpy((char *)result->data + authz_key->size, - groups_key->data, groups_key->size); - } - else - { - size = authz_key->size; - svn_membuf__create(result, size, pool); - memcpy(result->data, authz_key->data, authz_key->size); - } - - result->size = size; - return result; -} - -/* Implement svn_object_pool__getter_t on authz_object_t structures. - */ -static void * -getter(void *object, - void *baton, - apr_pool_t *pool) -{ - return ((authz_object_t *)object)->authz; -} - -/* API implementation */ - -svn_error_t * -svn_repos__authz_pool_create(svn_repos__authz_pool_t **authz_pool, - svn_repos__config_pool_t *config_pool, - svn_boolean_t thread_safe, - apr_pool_t *pool) -{ - svn_repos__authz_pool_t *result; - svn_object_pool__t *object_pool; - - /* there is no setter as we don't need to update existing authz */ - SVN_ERR(svn_object_pool__create(&object_pool, getter, NULL, thread_safe, - pool)); - - result = apr_pcalloc(pool, sizeof(*result)); - result->object_pool = object_pool; - result->config_pool = config_pool; - - *authz_pool = result; - return SVN_NO_ERROR; -} - -svn_error_t * -svn_repos__authz_pool_get(svn_authz_t **authz_p, - svn_repos__authz_pool_t *authz_pool, - const char *path, - const char *groups_path, - svn_boolean_t must_exist, - svn_repos_t *preferred_repos, - apr_pool_t *pool) -{ - apr_pool_t *authz_ref_pool - = svn_object_pool__new_wrapper_pool(authz_pool->object_pool); - authz_object_t *authz_ref - = apr_pcalloc(authz_ref_pool, sizeof(*authz_ref)); - svn_boolean_t have_all_keys; - - /* read the configurations */ - SVN_ERR(svn_repos__config_pool_get(&authz_ref->authz_cfg, - &authz_ref->authz_key, - authz_pool->config_pool, - path, must_exist, TRUE, - preferred_repos, authz_ref_pool)); - have_all_keys = authz_ref->authz_key != NULL; - - if (groups_path) - { - SVN_ERR(svn_repos__config_pool_get(&authz_ref->groups_cfg, - &authz_ref->groups_key, - authz_pool->config_pool, - groups_path, must_exist, TRUE, - preferred_repos, authz_ref_pool)); - have_all_keys &= authz_ref->groups_key != NULL; - } - - /* fall back to standard implementation in case we don't have all the - * facts (i.e. keys). */ - if (!have_all_keys) - return svn_error_trace(svn_repos_authz_read2(authz_p, path, groups_path, - must_exist, pool)); - - /* all keys are known and lookup is unambigious. */ - authz_ref->key = construct_key(authz_ref->authz_key, - authz_ref->groups_key, - authz_ref_pool); - - SVN_ERR(svn_object_pool__lookup((void **)authz_p, authz_pool->object_pool, - authz_ref->key, NULL, pool)); - if (*authz_p) - { - svn_pool_destroy(authz_ref_pool); - return SVN_NO_ERROR; - } - - authz_ref->authz = apr_palloc(authz_ref_pool, sizeof(*authz_ref->authz)); - authz_ref->authz->cfg = authz_ref->authz_cfg; - - if (groups_path) - { - /* Easy out: we prohibit local groups in the authz file when global - groups are being used. */ - if (svn_config_has_section(authz_ref->authz->cfg, - SVN_CONFIG_SECTION_GROUPS)) - return svn_error_createf(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL, - "Error reading authz file '%s' with " - "groups file '%s':" - "Authz file cannot contain any groups " - "when global groups are being used.", - path, groups_path); - - /* We simply need to add the [Groups] section to the authz config. - */ - svn_config__shallow_replace_section(authz_ref->authz->cfg, - authz_ref->groups_cfg, - SVN_CONFIG_SECTION_GROUPS); - } - - /* Make sure there are no errors in the configuration. */ - SVN_ERR(svn_repos__authz_validate(authz_ref->authz, authz_ref_pool)); - - SVN_ERR(svn_object_pool__insert((void **)authz_p, authz_pool->object_pool, - authz_ref->key, authz_ref, NULL, - authz_ref_pool, pool)); - - return SVN_NO_ERROR; -} diff --git a/subversion/libsvn_repos/commit.c b/subversion/libsvn_repos/commit.c index 1190acc29fc5..6ce4cc6f7ffd 100644 --- a/subversion/libsvn_repos/commit.c +++ b/subversion/libsvn_repos/commit.c @@ -124,6 +124,7 @@ struct dir_baton svn_revnum_t base_rev; /* the revision I'm based on */ svn_boolean_t was_copied; /* was this directory added with history? */ apr_pool_t *pool; /* my personal pool, in which I am allocated. */ + svn_boolean_t checked_write; /* TRUE after successfull write check */ }; @@ -131,6 +132,7 @@ struct file_baton { struct edit_baton *edit_baton; const char *path; /* the -absolute- path to this file in the fs */ + svn_boolean_t checked_write; /* TRUE after successfull write check */ }; @@ -171,6 +173,30 @@ out_of_date(const char *path, svn_node_kind_t kind) path); } +/* Perform an out of date check for base_rev against created rev, + and a sanity check of base_rev. */ +static svn_error_t * +check_out_of_date(struct edit_baton *eb, + const char *path, + svn_node_kind_t kind, + svn_revnum_t base_rev, + svn_revnum_t created_rev) +{ + if (base_rev < created_rev) + { + return out_of_date(path, kind); + } + else if (base_rev > created_rev) + { + if (base_rev > svn_fs_txn_base_revision(eb->txn)) + return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL, + _("No such revision %ld"), + base_rev); + } + + return SVN_NO_ERROR; +} + static svn_error_t * invoke_commit_cb(svn_commit_callback2_t commit_cb, @@ -184,15 +210,16 @@ invoke_commit_cb(svn_commit_callback2_t commit_cb, /* const */ svn_string_t *date; /* const */ svn_string_t *author; svn_commit_info_t *commit_info; + apr_hash_t *revprops; if (commit_cb == NULL) return SVN_NO_ERROR; - SVN_ERR(svn_fs_revision_prop(&date, fs, revision, SVN_PROP_REVISION_DATE, - scratch_pool)); - SVN_ERR(svn_fs_revision_prop(&author, fs, revision, - SVN_PROP_REVISION_AUTHOR, - scratch_pool)); + SVN_ERR(svn_fs_revision_proplist2(&revprops, fs, revision, + TRUE, scratch_pool, scratch_pool)); + + date = svn_hash_gets(revprops, SVN_PROP_REVISION_DATE); + author = svn_hash_gets(revprops, SVN_PROP_REVISION_AUTHOR); commit_info = svn_create_commit_info(scratch_pool); @@ -298,7 +325,6 @@ add_file_or_directory(const char *path, const char *fs_path; svn_fs_root_t *copy_root; svn_node_kind_t kind; - size_t repos_url_len; svn_repos_authz_access_t required; /* Copy requires recursive write access to the destination path @@ -320,14 +346,12 @@ add_file_or_directory(const char *path, /* For now, require that the url come from the same repository that this commit is operating on. */ copy_path = svn_path_uri_decode(copy_path, subpool); - repos_url_len = strlen(eb->repos_url_decoded); - if (strncmp(copy_path, eb->repos_url_decoded, repos_url_len) != 0) + fs_path = svn_cstring_skip_prefix(copy_path, eb->repos_url_decoded); + if (!fs_path) return svn_error_createf (SVN_ERR_FS_GENERAL, NULL, _("Source url '%s' is from different repository"), copy_path); - fs_path = apr_pstrdup(subpool, copy_path + repos_url_len); - /* Now use the "fs_path" as an absolute path within the repository to make the copy from. */ SVN_ERR(svn_fs_revision_root(©_root, eb->fs, @@ -364,14 +388,18 @@ add_file_or_directory(const char *path, /* Build a new child baton. */ if (is_dir) { - *return_baton = make_dir_baton(eb, pb, full_path, was_copied, - SVN_INVALID_REVNUM, pool); + struct dir_baton *new_db = make_dir_baton(eb, pb, full_path, was_copied, + SVN_INVALID_REVNUM, pool); + + new_db->checked_write = TRUE; /* Just created */ + *return_baton = new_db; } else { struct file_baton *new_fb = apr_pcalloc(pool, sizeof(*new_fb)); new_fb->edit_baton = eb; new_fb->path = full_path; + new_fb->checked_write = TRUE; /* Just created */ *return_baton = new_fb; } @@ -392,9 +420,9 @@ open_root(void *edit_baton, struct edit_baton *eb = edit_baton; svn_revnum_t youngest; - /* Ignore BASE_REVISION. We always build our transaction against - HEAD. However, we will keep it in our dir baton for out of - dateness checks. */ + /* We always build our transaction against HEAD. However, we will + sanity-check BASE_REVISION and keep it in our dir baton for out + of dateness checks. */ SVN_ERR(svn_fs_youngest_rev(&youngest, eb->fs, eb->pool)); if (base_revision > youngest) @@ -448,7 +476,6 @@ delete_entry(const char *path, struct dir_baton *parent = parent_baton; struct edit_baton *eb = parent->edit_baton; svn_node_kind_t kind; - svn_revnum_t cr_rev; svn_repos_authz_access_t required = svn_authz_write; const char *full_path; @@ -473,14 +500,18 @@ delete_entry(const char *path, /* Now, make sure we're deleting the node we *think* we're deleting, else return an out-of-dateness error. */ - SVN_ERR(svn_fs_node_created_rev(&cr_rev, eb->txn_root, full_path, pool)); - if (SVN_IS_VALID_REVNUM(revision) && (revision < cr_rev)) - return svn_error_trace(out_of_date(full_path, kind)); + if (SVN_IS_VALID_REVNUM(revision)) + { + svn_revnum_t cr_rev; + + SVN_ERR(svn_fs_node_created_rev(&cr_rev, eb->txn_root, full_path, pool)); + SVN_ERR(check_out_of_date(eb, full_path, kind, revision, cr_rev)); + } /* This routine is a mindless wrapper. We call svn_fs_delete() because that will delete files and recursively delete directories. */ - return svn_fs_delete(eb->txn_root, full_path, pool); + return svn_error_trace(svn_fs_delete(eb->txn_root, full_path, pool)); } @@ -535,18 +566,23 @@ apply_textdelta(void *file_baton, void **handler_baton) { struct file_baton *fb = file_baton; + struct edit_baton *eb = fb->edit_baton; - /* Check for write authorization. */ - SVN_ERR(check_authz(fb->edit_baton, fb->path, - fb->edit_baton->txn_root, - svn_authz_write, pool)); + if (!fb->checked_write) + { + /* Check for write authorization. */ + SVN_ERR(check_authz(eb, fb->path, eb->txn_root, + svn_authz_write, pool)); + fb->checked_write = TRUE; + } - return svn_fs_apply_textdelta(handler, handler_baton, - fb->edit_baton->txn_root, - fb->path, - base_checksum, - NULL, - pool); + return svn_error_trace( + svn_fs_apply_textdelta(handler, handler_baton, + eb->txn_root, + fb->path, + base_checksum, + NULL, + pool)); } @@ -590,8 +626,9 @@ open_file(const char *path, /* If the node our caller has is an older revision number than the one in our transaction, return an out-of-dateness error. */ - if (SVN_IS_VALID_REVNUM(base_revision) && (base_revision < cr_rev)) - return svn_error_trace(out_of_date(full_path, svn_node_file)); + if (SVN_IS_VALID_REVNUM(base_revision)) + SVN_ERR(check_out_of_date(eb, full_path, svn_node_file, + base_revision, cr_rev)); /* Build a new file baton */ new_fb = apr_pcalloc(pool, sizeof(*new_fb)); @@ -616,9 +653,13 @@ change_file_prop(void *file_baton, struct file_baton *fb = file_baton; struct edit_baton *eb = fb->edit_baton; - /* Check for write authorization. */ - SVN_ERR(check_authz(eb, fb->path, eb->txn_root, - svn_authz_write, pool)); + if (!fb->checked_write) + { + /* Check for write authorization. */ + SVN_ERR(check_authz(eb, fb->path, eb->txn_root, + svn_authz_write, pool)); + fb->checked_write = TRUE; + } return svn_repos_fs_change_node_prop(eb->txn_root, fb->path, name, value, pool); @@ -663,19 +704,24 @@ change_dir_prop(void *dir_baton, struct edit_baton *eb = db->edit_baton; /* Check for write authorization. */ - SVN_ERR(check_authz(eb, db->path, eb->txn_root, - svn_authz_write, pool)); - - if (SVN_IS_VALID_REVNUM(db->base_rev)) + if (!db->checked_write) { - /* Subversion rule: propchanges can only happen on a directory - which is up-to-date. */ - svn_revnum_t created_rev; - SVN_ERR(svn_fs_node_created_rev(&created_rev, - eb->txn_root, db->path, pool)); + SVN_ERR(check_authz(eb, db->path, eb->txn_root, + svn_authz_write, pool)); - if (db->base_rev < created_rev) - return svn_error_trace(out_of_date(db->path, svn_node_dir)); + if (SVN_IS_VALID_REVNUM(db->base_rev)) + { + /* Subversion rule: propchanges can only happen on a directory + which is up-to-date. */ + svn_revnum_t created_rev; + SVN_ERR(svn_fs_node_created_rev(&created_rev, + eb->txn_root, db->path, pool)); + + SVN_ERR(check_out_of_date(eb, db->path, svn_node_dir, + db->base_rev, created_rev)); + } + + db->checked_write = TRUE; /* Skip on further prop changes */ } return svn_repos_fs_change_node_prop(eb->txn_root, db->path, diff --git a/subversion/libsvn_repos/compat.c b/subversion/libsvn_repos/compat.c new file mode 100644 index 000000000000..405b1c415b8d --- /dev/null +++ b/subversion/libsvn_repos/compat.c @@ -0,0 +1,179 @@ +/* + * compat.c: compatibility shims to adapt between different API versions. + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#include "svn_repos.h" +#include "svn_compat.h" +#include "svn_hash.h" +#include "svn_props.h" +#include "svn_pools.h" + +#include "svn_private_config.h" + +#include "repos.h" + +#include "private/svn_repos_private.h" +#include "private/svn_subr_private.h" + + + +/*** log4 -> log5 ***/ + +/* Baton type to be used with both log4 compatibility callbacks. + * For each revision, we collect the CHANGES and then pass them + * on to INNER. */ +typedef struct log_entry_receiver_baton_t +{ + /* Pool to use to allocate CHANGES and its entries. + * Gets cleared after each revision. */ + apr_pool_t *changes_pool; + + /* Path changes reported so far for the current revision. + * Will be NULL before the first item gets added and will be reset + * to NULL after the INNER callback has returned. */ + apr_hash_t *changes; + + /* User-provided callback to send the log entry to. */ + svn_log_entry_receiver_t inner; + void *inner_baton; +} log_entry_receiver_baton_t; + +/* Return the action character (see svn_log_changed_path2_t) for KIND. + * Returns 0 for invalid KINDs. */ +static char +path_change_kind_to_char(svn_fs_path_change_kind_t kind) +{ + const char symbol[] = "MADR"; + + if (kind < svn_fs_path_change_modify || kind > svn_fs_path_change_replace) + return 0; + + return symbol[kind]; +} + +/* Implement svn_repos_path_change_receiver_t. + * Convert CHANGE and add it to the CHANGES list in *BATON. */ +static svn_error_t * +log4_path_change_receiver(void *baton, + svn_repos_path_change_t *change, + apr_pool_t *scratch_pool) +{ + log_entry_receiver_baton_t *b = baton; + svn_log_changed_path2_t *change_copy; + const char *path = apr_pstrmemdup(b->changes_pool, change->path.data, + change->path.len); + + /* Create a deep copy of the temporary CHANGE struct. */ + change_copy = svn_log_changed_path2_create(b->changes_pool); + change_copy->action = path_change_kind_to_char(change->change_kind); + + if (change->copyfrom_path) + change_copy->copyfrom_path = apr_pstrdup(b->changes_pool, + change->copyfrom_path); + + change_copy->copyfrom_rev = change->copyfrom_rev; + change_copy->node_kind = change->node_kind; + change_copy->text_modified = change->text_mod ? svn_tristate_true + : svn_tristate_false; + change_copy->props_modified = change->prop_mod ? svn_tristate_true + : svn_tristate_false; + + /* Auto-create the CHANGES container (happens for each first change + * in any revison. */ + if (b->changes == NULL) + b->changes = svn_hash__make(b->changes_pool); + + /* Add change to per-revision collection. */ + apr_hash_set(b->changes, path, change->path.len, change_copy); + + return SVN_NO_ERROR; +} + +/* Implement svn_log_entry_receiver_t. + * Combine the data gathered in BATON for this revision and send it + * to the user-provided log4-compatible callback. */ +static svn_error_t * +log4_entry_receiver(void *baton, + svn_repos_log_entry_t *log_entry, + apr_pool_t *scratch_pool) +{ + log_entry_receiver_baton_t *b = baton; + svn_log_entry_t *entry = svn_log_entry_create(scratch_pool); + + /* Complete the ENTRY. */ + entry->changed_paths = b->changes; + entry->revision = log_entry->revision; + entry->revprops = log_entry->revprops; + entry->has_children = log_entry->has_children; + entry->changed_paths2 = b->changes; + entry->non_inheritable = log_entry->non_inheritable; + entry->subtractive_merge = log_entry->subtractive_merge; + + /* Invoke the log4-compatible callback. */ + SVN_ERR(b->inner(b->inner_baton, entry, scratch_pool)); + + /* Release per-revision data. */ + svn_pool_clear(b->changes_pool); + b->changes = NULL; + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_repos__get_logs_compat(svn_repos_t *repos, + const apr_array_header_t *paths, + svn_revnum_t start, + svn_revnum_t end, + int limit, + svn_boolean_t discover_changed_paths, + svn_boolean_t strict_node_history, + svn_boolean_t include_merged_revisions, + const apr_array_header_t *revprops, + svn_repos_authz_func_t authz_read_func, + void *authz_read_baton, + svn_log_entry_receiver_t receiver, + void *receiver_baton, + apr_pool_t *pool) +{ + apr_pool_t *changes_pool = svn_pool_create(pool); + + log_entry_receiver_baton_t baton; + baton.changes_pool = changes_pool; + baton.changes = NULL; + baton.inner = receiver; + baton.inner_baton = receiver_baton; + + SVN_ERR(svn_repos_get_logs5(repos, paths, start, end, limit, + strict_node_history, + include_merged_revisions, + revprops, + authz_read_func, authz_read_baton, + discover_changed_paths + ? log4_path_change_receiver + : NULL, + &baton, + log4_entry_receiver, &baton, + pool)); + + svn_pool_destroy(changes_pool); + return SVN_NO_ERROR; +} diff --git a/subversion/libsvn_repos/config_file.c b/subversion/libsvn_repos/config_file.c new file mode 100644 index 000000000000..918727796eb7 --- /dev/null +++ b/subversion/libsvn_repos/config_file.c @@ -0,0 +1,386 @@ +/* + * config_file.c : efficiently read config files from disk or repo + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + + + + +#include "svn_checksum.h" +#include "svn_path.h" +#include "svn_pools.h" + +#include "private/svn_subr_private.h" +#include "private/svn_repos_private.h" +#include "private/svn_config_private.h" + +#include "config_file.h" + +#include "svn_private_config.h" + + + +struct config_access_t +{ + /* The last repository that we found the requested URL in. May be NULL. */ + svn_repos_t *repos; + + /* Owning pool of this structure and is private to this structure. + * All objects with the lifetime of this access object will be allocated + * from this pool. */ + apr_pool_t *pool; +}; + + + +/* A stream object that gives access to a representation's content but + * delays accessing the repository data until the stream is first used. + * IOW, the stream object is cheap as long as it is not accessed. + */ +typedef struct presentation_stream_baton_t +{ + svn_fs_root_t *root; + const char *fs_path; + apr_pool_t *pool; + svn_stream_t *inner; +} presentation_stream_baton_t; + +static svn_error_t * +auto_open_inner_stream(presentation_stream_baton_t *b) +{ + if (!b->inner) + { + svn_filesize_t length; + svn_stream_t *stream; + svn_stringbuf_t *contents; + + SVN_ERR(svn_fs_file_length(&length, b->root, b->fs_path, b->pool)); + SVN_ERR(svn_fs_file_contents(&stream, b->root, b->fs_path, b->pool)); + SVN_ERR(svn_stringbuf_from_stream(&contents, stream, + (apr_size_t)length, b->pool)); + b->inner = svn_stream_from_stringbuf(contents, b->pool); + } + + return SVN_NO_ERROR; +} + +static svn_error_t * +read_handler_rep(void *baton, char *buffer, apr_size_t *len) +{ + presentation_stream_baton_t *b = baton; + SVN_ERR(auto_open_inner_stream(b)); + + return svn_error_trace(svn_stream_read2(b->inner, buffer, len)); +} + +static svn_error_t * +mark_handler_rep(void *baton, svn_stream_mark_t **mark, apr_pool_t *pool) +{ + presentation_stream_baton_t *b = baton; + SVN_ERR(auto_open_inner_stream(b)); + + return svn_error_trace(svn_stream_mark(b->inner, mark, pool)); +} + +static svn_error_t * +seek_handler_rep(void *baton, const svn_stream_mark_t *mark) +{ + presentation_stream_baton_t *b = baton; + SVN_ERR(auto_open_inner_stream(b)); + + return svn_error_trace(svn_stream_seek(b->inner, mark)); +} + +static svn_error_t * +skip_handler_rep(void *baton, apr_size_t len) +{ + presentation_stream_baton_t *b = baton; + SVN_ERR(auto_open_inner_stream(b)); + + return svn_error_trace(svn_stream_skip(b->inner, len)); +} + +static svn_error_t * +data_available_handler_rep(void *baton, svn_boolean_t *data_available) +{ + presentation_stream_baton_t *b = baton; + SVN_ERR(auto_open_inner_stream(b)); + + return svn_error_trace(svn_stream_data_available(b->inner, data_available)); +} + +static svn_error_t * +readline_handler_rep(void *baton, + svn_stringbuf_t **stringbuf, + const char *eol, + svn_boolean_t *eof, + apr_pool_t *pool) +{ + presentation_stream_baton_t *b = baton; + SVN_ERR(auto_open_inner_stream(b)); + + return svn_error_trace(svn_stream_readline(b->inner, stringbuf, eol, eof, + pool)); +} + +/* Return a lazy access stream for FS_PATH under ROOT, allocated in POOL. */ +static svn_stream_t * +representation_stream(svn_fs_root_t *root, + const char *fs_path, + apr_pool_t *pool) +{ + svn_stream_t *stream; + presentation_stream_baton_t *baton; + + baton = apr_pcalloc(pool, sizeof(*baton)); + baton->root = root; + baton->fs_path = fs_path; + baton->pool = pool; + + stream = svn_stream_create(baton, pool); + svn_stream_set_read2(stream, read_handler_rep, read_handler_rep); + svn_stream_set_mark(stream, mark_handler_rep); + svn_stream_set_seek(stream, seek_handler_rep); + svn_stream_set_skip(stream, skip_handler_rep); + svn_stream_set_data_available(stream, data_available_handler_rep); + svn_stream_set_readline(stream, readline_handler_rep); + return stream; +} + +/* Handle the case of a file PATH / url pointing to anything that is either + * not a file or does not exist at all. The case is given by NODE_KIND. + * + * If MUST_EXIST is not set and the file does not exist at all, return a + * default *STREAM and *CHECKSUM allocated in the context of ACCESS, or an + * error otherwise. + */ +static svn_error_t * +handle_missing_file(svn_stream_t **stream, + svn_checksum_t **checksum, + config_access_t *access, + const char *path, + svn_boolean_t must_exist, + svn_node_kind_t node_kind) +{ + if (node_kind == svn_node_none && !must_exist) + { + *stream = svn_stream_empty(access->pool); + SVN_ERR(svn_checksum(checksum, svn_checksum_md5, "", 0, access->pool)); + } + else if (node_kind != svn_node_file) + { + return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL, + "'%s' is not a file", path); + } + + return SVN_NO_ERROR; +} + +/* Open the in-repository file at URL, return its content checksum in + * *CHECKSUM and the content itself through *STREAM. Allocate those with + * the lifetime of ACCESS and use SCRATCH_POOL for temporaries. + * + * Error out when the file does not exist but MUST_EXIST is set. + */ +static svn_error_t * +get_repos_config(svn_stream_t **stream, + svn_checksum_t **checksum, + config_access_t *access, + const char *url, + svn_boolean_t must_exist, + apr_pool_t *scratch_pool) +{ + svn_fs_t *fs; + svn_fs_root_t *root; + svn_revnum_t youngest_rev; + svn_node_kind_t node_kind; + const char *dirent; + const char *fs_path; + const char *repos_root_dirent; + + SVN_ERR(svn_uri_get_dirent_from_file_url(&dirent, url, access->pool)); + + /* Maybe we can use the repos hint instance instead of creating a + * new one. */ + if (access->repos) + { + repos_root_dirent = svn_repos_path(access->repos, scratch_pool); + if (!svn_dirent_is_absolute(repos_root_dirent)) + SVN_ERR(svn_dirent_get_absolute(&repos_root_dirent, + repos_root_dirent, + scratch_pool)); + + if (!svn_dirent_is_ancestor(repos_root_dirent, dirent)) + access->repos = NULL; + } + + /* Open repos if no suitable repos is available. */ + if (!access->repos) + { + /* Search for a repository in the full path. */ + repos_root_dirent = svn_repos_find_root_path(dirent, scratch_pool); + + /* Attempt to open a repository at repos_root_dirent. */ + SVN_ERR(svn_repos_open3(&access->repos, repos_root_dirent, NULL, + access->pool, scratch_pool)); + } + + fs_path = &dirent[strlen(repos_root_dirent)]; + + /* Get the filesystem. */ + fs = svn_repos_fs(access->repos); + + /* Find HEAD and the revision root */ + SVN_ERR(svn_fs_youngest_rev(&youngest_rev, fs, scratch_pool)); + SVN_ERR(svn_fs_revision_root(&root, fs, youngest_rev, access->pool)); + + /* Special case: non-existent paths may be handled as "empty" contents. */ + SVN_ERR(svn_fs_check_path(&node_kind, root, fs_path, scratch_pool)); + if (node_kind != svn_node_file) + return svn_error_trace(handle_missing_file(stream, checksum, access, + url, must_exist, node_kind)); + + /* Fetch checksum and see whether we already have a matching config */ + SVN_ERR(svn_fs_file_checksum(checksum, svn_checksum_md5, root, fs_path, + TRUE, access->pool)); + + *stream = representation_stream(root, fs_path, access->pool); + + return SVN_NO_ERROR; +} + +/* Open the file at PATH, return its content checksum in CHECKSUM and the + * content itself through *STREAM. Allocate those with the lifetime of + * ACCESS. + */ +static svn_error_t * +get_file_config(svn_stream_t **stream, + svn_checksum_t **checksum, + config_access_t *access, + const char *path, + svn_boolean_t must_exist, + apr_pool_t *scratch_pool) +{ + svn_stringbuf_t *contents; + svn_node_kind_t node_kind; + + /* Special case: non-existent paths may be handled as "empty" contents. */ + SVN_ERR(svn_io_check_path(path, &node_kind, scratch_pool)); + if (node_kind != svn_node_file) + return svn_error_trace(handle_missing_file(stream, checksum, access, + path, must_exist, node_kind)); + + /* Now, we should be able to read the file. */ + SVN_ERR(svn_stringbuf_from_file2(&contents, path, access->pool)); + + /* calculate MD5 over the whole file contents */ + SVN_ERR(svn_checksum(checksum, svn_checksum_md5, + contents->data, contents->len, access->pool)); + *stream = svn_stream_from_stringbuf(contents, access->pool); + + return SVN_NO_ERROR; +} + +/* Read the configuration from path, URL or registry sub-tree PATH, return + * its content checksum in CHECKSUM and the content itself through *STREAM. + * Allocate those with the lifetime of ACCESS. + */ +static svn_error_t * +get_generic_config(svn_stream_t **stream, + svn_checksum_t **checksum, + config_access_t *access, + const char *path, + svn_boolean_t must_exist, + apr_pool_t *scratch_pool) +{ + svn_stringbuf_t *contents = svn_stringbuf_create_empty(access->pool); + svn_config_t *config; + + /* Read the configuration and serialize it into CONTENTS. + * That copy can then be processed by the authz parser etc. */ + SVN_ERR(svn_config_read3(&config, path, must_exist, TRUE, TRUE, + scratch_pool)); + SVN_ERR(svn_config__write(svn_stream_from_stringbuf(contents, scratch_pool), + config, scratch_pool)); + + /* calculate MD5 over the whole file contents */ + SVN_ERR(svn_checksum(checksum, svn_checksum_md5, + contents->data, contents->len, access->pool)); + *stream = svn_stream_from_stringbuf(contents, access->pool); + + return SVN_NO_ERROR; +} + +config_access_t * +svn_repos__create_config_access(svn_repos_t *repos_hint, + apr_pool_t *result_pool) +{ + apr_pool_t *pool = svn_pool_create(result_pool); + config_access_t *result = apr_pcalloc(pool, sizeof(*result)); + + result->repos = repos_hint; + result->pool = pool; + + return result; +} + +void +svn_repos__destroy_config_access(config_access_t *access) +{ + svn_pool_destroy(access->pool); +} + +svn_error_t * +svn_repos__get_config(svn_stream_t **stream, + svn_checksum_t **checksum, + config_access_t *access, + const char *path, + svn_boolean_t must_exist, + apr_pool_t *scratch_pool) +{ + svn_error_t *err; + /* Directly access the config data. */ + if (svn_path_is_url(path)) + err = get_repos_config(stream, checksum, access, path, must_exist, + scratch_pool); + else + err = get_file_config(stream, checksum, access, path, must_exist, + scratch_pool); + + /* Fallback to indirect access using the generic config file parser. + * This is mainly used for registry support under Win32. */ + if (err) + { + svn_error_t *err2 = get_generic_config(stream, checksum, access, path, + must_exist, scratch_pool); + if (err2) + { + svn_error_clear(err2); + } + else + { + svn_error_clear(err); + err = SVN_NO_ERROR; + } + } + + return svn_error_trace(err); +} diff --git a/subversion/libsvn_repos/config_file.h b/subversion/libsvn_repos/config_file.h new file mode 100644 index 000000000000..7fce18f13608 --- /dev/null +++ b/subversion/libsvn_repos/config_file.h @@ -0,0 +1,74 @@ +/* config_file.h : authz parsing and searching, private to libsvn_repos + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#ifndef SVN_REPOS_CONFIG_FILE_H +#define SVN_REPOS_CONFIG_FILE_H + +#include +#include +#include + +#include "svn_config.h" +#include "svn_error.h" +#include "svn_io.h" +#include "svn_repos.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + + +/* An opaque struct that helps making config data access resource efficient. */ +typedef struct config_access_t config_access_t; + +/* Return a new config access struct allocated in RESULT_POOL. + * Try to access REPOS_HINT first when resolving URLs; may be NULL. */ +config_access_t * +svn_repos__create_config_access(svn_repos_t *repos_hint, + apr_pool_t *result_pool); + +/* Release all resources allocated while using ACCESS. */ +void +svn_repos__destroy_config_access(config_access_t *access); + +/* Using ACCESS as a helper object, access the textual configuration at PATH, + * which may be an URL or a local path. Return content's checksum in + * *CHECKSUM and provide its content in *STREAM. + * + * The access will fail if the item does not exist and MUST_EXIST is set. + * The result has the same lifetime as ACCESS. Use SCRATCH_POOL for + * temporary allocations. + */ +svn_error_t * +svn_repos__get_config(svn_stream_t **stream, + svn_checksum_t **checksum, + config_access_t *access, + const char *path, + svn_boolean_t must_exist, + apr_pool_t *scratch_pool); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* SVN_REPOS_CONFIG_FILE_H */ diff --git a/subversion/libsvn_repos/config_pool.c b/subversion/libsvn_repos/config_pool.c index 164bd983c02b..acf4be34061e 100644 --- a/subversion/libsvn_repos/config_pool.c +++ b/subversion/libsvn_repos/config_pool.c @@ -25,110 +25,17 @@ #include "svn_checksum.h" -#include "svn_config.h" -#include "svn_error.h" -#include "svn_hash.h" #include "svn_path.h" #include "svn_pools.h" -#include "svn_repos.h" -#include "private/svn_dep_compat.h" -#include "private/svn_mutex.h" #include "private/svn_subr_private.h" #include "private/svn_repos_private.h" -#include "private/svn_object_pool.h" #include "svn_private_config.h" - -/* Our wrapper structure for parsed svn_config_t* instances. All data in - * CS_CFG and CI_CFG is expanded (to make it thread-safe) and considered - * read-only. - */ -typedef struct config_object_t -{ - /* UUID of the configuration contents. - * This is a SHA1 checksum of the parsed textual representation of CFG. */ - svn_checksum_t *key; - - /* Parsed and expanded configuration. At least one of the following - * must not be NULL. */ - - /* Case-sensitive config. May be NULL */ - svn_config_t *cs_cfg; - - /* Case-insensitive config. May be NULL */ - svn_config_t *ci_cfg; -} config_object_t; - - -/* Data structure used to short-circuit the repository access for configs - * read via URL. After reading such a config successfully, we store key - * repository information here and will validate it without actually opening - * the repository. - * - * As this is only an optimization and may create many entries in - * svn_repos__config_pool_t's IN_REPO_HASH_POOL index, we clean them up - * once in a while. - */ -typedef struct in_repo_config_t -{ - /* URL used to open the configuration */ - const char *url; - - /* Path of the repository that contained URL */ - const char *repo_root; - - /* Head revision of that repository when last read */ - svn_revnum_t revision; - - /* Contents checksum of the file stored under URL@REVISION */ - svn_checksum_t *key; -} in_repo_config_t; - - -/* Core data structure extending the encapsulated OBJECT_POOL. All access - * to it must be serialized using the OBJECT_POOL->MUTEX. - * - * To speed up URL@HEAD lookups, we maintain IN_REPO_CONFIGS as a secondary - * hash index. It maps URLs as provided by the caller onto in_repo_config_t - * instances. If that is still up-to-date, a further lookup into CONFIG - * may yield the desired configuration without the need to actually open - * the respective repository. - * - * Unused configurations that are kept in the IN_REPO_CONFIGS hash and may - * be cleaned up when the hash is about to grow. - */ -struct svn_repos__config_pool_t -{ - svn_object_pool__t *object_pool; - - /* URL -> in_repo_config_t* mapping. - * This is only a partial index and will get cleared regularly. */ - apr_hash_t *in_repo_configs; - - /* allocate the IN_REPO_CONFIGS index and in_repo_config_t here */ - apr_pool_t *in_repo_hash_pool; -}; +#include "config_file.h" -/* Return an automatic reference to the CFG member in CONFIG that will be - * released when POOL gets cleaned up. The case sensitivity flag in *BATON - * selects the desired option and section name matching mode. - */ -static void * -getter(void *object, - void *baton, - apr_pool_t *pool) -{ - config_object_t *wrapper = object; - svn_boolean_t *case_sensitive = baton; - svn_config_t *config = *case_sensitive ? wrapper->cs_cfg : wrapper->ci_cfg; - - /* we need to duplicate the root structure as it contains temp. buffers */ - return config ? svn_config__shallow_copy(config, pool) : NULL; -} - /* Return a memory buffer structure allocated in POOL and containing the * data from CHECKSUM. */ @@ -146,288 +53,43 @@ checksum_as_key(svn_checksum_t *checksum, return result; } -/* Copy the configuration from the wrapper in SOURCE to the wrapper in - * *TARGET with the case sensitivity flag in *BATON selecting the config - * to copy. This is usually done to add the missing case-(in)-sensitive - * variant. Since we must hold all data in *TARGET from the same POOL, - * a deep copy is required. - */ -static svn_error_t * -setter(void **target, - void *source, - void *baton, - apr_pool_t *pool) -{ - svn_boolean_t *case_sensitive = baton; - config_object_t *target_cfg = *(config_object_t **)target; - config_object_t *source_cfg = source; - - /* Maybe, we created a variant with different case sensitivity? */ - if (*case_sensitive && target_cfg->cs_cfg == NULL) - { - SVN_ERR(svn_config_dup(&target_cfg->cs_cfg, source_cfg->cs_cfg, pool)); - svn_config__set_read_only(target_cfg->cs_cfg, pool); - } - else if (!*case_sensitive && target_cfg->ci_cfg == NULL) - { - SVN_ERR(svn_config_dup(&target_cfg->ci_cfg, source_cfg->ci_cfg, pool)); - svn_config__set_read_only(target_cfg->ci_cfg, pool); - } - - return SVN_NO_ERROR; -} - -/* Set *CFG to the configuration passed in as text in CONTENTS and *KEY to - * the corresponding object pool key. If no such configuration exists in - * CONFIG_POOL, yet, parse CONTENTS and cache the result. CASE_SENSITIVE - * controls option and section name matching. +/* Set *CFG to the configuration serialized in STREAM and cache it in + * CONFIG_POOL under CHECKSUM. The configuration will only be parsed if + * we can't find it the CONFIG_POOL already. * * RESULT_POOL determines the lifetime of the returned reference and * SCRATCH_POOL is being used for temporary allocations. */ static svn_error_t * -auto_parse(svn_config_t **cfg, - svn_membuf_t **key, - svn_repos__config_pool_t *config_pool, - svn_stringbuf_t *contents, - svn_boolean_t case_sensitive, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) +find_config(svn_config_t **cfg, + svn_repos__config_pool_t *config_pool, + svn_stream_t *stream, + svn_checksum_t *checksum, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { - svn_checksum_t *checksum; - config_object_t *config_object; - apr_pool_t *cfg_pool; + /* First, attempt the cache lookup. */ + svn_membuf_t *key = checksum_as_key(checksum, scratch_pool); + SVN_ERR(svn_object_pool__lookup((void **)cfg, config_pool, key, + result_pool)); - /* calculate SHA1 over the whole file contents */ - SVN_ERR(svn_stream_close - (svn_stream_checksummed2 - (svn_stream_from_stringbuf(contents, scratch_pool), - &checksum, NULL, svn_checksum_sha1, TRUE, scratch_pool))); - - /* return reference to suitable config object if that already exists */ - *key = checksum_as_key(checksum, result_pool); - SVN_ERR(svn_object_pool__lookup((void **)cfg, config_pool->object_pool, - *key, &case_sensitive, result_pool)); - if (*cfg) - return SVN_NO_ERROR; - - /* create a pool for the new config object and parse the data into it */ - cfg_pool = svn_object_pool__new_wrapper_pool(config_pool->object_pool); - - config_object = apr_pcalloc(cfg_pool, sizeof(*config_object)); - - SVN_ERR(svn_config_parse(case_sensitive ? &config_object->cs_cfg - : &config_object->ci_cfg, - svn_stream_from_stringbuf(contents, scratch_pool), - case_sensitive, case_sensitive, cfg_pool)); - - /* switch config data to r/o mode to guarantee thread-safe access */ - svn_config__set_read_only(case_sensitive ? config_object->cs_cfg - : config_object->ci_cfg, - cfg_pool); - - /* add config in pool, handle loads races and return the right config */ - SVN_ERR(svn_object_pool__insert((void **)cfg, config_pool->object_pool, - *key, config_object, &case_sensitive, - cfg_pool, result_pool)); - - return SVN_NO_ERROR; -} - -/* Store a URL@REVISION to CHECKSUM, REPOS_ROOT in CONFIG_POOL. - */ -static svn_error_t * -add_checksum(svn_repos__config_pool_t *config_pool, - const char *url, - const char *repos_root, - svn_revnum_t revision, - svn_checksum_t *checksum) -{ - apr_size_t path_len = strlen(url); - apr_pool_t *pool = config_pool->in_repo_hash_pool; - in_repo_config_t *config = apr_hash_get(config_pool->in_repo_configs, - url, path_len); - if (config) - { - /* update the existing entry */ - memcpy((void *)config->key->digest, checksum->digest, - svn_checksum_size(checksum)); - config->revision = revision; - - /* duplicate the string only if necessary */ - if (strcmp(config->repo_root, repos_root)) - config->repo_root = apr_pstrdup(pool, repos_root); - } - else - { - /* insert a new entry. - * Limit memory consumption by cyclically clearing pool and hash. */ - if (2 * svn_object_pool__count(config_pool->object_pool) - < apr_hash_count(config_pool->in_repo_configs)) - { - svn_pool_clear(pool); - config_pool->in_repo_configs = svn_hash__make(pool); - } - - /* construct the new entry */ - config = apr_pcalloc(pool, sizeof(*config)); - config->key = svn_checksum_dup(checksum, pool); - config->url = apr_pstrmemdup(pool, url, path_len); - config->repo_root = apr_pstrdup(pool, repos_root); - config->revision = revision; - - /* add to index */ - apr_hash_set(config_pool->in_repo_configs, url, path_len, config); - } - - return SVN_NO_ERROR; -} - -/* Set *CFG to the configuration stored in URL@HEAD and cache it in - * CONFIG_POOL. CASE_SENSITIVE controls - * option and section name matching. If PREFERRED_REPOS is given, - * use that if it also matches URL. - * - * RESULT_POOL determines the lifetime of the returned reference and - * SCRATCH_POOL is being used for temporary allocations. - */ -static svn_error_t * -find_repos_config(svn_config_t **cfg, - svn_membuf_t **key, - svn_repos__config_pool_t *config_pool, - const char *url, - svn_boolean_t case_sensitive, - svn_repos_t *preferred_repos, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) -{ - svn_repos_t *repos = NULL; - svn_fs_t *fs; - svn_fs_root_t *root; - svn_revnum_t youngest_rev; - svn_node_kind_t node_kind; - const char *dirent; - svn_stream_t *stream; - const char *fs_path; - const char *repos_root_dirent; - svn_checksum_t *checksum; - svn_stringbuf_t *contents; - - *cfg = NULL; - SVN_ERR(svn_uri_get_dirent_from_file_url(&dirent, url, scratch_pool)); - - /* maybe we can use the preferred repos instance instead of creating a - * new one */ - if (preferred_repos) - { - repos_root_dirent = svn_repos_path(preferred_repos, scratch_pool); - if (!svn_dirent_is_absolute(repos_root_dirent)) - SVN_ERR(svn_dirent_get_absolute(&repos_root_dirent, - repos_root_dirent, - scratch_pool)); - - if (svn_dirent_is_ancestor(repos_root_dirent, dirent)) - repos = preferred_repos; - } - - /* open repos if no suitable preferred repos was provided. */ - if (!repos) - { - /* Search for a repository in the full path. */ - repos_root_dirent = svn_repos_find_root_path(dirent, scratch_pool); - - /* Attempt to open a repository at repos_root_dirent. */ - SVN_ERR(svn_repos_open3(&repos, repos_root_dirent, NULL, - scratch_pool, scratch_pool)); - } - - fs_path = &dirent[strlen(repos_root_dirent)]; - - /* Get the filesystem. */ - fs = svn_repos_fs(repos); - - /* Find HEAD and the revision root */ - SVN_ERR(svn_fs_youngest_rev(&youngest_rev, fs, scratch_pool)); - SVN_ERR(svn_fs_revision_root(&root, fs, youngest_rev, scratch_pool)); - - /* Fetch checksum and see whether we already have a matching config */ - SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_sha1, root, fs_path, - FALSE, scratch_pool)); - if (checksum) - { - *key = checksum_as_key(checksum, scratch_pool); - SVN_ERR(svn_object_pool__lookup((void **)cfg, config_pool->object_pool, - *key, &case_sensitive, result_pool)); - } - - /* not parsed, yet? */ + /* Not found? => parse and cache */ if (!*cfg) { - svn_filesize_t length; + svn_config_t *config; - /* fetch the file contents */ - SVN_ERR(svn_fs_check_path(&node_kind, root, fs_path, scratch_pool)); - if (node_kind != svn_node_file) - return SVN_NO_ERROR; + /* create a pool for the new config object and parse the data into it */ + apr_pool_t *cfg_pool = svn_object_pool__new_item_pool(config_pool); + SVN_ERR(svn_config_parse(&config, stream, FALSE, FALSE, cfg_pool)); - SVN_ERR(svn_fs_file_length(&length, root, fs_path, scratch_pool)); - SVN_ERR(svn_fs_file_contents(&stream, root, fs_path, scratch_pool)); - SVN_ERR(svn_stringbuf_from_stream(&contents, stream, - (apr_size_t)length, scratch_pool)); + /* switch config data to r/o mode to guarantee thread-safe access */ + svn_config__set_read_only(config, cfg_pool); - /* handle it like ordinary file contents and cache it */ - SVN_ERR(auto_parse(cfg, key, config_pool, contents, case_sensitive, - result_pool, scratch_pool)); + /* add config in pool, handle loads races and return the right config */ + SVN_ERR(svn_object_pool__insert((void **)cfg, config_pool, key, + config, cfg_pool, result_pool)); } - /* store the (path,rev) -> checksum mapping as well */ - if (*cfg && checksum) - SVN_MUTEX__WITH_LOCK(svn_object_pool__mutex(config_pool->object_pool), - add_checksum(config_pool, url, repos_root_dirent, - youngest_rev, checksum)); - - return SVN_NO_ERROR; -} - -/* Given the URL, search the CONFIG_POOL for an entry that maps it URL to - * a content checksum and is still up-to-date. If this could be found, - * return the object's *KEY. Use POOL for allocations. - * - * Requires external serialization on CONFIG_POOL. - * - * Note that this is only the URL(+rev) -> Checksum lookup and does not - * guarantee that there is actually a config object available for *KEY. - */ -static svn_error_t * -key_by_url(svn_membuf_t **key, - svn_repos__config_pool_t *config_pool, - const char *url, - apr_pool_t *pool) -{ - svn_error_t *err; - svn_stringbuf_t *contents; - apr_int64_t current; - - /* hash lookup url -> sha1 -> config */ - in_repo_config_t *config = svn_hash_gets(config_pool->in_repo_configs, url); - *key = NULL; - if (!config) - return SVN_NO_ERROR; - - /* found *some* reference to a configuration. - * Verify that it is still current. Will fail for BDB repos. */ - err = svn_stringbuf_from_file2(&contents, - svn_dirent_join(config->repo_root, - "db/current", pool), - pool); - if (!err) - err = svn_cstring_atoi64(¤t, contents->data); - - if (err) - svn_error_clear(err); - else if (current == config->revision) - *key = checksum_as_key(config->key, pool); - return SVN_NO_ERROR; } @@ -438,94 +100,49 @@ svn_repos__config_pool_create(svn_repos__config_pool_t **config_pool, svn_boolean_t thread_safe, apr_pool_t *pool) { - svn_repos__config_pool_t *result; - svn_object_pool__t *object_pool; - - SVN_ERR(svn_object_pool__create(&object_pool, getter, setter, - thread_safe, pool)); - - /* construct the config pool in our private ROOT_POOL to survive POOL - * cleanup and to prevent threading issues with the allocator */ - result = apr_pcalloc(pool, sizeof(*result)); - - result->object_pool = object_pool; - result->in_repo_hash_pool = svn_pool_create(pool); - result->in_repo_configs = svn_hash__make(result->in_repo_hash_pool); - - *config_pool = result; - return SVN_NO_ERROR; + return svn_error_trace(svn_object_pool__create(config_pool, + thread_safe, pool)); } svn_error_t * svn_repos__config_pool_get(svn_config_t **cfg, - svn_membuf_t **key, svn_repos__config_pool_t *config_pool, const char *path, svn_boolean_t must_exist, - svn_boolean_t case_sensitive, svn_repos_t *preferred_repos, apr_pool_t *pool) { svn_error_t *err = SVN_NO_ERROR; apr_pool_t *scratch_pool = svn_pool_create(pool); + config_access_t *access = svn_repos__create_config_access(preferred_repos, + scratch_pool); + svn_stream_t *stream; + svn_checksum_t *checksum; - /* make sure we always have a *KEY object */ - svn_membuf_t *local_key = NULL; - if (key == NULL) - key = &local_key; - else - *key = NULL; + *cfg = NULL; + err = svn_repos__get_config(&stream, &checksum, access, path, must_exist, + scratch_pool); + if (!err) + err = svn_error_quick_wrapf(find_config(cfg, config_pool, stream, + checksum, pool, scratch_pool), + "Error while parsing config file: '%s':", + path); - if (svn_path_is_url(path)) + /* Let the standard implementation handle all the difficult cases. + * Note that for in-repo configs, there are no further special cases to + * check for and deal with. */ + if (!*cfg && !svn_path_is_url(path)) { - /* Read config file from repository. - * Attempt a quick lookup first. */ - SVN_MUTEX__WITH_LOCK(svn_object_pool__mutex(config_pool->object_pool), - key_by_url(key, config_pool, path, pool)); - if (*key) - { - SVN_ERR(svn_object_pool__lookup((void **)cfg, - config_pool->object_pool, - *key, &case_sensitive, pool)); - if (*cfg) - { - svn_pool_destroy(scratch_pool); - return SVN_NO_ERROR; - } - } - - /* Read and cache the configuration. This may fail. */ - err = find_repos_config(cfg, key, config_pool, path, case_sensitive, - preferred_repos, pool, scratch_pool); - if (err || !*cfg) - { - /* let the standard implementation handle all the difficult cases */ - svn_error_clear(err); - err = svn_repos__retrieve_config(cfg, path, must_exist, - case_sensitive, pool); - } - } - else - { - /* Outside of repo file. Read it. */ - svn_stringbuf_t *contents; - err = svn_stringbuf_from_file2(&contents, path, scratch_pool); - if (err) - { - /* let the standard implementation handle all the difficult cases */ - svn_error_clear(err); - err = svn_config_read3(cfg, path, must_exist, case_sensitive, - case_sensitive, pool); - } - else - { - /* parsing and caching will always succeed */ - err = auto_parse(cfg, key, config_pool, contents, case_sensitive, - pool, scratch_pool); - } + svn_error_clear(err); + err = svn_config_read3(cfg, path, must_exist, FALSE, FALSE, pool); } + svn_repos__destroy_config_access(access); svn_pool_destroy(scratch_pool); - return err; + /* we need to duplicate the root structure as it contains temp. buffers */ + if (*cfg) + *cfg = svn_config__shallow_copy(*cfg, pool); + + return svn_error_trace(err); } diff --git a/subversion/libsvn_repos/delta.c b/subversion/libsvn_repos/delta.c index 3e28c70b8d0e..9b1448d91bfd 100644 --- a/subversion/libsvn_repos/delta.c +++ b/subversion/libsvn_repos/delta.c @@ -266,6 +266,13 @@ svn_repos_dir_delta2(svn_fs_root_t *src_root, _("Invalid editor anchoring; at least one of the " "input paths is not a directory and there was no source entry")); + /* Don't report / compare stale revprops. However, revprop changes that + * are made by a 3rd party outside this delta operation, may not be + * detected as per our visibility guarantees. Reset the revprop caches + * for both roots in case they belong to different svn_fs_t instances. */ + SVN_ERR(svn_fs_refresh_revision_props(svn_fs_root_fs(tgt_root), pool)); + SVN_ERR(svn_fs_refresh_revision_props(svn_fs_root_fs(src_root), pool)); + /* Set the global target revision if one can be determined. */ if (svn_fs_is_revision_root(tgt_root)) { @@ -491,8 +498,8 @@ delta_proplists(struct context *c, SVN_ERR(change_fn(c, object, SVN_PROP_ENTRY_COMMITTED_REV, cr_str, subpool)); - SVN_ERR(svn_fs_revision_proplist(&r_props, fs, committed_rev, - pool)); + SVN_ERR(svn_fs_revision_proplist2(&r_props, fs, committed_rev, + FALSE, pool, subpool)); /* Transmit the committed-date. */ committed_date = svn_hash_gets(r_props, SVN_PROP_REVISION_DATE); @@ -596,19 +603,6 @@ send_text_delta(struct context *c, } } -svn_error_t * -svn_repos__compare_files(svn_boolean_t *changed_p, - svn_fs_root_t *root1, - const char *path1, - svn_fs_root_t *root2, - const char *path2, - apr_pool_t *pool) -{ - return svn_error_trace(svn_fs_contents_different(changed_p, root1, path1, - root2, path2, pool)); -} - - /* Make the appropriate edits on FILE_BATON to change its contents and properties from those in SOURCE_PATH to those in TARGET_PATH. */ static svn_error_t * diff --git a/subversion/libsvn_repos/deprecated.c b/subversion/libsvn_repos/deprecated.c index fe9d1d22761f..f502623a20ea 100644 --- a/subversion/libsvn_repos/deprecated.c +++ b/subversion/libsvn_repos/deprecated.c @@ -29,12 +29,17 @@ #include "svn_repos.h" #include "svn_compat.h" #include "svn_hash.h" +#include "svn_path.h" #include "svn_props.h" +#include "svn_pools.h" #include "svn_private_config.h" #include "repos.h" +#include "private/svn_repos_private.h" +#include "private/svn_subr_private.h" + @@ -503,8 +508,71 @@ svn_repos_fs_get_locks(apr_hash_t **locks, authz_read_baton, pool)); } +static svn_error_t * +mergeinfo_receiver(const char *path, + svn_mergeinfo_t mergeinfo, + void *baton, + apr_pool_t *scratch_pool) +{ + svn_mergeinfo_catalog_t catalog = baton; + apr_pool_t *result_pool = apr_hash_pool_get(catalog); + apr_size_t len = strlen(path); + + apr_hash_set(catalog, + apr_pstrmemdup(result_pool, path, len), + len, + svn_mergeinfo_dup(mergeinfo, result_pool)); + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_repos_fs_get_mergeinfo(svn_mergeinfo_catalog_t *mergeinfo, + svn_repos_t *repos, + const apr_array_header_t *paths, + svn_revnum_t rev, + svn_mergeinfo_inheritance_t inherit, + svn_boolean_t include_descendants, + svn_repos_authz_func_t authz_read_func, + void *authz_read_baton, + apr_pool_t *pool) +{ + svn_mergeinfo_catalog_t result_catalog = svn_hash__make(pool); + SVN_ERR(svn_repos_fs_get_mergeinfo2(repos, paths, rev, inherit, + include_descendants, + authz_read_func, authz_read_baton, + mergeinfo_receiver, result_catalog, + pool)); + *mergeinfo = result_catalog; + + return SVN_NO_ERROR; +} /*** From logs.c ***/ +svn_error_t * +svn_repos_get_logs4(svn_repos_t *repos, + const apr_array_header_t *paths, + svn_revnum_t start, + svn_revnum_t end, + int limit, + svn_boolean_t discover_changed_paths, + svn_boolean_t strict_node_history, + svn_boolean_t include_merged_revisions, + const apr_array_header_t *revprops, + svn_repos_authz_func_t authz_read_func, + void *authz_read_baton, + svn_log_entry_receiver_t receiver, + void *receiver_baton, + apr_pool_t *pool) +{ + return svn_repos__get_logs_compat(repos, paths, start, end, limit, + discover_changed_paths, + strict_node_history, + include_merged_revisions, revprops, + authz_read_func, authz_read_baton, + receiver, receiver_baton, pool); +} + svn_error_t * svn_repos_get_logs3(svn_repos_t *repos, const apr_array_header_t *paths, @@ -731,6 +799,34 @@ repos_notify_handler(void *baton, } } +svn_error_t * +svn_repos_dump_fs3(svn_repos_t *repos, + svn_stream_t *stream, + svn_revnum_t start_rev, + svn_revnum_t end_rev, + svn_boolean_t incremental, + svn_boolean_t use_deltas, + svn_repos_notify_func_t notify_func, + void *notify_baton, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *pool) +{ + return svn_error_trace(svn_repos_dump_fs4(repos, + stream, + start_rev, + end_rev, + incremental, + use_deltas, + TRUE, + TRUE, + notify_func, + notify_baton, + NULL, NULL, + cancel_func, + cancel_baton, + pool)); +} svn_error_t * svn_repos_dump_fs2(svn_repos_t *repos, @@ -805,6 +901,31 @@ svn_repos_verify_fs(svn_repos_t *repos, /*** From load.c ***/ +svn_error_t * +svn_repos_load_fs5(svn_repos_t *repos, + svn_stream_t *dumpstream, + svn_revnum_t start_rev, + svn_revnum_t end_rev, + enum svn_repos_load_uuid uuid_action, + const char *parent_dir, + svn_boolean_t use_pre_commit_hook, + svn_boolean_t use_post_commit_hook, + svn_boolean_t validate_props, + svn_boolean_t ignore_dates, + svn_repos_notify_func_t notify_func, + void *notify_baton, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *pool) +{ + return svn_repos_load_fs6(repos, dumpstream, start_rev, end_rev, + uuid_action, parent_dir, + use_post_commit_hook, use_post_commit_hook, + validate_props, ignore_dates, FALSE, + notify_func, notify_baton, + cancel_func, cancel_baton, pool); +} + svn_error_t * svn_repos_load_fs4(svn_repos_t *repos, svn_stream_t *dumpstream, @@ -996,6 +1117,40 @@ svn_repos_load_fs(svn_repos_t *repos, cancel_func, cancel_baton, pool); } +svn_error_t * +svn_repos_get_fs_build_parser5(const svn_repos_parse_fns3_t **parser, + void **parse_baton, + svn_repos_t *repos, + svn_revnum_t start_rev, + svn_revnum_t end_rev, + svn_boolean_t use_history, + svn_boolean_t validate_props, + enum svn_repos_load_uuid uuid_action, + const char *parent_dir, + svn_boolean_t use_pre_commit_hook, + svn_boolean_t use_post_commit_hook, + svn_boolean_t ignore_dates, + svn_repos_notify_func_t notify_func, + void *notify_baton, + apr_pool_t *pool) +{ + SVN_ERR(svn_repos_get_fs_build_parser6(parser, parse_baton, + repos, + start_rev, end_rev, + use_history, + validate_props, + uuid_action, + parent_dir, + use_pre_commit_hook, + use_post_commit_hook, + ignore_dates, + FALSE /* normalize_props */, + notify_func, + notify_baton, + pool)); + return SVN_NO_ERROR; +} + svn_error_t * svn_repos_get_fs_build_parser4(const svn_repos_parse_fns3_t **callbacks, void **parse_baton, @@ -1117,10 +1272,31 @@ svn_repos_fs_begin_txn_for_update(svn_fs_txn_t **txn_p, /*** From authz.c ***/ +svn_error_t * +svn_repos_authz_read2(svn_authz_t **authz_p, + const char *path, + const char *groups_path, + svn_boolean_t must_exist, + apr_pool_t *pool) +{ + apr_pool_t *scratch_pool = svn_pool_create(pool); + svn_error_t *err = svn_repos_authz_read3(authz_p, path, groups_path, + must_exist, NULL, + pool, scratch_pool); + svn_pool_destroy(scratch_pool); + + return svn_error_trace(err); +} + svn_error_t * svn_repos_authz_read(svn_authz_t **authz_p, const char *file, svn_boolean_t must_exist, apr_pool_t *pool) { - return svn_repos__authz_read(authz_p, file, NULL, must_exist, - FALSE, pool); + /* Prevent accidental new features in existing API. */ + if (svn_path_is_url(file)) + return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL, + "'%s' is not a file name", file); + + return svn_error_trace(svn_repos_authz_read2(authz_p, file, NULL, + must_exist, pool)); } diff --git a/subversion/libsvn_repos/dump.c b/subversion/libsvn_repos/dump.c index 189d724cd2de..960bba5816f1 100644 --- a/subversion/libsvn_repos/dump.c +++ b/subversion/libsvn_repos/dump.c @@ -326,7 +326,7 @@ store_delta(apr_file_t **tempfile, svn_filesize_t *len, svn_fs_root_t *newroot, const char *newpath, apr_pool_t *pool) { svn_stream_t *temp_stream; - apr_off_t offset = 0; + apr_off_t offset; svn_txdelta_stream_t *delta_stream; svn_txdelta_window_handler_t wh; void *whb; @@ -346,7 +346,7 @@ store_delta(apr_file_t **tempfile, svn_filesize_t *len, SVN_ERR(svn_txdelta_send_txstream(delta_stream, wh, whb, pool)); /* Get the length of the temporary file and rewind it. */ - SVN_ERR(svn_io_file_seek(*tempfile, APR_CUR, &offset, pool)); + SVN_ERR(svn_io_file_get_offset(&offset, *tempfile, pool)); *len = offset; offset = 0; return svn_io_file_seek(*tempfile, APR_SET, &offset, pool); @@ -1922,50 +1922,90 @@ get_dump_editor(const svn_delta_editor_t **editor, /* Helper for svn_repos_dump_fs. - Write a revision record of REV in FS to writable STREAM, using POOL. + Write a revision record of REV in REPOS to writable STREAM, using POOL. + Dump revision properties as well if INCLUDE_REVPROPS has been set. + AUTHZ_FUNC and AUTHZ_BATON are passed directly to the repos layer. */ static svn_error_t * write_revision_record(svn_stream_t *stream, - svn_fs_t *fs, + svn_repos_t *repos, svn_revnum_t rev, + svn_boolean_t include_revprops, + svn_repos_authz_func_t authz_func, + void *authz_baton, apr_pool_t *pool) { apr_hash_t *props; apr_time_t timetemp; svn_string_t *datevalue; - SVN_ERR(svn_fs_revision_proplist(&props, fs, rev, pool)); - - /* Run revision date properties through the time conversion to - canonicalize them. */ - /* ### Remove this when it is no longer needed for sure. */ - datevalue = svn_hash_gets(props, SVN_PROP_REVISION_DATE); - if (datevalue) + if (include_revprops) { - SVN_ERR(svn_time_from_cstring(&timetemp, datevalue->data, pool)); - datevalue = svn_string_create(svn_time_to_cstring(timetemp, pool), - pool); - svn_hash_sets(props, SVN_PROP_REVISION_DATE, datevalue); + SVN_ERR(svn_repos_fs_revision_proplist(&props, repos, rev, + authz_func, authz_baton, pool)); + + /* Run revision date properties through the time conversion to + canonicalize them. */ + /* ### Remove this when it is no longer needed for sure. */ + datevalue = svn_hash_gets(props, SVN_PROP_REVISION_DATE); + if (datevalue) + { + SVN_ERR(svn_time_from_cstring(&timetemp, datevalue->data, pool)); + datevalue = svn_string_create(svn_time_to_cstring(timetemp, pool), + pool); + svn_hash_sets(props, SVN_PROP_REVISION_DATE, datevalue); + } + } + else + { + /* Although we won't use it, we still need this container for the + call below. */ + props = apr_hash_make(pool); } SVN_ERR(svn_repos__dump_revision_record(stream, rev, NULL, props, - TRUE /*props_section_always*/, + include_revprops, pool)); return SVN_NO_ERROR; } +/* Baton for dump_filter_authz_func(). */ +typedef struct dump_filter_baton_t +{ + svn_repos_dump_filter_func_t filter_func; + void *filter_baton; +} dump_filter_baton_t; + +/* Implements svn_repos_authz_func_t. */ +static svn_error_t * +dump_filter_authz_func(svn_boolean_t *allowed, + svn_fs_root_t *root, + const char *path, + void *baton, + apr_pool_t *pool) +{ + dump_filter_baton_t *b = baton; + + return svn_error_trace(b->filter_func(allowed, root, path, b->filter_baton, + pool)); +} + /* The main dumper. */ svn_error_t * -svn_repos_dump_fs3(svn_repos_t *repos, +svn_repos_dump_fs4(svn_repos_t *repos, svn_stream_t *stream, svn_revnum_t start_rev, svn_revnum_t end_rev, svn_boolean_t incremental, svn_boolean_t use_deltas, + svn_boolean_t include_revprops, + svn_boolean_t include_changes, svn_repos_notify_func_t notify_func, void *notify_baton, + svn_repos_dump_filter_func_t filter_func, + void *filter_baton, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *pool) @@ -1974,13 +2014,19 @@ svn_repos_dump_fs3(svn_repos_t *repos, void *dump_edit_baton = NULL; svn_revnum_t rev; svn_fs_t *fs = svn_repos_fs(repos); - apr_pool_t *subpool = svn_pool_create(pool); + apr_pool_t *iterpool = svn_pool_create(pool); svn_revnum_t youngest; const char *uuid; int version; svn_boolean_t found_old_reference = FALSE; svn_boolean_t found_old_mergeinfo = FALSE; svn_repos_notify_t *notify; + svn_repos_authz_func_t authz_func; + dump_filter_baton_t authz_baton = {0}; + + /* Make sure we catch up on the latest revprop changes. This is the only + * time we will refresh the revprop data in this query. */ + SVN_ERR(svn_fs_refresh_revision_props(fs, pool)); /* Determine the current youngest revision of the filesystem. */ SVN_ERR(svn_fs_youngest_rev(&youngest, fs, pool)); @@ -2005,6 +2051,20 @@ svn_repos_dump_fs3(svn_repos_t *repos, "(youngest revision is %ld)"), end_rev, youngest); + /* We use read authz callback to implement dump filtering. If there is no + * read access for some node, it will be excluded from dump as well as + * references to it (e.g. copy source). */ + if (filter_func) + { + authz_func = dump_filter_authz_func; + authz_baton.filter_func = filter_func; + authz_baton.filter_baton = filter_baton; + } + else + { + authz_func = NULL; + } + /* Write out the UUID. */ SVN_ERR(svn_fs_get_uuid(fs, &uuid, pool)); @@ -2033,18 +2093,20 @@ svn_repos_dump_fs3(svn_repos_t *repos, svn_fs_root_t *to_root; svn_boolean_t use_deltas_for_rev; - svn_pool_clear(subpool); + svn_pool_clear(iterpool); /* Check for cancellation. */ if (cancel_func) SVN_ERR(cancel_func(cancel_baton)); /* Write the revision record. */ - SVN_ERR(write_revision_record(stream, fs, rev, subpool)); + SVN_ERR(write_revision_record(stream, repos, rev, include_revprops, + authz_func, &authz_baton, iterpool)); /* When dumping revision 0, we just write out the revision record. - The parser might want to use its properties. */ - if (rev == 0) + The parser might want to use its properties. + If we don't want revision changes at all, skip in any case. */ + if (rev == 0 || !include_changes) goto loop_end; /* Fetch the editor which dumps nodes to a file. Regardless of @@ -2056,10 +2118,10 @@ svn_repos_dump_fs3(svn_repos_t *repos, &found_old_mergeinfo, NULL, notify_func, notify_baton, start_rev, use_deltas_for_rev, FALSE, FALSE, - subpool)); + iterpool)); /* Drive the editor in one way or another. */ - SVN_ERR(svn_fs_revision_root(&to_root, fs, rev, subpool)); + SVN_ERR(svn_fs_revision_root(&to_root, fs, rev, iterpool)); /* If this is the first revision of a non-incremental dump, we're in for a full tree dump. Otherwise, we want to simply @@ -2068,35 +2130,34 @@ svn_repos_dump_fs3(svn_repos_t *repos, { /* Compare against revision 0, so everything appears to be added. */ svn_fs_root_t *from_root; - SVN_ERR(svn_fs_revision_root(&from_root, fs, 0, subpool)); + SVN_ERR(svn_fs_revision_root(&from_root, fs, 0, iterpool)); SVN_ERR(svn_repos_dir_delta2(from_root, "", "", to_root, "", dump_editor, dump_edit_baton, - NULL, - NULL, + authz_func, &authz_baton, FALSE, /* don't send text-deltas */ svn_depth_infinity, FALSE, /* don't send entry props */ FALSE, /* don't ignore ancestry */ - subpool)); + iterpool)); } else { /* The normal case: compare consecutive revs. */ SVN_ERR(svn_repos_replay2(to_root, "", SVN_INVALID_REVNUM, FALSE, dump_editor, dump_edit_baton, - NULL, NULL, subpool)); + authz_func, &authz_baton, iterpool)); /* While our editor close_edit implementation is a no-op, we still do this for completeness. */ - SVN_ERR(dump_editor->close_edit(dump_edit_baton, subpool)); + SVN_ERR(dump_editor->close_edit(dump_edit_baton, iterpool)); } loop_end: if (notify_func) { notify->revision = rev; - notify_func(notify_baton, notify, subpool); + notify_func(notify_baton, notify, iterpool); } } @@ -2107,12 +2168,12 @@ svn_repos_dump_fs3(svn_repos_t *repos, warning, since the inline warnings already issued might easily be missed. */ - notify = svn_repos_notify_create(svn_repos_notify_dump_end, subpool); - notify_func(notify_baton, notify, subpool); + notify = svn_repos_notify_create(svn_repos_notify_dump_end, iterpool); + notify_func(notify_baton, notify, iterpool); if (found_old_reference) { - notify_warning(subpool, notify_func, notify_baton, + notify_warning(iterpool, notify_func, notify_baton, svn_repos_notify_warning_found_old_reference, _("The range of revisions dumped " "contained references to " @@ -2124,7 +2185,7 @@ svn_repos_dump_fs3(svn_repos_t *repos, in dumped mergeinfo. */ if (found_old_mergeinfo) { - notify_warning(subpool, notify_func, notify_baton, + notify_warning(iterpool, notify_func, notify_baton, svn_repos_notify_warning_found_old_mergeinfo, _("The range of revisions dumped " "contained mergeinfo " @@ -2133,7 +2194,7 @@ svn_repos_dump_fs3(svn_repos_t *repos, } } - svn_pool_destroy(subpool); + svn_pool_destroy(iterpool); return SVN_NO_ERROR; } @@ -2314,7 +2375,8 @@ verify_one_revision(svn_fs_t *fs, do this for completeness. */ SVN_ERR(cancel_editor->close_edit(cancel_edit_baton, scratch_pool)); - SVN_ERR(svn_fs_revision_proplist(&props, fs, rev, scratch_pool)); + SVN_ERR(svn_fs_revision_proplist2(&props, fs, rev, FALSE, scratch_pool, + scratch_pool)); return SVN_NO_ERROR; } @@ -2394,6 +2456,10 @@ svn_repos_verify_fs3(svn_repos_t *repos, struct verify_fs_notify_func_baton_t *verify_notify_baton = NULL; svn_error_t *err; + /* Make sure we catch up on the latest revprop changes. This is the only + * time we will refresh the revprop data in this query. */ + SVN_ERR(svn_fs_refresh_revision_props(fs, pool)); + /* Determine the current youngest revision of the filesystem. */ SVN_ERR(svn_fs_youngest_rev(&youngest, fs, pool)); diff --git a/subversion/libsvn_repos/fs-wrap.c b/subversion/libsvn_repos/fs-wrap.c index b46cda650fc2..f895d5aa0c22 100644 --- a/subversion/libsvn_repos/fs-wrap.c +++ b/subversion/libsvn_repos/fs-wrap.c @@ -33,6 +33,7 @@ #include "svn_repos.h" #include "svn_time.h" #include "svn_sorts.h" +#include "svn_subst.h" #include "repos.h" #include "svn_private_config.h" #include "private/svn_repos_private.h" @@ -58,6 +59,8 @@ svn_repos_fs_commit_txn(const char **conflict_p, apr_hash_t *hooks_env; *new_rev = SVN_INVALID_REVNUM; + if (conflict_p) + *conflict_p = NULL; /* Parse the hooks-env file (if any). */ SVN_ERR(svn_repos__parse_hooks_env(&hooks_env, repos->hooks_env_path, @@ -233,10 +236,13 @@ svn_repos__validate_prop(const char *name, * carriage return characters ('\r'). */ if (strchr(value->data, '\r') != NULL) { - return svn_error_createf - (SVN_ERR_BAD_PROPERTY_VALUE, NULL, + svn_error_t *err = svn_error_createf + (SVN_ERR_BAD_PROPERTY_VALUE_EOL, NULL, _("Cannot accept non-LF line endings in '%s' property"), name); + + return svn_error_create(SVN_ERR_BAD_PROPERTY_VALUE, err, + _("Invalid property value")); } } @@ -257,6 +263,34 @@ svn_repos__validate_prop(const char *name, } +svn_error_t * +svn_repos__normalize_prop(const svn_string_t **result_p, + svn_boolean_t *normalized_p, + const char *name, + const svn_string_t *value, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + if (svn_prop_needs_translation(name) && value) + { + svn_string_t *new_value; + + SVN_ERR(svn_subst_translate_string2(&new_value, NULL, normalized_p, + value, "UTF-8", TRUE, + result_pool, scratch_pool)); + *result_p = new_value; + } + else + { + *result_p = svn_string_dup(value, result_pool); + if (normalized_p) + *normalized_p = FALSE; + } + + return SVN_NO_ERROR; +} + + /* Verify the mergeinfo property value VALUE and return an error if it * is invalid. The PATH on which that property is set is used for error * messages only. Use SCRATCH_POOL for temporary allocations. */ @@ -378,7 +412,8 @@ svn_repos_fs_change_rev_prop4(svn_repos_t *repos, * to the hooks to be accurate. */ svn_string_t *old_value2; - SVN_ERR(svn_fs_revision_prop(&old_value2, repos->fs, rev, name, pool)); + SVN_ERR(svn_fs_revision_prop2(&old_value2, repos->fs, rev, name, + TRUE, pool, pool)); old_value = old_value2; } @@ -448,12 +483,13 @@ svn_repos_fs_revision_prop(svn_string_t **value_p, *value_p = NULL; else - SVN_ERR(svn_fs_revision_prop(value_p, repos->fs, - rev, propname, pool)); + SVN_ERR(svn_fs_revision_prop2(value_p, repos->fs, + rev, propname, TRUE, pool, pool)); } else /* wholly readable revision */ { - SVN_ERR(svn_fs_revision_prop(value_p, repos->fs, rev, propname, pool)); + SVN_ERR(svn_fs_revision_prop2(value_p, repos->fs, rev, propname, TRUE, + pool, pool)); } return SVN_NO_ERROR; @@ -486,7 +522,8 @@ svn_repos_fs_revision_proplist(apr_hash_t **table_p, svn_string_t *value; /* Produce two property hashtables, both in POOL. */ - SVN_ERR(svn_fs_revision_proplist(&tmphash, repos->fs, rev, pool)); + SVN_ERR(svn_fs_revision_proplist2(&tmphash, repos->fs, rev, TRUE, + pool, pool)); *table_p = apr_hash_make(pool); /* If they exist, we only copy svn:author and svn:date into the @@ -501,7 +538,8 @@ svn_repos_fs_revision_proplist(apr_hash_t **table_p, } else /* wholly readable revision */ { - SVN_ERR(svn_fs_revision_proplist(table_p, repos->fs, rev, pool)); + SVN_ERR(svn_fs_revision_proplist2(table_p, repos->fs, rev, TRUE, + pool, pool)); } return SVN_NO_ERROR; @@ -895,25 +933,26 @@ svn_repos_fs_get_locks2(apr_hash_t **locks, svn_error_t * -svn_repos_fs_get_mergeinfo(svn_mergeinfo_catalog_t *mergeinfo, - svn_repos_t *repos, - const apr_array_header_t *paths, - svn_revnum_t rev, - svn_mergeinfo_inheritance_t inherit, - svn_boolean_t include_descendants, - svn_repos_authz_func_t authz_read_func, - void *authz_read_baton, - apr_pool_t *pool) +svn_repos_fs_get_mergeinfo2(svn_repos_t *repos, + const apr_array_header_t *paths, + svn_revnum_t rev, + svn_mergeinfo_inheritance_t inherit, + svn_boolean_t include_descendants, + svn_repos_authz_func_t authz_read_func, + void *authz_read_baton, + svn_repos_mergeinfo_receiver_t receiver, + void *receiver_baton, + apr_pool_t *scratch_pool) { /* Here we cast away 'const', but won't try to write through this pointer * without first allocating a new array. */ apr_array_header_t *readable_paths = (apr_array_header_t *) paths; svn_fs_root_t *root; - apr_pool_t *iterpool = svn_pool_create(pool); + apr_pool_t *iterpool = svn_pool_create(scratch_pool); if (!SVN_IS_VALID_REVNUM(rev)) - SVN_ERR(svn_fs_youngest_rev(&rev, repos->fs, pool)); - SVN_ERR(svn_fs_revision_root(&root, repos->fs, rev, pool)); + SVN_ERR(svn_fs_youngest_rev(&rev, repos->fs, scratch_pool)); + SVN_ERR(svn_fs_revision_root(&root, repos->fs, rev, scratch_pool)); /* Filter out unreadable paths before divining merge tracking info. */ if (authz_read_func) @@ -934,7 +973,7 @@ svn_repos_fs_get_mergeinfo(svn_mergeinfo_catalog_t *mergeinfo, /* Requested paths differ from readable paths. Fork list of readable paths from requested paths. */ int j; - readable_paths = apr_array_make(pool, paths->nelts - 1, + readable_paths = apr_array_make(scratch_pool, paths->nelts - 1, sizeof(char *)); for (j = 0; j < i; j++) { @@ -951,10 +990,10 @@ svn_repos_fs_get_mergeinfo(svn_mergeinfo_catalog_t *mergeinfo, the change itself. */ /* ### TODO(reint): ... but how about descendant merged-to paths? */ if (readable_paths->nelts > 0) - SVN_ERR(svn_fs_get_mergeinfo2(mergeinfo, root, readable_paths, inherit, - include_descendants, TRUE, pool, pool)); - else - *mergeinfo = apr_hash_make(pool); + SVN_ERR(svn_fs_get_mergeinfo3(root, readable_paths, inherit, + include_descendants, TRUE, + receiver, receiver_baton, + scratch_pool)); svn_pool_destroy(iterpool); return SVN_NO_ERROR; @@ -975,15 +1014,18 @@ pack_notify_func(void *baton, { struct pack_notify_baton *pnb = baton; svn_repos_notify_t *notify; + svn_repos_notify_action_t repos_action; /* Simple conversion works for these values. */ SVN_ERR_ASSERT(pack_action >= svn_fs_pack_notify_start - && pack_action <= svn_fs_pack_notify_end_revprop); + && pack_action <= svn_fs_pack_notify_noop); - notify = svn_repos_notify_create(pack_action - + svn_repos_notify_pack_shard_start - - svn_fs_pack_notify_start, - pool); + repos_action = pack_action == svn_fs_pack_notify_noop + ? svn_repos_notify_pack_noop + : pack_action + svn_repos_notify_pack_shard_start + - svn_fs_pack_notify_start; + + notify = svn_repos_notify_create(repos_action, pool); notify->shard = shard; pnb->notify_func(pnb->notify_baton, notify, pool); diff --git a/subversion/libsvn_repos/hooks.c b/subversion/libsvn_repos/hooks.c index a4cc2491416f..8d17a82c31bd 100644 --- a/subversion/libsvn_repos/hooks.c +++ b/subversion/libsvn_repos/hooks.c @@ -476,11 +476,8 @@ svn_repos__hooks_start_commit(svn_repos_t *repos, if (capabilities) { - capabilities_string = svn_cstring_join(capabilities, ":", pool); - - /* Get rid of that annoying final colon. */ - if (capabilities_string[0]) - capabilities_string[strlen(capabilities_string) - 1] = '\0'; + capabilities_string = svn_cstring_join2(capabilities, ":", + FALSE, pool); } else { @@ -799,8 +796,8 @@ svn_repos__hooks_post_lock(svn_repos_t *repos, { const char *args[5]; apr_file_t *stdin_handle = NULL; - svn_string_t *paths_str = svn_string_create(svn_cstring_join - (paths, "\n", pool), + svn_string_t *paths_str = svn_string_create(svn_cstring_join2 + (paths, "\n", TRUE, pool), pool); SVN_ERR(create_temp_file(&stdin_handle, paths_str, pool)); @@ -875,8 +872,8 @@ svn_repos__hooks_post_unlock(svn_repos_t *repos, { const char *args[5]; apr_file_t *stdin_handle = NULL; - svn_string_t *paths_str = svn_string_create(svn_cstring_join - (paths, "\n", pool), + svn_string_t *paths_str = svn_string_create(svn_cstring_join2 + (paths, "\n", TRUE, pool), pool); SVN_ERR(create_temp_file(&stdin_handle, paths_str, pool)); diff --git a/subversion/libsvn_repos/list.c b/subversion/libsvn_repos/list.c new file mode 100644 index 000000000000..ef8ac32b1b38 --- /dev/null +++ b/subversion/libsvn_repos/list.c @@ -0,0 +1,340 @@ +/* list.c : listing repository contents + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#include +#include + +#include "svn_pools.h" +#include "svn_error.h" +#include "svn_dirent_uri.h" +#include "svn_time.h" + +#include "private/svn_repos_private.h" +#include "private/svn_sorts_private.h" +#include "private/svn_utf_private.h" +#include "svn_private_config.h" /* for SVN_TEMPLATE_ROOT_DIR */ + +#include "repos.h" + + + +/* Utility function. Given DIRENT->KIND, set all other elements of *DIRENT + * with the values retrieved for PATH under ROOT. Allocate them in POOL. + */ +static svn_error_t * +fill_dirent(svn_dirent_t *dirent, + svn_fs_root_t *root, + const char *path, + apr_pool_t *scratch_pool) +{ + const char *datestring; + + if (dirent->kind == svn_node_file) + SVN_ERR(svn_fs_file_length(&(dirent->size), root, path, scratch_pool)); + else + dirent->size = SVN_INVALID_FILESIZE; + + SVN_ERR(svn_fs_node_has_props(&dirent->has_props, root, path, + scratch_pool)); + + SVN_ERR(svn_repos_get_committed_info(&(dirent->created_rev), + &datestring, + &(dirent->last_author), + root, path, scratch_pool)); + if (datestring) + SVN_ERR(svn_time_from_cstring(&(dirent->time), datestring, + scratch_pool)); + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_repos_stat(svn_dirent_t **dirent, + svn_fs_root_t *root, + const char *path, + apr_pool_t *pool) +{ + svn_node_kind_t kind; + svn_dirent_t *ent; + + SVN_ERR(svn_fs_check_path(&kind, root, path, pool)); + + if (kind == svn_node_none) + { + *dirent = NULL; + return SVN_NO_ERROR; + } + + ent = svn_dirent_create(pool); + ent->kind = kind; + + SVN_ERR(fill_dirent(ent, root, path, pool)); + + *dirent = ent; + return SVN_NO_ERROR; +} + +/* Return TRUE of DIRNAME matches any of the const char * in PATTERNS. + * Note that any DIRNAME will match if PATTERNS is empty. + * Use SCRATCH_BUFFER for temporary string contents. */ +static svn_boolean_t +matches_any(const char *dirname, + const apr_array_header_t *patterns, + svn_membuf_t *scratch_buffer) +{ + return patterns + ? svn_utf__fuzzy_glob_match(dirname, patterns, scratch_buffer) + : TRUE; +} + +/* Utility to prevent code duplication. + * + * Construct a svn_dirent_t for PATH of type KIND under ROOT and, if + * PATH_INFO_ONLY is not set, fill it. Call RECEIVER with the result + * and RECEIVER_BATON. + * + * Use SCRATCH_POOL for temporary allocations. + */ +static svn_error_t * +report_dirent(svn_fs_root_t *root, + const char *path, + svn_node_kind_t kind, + svn_boolean_t path_info_only, + svn_repos_dirent_receiver_t receiver, + void *receiver_baton, + apr_pool_t *scratch_pool) +{ + svn_dirent_t dirent = { 0 }; + + /* Fetch the details to report - if required. */ + dirent.kind = kind; + if (!path_info_only) + SVN_ERR(fill_dirent(&dirent, root, path, scratch_pool)); + + /* Report the entry. */ + SVN_ERR(receiver(path, &dirent, receiver_baton, scratch_pool)); + + return SVN_NO_ERROR; +} + +/* Utility data struct, used to attach a filter result flag to a dirent. */ +typedef struct filtered_dirent_t +{ + /* Actual dirent, never NULL. */ + svn_fs_dirent_t *dirent; + + /* DIRENT passed the filter. */ + svn_boolean_t is_match; +} filtered_dirent_t; + +/* Implement a standard sort function for filtered_dirent_t *, sorting them + * by entry name. */ +static int +compare_filtered_dirent(const void *lhs, + const void *rhs) +{ + const filtered_dirent_t *lhs_dirent = (const filtered_dirent_t *)lhs; + const filtered_dirent_t *rhs_dirent = (const filtered_dirent_t *)rhs; + + return strcmp(lhs_dirent->dirent->name, rhs_dirent->dirent->name); +} + +/* Core of svn_repos_list with the same parameter list. + * + * However, DEPTH is not svn_depth_empty and PATH has already been reported. + * Therefore, we can call this recursively. + * + * Uses SCRATCH_BUFFER for temporary string contents. + */ +static svn_error_t * +do_list(svn_fs_root_t *root, + const char *path, + const apr_array_header_t *patterns, + svn_depth_t depth, + svn_boolean_t path_info_only, + svn_repos_authz_func_t authz_read_func, + void *authz_read_baton, + svn_repos_dirent_receiver_t receiver, + void *receiver_baton, + svn_cancel_func_t cancel_func, + void *cancel_baton, + svn_membuf_t *scratch_buffer, + apr_pool_t *scratch_pool) +{ + apr_hash_t *entries; + apr_pool_t *iterpool = svn_pool_create(scratch_pool); + apr_hash_index_t *hi; + apr_array_header_t *sorted; + int i; + + /* Fetch all directory entries, filter and sort them. + * + * Performance trade-off: + * Constructing a full path vs. faster sort due to authz filtering. + * We filter according to DEPTH and PATTERNS only because constructing + * the full path required for authz is somewhat expensive and we don't + * want to do this twice while authz will rarely filter paths out. + */ + SVN_ERR(svn_fs_dir_entries(&entries, root, path, scratch_pool)); + sorted = apr_array_make(scratch_pool, apr_hash_count(entries), + sizeof(filtered_dirent_t)); + for (hi = apr_hash_first(scratch_pool, entries); hi; hi = apr_hash_next(hi)) + { + filtered_dirent_t filtered; + svn_pool_clear(iterpool); + + filtered.dirent = apr_hash_this_val(hi); + + /* Skip directories if we want to report files only. */ + if (filtered.dirent->kind == svn_node_dir && depth == svn_depth_files) + continue; + + /* We can skip files that don't match any of the search patterns. */ + filtered.is_match = matches_any(filtered.dirent->name, patterns, + scratch_buffer); + if (!filtered.is_match && filtered.dirent->kind == svn_node_file) + continue; + + APR_ARRAY_PUSH(sorted, filtered_dirent_t) = filtered; + } + + svn_sort__array(sorted, compare_filtered_dirent); + + /* Iterate over all remaining directory entries and report them. + * Recurse into sub-directories if requested. */ + for (i = 0; i < sorted->nelts; ++i) + { + const char *sub_path; + filtered_dirent_t *filtered; + svn_fs_dirent_t *dirent; + + svn_pool_clear(iterpool); + + filtered = &APR_ARRAY_IDX(sorted, i, filtered_dirent_t); + dirent = filtered->dirent; + + /* Skip paths that we don't have access to? */ + sub_path = svn_dirent_join(path, dirent->name, iterpool); + if (authz_read_func) + { + svn_boolean_t has_access; + SVN_ERR(authz_read_func(&has_access, root, sub_path, + authz_read_baton, iterpool)); + if (!has_access) + continue; + } + + /* Report entry, if it passed the filter. */ + if (filtered->is_match) + SVN_ERR(report_dirent(root, sub_path, dirent->kind, path_info_only, + receiver, receiver_baton, iterpool)); + + /* Check for cancellation before recursing down. This should be + * slightly more responsive for deep trees. */ + if (cancel_func) + SVN_ERR(cancel_func(cancel_baton)); + + /* Recurse on directories. */ + if (depth == svn_depth_infinity && dirent->kind == svn_node_dir) + SVN_ERR(do_list(root, sub_path, patterns, svn_depth_infinity, + path_info_only, authz_read_func, authz_read_baton, + receiver, receiver_baton, cancel_func, + cancel_baton, scratch_buffer, iterpool)); + } + + svn_pool_destroy(iterpool); + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_repos_list(svn_fs_root_t *root, + const char *path, + const apr_array_header_t *patterns, + svn_depth_t depth, + svn_boolean_t path_info_only, + svn_repos_authz_func_t authz_read_func, + void *authz_read_baton, + svn_repos_dirent_receiver_t receiver, + void *receiver_baton, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *scratch_pool) +{ + svn_membuf_t scratch_buffer; + + /* Parameter check. */ + svn_node_kind_t kind; + if (depth < svn_depth_empty) + return svn_error_createf(SVN_ERR_REPOS_BAD_ARGS, NULL, + "Invalid depth '%d' in svn_repos_list", depth); + + /* Do we have access this sub-tree? */ + if (authz_read_func) + { + svn_boolean_t has_access; + SVN_ERR(authz_read_func(&has_access, root, path, authz_read_baton, + scratch_pool)); + if (!has_access) + return SVN_NO_ERROR; + } + + /* Does the sub-tree even exist? + * + * Note that we must do this after the authz check to not indirectly + * confirm the existence of PATH. */ + SVN_ERR(svn_fs_check_path(&kind, root, path, scratch_pool)); + if (kind == svn_node_file) + { + /* There is no recursion on files. */ + depth = svn_depth_empty; + } + else if (kind != svn_node_dir) + { + return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL, + _("Path '%s' not found"), path); + } + + /* Special case: Empty pattern list. + * We don't want the server to waste time here. */ + if (patterns && patterns->nelts == 0) + return SVN_NO_ERROR; + + /* We need a scratch buffer for temporary string data. + * Create one with a reasonable initial size. */ + svn_membuf__create(&scratch_buffer, 256, scratch_pool); + + /* Actually report PATH, if it passes the filters. */ + if (matches_any(svn_dirent_dirname(path, scratch_pool), patterns, + &scratch_buffer)) + SVN_ERR(report_dirent(root, path, kind, path_info_only, + receiver, receiver_baton, scratch_pool)); + + /* Report directory contents if requested. */ + if (depth > svn_depth_empty) + SVN_ERR(do_list(root, path, patterns, depth, + path_info_only, authz_read_func, authz_read_baton, + receiver, receiver_baton, cancel_func, cancel_baton, + &scratch_buffer, scratch_pool)); + + return SVN_NO_ERROR; +} diff --git a/subversion/libsvn_repos/load-fs-vtable.c b/subversion/libsvn_repos/load-fs-vtable.c index ca3a5cd34d17..f6c6bf660b12 100644 --- a/subversion/libsvn_repos/load-fs-vtable.c +++ b/subversion/libsvn_repos/load-fs-vtable.c @@ -55,6 +55,7 @@ struct parse_baton svn_boolean_t use_history; svn_boolean_t validate_props; svn_boolean_t ignore_dates; + svn_boolean_t normalize_props; svn_boolean_t use_pre_commit_hook; svn_boolean_t use_post_commit_hook; enum svn_repos_load_uuid uuid_action; @@ -163,8 +164,12 @@ change_rev_prop(svn_repos_t *repos, const char *name, const svn_string_t *value, svn_boolean_t validate_props, + svn_boolean_t normalize_props, apr_pool_t *pool) { + if (normalize_props) + SVN_ERR(svn_repos__normalize_prop(&value, NULL, name, value, pool, pool)); + if (validate_props) return svn_repos_fs_change_rev_prop4(repos, revision, NULL, name, NULL, value, FALSE, FALSE, @@ -623,14 +628,6 @@ maybe_add_with_history(struct node_baton *nb, return SVN_NO_ERROR; } -static svn_error_t * -magic_header_record(int version, - void *parse_baton, - apr_pool_t *pool) -{ - return SVN_NO_ERROR; -} - static svn_error_t * uuid_record(const char *uuid, void *parse_baton, @@ -1022,7 +1019,8 @@ close_revision(void *baton) apr_array_header_t *diff; int i; - SVN_ERR(svn_fs_revision_proplist(&orig_props, pb->fs, 0, rb->pool)); + SVN_ERR(svn_fs_revision_proplist2(&orig_props, pb->fs, 0, TRUE, + rb->pool, rb->pool)); new_props = svn_prop_array_to_hash(rb->revprops, rb->pool); SVN_ERR(svn_prop_diffs(&diff, new_props, orig_props, rb->pool)); @@ -1031,7 +1029,8 @@ close_revision(void *baton) const svn_prop_t *prop = &APR_ARRAY_IDX(diff, i, svn_prop_t); SVN_ERR(change_rev_prop(pb->repos, 0, prop->name, prop->value, - pb->validate_props, rb->pool)); + pb->validate_props, pb->normalize_props, + rb->pool)); } } @@ -1049,6 +1048,23 @@ close_revision(void *baton) prop->value = NULL; } + if (rb->pb->normalize_props) + { + apr_pool_t *iterpool; + int i; + + iterpool = svn_pool_create(rb->pool); + for (i = 0; i < rb->revprops->nelts; i++) + { + svn_prop_t *prop = &APR_ARRAY_IDX(rb->revprops, i, svn_prop_t); + + svn_pool_clear(iterpool); + SVN_ERR(svn_repos__normalize_prop(&prop->value, NULL, prop->name, + prop->value, rb->pool, iterpool)); + } + svn_pool_destroy(iterpool); + } + /* Apply revision property changes. */ if (rb->pb->validate_props) SVN_ERR(svn_repos_fs_change_txn_props(rb->txn, rb->revprops, rb->pool)); @@ -1165,7 +1181,7 @@ close_revision(void *baton) svn_error_t * -svn_repos_get_fs_build_parser5(const svn_repos_parse_fns3_t **callbacks, +svn_repos_get_fs_build_parser6(const svn_repos_parse_fns3_t **callbacks, void **parse_baton, svn_repos_t *repos, svn_revnum_t start_rev, @@ -1177,6 +1193,7 @@ svn_repos_get_fs_build_parser5(const svn_repos_parse_fns3_t **callbacks, svn_boolean_t use_pre_commit_hook, svn_boolean_t use_post_commit_hook, svn_boolean_t ignore_dates, + svn_boolean_t normalize_props, svn_repos_notify_func_t notify_func, void *notify_baton, apr_pool_t *pool) @@ -1194,7 +1211,7 @@ svn_repos_get_fs_build_parser5(const svn_repos_parse_fns3_t **callbacks, if (SVN_IS_VALID_REVNUM(start_rev)) SVN_ERR_ASSERT(start_rev <= end_rev); - parser->magic_header_record = magic_header_record; + parser->magic_header_record = NULL; parser->uuid_record = uuid_record; parser->new_revision_record = new_revision_record; parser->new_node_record = new_node_record; @@ -1225,6 +1242,7 @@ svn_repos_get_fs_build_parser5(const svn_repos_parse_fns3_t **callbacks, pb->use_pre_commit_hook = use_pre_commit_hook; pb->use_post_commit_hook = use_post_commit_hook; pb->ignore_dates = ignore_dates; + pb->normalize_props = normalize_props; *callbacks = parser; *parse_baton = pb; @@ -1233,7 +1251,7 @@ svn_repos_get_fs_build_parser5(const svn_repos_parse_fns3_t **callbacks, svn_error_t * -svn_repos_load_fs5(svn_repos_t *repos, +svn_repos_load_fs6(svn_repos_t *repos, svn_stream_t *dumpstream, svn_revnum_t start_rev, svn_revnum_t end_rev, @@ -1243,6 +1261,7 @@ svn_repos_load_fs5(svn_repos_t *repos, svn_boolean_t use_post_commit_hook, svn_boolean_t validate_props, svn_boolean_t ignore_dates, + svn_boolean_t normalize_props, svn_repos_notify_func_t notify_func, void *notify_baton, svn_cancel_func_t cancel_func, @@ -1254,7 +1273,7 @@ svn_repos_load_fs5(svn_repos_t *repos, /* This is really simple. */ - SVN_ERR(svn_repos_get_fs_build_parser5(&parser, &parse_baton, + SVN_ERR(svn_repos_get_fs_build_parser6(&parser, &parse_baton, repos, start_rev, end_rev, TRUE, /* look for copyfrom revs */ @@ -1264,6 +1283,7 @@ svn_repos_load_fs5(svn_repos_t *repos, use_pre_commit_hook, use_post_commit_hook, ignore_dates, + normalize_props, notify_func, notify_baton, pool)); @@ -1271,3 +1291,226 @@ svn_repos_load_fs5(svn_repos_t *repos, return svn_repos_parse_dumpstream3(dumpstream, parser, parse_baton, FALSE, cancel_func, cancel_baton, pool); } + +/*----------------------------------------------------------------------*/ + +/** The same functionality for revprops only **/ + +/* Implement svn_repos_parse_fns3_t.new_revision_record. + * + * Because the revision is supposed to already exist, we don't need to + * start transactions etc. */ +static svn_error_t * +revprops_new_revision_record(void **revision_baton, + apr_hash_t *headers, + void *parse_baton, + apr_pool_t *pool) +{ + struct parse_baton *pb = parse_baton; + struct revision_baton *rb; + + rb = make_revision_baton(headers, pb, pool); + + /* If we're skipping this revision, try to notify someone. */ + if (rb->skipped && pb->notify_func) + { + /* ### TODO: Use proper scratch pool instead of pb->notify_pool */ + svn_repos_notify_t *notify = svn_repos_notify_create( + svn_repos_notify_load_skipped_rev, + pb->notify_pool); + + notify->old_revision = rb->rev; + pb->notify_func(pb->notify_baton, notify, pb->notify_pool); + svn_pool_clear(pb->notify_pool); + } + + /* If we're parsing revision 0, only the revision props are (possibly) + interesting to us: when loading the stream into an empty + filesystem, then we want new filesystem's revision 0 to have the + same props. Otherwise, we just ignore revision 0 in the stream. */ + + *revision_baton = rb; + return SVN_NO_ERROR; +} + +/* Implement svn_repos_parse_fns3_t.close_revision. + * + * Simply set the revprops we previously parsed and send notifications. + * This is the place where we will detect missing revisions. */ +static svn_error_t * +revprops_close_revision(void *baton) +{ + struct revision_baton *rb = baton; + struct parse_baton *pb = rb->pb; + apr_hash_t *orig_props; + apr_hash_t *new_props; + apr_array_header_t *diff; + int i; + + /* If we're skipping this revision we're done here. */ + if (rb->skipped) + return SVN_NO_ERROR; + + /* If the dumpstream doesn't have an 'svn:date' property and we + aren't ignoring the dates in the dumpstream altogether, remove + any 'svn:date' revision property that was set by FS layer when + the TXN was created. */ + if (! (pb->ignore_dates || rb->datestamp)) + { + svn_prop_t *prop = &APR_ARRAY_PUSH(rb->revprops, svn_prop_t); + prop->name = SVN_PROP_REVISION_DATE; + prop->value = NULL; + } + + SVN_ERR(svn_fs_revision_proplist2(&orig_props, pb->fs, rb->rev, TRUE, + rb->pool, rb->pool)); + new_props = svn_prop_array_to_hash(rb->revprops, rb->pool); + SVN_ERR(svn_prop_diffs(&diff, new_props, orig_props, rb->pool)); + + for (i = 0; i < diff->nelts; i++) + { + const svn_prop_t *prop = &APR_ARRAY_IDX(diff, i, svn_prop_t); + + SVN_ERR(change_rev_prop(pb->repos, rb->rev, prop->name, prop->value, + pb->validate_props, pb->normalize_props, + rb->pool)); + } + + if (pb->notify_func) + { + /* ### TODO: Use proper scratch pool instead of pb->notify_pool */ + svn_repos_notify_t *notify = svn_repos_notify_create( + svn_repos_notify_load_revprop_set, + pb->notify_pool); + + notify->new_revision = rb->rev; + notify->old_revision = SVN_INVALID_REVNUM; + pb->notify_func(pb->notify_baton, notify, pb->notify_pool); + svn_pool_clear(pb->notify_pool); + } + + return SVN_NO_ERROR; +} + +/* Set *CALLBACKS and *PARSE_BATON to a vtable parser which commits new + * revisions to the fs in REPOS. Allocate the objects in RESULT_POOL. + * + * START_REV and END_REV act as filters, the lower and upper (inclusive) + * range values of revisions in DUMPSTREAM which will be loaded. Either + * both of these values are #SVN_INVALID_REVNUM (in which case no + * revision-based filtering occurs at all), or both are valid revisions + * (where START_REV is older than or equivalent to END_REV). + * + * START_REV and END_REV act as filters, the lower and upper (inclusive) + * range values of revisions which will + * be loaded. Either both of these values are #SVN_INVALID_REVNUM (in + * which case no revision-based filtering occurs at all), or both are + * valid revisions (where START_REV is older than or equivalent to + * END_REV). They refer to dump stream revision numbers rather than + * committed revision numbers. + * + * If VALIDATE_PROPS is set, then validate Subversion revision properties + * (those in the svn: namespace) against established rules for those things. + * + * If IGNORE_DATES is set, ignore any revision datestamps found in + * DUMPSTREAM, keeping whatever timestamps the revisions currently have. + * + * If NORMALIZE_PROPS is set, attempt to normalize invalid Subversion + * revision and node properties (those in the svn: namespace) so that + * their values would follow the established rules for them. Currently, + * this means translating non-LF line endings in the property values to LF. + */ +static svn_error_t * +build_revprop_parser(const svn_repos_parse_fns3_t **callbacks, + void **parse_baton, + svn_repos_t *repos, + svn_revnum_t start_rev, + svn_revnum_t end_rev, + svn_boolean_t validate_props, + svn_boolean_t ignore_dates, + svn_boolean_t normalize_props, + svn_repos_notify_func_t notify_func, + void *notify_baton, + apr_pool_t *result_pool) +{ + svn_repos_parse_fns3_t *parser = apr_pcalloc(result_pool, sizeof(*parser)); + struct parse_baton *pb = apr_pcalloc(result_pool, sizeof(*pb)); + + SVN_ERR_ASSERT((SVN_IS_VALID_REVNUM(start_rev) && + SVN_IS_VALID_REVNUM(end_rev)) + || ((! SVN_IS_VALID_REVNUM(start_rev)) && + (! SVN_IS_VALID_REVNUM(end_rev)))); + if (SVN_IS_VALID_REVNUM(start_rev)) + SVN_ERR_ASSERT(start_rev <= end_rev); + + parser->magic_header_record = NULL; + parser->uuid_record = uuid_record; + parser->new_revision_record = revprops_new_revision_record; + parser->new_node_record = NULL; + parser->set_revision_property = set_revision_property; + parser->set_node_property = NULL; + parser->remove_node_props = NULL; + parser->set_fulltext = NULL; + parser->close_node = NULL; + parser->close_revision = revprops_close_revision; + parser->delete_node_property = NULL; + parser->apply_textdelta = NULL; + + pb->repos = repos; + pb->fs = svn_repos_fs(repos); + pb->use_history = FALSE; + pb->validate_props = validate_props; + pb->notify_func = notify_func; + pb->notify_baton = notify_baton; + pb->uuid_action = svn_repos_load_uuid_ignore; /* Never touch the UUID. */ + pb->parent_dir = NULL; + pb->pool = result_pool; + pb->notify_pool = svn_pool_create(result_pool); + pb->rev_map = NULL; + pb->oldest_dumpstream_rev = SVN_INVALID_REVNUM; + pb->last_rev_mapped = SVN_INVALID_REVNUM; + pb->start_rev = start_rev; + pb->end_rev = end_rev; + pb->use_pre_commit_hook = FALSE; + pb->use_post_commit_hook = FALSE; + pb->ignore_dates = ignore_dates; + pb->normalize_props = normalize_props; + + *callbacks = parser; + *parse_baton = pb; + return SVN_NO_ERROR; +} + + +svn_error_t * +svn_repos_load_fs_revprops(svn_repos_t *repos, + svn_stream_t *dumpstream, + svn_revnum_t start_rev, + svn_revnum_t end_rev, + svn_boolean_t validate_props, + svn_boolean_t ignore_dates, + svn_boolean_t normalize_props, + svn_repos_notify_func_t notify_func, + void *notify_baton, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *scratch_pool) +{ + const svn_repos_parse_fns3_t *parser; + void *parse_baton; + + /* This is really simple. */ + + SVN_ERR(build_revprop_parser(&parser, &parse_baton, + repos, + start_rev, end_rev, + validate_props, + ignore_dates, + normalize_props, + notify_func, + notify_baton, + scratch_pool)); + + return svn_repos_parse_dumpstream3(dumpstream, parser, parse_baton, FALSE, + cancel_func, cancel_baton, scratch_pool); +} diff --git a/subversion/libsvn_repos/load.c b/subversion/libsvn_repos/load.c index 96eda85cb183..27cf4a174552 100644 --- a/subversion/libsvn_repos/load.c +++ b/subversion/libsvn_repos/load.c @@ -385,7 +385,135 @@ parse_format_version(int *version, return SVN_NO_ERROR; } +/*----------------------------------------------------------------------*/ + +/** Dummy callback implementations for functions not provided by the user **/ +static svn_error_t * +dummy_handler_magic_header_record(int version, + void *parse_baton, + apr_pool_t *pool) +{ + return SVN_NO_ERROR; +} + +static svn_error_t * +dummy_handler_uuid_record(const char *uuid, + void *parse_baton, + apr_pool_t *pool) +{ + return SVN_NO_ERROR; +} + +static svn_error_t * +dummy_handler_new_revision_record(void **revision_baton, + apr_hash_t *headers, + void *parse_baton, + apr_pool_t *pool) +{ + *revision_baton = NULL; + return SVN_NO_ERROR; +} + +static svn_error_t * +dummy_handler_new_node_record(void **node_baton, + apr_hash_t *headers, + void *revision_baton, + apr_pool_t *pool) +{ + *node_baton = NULL; + return SVN_NO_ERROR; +} + +static svn_error_t * +dummy_handler_set_revision_property(void *revision_baton, + const char *name, + const svn_string_t *value) +{ + return SVN_NO_ERROR; +} + +static svn_error_t * +dummy_handler_set_node_property(void *node_baton, + const char *name, + const svn_string_t *value) +{ + return SVN_NO_ERROR; +} + +static svn_error_t * +dummy_handler_delete_node_property(void *node_baton, + const char *name) +{ + return SVN_NO_ERROR; +} + +static svn_error_t * +dummy_handler_remove_node_props(void *node_baton) +{ + return SVN_NO_ERROR; +} + +static svn_error_t * +dummy_handler_set_fulltext(svn_stream_t **stream, + void *node_baton) +{ + return SVN_NO_ERROR; +} + +static svn_error_t * +dummy_handler_apply_textdelta(svn_txdelta_window_handler_t *handler, + void **handler_baton, + void *node_baton) +{ + /* Only called by parse_text_block() and that tests for NULL handlers. */ + *handler = NULL; + *handler_baton = NULL; + return SVN_NO_ERROR; +} + +static svn_error_t * +dummy_handler_close_node(void *node_baton) +{ + return SVN_NO_ERROR; +} + +static svn_error_t * +dummy_handler_close_revision(void *revision_baton) +{ + return SVN_NO_ERROR; +} + +/* Helper macro to copy the function pointer SOURCE->NAME to DEST->NAME. + * If the source pointer is NULL, pick the corresponding dummy handler + * instead. */ +#define SET_VTABLE_ENTRY(dest, source, name) \ + dest->name = provided->name ? provided->name : dummy_handler_##name + +/* Return a copy of PROVIDED with all NULL callbacks replaced by a dummy + * handler. Allocate the result in RESULT_POOL. */ +static const svn_repos_parse_fns3_t * +complete_vtable(const svn_repos_parse_fns3_t *provided, + apr_pool_t *result_pool) +{ + svn_repos_parse_fns3_t *completed = apr_pcalloc(result_pool, + sizeof(*completed)); + + SET_VTABLE_ENTRY(completed, provided, magic_header_record); + SET_VTABLE_ENTRY(completed, provided, uuid_record); + SET_VTABLE_ENTRY(completed, provided, new_revision_record); + SET_VTABLE_ENTRY(completed, provided, new_node_record); + SET_VTABLE_ENTRY(completed, provided, set_revision_property); + SET_VTABLE_ENTRY(completed, provided, set_node_property); + SET_VTABLE_ENTRY(completed, provided, delete_node_property); + SET_VTABLE_ENTRY(completed, provided, remove_node_props); + SET_VTABLE_ENTRY(completed, provided, set_fulltext); + SET_VTABLE_ENTRY(completed, provided, apply_textdelta); + SET_VTABLE_ENTRY(completed, provided, close_node); + SET_VTABLE_ENTRY(completed, provided, close_revision); + + return completed; +} /*----------------------------------------------------------------------*/ @@ -410,6 +538,10 @@ svn_repos_parse_dumpstream3(svn_stream_t *stream, apr_pool_t *nodepool = svn_pool_create(pool); int version; + /* Make sure we can blindly invoke callbacks. */ + parse_fns = complete_vtable(parse_fns, pool); + + /* Start parsing process. */ SVN_ERR(svn_stream_readline(stream, &linebuf, "\n", &eof, linepool)); if (eof) return stream_ran_dry(); diff --git a/subversion/libsvn_repos/log.c b/subversion/libsvn_repos/log.c index 82caf0219ea8..7dec5dd8d5b7 100644 --- a/subversion/libsvn_repos/log.c +++ b/subversion/libsvn_repos/log.c @@ -43,8 +43,72 @@ #include "private/svn_mergeinfo_private.h" #include "private/svn_subr_private.h" #include "private/svn_sorts_private.h" +#include "private/svn_string_private.h" +/* This is a mere convenience struct such that we don't need to pass that + many parameters around individually. */ +typedef struct log_callbacks_t +{ + svn_repos_path_change_receiver_t path_change_receiver; + void *path_change_receiver_baton; + svn_repos_log_entry_receiver_t revision_receiver; + void *revision_receiver_baton; + svn_repos_authz_func_t authz_read_func; + void *authz_read_baton; +} log_callbacks_t; + + +svn_repos_path_change_t * +svn_repos_path_change_create(apr_pool_t *result_pool) +{ + svn_repos_path_change_t *change = apr_pcalloc(result_pool, sizeof(*change)); + + change->path.data = ""; + change->change_kind = svn_fs_path_change_reset; + change->mergeinfo_mod = svn_tristate_unknown; + change->copyfrom_rev = SVN_INVALID_REVNUM; + + return change; +} + +svn_repos_path_change_t * +svn_repos_path_change_dup(svn_repos_path_change_t *change, + apr_pool_t *result_pool) +{ + svn_repos_path_change_t *new_change = apr_pmemdup(result_pool, change, + sizeof(*new_change)); + + new_change->path.data = apr_pstrmemdup(result_pool, change->path.data, + change->path.len); + if (change->copyfrom_path) + new_change->copyfrom_path = apr_pstrdup(result_pool, + change->copyfrom_path); + + return new_change; +} + +svn_repos_log_entry_t * +svn_repos_log_entry_create(apr_pool_t *result_pool) +{ + svn_repos_log_entry_t *log_entry = apr_pcalloc(result_pool, + sizeof(*log_entry)); + + return log_entry; +} + +svn_repos_log_entry_t * +svn_repos_log_entry_dup(const svn_repos_log_entry_t *log_entry, + apr_pool_t *result_pool) +{ + svn_repos_log_entry_t *new_entry = apr_pmemdup(result_pool, log_entry, + sizeof(*new_entry)); + + if (log_entry->revprops) + new_entry->revprops = svn_prop_hash_dup(log_entry->revprops, result_pool); + + return new_entry; +} svn_error_t * svn_repos_check_revision_access(svn_repos_revision_access_level_t *access_level, @@ -56,11 +120,11 @@ svn_repos_check_revision_access(svn_repos_revision_access_level_t *access_level, { svn_fs_t *fs = svn_repos_fs(repos); svn_fs_root_t *rev_root; - apr_hash_t *changes; - apr_hash_index_t *hi; + svn_fs_path_change_iterator_t *iterator; + svn_fs_path_change3_t *change; svn_boolean_t found_readable = FALSE; svn_boolean_t found_unreadable = FALSE; - apr_pool_t *subpool; + apr_pool_t *iterpool; /* By default, we'll grant full read access to REVISION. */ *access_level = svn_repos_revision_access_full; @@ -71,25 +135,27 @@ svn_repos_check_revision_access(svn_repos_revision_access_level_t *access_level, /* Fetch the changes associated with REVISION. */ SVN_ERR(svn_fs_revision_root(&rev_root, fs, revision, pool)); - SVN_ERR(svn_fs_paths_changed2(&changes, rev_root, pool)); + SVN_ERR(svn_fs_paths_changed3(&iterator, rev_root, pool, pool)); + SVN_ERR(svn_fs_path_change_get(&change, iterator)); - /* No changed paths? We're done. */ - if (apr_hash_count(changes) == 0) + /* No changed paths? We're done. + + Note that the check at "decision:" assumes that at least one + path has been processed. So, this actually affects functionality. */ + if (!change) return SVN_NO_ERROR; /* Otherwise, we have to check the readability of each changed path, or at least enough to answer the question asked. */ - subpool = svn_pool_create(pool); - for (hi = apr_hash_first(pool, changes); hi; hi = apr_hash_next(hi)) + iterpool = svn_pool_create(pool); + while (change) { - const char *key = apr_hash_this_key(hi); - svn_fs_path_change2_t *change = apr_hash_this_val(hi); svn_boolean_t readable; - svn_pool_clear(subpool); + svn_pool_clear(iterpool); - SVN_ERR(authz_read_func(&readable, rev_root, key, - authz_read_baton, subpool)); + SVN_ERR(authz_read_func(&readable, rev_root, change->path.data, + authz_read_baton, iterpool)); if (! readable) found_unreadable = TRUE; else @@ -109,15 +175,16 @@ svn_repos_check_revision_access(svn_repos_revision_access_level_t *access_level, svn_revnum_t copyfrom_rev; SVN_ERR(svn_fs_copied_from(©from_rev, ©from_path, - rev_root, key, subpool)); + rev_root, change->path.data, + iterpool)); if (copyfrom_path && SVN_IS_VALID_REVNUM(copyfrom_rev)) { svn_fs_root_t *copyfrom_root; SVN_ERR(svn_fs_revision_root(©from_root, fs, - copyfrom_rev, subpool)); + copyfrom_rev, iterpool)); SVN_ERR(authz_read_func(&readable, copyfrom_root, copyfrom_path, - authz_read_baton, subpool)); + authz_read_baton, iterpool)); if (! readable) found_unreadable = TRUE; @@ -134,10 +201,12 @@ svn_repos_check_revision_access(svn_repos_revision_access_level_t *access_level, default: break; } + + SVN_ERR(svn_fs_path_change_get(&change, iterator)); } decision: - svn_pool_destroy(subpool); + svn_pool_destroy(iterpool); /* Either every changed path was unreadable... */ if (! found_readable) @@ -152,21 +221,14 @@ svn_repos_check_revision_access(svn_repos_revision_access_level_t *access_level, } -/* Store as keys in CHANGED the paths of all node in ROOT that show a - * significant change. "Significant" means that the text or - * properties of the node were changed, or that the node was added or - * deleted. +/* Find all significant changes under ROOT and, if not NULL, report them + * to the CALLBACKS->PATH_CHANGE_RECEIVER. "Significant" means that the + * text or properties of the node were changed, or that the node was added + * or deleted. * - * The CHANGED hash set and its keys and values are allocated in POOL; - * keys are const char * paths and values are svn_log_changed_path_t. - * - * To prevent changes from being processed over and over again, the - * changed paths for ROOT may be passed in PREFETCHED_CHANGES. If the - * latter is NULL, we will request the list inside this function. - * - * If optional AUTHZ_READ_FUNC is non-NULL, then use it (with - * AUTHZ_READ_BATON and FS) to check whether each changed-path (and - * copyfrom_path) is readable: + * If optional CALLBACKS->AUTHZ_READ_FUNC is non-NULL, then use it (with + * CALLBACKS->AUTHZ_READ_BATON and FS) to check whether each changed-path + * (and copyfrom_path) is readable: * * - If absolutely every changed-path (and copyfrom_path) is * readable, then return the full CHANGED hash, and set @@ -184,40 +246,22 @@ svn_repos_check_revision_access(svn_repos_revision_access_level_t *access_level, */ static svn_error_t * detect_changed(svn_repos_revision_access_level_t *access_level, - apr_hash_t **changed, svn_fs_root_t *root, svn_fs_t *fs, - apr_hash_t *prefetched_changes, - svn_repos_authz_func_t authz_read_func, - void *authz_read_baton, - apr_pool_t *pool) + const log_callbacks_t *callbacks, + apr_pool_t *scratch_pool) { - apr_hash_t *changes = prefetched_changes; - apr_hash_index_t *hi; + svn_fs_path_change_iterator_t *iterator; + svn_fs_path_change3_t *change; apr_pool_t *iterpool; svn_boolean_t found_readable = FALSE; svn_boolean_t found_unreadable = FALSE; - /* If we create the CHANGES hash ourselves, we can reuse it as the - * result hash as it contains the exact same keys - but with _all_ - * values being replaced by structs of a different type. */ - if (changes == NULL) - { - SVN_ERR(svn_fs_paths_changed2(&changes, root, pool)); + /* Retrieve the first change in the list. */ + SVN_ERR(svn_fs_paths_changed3(&iterator, root, scratch_pool, scratch_pool)); + SVN_ERR(svn_fs_path_change_get(&change, iterator)); - /* If we are going to filter the results, we won't use the exact - * same keys but put them into a new hash. */ - if (authz_read_func) - *changed = svn_hash__make(pool); - else - *changed = changes; - } - else - { - *changed = svn_hash__make(pool); - } - - if (apr_hash_count(changes) == 0) + if (!change) { /* No paths changed in this revision? Uh, sure, I guess the revision is readable, then. */ @@ -225,30 +269,26 @@ detect_changed(svn_repos_revision_access_level_t *access_level, return SVN_NO_ERROR; } - iterpool = svn_pool_create(pool); - for (hi = apr_hash_first(pool, changes); hi; hi = apr_hash_next(hi)) + iterpool = svn_pool_create(scratch_pool); + while (change) { /* NOTE: Much of this loop is going to look quite similar to svn_repos_check_revision_access(), but we have to do more things here, so we'll live with the duplication. */ - const char *path = apr_hash_this_key(hi); - apr_ssize_t path_len = apr_hash_this_key_len(hi); - svn_fs_path_change2_t *change = apr_hash_this_val(hi); - char action; - svn_log_changed_path2_t *item; - + const char *path = change->path.data; svn_pool_clear(iterpool); /* Skip path if unreadable. */ - if (authz_read_func) + if (callbacks->authz_read_func) { svn_boolean_t readable; - SVN_ERR(authz_read_func(&readable, - root, path, - authz_read_baton, iterpool)); + SVN_ERR(callbacks->authz_read_func(&readable, root, path, + callbacks->authz_read_baton, + iterpool)); if (! readable) { found_unreadable = TRUE; + SVN_ERR(svn_fs_path_change_get(&change, iterator)); continue; } } @@ -256,41 +296,9 @@ detect_changed(svn_repos_revision_access_level_t *access_level, /* At least one changed-path was readable. */ found_readable = TRUE; - switch (change->change_kind) - { - case svn_fs_path_change_reset: - continue; - - case svn_fs_path_change_add: - action = 'A'; - break; - - case svn_fs_path_change_replace: - action = 'R'; - break; - - case svn_fs_path_change_delete: - action = 'D'; - break; - - case svn_fs_path_change_modify: - default: - action = 'M'; - break; - } - - item = svn_log_changed_path2_create(pool); - item->action = action; - item->node_kind = change->node_kind; - item->copyfrom_rev = SVN_INVALID_REVNUM; - item->text_modified = change->text_mod ? svn_tristate_true - : svn_tristate_false; - item->props_modified = change->prop_mod ? svn_tristate_true - : svn_tristate_false; - /* Pre-1.6 revision files don't store the change path kind, so fetch it manually. */ - if (item->node_kind == svn_node_unknown) + if (change->node_kind == svn_node_unknown) { svn_fs_root_t *check_root = root; const char *check_path = path; @@ -315,18 +323,19 @@ detect_changed(svn_repos_revision_access_level_t *access_level, SVN_ERR(svn_fs_history_prev2(&history, history, TRUE, iterpool, iterpool)); - SVN_ERR(svn_fs_history_location(&parent_path, &prev_rev, history, - iterpool)); - SVN_ERR(svn_fs_revision_root(&check_root, fs, prev_rev, iterpool)); + SVN_ERR(svn_fs_history_location(&parent_path, &prev_rev, + history, iterpool)); + SVN_ERR(svn_fs_revision_root(&check_root, fs, prev_rev, + iterpool)); check_path = svn_fspath__join(parent_path, name, iterpool); } - SVN_ERR(svn_fs_check_path(&item->node_kind, check_root, check_path, + SVN_ERR(svn_fs_check_path(&change->node_kind, check_root, check_path, iterpool)); } - - if ((action == 'A') || (action == 'R')) + if ( (change->change_kind == svn_fs_path_change_add) + || (change->change_kind == svn_fs_path_change_replace)) { const char *copyfrom_path = change->copyfrom_path; svn_revnum_t copyfrom_rev = change->copyfrom_rev; @@ -338,35 +347,44 @@ detect_changed(svn_repos_revision_access_level_t *access_level, { SVN_ERR(svn_fs_copied_from(©from_rev, ©from_path, root, path, iterpool)); - copyfrom_path = apr_pstrdup(pool, copyfrom_path); + change->copyfrom_known = TRUE; } if (copyfrom_path && SVN_IS_VALID_REVNUM(copyfrom_rev)) { svn_boolean_t readable = TRUE; - if (authz_read_func) + if (callbacks->authz_read_func) { svn_fs_root_t *copyfrom_root; SVN_ERR(svn_fs_revision_root(©from_root, fs, copyfrom_rev, iterpool)); - SVN_ERR(authz_read_func(&readable, - copyfrom_root, copyfrom_path, - authz_read_baton, iterpool)); + SVN_ERR(callbacks->authz_read_func(&readable, + copyfrom_root, + copyfrom_path, + callbacks->authz_read_baton, + iterpool)); if (! readable) found_unreadable = TRUE; } if (readable) { - item->copyfrom_path = copyfrom_path; - item->copyfrom_rev = copyfrom_rev; + change->copyfrom_path = copyfrom_path; + change->copyfrom_rev = copyfrom_rev; } } } - apr_hash_set(*changed, path, path_len, item); + if (callbacks->path_change_receiver) + SVN_ERR(callbacks->path_change_receiver( + callbacks->path_change_receiver_baton, + change, + iterpool)); + + /* Next changed path. */ + SVN_ERR(svn_fs_path_change_get(&change, iterator)); } svn_pool_destroy(iterpool); @@ -593,23 +611,21 @@ next_history_rev(const apr_array_header_t *histories) /* Set *DELETED_MERGEINFO_CATALOG and *ADDED_MERGEINFO_CATALOG to catalogs describing how mergeinfo values on paths (which are the - keys of those catalogs) were changed in REV. If *PREFETCHED_CHANGES - already contains the changed paths for REV, use that. Otherwise, - request that data and return it in *PREFETCHED_CHANGES. */ + keys of those catalogs) were changed in REV. */ /* ### TODO: This would make a *great*, useful public function, ### svn_repos_fs_mergeinfo_changed()! -- cmpilato */ static svn_error_t * fs_mergeinfo_changed(svn_mergeinfo_catalog_t *deleted_mergeinfo_catalog, svn_mergeinfo_catalog_t *added_mergeinfo_catalog, - apr_hash_t **prefetched_changes, svn_fs_t *fs, svn_revnum_t rev, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { svn_fs_root_t *root; - apr_pool_t *iterpool; - apr_hash_index_t *hi; + apr_pool_t *iterpool, *iterator_pool; + svn_fs_path_change_iterator_t *iterator; + svn_fs_path_change3_t *change; svn_boolean_t any_mergeinfo = FALSE; svn_boolean_t any_copy = FALSE; @@ -621,56 +637,69 @@ fs_mergeinfo_changed(svn_mergeinfo_catalog_t *deleted_mergeinfo_catalog, if (rev == 0) return SVN_NO_ERROR; + /* FS iterators are potentially heavy objects. + * Hold them in a separate pool to clean them up asap. */ + iterator_pool = svn_pool_create(scratch_pool); + /* We're going to use the changed-paths information for REV to narrow down our search. */ SVN_ERR(svn_fs_revision_root(&root, fs, rev, scratch_pool)); - if (*prefetched_changes == NULL) - SVN_ERR(svn_fs_paths_changed2(prefetched_changes, root, scratch_pool)); + SVN_ERR(svn_fs_paths_changed3(&iterator, root, iterator_pool, + iterator_pool)); + SVN_ERR(svn_fs_path_change_get(&change, iterator)); /* Look for copies and (potential) mergeinfo changes. - We will use both flags to take shortcuts further down the road. */ - for (hi = apr_hash_first(scratch_pool, *prefetched_changes); - hi; - hi = apr_hash_next(hi)) - { - svn_fs_path_change2_t *change = apr_hash_this_val(hi); + We will use both flags to take shortcuts further down the road. + The critical information here is whether there are any copies + because that greatly influences the costs for log processing. + So, it is faster to iterate over the changes twice - in the worst + case b/c most times there is no m/i at all and we exit out early + without any overhead. + */ + while (change && (!any_mergeinfo || !any_copy)) + { /* If there was a prop change and we are not positive that _no_ mergeinfo change happened, we must assume that it might have. */ if (change->mergeinfo_mod != svn_tristate_false && change->prop_mod) any_mergeinfo = TRUE; - switch (change->change_kind) - { - case svn_fs_path_change_add: - case svn_fs_path_change_replace: - any_copy = TRUE; - break; + if ( (change->change_kind == svn_fs_path_change_add) + || (change->change_kind == svn_fs_path_change_replace)) + any_copy = TRUE; - default: - break; - } + SVN_ERR(svn_fs_path_change_get(&change, iterator)); } /* No potential mergeinfo changes? We're done. */ if (! any_mergeinfo) - return SVN_NO_ERROR; + { + svn_pool_destroy(iterator_pool); + return SVN_NO_ERROR; + } + + /* There is or may be some m/i change. Look closely now. */ + svn_pool_clear(iterator_pool); + SVN_ERR(svn_fs_paths_changed3(&iterator, root, iterator_pool, + iterator_pool)); /* Loop over changes, looking for anything that might carry an svn:mergeinfo change and is one of our paths of interest, or a child or [grand]parent directory thereof. */ iterpool = svn_pool_create(scratch_pool); - for (hi = apr_hash_first(scratch_pool, *prefetched_changes); - hi; - hi = apr_hash_next(hi)) + while (TRUE) { const char *changed_path; - svn_fs_path_change2_t *change = apr_hash_this_val(hi); const char *base_path = NULL; svn_revnum_t base_rev = SVN_INVALID_REVNUM; svn_fs_root_t *base_root = NULL; svn_string_t *prev_mergeinfo_value = NULL, *mergeinfo_value; + /* Next change. */ + SVN_ERR(svn_fs_path_change_get(&change, iterator)); + if (!change) + break; + /* Cheap pre-checks that don't require memory allocation etc. */ /* No mergeinfo change? -> nothing to do here. */ @@ -682,7 +711,7 @@ fs_mergeinfo_changed(svn_mergeinfo_catalog_t *deleted_mergeinfo_catalog, continue; /* Begin actual processing */ - changed_path = apr_hash_this_key(hi); + changed_path = change->path.data; svn_pool_clear(iterpool); switch (change->change_kind) @@ -840,20 +869,18 @@ fs_mergeinfo_changed(svn_mergeinfo_catalog_t *deleted_mergeinfo_catalog, } svn_pool_destroy(iterpool); + svn_pool_destroy(iterator_pool); + return SVN_NO_ERROR; } /* Determine what (if any) mergeinfo for PATHS was modified in revision REV, returning the differences for added mergeinfo in - *ADDED_MERGEINFO and deleted mergeinfo in *DELETED_MERGEINFO. - If *PREFETCHED_CHANGES already contains the changed paths for - REV, use that. Otherwise, request that data and return it in - *PREFETCHED_CHANGES. */ + *ADDED_MERGEINFO and deleted mergeinfo in *DELETED_MERGEINFO. */ static svn_error_t * get_combined_mergeinfo_changes(svn_mergeinfo_t *added_mergeinfo, svn_mergeinfo_t *deleted_mergeinfo, - apr_hash_t **prefetched_changes, svn_fs_t *fs, const apr_array_header_t *paths, svn_revnum_t rev, @@ -882,7 +909,6 @@ get_combined_mergeinfo_changes(svn_mergeinfo_t *added_mergeinfo, /* Fetch the mergeinfo changes for REV. */ err = fs_mergeinfo_changed(&deleted_mergeinfo_catalog, &added_mergeinfo_catalog, - prefetched_changes, fs, rev, scratch_pool, scratch_pool); if (err) @@ -1071,38 +1097,31 @@ get_combined_mergeinfo_changes(svn_mergeinfo_t *added_mergeinfo, /* Fill LOG_ENTRY with history information in FS at REV. */ static svn_error_t * -fill_log_entry(svn_log_entry_t *log_entry, +fill_log_entry(svn_repos_log_entry_t *log_entry, svn_revnum_t rev, svn_fs_t *fs, - apr_hash_t *prefetched_changes, - svn_boolean_t discover_changed_paths, const apr_array_header_t *revprops, - svn_repos_authz_func_t authz_read_func, - void *authz_read_baton, + const log_callbacks_t *callbacks, apr_pool_t *pool) { - apr_hash_t *r_props, *changed_paths = NULL; + apr_hash_t *r_props; svn_boolean_t get_revprops = TRUE, censor_revprops = FALSE; svn_boolean_t want_revprops = !revprops || revprops->nelts; /* Discover changed paths if the user requested them or if we need to check that they are readable. */ if ((rev > 0) - && (authz_read_func || discover_changed_paths)) + && (callbacks->authz_read_func || callbacks->path_change_receiver)) { svn_fs_root_t *newroot; svn_repos_revision_access_level_t access_level; SVN_ERR(svn_fs_revision_root(&newroot, fs, rev, pool)); - SVN_ERR(detect_changed(&access_level, &changed_paths, - newroot, fs, prefetched_changes, - authz_read_func, authz_read_baton, - pool)); + SVN_ERR(detect_changed(&access_level, newroot, fs, callbacks, pool)); if (access_level == svn_repos_revision_access_none) { /* All changed-paths are unreadable, so clear all fields. */ - changed_paths = NULL; get_revprops = FALSE; } else if (access_level == svn_repos_revision_access_partial) @@ -1112,17 +1131,13 @@ fill_log_entry(svn_log_entry_t *log_entry, missing from the hash.) */ censor_revprops = TRUE; } - - /* It may be the case that an authz func was passed in, but - the user still doesn't want to see any changed-paths. */ - if (! discover_changed_paths) - changed_paths = NULL; } if (get_revprops && want_revprops) { /* User is allowed to see at least some revprops. */ - SVN_ERR(svn_fs_revision_proplist(&r_props, fs, rev, pool)); + SVN_ERR(svn_fs_revision_proplist2(&r_props, fs, rev, FALSE, pool, + pool)); if (revprops == NULL) { /* Requested all revprops... */ @@ -1150,9 +1165,9 @@ fill_log_entry(svn_log_entry_t *log_entry, we want static initialization here and must therefore emulate strlen(x) by sizeof(x)-1. */ static const svn_string_t svn_prop_revision_author - = {SVN_PROP_REVISION_AUTHOR, sizeof(SVN_PROP_REVISION_AUTHOR)-1}; + = SVN__STATIC_STRING(SVN_PROP_REVISION_AUTHOR); static const svn_string_t svn_prop_revision_date - = {SVN_PROP_REVISION_DATE, sizeof(SVN_PROP_REVISION_DATE)-1}; + = SVN__STATIC_STRING(SVN_PROP_REVISION_DATE); /* often only the standard revprops got requested and delivered. In that case, we can simply pass the hash on. */ @@ -1192,20 +1207,83 @@ fill_log_entry(svn_log_entry_t *log_entry, } } - log_entry->changed_paths = changed_paths; - log_entry->changed_paths2 = changed_paths; log_entry->revision = rev; return SVN_NO_ERROR; } -/* Send a log message for REV to RECEIVER with its RECEIVER_BATON. +/* Baton type to be used with the interesting_merge callback. */ +typedef struct interesting_merge_baton_t +{ + /* What we are looking for. */ + svn_revnum_t rev; + svn_mergeinfo_t log_target_history_as_mergeinfo; + + /* Set to TRUE if we found it. */ + svn_boolean_t found_rev_of_interest; + + /* We need to invoke this user-provided callback if not NULL. */ + svn_repos_path_change_receiver_t inner; + void *inner_baton; +} interesting_merge_baton_t; + +/* Implements svn_repos_path_change_receiver_t. + * *BATON is a interesting_merge_baton_t. + * + * If BATON->REV a merged revision that is not already part of + * BATON->LOG_TARGET_HISTORY_AS_MERGEINFO, set BATON->FOUND_REV_OF_INTEREST. + */ +static svn_error_t * +interesting_merge(void *baton, + svn_repos_path_change_t *change, + apr_pool_t *scratch_pool) +{ + interesting_merge_baton_t *b = baton; + apr_hash_index_t *hi; + + if (b->inner) + SVN_ERR(b->inner(b->inner_baton, change, scratch_pool)); + + if (b->found_rev_of_interest) + return SVN_NO_ERROR; + + /* Look at each path on the log target's mergeinfo. */ + for (hi = apr_hash_first(scratch_pool, b->log_target_history_as_mergeinfo); + hi; + hi = apr_hash_next(hi)) + { + const char *mergeinfo_path = apr_hash_this_key(hi); + svn_rangelist_t *rangelist = apr_hash_this_val(hi); + + /* Check whether CHANGED_PATH at revision REV is a child of + a (path, revision) tuple in LOG_TARGET_HISTORY_AS_MERGEINFO. */ + if (svn_fspath__skip_ancestor(mergeinfo_path, change->path.data)) + { + int i; + + for (i = 0; i < rangelist->nelts; i++) + { + svn_merge_range_t *range + = APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *); + if (b->rev > range->start && b->rev <= range->end) + return SVN_NO_ERROR; + } + } + } + + b->found_rev_of_interest = TRUE; + + return SVN_NO_ERROR; +} + +/* Send a log message for REV to the CALLBACKS. FS is used with REV to fetch the interesting history information, such as changed paths, revprops, etc. - The detect_changed function is used if either AUTHZ_READ_FUNC is - not NULL, or if DISCOVER_CHANGED_PATHS is TRUE. See it for details. + The detect_changed function is used if either CALLBACKS->AUTHZ_READ_FUNC + is not NULL, or if CALLBACKS->PATH_CHANGE_RECEIVER is not NULL. + See it for details. If DESCENDING_ORDER is true, send child messages in descending order. @@ -1227,107 +1305,51 @@ fill_log_entry(svn_log_entry_t *log_entry, static svn_error_t * send_log(svn_revnum_t rev, svn_fs_t *fs, - apr_hash_t *prefetched_changes, svn_mergeinfo_t log_target_history_as_mergeinfo, svn_bit_array__t *nested_merges, - svn_boolean_t discover_changed_paths, svn_boolean_t subtractive_merge, svn_boolean_t handling_merged_revision, const apr_array_header_t *revprops, svn_boolean_t has_children, - svn_log_entry_receiver_t receiver, - void *receiver_baton, - svn_repos_authz_func_t authz_read_func, - void *authz_read_baton, + const log_callbacks_t *callbacks, apr_pool_t *pool) { - svn_log_entry_t *log_entry; - /* Assume we want to send the log for REV. */ - svn_boolean_t found_rev_of_interest = TRUE; + svn_repos_log_entry_t log_entry = { 0 }; + log_callbacks_t my_callbacks = *callbacks; - log_entry = svn_log_entry_create(pool); - SVN_ERR(fill_log_entry(log_entry, rev, fs, prefetched_changes, - discover_changed_paths || handling_merged_revision, - revprops, authz_read_func, authz_read_baton, pool)); - log_entry->has_children = has_children; - log_entry->subtractive_merge = subtractive_merge; + interesting_merge_baton_t baton; /* Is REV a merged revision that is already part of LOG_TARGET_HISTORY_AS_MERGEINFO? If so then there is no - need to send it, since it already was (or will be) sent. */ + need to send it, since it already was (or will be) sent. + + Use our callback to snoop through the changes. */ if (handling_merged_revision - && log_entry->changed_paths2 && log_target_history_as_mergeinfo && apr_hash_count(log_target_history_as_mergeinfo)) { - apr_hash_index_t *hi; - apr_pool_t *iterpool = svn_pool_create(pool); + baton.found_rev_of_interest = FALSE; + baton.rev = rev; + baton.log_target_history_as_mergeinfo = log_target_history_as_mergeinfo; + baton.inner = callbacks->path_change_receiver; + baton.inner_baton = callbacks->path_change_receiver_baton; - /* REV was merged in, but it might already be part of the log target's - natural history, so change our starting assumption. */ - found_rev_of_interest = FALSE; - - /* Look at each changed path in REV. */ - for (hi = apr_hash_first(pool, log_entry->changed_paths2); - hi; - hi = apr_hash_next(hi)) - { - svn_boolean_t path_is_in_history = FALSE; - const char *changed_path = apr_hash_this_key(hi); - apr_hash_index_t *hi2; - - /* Look at each path on the log target's mergeinfo. */ - for (hi2 = apr_hash_first(iterpool, - log_target_history_as_mergeinfo); - hi2; - hi2 = apr_hash_next(hi2)) - { - const char *mergeinfo_path = apr_hash_this_key(hi2); - svn_rangelist_t *rangelist = apr_hash_this_val(hi2); - - /* Check whether CHANGED_PATH at revision REV is a child of - a (path, revision) tuple in LOG_TARGET_HISTORY_AS_MERGEINFO. */ - if (svn_fspath__skip_ancestor(mergeinfo_path, changed_path)) - { - int i; - - for (i = 0; i < rangelist->nelts; i++) - { - svn_merge_range_t *range = - APR_ARRAY_IDX(rangelist, i, - svn_merge_range_t *); - if (rev > range->start && rev <= range->end) - { - path_is_in_history = TRUE; - break; - } - } - } - if (path_is_in_history) - break; - } - svn_pool_clear(iterpool); - - if (!path_is_in_history) - { - /* If even one path in LOG_ENTRY->CHANGED_PATHS2 is not part of - LOG_TARGET_HISTORY_AS_MERGEINFO, then we want to send the - log for REV. */ - found_rev_of_interest = TRUE; - break; - } - } - svn_pool_destroy(iterpool); + my_callbacks.path_change_receiver = interesting_merge; + my_callbacks.path_change_receiver_baton = &baton; + callbacks = &my_callbacks; + } + else + { + baton.found_rev_of_interest = TRUE; } - /* If we only got changed paths the sake of detecting redundant merged - revisions, then be sure we don't send that info to the receiver. */ - if (!discover_changed_paths && handling_merged_revision) - log_entry->changed_paths = log_entry->changed_paths2 = NULL; + SVN_ERR(fill_log_entry(&log_entry, rev, fs, revprops, callbacks, pool)); + log_entry.has_children = has_children; + log_entry.subtractive_merge = subtractive_merge; /* Send the entry to the receiver, unless it is a redundant merged revision. */ - if (found_rev_of_interest) + if (baton.found_rev_of_interest) { apr_pool_t *scratch_pool; @@ -1351,7 +1373,8 @@ send_log(svn_revnum_t rev, /* Pass a scratch pool to ensure no temporary state stored by the receiver callback persists. */ scratch_pool = svn_pool_create(pool); - SVN_ERR(receiver(receiver_baton, log_entry, scratch_pool)); + SVN_ERR(callbacks->revision_receiver(callbacks->revision_receiver_baton, + &log_entry, scratch_pool)); svn_pool_destroy(scratch_pool); } @@ -1700,7 +1723,6 @@ do_logs(svn_fs_t *fs, svn_revnum_t hist_start, svn_revnum_t hist_end, int limit, - svn_boolean_t discover_changed_paths, svn_boolean_t strict_node_history, svn_boolean_t include_merged_revisions, svn_boolean_t handling_merged_revisions, @@ -1708,10 +1730,7 @@ do_logs(svn_fs_t *fs, svn_boolean_t ignore_missing_locations, const apr_array_header_t *revprops, svn_boolean_t descending_order, - svn_log_entry_receiver_t receiver, - void *receiver_baton, - svn_repos_authz_func_t authz_read_func, - void *authz_read_baton, + log_callbacks_t *callbacks, apr_pool_t *pool); /* Comparator function for handle_merged_revisions(). Sorts path_list_range @@ -1753,17 +1772,13 @@ handle_merged_revisions(svn_revnum_t rev, svn_mergeinfo_t processed, svn_mergeinfo_t added_mergeinfo, svn_mergeinfo_t deleted_mergeinfo, - svn_boolean_t discover_changed_paths, svn_boolean_t strict_node_history, const apr_array_header_t *revprops, - svn_log_entry_receiver_t receiver, - void *receiver_baton, - svn_repos_authz_func_t authz_read_func, - void *authz_read_baton, + log_callbacks_t *callbacks, apr_pool_t *pool) { apr_array_header_t *combined_list = NULL; - svn_log_entry_t *empty_log_entry; + svn_repos_log_entry_t empty_log_entry = { 0 }; apr_pool_t *iterpool; int i; @@ -1794,17 +1809,16 @@ handle_merged_revisions(svn_revnum_t rev, SVN_ERR(do_logs(fs, pl_range->paths, log_target_history_as_mergeinfo, processed, nested_merges, pl_range->range.start, pl_range->range.end, 0, - discover_changed_paths, strict_node_history, + strict_node_history, TRUE, pl_range->reverse_merge, TRUE, TRUE, - revprops, TRUE, receiver, receiver_baton, - authz_read_func, authz_read_baton, iterpool)); + revprops, TRUE, callbacks, iterpool)); } svn_pool_destroy(iterpool); /* Send the empty revision. */ - empty_log_entry = svn_log_entry_create(pool); - empty_log_entry->revision = SVN_INVALID_REVNUM; - return (*receiver)(receiver_baton, empty_log_entry, pool); + empty_log_entry.revision = SVN_INVALID_REVNUM; + return (callbacks->revision_receiver)(callbacks->revision_receiver_baton, + &empty_log_entry, pool); } /* This is used by do_logs to differentiate between forward and @@ -1907,8 +1921,7 @@ store_search(svn_mergeinfo_t processed, const char *path = APR_ARRAY_IDX(paths, i, const char *); svn_rangelist_t *ranges = apr_array_make(processed_pool, 1, sizeof(svn_merge_range_t*)); - svn_merge_range_t *range = apr_palloc(processed_pool, - sizeof(svn_merge_range_t)); + svn_merge_range_t *range = apr_palloc(processed_pool, sizeof(*range)); range->start = start; range->end = end; @@ -1922,10 +1935,10 @@ store_search(svn_mergeinfo_t processed, return SVN_NO_ERROR; } -/* Find logs for PATHS from HIST_START to HIST_END in FS, and invoke - RECEIVER with RECEIVER_BATON on them. If DESCENDING_ORDER is TRUE, send - the logs back as we find them, else buffer the logs and send them back - in youngest->oldest order. +/* Find logs for PATHS from HIST_START to HIST_END in FS, and invoke the + CALLBACKS on them. If DESCENDING_ORDER is TRUE, send the logs back as + we find them, else buffer the logs and send them back in youngest->oldest + order. If IGNORE_MISSING_LOCATIONS is set, don't treat requests for bogus repository locations as fatal -- just ignore them. @@ -1935,7 +1948,7 @@ store_search(svn_mergeinfo_t processed, If HANDLING_MERGED_REVISIONS is TRUE then this is a recursive call for merged revisions, see INCLUDE_MERGED_REVISIONS argument to - svn_repos_get_logs4(). If SUBTRACTIVE_MERGE is true, then this is a + svn_repos_get_logs5(). If SUBTRACTIVE_MERGE is true, then this is a recursive call for reverse merged revisions. If NESTED_MERGES is not NULL then it is a hash of revisions (svn_revnum_t * @@ -1950,7 +1963,7 @@ store_search(svn_mergeinfo_t processed, revisions that have already been searched. Allocated like NESTED_MERGES above. - All other parameters are the same as svn_repos_get_logs4(). + All other parameters are the same as svn_repos_get_logs5(). */ static svn_error_t * do_logs(svn_fs_t *fs, @@ -1961,7 +1974,6 @@ do_logs(svn_fs_t *fs, svn_revnum_t hist_start, svn_revnum_t hist_end, int limit, - svn_boolean_t discover_changed_paths, svn_boolean_t strict_node_history, svn_boolean_t include_merged_revisions, svn_boolean_t subtractive_merge, @@ -1969,10 +1981,7 @@ do_logs(svn_fs_t *fs, svn_boolean_t ignore_missing_locations, const apr_array_header_t *revprops, svn_boolean_t descending_order, - svn_log_entry_receiver_t receiver, - void *receiver_baton, - svn_repos_authz_func_t authz_read_func, - void *authz_read_baton, + log_callbacks_t *callbacks, apr_pool_t *pool) { apr_pool_t *iterpool, *iterpool2; @@ -2005,7 +2014,8 @@ do_logs(svn_fs_t *fs, revisions contain real changes to at least one of our paths. */ SVN_ERR(get_path_histories(&histories, fs, paths, hist_start, hist_end, strict_node_history, ignore_missing_locations, - authz_read_func, authz_read_baton, pool)); + callbacks->authz_read_func, + callbacks->authz_read_baton, pool)); /* Loop through all the revisions in the range and add any where a path was changed to the array, or if they wanted @@ -2029,9 +2039,10 @@ do_logs(svn_fs_t *fs, /* Check history for this path in current rev. */ SVN_ERR(check_history(&changed, info, fs, current, - strict_node_history, authz_read_func, - authz_read_baton, hist_start, pool, - iterpool2)); + strict_node_history, + callbacks->authz_read_func, + callbacks->authz_read_baton, + hist_start, pool, iterpool2)); if (! info->done) any_histories_left = TRUE; } @@ -2044,7 +2055,6 @@ do_logs(svn_fs_t *fs, svn_mergeinfo_t added_mergeinfo = NULL; svn_mergeinfo_t deleted_mergeinfo = NULL; svn_boolean_t has_children = FALSE; - apr_hash_t *changes = NULL; /* If we're including merged revisions, we need to calculate the mergeinfo deltas committed in this revision to our @@ -2065,7 +2075,6 @@ do_logs(svn_fs_t *fs, } SVN_ERR(get_combined_mergeinfo_changes(&added_mergeinfo, &deleted_mergeinfo, - &changes, fs, cur_paths, current, iterpool, iterpool)); @@ -2078,13 +2087,10 @@ do_logs(svn_fs_t *fs, in anyway). */ if (descending_order) { - SVN_ERR(send_log(current, fs, changes, + SVN_ERR(send_log(current, fs, log_target_history_as_mergeinfo, nested_merges, - discover_changed_paths, subtractive_merge, handling_merged_revisions, - revprops, has_children, - receiver, receiver_baton, - authz_read_func, authz_read_baton, iterpool)); + revprops, has_children, callbacks, iterpool)); if (has_children) /* Implies include_merged_revisions == TRUE */ { @@ -2103,12 +2109,9 @@ do_logs(svn_fs_t *fs, log_target_history_as_mergeinfo, nested_merges, processed, added_mergeinfo, deleted_mergeinfo, - discover_changed_paths, strict_node_history, revprops, - receiver, receiver_baton, - authz_read_func, - authz_read_baton, + callbacks, iterpool)); } if (limit && ++send_count >= limit) @@ -2176,20 +2179,17 @@ do_logs(svn_fs_t *fs, if (rev_mergeinfo) { struct added_deleted_mergeinfo *add_and_del_mergeinfo = - apr_hash_get(rev_mergeinfo, ¤t, sizeof(svn_revnum_t)); + apr_hash_get(rev_mergeinfo, ¤t, sizeof(current)); added_mergeinfo = add_and_del_mergeinfo->added_mergeinfo; deleted_mergeinfo = add_and_del_mergeinfo->deleted_mergeinfo; has_children = (apr_hash_count(added_mergeinfo) > 0 || apr_hash_count(deleted_mergeinfo) > 0); } - SVN_ERR(send_log(current, fs, NULL, + SVN_ERR(send_log(current, fs, log_target_history_as_mergeinfo, nested_merges, - discover_changed_paths, subtractive_merge, - handling_merged_revisions, - revprops, has_children, - receiver, receiver_baton, authz_read_func, - authz_read_baton, iterpool)); + subtractive_merge, handling_merged_revisions, + revprops, has_children, callbacks, iterpool)); if (has_children) { if (!nested_merges) @@ -2204,12 +2204,8 @@ do_logs(svn_fs_t *fs, processed, added_mergeinfo, deleted_mergeinfo, - discover_changed_paths, strict_node_history, - revprops, - receiver, receiver_baton, - authz_read_func, - authz_read_baton, + revprops, callbacks, iterpool)); } if (limit && i + 1 >= limit) @@ -2227,7 +2223,7 @@ struct location_segment_baton apr_pool_t *pool; }; -/* svn_location_segment_receiver_t implementation for svn_repos_get_logs4. */ +/* svn_location_segment_receiver_t implementation for svn_repos_get_logs5. */ static svn_error_t * location_segment_receiver(svn_location_segment_t *segment, void *baton, @@ -2247,7 +2243,7 @@ location_segment_receiver(svn_location_segment_t *segment, filesystem. START_REV and END_REV must be valid revisions. RESULT_POOL is used to allocate *PATHS_HISTORY_MERGEINFO, SCRATCH_POOL is used for all other (temporary) allocations. Other parameters are the same as - svn_repos_get_logs4(). */ + svn_repos_get_logs5(). */ static svn_error_t * get_paths_history_as_mergeinfo(svn_mergeinfo_t *paths_history_mergeinfo, svn_repos_t *repos, @@ -2308,41 +2304,56 @@ get_paths_history_as_mergeinfo(svn_mergeinfo_t *paths_history_mergeinfo, } svn_error_t * -svn_repos_get_logs4(svn_repos_t *repos, +svn_repos_get_logs5(svn_repos_t *repos, const apr_array_header_t *paths, svn_revnum_t start, svn_revnum_t end, int limit, - svn_boolean_t discover_changed_paths, svn_boolean_t strict_node_history, svn_boolean_t include_merged_revisions, const apr_array_header_t *revprops, svn_repos_authz_func_t authz_read_func, void *authz_read_baton, - svn_log_entry_receiver_t receiver, - void *receiver_baton, - apr_pool_t *pool) + svn_repos_path_change_receiver_t path_change_receiver, + void *path_change_receiver_baton, + svn_repos_log_entry_receiver_t revision_receiver, + void *revision_receiver_baton, + apr_pool_t *scratch_pool) { svn_revnum_t head = SVN_INVALID_REVNUM; svn_fs_t *fs = repos->fs; svn_boolean_t descending_order; svn_mergeinfo_t paths_history_mergeinfo = NULL; + log_callbacks_t callbacks; + + callbacks.path_change_receiver = path_change_receiver; + callbacks.path_change_receiver_baton = path_change_receiver_baton; + callbacks.revision_receiver = revision_receiver; + callbacks.revision_receiver_baton = revision_receiver_baton; + callbacks.authz_read_func = authz_read_func; + callbacks.authz_read_baton = authz_read_baton; if (revprops) { int i; apr_array_header_t *new_revprops - = apr_array_make(pool, revprops->nelts, sizeof(svn_string_t *)); + = apr_array_make(scratch_pool, revprops->nelts, + sizeof(svn_string_t *)); for (i = 0; i < revprops->nelts; ++i) APR_ARRAY_PUSH(new_revprops, svn_string_t *) - = svn_string_create(APR_ARRAY_IDX(revprops, i, const char *), pool); + = svn_string_create(APR_ARRAY_IDX(revprops, i, const char *), + scratch_pool); revprops = new_revprops; } + /* Make sure we catch up on the latest revprop changes. This is the only + * time we will refresh the revprop data in this query. */ + SVN_ERR(svn_fs_refresh_revision_props(fs, scratch_pool)); + /* Setup log range. */ - SVN_ERR(svn_fs_youngest_rev(&head, fs, pool)); + SVN_ERR(svn_fs_youngest_rev(&head, fs, scratch_pool)); if (! SVN_IS_VALID_REVNUM(start)) start = head; @@ -2371,7 +2382,7 @@ svn_repos_get_logs4(svn_repos_t *repos, } if (! paths) - paths = apr_array_make(pool, 0, sizeof(const char *)); + paths = apr_array_make(scratch_pool, 0, sizeof(const char *)); /* If we're not including merged revisions, and we were given no paths or a single empty (or "/") path, then we can bypass a bunch @@ -2386,7 +2397,7 @@ svn_repos_get_logs4(svn_repos_t *repos, { apr_uint64_t send_count = 0; int i; - apr_pool_t *iterpool = svn_pool_create(pool); + apr_pool_t *iterpool = svn_pool_create(scratch_pool); /* If we are provided an authz callback function, use it to verify that the user has read access to the root path in the @@ -2402,9 +2413,10 @@ svn_repos_get_logs4(svn_repos_t *repos, svn_fs_root_t *rev_root; SVN_ERR(svn_fs_revision_root(&rev_root, fs, - descending_order ? end : start, pool)); + descending_order ? end : start, + scratch_pool)); SVN_ERR(authz_read_func(&readable, rev_root, "", - authz_read_baton, pool)); + authz_read_baton, scratch_pool)); if (! readable) return svn_error_create(SVN_ERR_AUTHZ_UNREADABLE, NULL, NULL); } @@ -2422,10 +2434,9 @@ svn_repos_get_logs4(svn_repos_t *repos, rev = end - i; else rev = start + i; - SVN_ERR(send_log(rev, fs, NULL, NULL, NULL, - discover_changed_paths, FALSE, - FALSE, revprops, FALSE, receiver, receiver_baton, - authz_read_func, authz_read_baton, iterpool)); + SVN_ERR(send_log(rev, fs, NULL, NULL, + FALSE, FALSE, revprops, FALSE, + &callbacks, iterpool)); } svn_pool_destroy(iterpool); @@ -2439,19 +2450,18 @@ svn_repos_get_logs4(svn_repos_t *repos, http://subversion.tigris.org/issues/show_bug.cgi?id=3650#desc5 */ if (include_merged_revisions) { - apr_pool_t *subpool = svn_pool_create(pool); + apr_pool_t *subpool = svn_pool_create(scratch_pool); SVN_ERR(get_paths_history_as_mergeinfo(&paths_history_mergeinfo, repos, paths, start, end, authz_read_func, authz_read_baton, - pool, subpool)); + scratch_pool, subpool)); svn_pool_destroy(subpool); } - return do_logs(repos->fs, paths, paths_history_mergeinfo, NULL, NULL, start, end, - limit, discover_changed_paths, strict_node_history, + return do_logs(repos->fs, paths, paths_history_mergeinfo, NULL, NULL, + start, end, limit, strict_node_history, include_merged_revisions, FALSE, FALSE, FALSE, - revprops, descending_order, receiver, receiver_baton, - authz_read_func, authz_read_baton, pool); + revprops, descending_order, &callbacks, scratch_pool); } diff --git a/subversion/libsvn_repos/replay.c b/subversion/libsvn_repos/replay.c index bcf260c47a04..9bcc667f6da4 100644 --- a/subversion/libsvn_repos/replay.c +++ b/subversion/libsvn_repos/replay.c @@ -198,7 +198,7 @@ add_subdir(svn_fs_root_t *source_root, for (hi = apr_hash_first(pool, dirents); hi; hi = apr_hash_next(hi)) { - svn_fs_path_change2_t *change; + svn_fs_path_change3_t *change; svn_boolean_t readable = TRUE; svn_fs_dirent_t *dent = apr_hash_this_val(hi); const char *copyfrom_path = NULL; @@ -412,7 +412,7 @@ fill_copyfrom(svn_fs_root_t **copyfrom_root, svn_revnum_t *copyfrom_rev, svn_boolean_t *src_readable, svn_fs_root_t *root, - svn_fs_path_change2_t *change, + svn_fs_path_change3_t *change, svn_repos_authz_func_t authz_read_func, void *authz_read_baton, const char *path, @@ -463,7 +463,7 @@ path_driver_cb_func(void **dir_baton, const svn_delta_editor_t *editor = cb->editor; void *edit_baton = cb->edit_baton; svn_fs_root_t *root = cb->root; - svn_fs_path_change2_t *change; + svn_fs_path_change3_t *change; svn_boolean_t do_add = FALSE, do_delete = FALSE; void *file_baton = NULL; svn_revnum_t copyfrom_rev; @@ -555,10 +555,6 @@ path_driver_cb_func(void **dir_baton, return svn_error_create(SVN_ERR_FS_ALREADY_EXISTS, NULL, _("Root directory already exists.")); - /* A NULL parent_baton will cause a segfault. It should never be - NULL for non-root paths. */ - SVN_ERR_ASSERT(parent_baton); - /* Was this node copied? */ SVN_ERR(fill_copyfrom(©from_root, ©from_path, ©from_rev, &src_readable, root, change, @@ -847,6 +843,80 @@ fetch_props_func(apr_hash_t **props, +/* Retrieve the path changes under ROOT, filter them with AUTHZ_READ_FUNC + and AUTHZ_READ_BATON and return those that intersect with BASE_RELPATH. + + The svn_fs_path_change3_t* will be returned in *CHANGED_PATHS, keyed by + their path. The paths themselves are additionally returned in *PATHS. + + Allocate the returned data in RESULT_POOL and use SCRATCH_POOL for + temporary allocations. + */ +static svn_error_t * +get_relevant_changes(apr_hash_t **changed_paths, + apr_array_header_t **paths, + svn_fs_root_t *root, + const char *base_relpath, + svn_repos_authz_func_t authz_read_func, + void *authz_read_baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_fs_path_change_iterator_t *iterator; + svn_fs_path_change3_t *change; + apr_pool_t *iterpool = svn_pool_create(scratch_pool); + + /* Fetch the paths changed under ROOT. */ + SVN_ERR(svn_fs_paths_changed3(&iterator, root, scratch_pool, scratch_pool)); + SVN_ERR(svn_fs_path_change_get(&change, iterator)); + + /* Make an array from the keys of our CHANGED_PATHS hash, and copy + the values into a new hash whose keys have no leading slashes. */ + *paths = apr_array_make(result_pool, 16, sizeof(const char *)); + *changed_paths = apr_hash_make(result_pool); + while (change) + { + const char *path = change->path.data; + apr_ssize_t keylen = change->path.len; + svn_boolean_t allowed = TRUE; + + svn_pool_clear(iterpool); + if (authz_read_func) + SVN_ERR(authz_read_func(&allowed, root, path, authz_read_baton, + iterpool)); + + if (allowed) + { + if (path[0] == '/') + { + path++; + keylen--; + } + + /* If the base_path doesn't match the top directory of this path + we don't want anything to do with it... + ...unless this was a change to one of the parent directories of + base_path. */ + if ( svn_relpath_skip_ancestor(base_relpath, path) + || svn_relpath_skip_ancestor(path, base_relpath)) + { + change = svn_fs_path_change3_dup(change, result_pool); + path = change->path.data; + if (path[0] == '/') + path++; + + APR_ARRAY_PUSH(*paths, const char *) = path; + apr_hash_set(*changed_paths, path, keylen, change); + } + } + + SVN_ERR(svn_fs_path_change_get(&change, iterator)); + } + + svn_pool_destroy(iterpool); + return SVN_NO_ERROR; +} + svn_error_t * svn_repos_replay2(svn_fs_root_t *root, const char *base_path, @@ -859,9 +929,7 @@ svn_repos_replay2(svn_fs_root_t *root, apr_pool_t *pool) { #ifndef USE_EV2_IMPL - apr_hash_t *fs_changes; apr_hash_t *changed_paths; - apr_hash_index_t *hi; apr_array_header_t *paths; struct path_driver_cb_baton cb_baton; @@ -873,54 +941,15 @@ svn_repos_replay2(svn_fs_root_t *root, return SVN_NO_ERROR; } - /* Fetch the paths changed under ROOT. */ - SVN_ERR(svn_fs_paths_changed2(&fs_changes, root, pool)); - if (! base_path) base_path = ""; else if (base_path[0] == '/') ++base_path; - /* Make an array from the keys of our CHANGED_PATHS hash, and copy - the values into a new hash whose keys have no leading slashes. */ - paths = apr_array_make(pool, apr_hash_count(fs_changes), - sizeof(const char *)); - changed_paths = apr_hash_make(pool); - for (hi = apr_hash_first(pool, fs_changes); hi; hi = apr_hash_next(hi)) - { - const char *path = apr_hash_this_key(hi); - apr_ssize_t keylen = apr_hash_this_key_len(hi); - svn_fs_path_change2_t *change = apr_hash_this_val(hi); - svn_boolean_t allowed = TRUE; - - if (authz_read_func) - SVN_ERR(authz_read_func(&allowed, root, path, authz_read_baton, - pool)); - - if (allowed) - { - if (path[0] == '/') - { - path++; - keylen--; - } - - /* If the base_path doesn't match the top directory of this path - we don't want anything to do with it... */ - if (svn_relpath_skip_ancestor(base_path, path) != NULL) - { - APR_ARRAY_PUSH(paths, const char *) = path; - apr_hash_set(changed_paths, path, keylen, change); - } - /* ...unless this was a change to one of the parent directories of - base_path. */ - else if (svn_relpath_skip_ancestor(path, base_path) != NULL) - { - APR_ARRAY_PUSH(paths, const char *) = path; - apr_hash_set(changed_paths, path, keylen, change); - } - } - } + /* Fetch the paths changed under ROOT. */ + SVN_ERR(get_relevant_changes(&changed_paths, &paths, root, base_path, + authz_read_func, authz_read_baton, + pool, pool)); /* If we were not given a low water mark, assume that everything is there, all the way back to revision 0. */ @@ -971,6 +1000,11 @@ svn_repos_replay2(svn_fs_root_t *root, const char *repos_root = ""; void *unlock_baton; + /* If we were not given a low water mark, assume that everything is there, + all the way back to revision 0. */ + if (! SVN_IS_VALID_REVNUM(low_water_mark)) + low_water_mark = 0; + /* Special-case r0, which we know is an empty revision; if we don't special-case it we might end up trying to compare it to "r-1". */ if (svn_fs_is_revision_root(root) @@ -1061,7 +1095,7 @@ add_subdir_ev2(svn_fs_root_t *source_root, for (hi = apr_hash_first(scratch_pool, dirents); hi; hi = apr_hash_next(hi)) { - svn_fs_path_change2_t *change; + svn_fs_path_change3_t *change; svn_boolean_t readable = TRUE; svn_fs_dirent_t *dent = apr_hash_this_val(hi); const char *copyfrom_path = NULL; @@ -1189,7 +1223,7 @@ replay_node(svn_fs_root_t *root, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - svn_fs_path_change2_t *change; + svn_fs_path_change3_t *change; svn_boolean_t do_add = FALSE; svn_boolean_t do_delete = FALSE; svn_revnum_t copyfrom_rev; @@ -1484,16 +1518,14 @@ svn_repos__replay_ev2(svn_fs_root_t *root, void *authz_read_baton, apr_pool_t *scratch_pool) { - apr_hash_t *fs_changes; apr_hash_t *changed_paths; - apr_hash_index_t *hi; apr_array_header_t *paths; apr_array_header_t *copies; apr_pool_t *iterpool; svn_error_t *err = SVN_NO_ERROR; int i; - SVN_ERR_ASSERT(!svn_dirent_is_absolute(base_repos_relpath)); + SVN_ERR_ASSERT(svn_relpath_is_canonical(base_repos_relpath)); /* Special-case r0, which we know is an empty revision; if we don't special-case it we might end up trying to compare it to "r-1". */ @@ -1504,49 +1536,10 @@ svn_repos__replay_ev2(svn_fs_root_t *root, } /* Fetch the paths changed under ROOT. */ - SVN_ERR(svn_fs_paths_changed2(&fs_changes, root, scratch_pool)); - - /* Make an array from the keys of our CHANGED_PATHS hash, and copy - the values into a new hash whose keys have no leading slashes. */ - paths = apr_array_make(scratch_pool, apr_hash_count(fs_changes), - sizeof(const char *)); - changed_paths = apr_hash_make(scratch_pool); - for (hi = apr_hash_first(scratch_pool, fs_changes); hi; - hi = apr_hash_next(hi)) - { - const char *path = apr_hash_this_key(hi); - apr_ssize_t keylen = apr_hash_this_key_len(hi); - svn_fs_path_change2_t *change = apr_hash_this_val(hi); - svn_boolean_t allowed = TRUE; - - if (authz_read_func) - SVN_ERR(authz_read_func(&allowed, root, path, authz_read_baton, - scratch_pool)); - - if (allowed) - { - if (path[0] == '/') - { - path++; - keylen--; - } - - /* If the base_path doesn't match the top directory of this path - we don't want anything to do with it... */ - if (svn_relpath_skip_ancestor(base_repos_relpath, path) != NULL) - { - APR_ARRAY_PUSH(paths, const char *) = path; - apr_hash_set(changed_paths, path, keylen, change); - } - /* ...unless this was a change to one of the parent directories of - base_path. */ - else if (svn_relpath_skip_ancestor(path, base_repos_relpath) != NULL) - { - APR_ARRAY_PUSH(paths, const char *) = path; - apr_hash_set(changed_paths, path, keylen, change); - } - } - } + SVN_ERR(get_relevant_changes(&changed_paths, &paths, root, + base_repos_relpath, + authz_read_func, authz_read_baton, + scratch_pool, scratch_pool)); /* If we were not given a low water mark, assume that everything is there, all the way back to revision 0. */ diff --git a/subversion/libsvn_repos/reporter.c b/subversion/libsvn_repos/reporter.c index 76c72016144c..f56cb2ee980c 100644 --- a/subversion/libsvn_repos/reporter.c +++ b/subversion/libsvn_repos/reporter.c @@ -481,10 +481,12 @@ get_revision_info(report_baton_t *b, { /* Info is not available, yet. Get all revprops. */ - SVN_ERR(svn_fs_revision_proplist(&r_props, - b->repos->fs, - rev, - scratch_pool)); + SVN_ERR(svn_fs_revision_proplist2(&r_props, + b->repos->fs, + rev, + FALSE, + scratch_pool, + scratch_pool)); /* Extract the committed-date. */ cdate = svn_hash_gets(r_props, SVN_PROP_REVISION_DATE); @@ -520,19 +522,13 @@ delta_proplists(report_baton_t *b, svn_revnum_t s_rev, const char *s_path, { svn_fs_root_t *s_root; apr_hash_t *s_props = NULL, *t_props; - apr_array_header_t *prop_diffs; - int i; svn_revnum_t crev; - revision_info_t *revision_info; - svn_boolean_t changed; - const svn_prop_t *pc; - svn_lock_t *lock; - apr_hash_index_t *hi; /* Fetch the created-rev and send entry props. */ SVN_ERR(svn_fs_node_created_rev(&crev, b->t_root, t_path, pool)); if (SVN_IS_VALID_REVNUM(crev)) { + revision_info_t *revision_info; /* convert committed-rev to string */ char buf[SVN_INT64_BUFFER_SIZE]; svn_string_t cr_str; @@ -563,6 +559,7 @@ delta_proplists(report_baton_t *b, svn_revnum_t s_rev, const char *s_path, /* Update lock properties. */ if (lock_token) { + svn_lock_t *lock; SVN_ERR(svn_fs_get_lock(&lock, b->repos->fs, t_path, pool)); /* Delete a defunct lock. */ @@ -573,6 +570,7 @@ delta_proplists(report_baton_t *b, svn_revnum_t s_rev, const char *s_path, if (s_path) { + svn_boolean_t changed; SVN_ERR(get_source_root(b, &s_root, s_rev)); /* Is this deltification worth our time? */ @@ -590,16 +588,20 @@ delta_proplists(report_baton_t *b, svn_revnum_t s_rev, const char *s_path, if (s_props && apr_hash_count(s_props)) { + apr_array_header_t *prop_diffs; + int i; + /* Now transmit the differences. */ SVN_ERR(svn_prop_diffs(&prop_diffs, t_props, s_props, pool)); for (i = 0; i < prop_diffs->nelts; i++) { - pc = &APR_ARRAY_IDX(prop_diffs, i, svn_prop_t); + const svn_prop_t *pc = &APR_ARRAY_IDX(prop_diffs, i, svn_prop_t); SVN_ERR(change_fn(b, object, pc->name, pc->value, pool)); } } else if (apr_hash_count(t_props)) { + apr_hash_index_t *hi; /* So source, i.e. all new. Transmit all target props. */ for (hi = apr_hash_first(pool, t_props); hi; hi = apr_hash_next(hi)) { @@ -669,7 +671,6 @@ delta_files(report_baton_t *b, void *file_baton, svn_revnum_t s_rev, const char *s_path, const char *t_path, const char *lock_token, apr_pool_t *pool) { - svn_boolean_t changed; svn_fs_root_t *s_root = NULL; svn_txdelta_stream_t *dstream = NULL; svn_checksum_t *s_checksum; @@ -683,14 +684,15 @@ delta_files(report_baton_t *b, void *file_baton, svn_revnum_t s_rev, if (s_path) { + svn_boolean_t changed; SVN_ERR(get_source_root(b, &s_root, s_rev)); /* We're not interested in the theoretical difference between "has contents which have not changed with respect to" and "has the same actual contents as" when sending text-deltas. If we know the delta is an empty one, we avoiding sending it in either case. */ - SVN_ERR(svn_repos__compare_files(&changed, b->t_root, t_path, - s_root, s_path, pool)); + SVN_ERR(svn_fs_contents_different(&changed, b->t_root, t_path, + s_root, s_path, pool)); if (!changed) return SVN_NO_ERROR; @@ -971,11 +973,11 @@ update_entry(report_baton_t *b, svn_revnum_t s_rev, const char *s_path, if (s_root == NULL) SVN_ERR(get_source_root(b, &s_root, s_rev)); - SVN_ERR(svn_fs_props_different(&changed, s_root, s_path, - b->t_root, t_path, pool)); + SVN_ERR(svn_fs_props_changed(&changed, s_root, s_path, + b->t_root, t_path, pool)); if (!changed) - SVN_ERR(svn_fs_contents_different(&changed, s_root, s_path, - b->t_root, t_path, pool)); + SVN_ERR(svn_fs_contents_changed(&changed, s_root, s_path, + b->t_root, t_path, pool)); } if ((distance == 0 || !changed) && !any_path_info(b, e_path) @@ -1567,6 +1569,7 @@ svn_repos_finish_report(void *baton, apr_pool_t *pool) { report_baton_t *b = baton; + SVN_ERR(svn_fs_refresh_revision_props(svn_repos_fs(b->repos), pool)); return svn_error_trace(finish_report(b, pool)); } diff --git a/subversion/libsvn_repos/repos.c b/subversion/libsvn_repos/repos.c index 1d62aeb501f1..2333f561efda 100644 --- a/subversion/libsvn_repos/repos.c +++ b/subversion/libsvn_repos/repos.c @@ -393,15 +393,15 @@ create_hooks(svn_repos_t *repos, apr_pool_t *pool) "# e.g.: \"" SVN_RA_CAPABILITY_MERGEINFO ":some-other-capability\" " \ "(the order is undefined)." NL "#" NL +"# The list is self-reported by the client. Therefore, you should not" NL +"# make security assumptions based on the capabilities list, nor should" NL +"# you assume that clients reliably report every capability they have." NL +"#" NL "# Note: The TXN-NAME parameter is new in Subversion 1.8. Prior to version" NL "# 1.8, the start-commit hook was invoked before the commit txn was even" NL "# created, so the ability to inspect the commit txn and its metadata from" NL "# within the start-commit hook was not possible." NL "# " NL -"# The list is self-reported by the client. Therefore, you should not" NL -"# make security assumptions based on the capabilities list, nor should" NL -"# you assume that clients reliably report every capability they have." NL -"#" NL "# If the hook program exits with success, the commit continues; but" NL "# if it exits with failure (non-zero), the commit is stopped before" NL "# a Subversion txn is created, and STDERR is returned to the client." NL; @@ -882,7 +882,7 @@ create_conf(svn_repos_t *repos, apr_pool_t *pool) "[sasl]" NL "### This option specifies whether you want to use the Cyrus SASL" NL "### library for authentication. Default is false." NL -"### This section will be ignored if svnserve is not built with Cyrus" NL +"### Enabling this option requires svnserve to have been built with Cyrus" NL "### SASL support; to check, run 'svnserve --version' and look for a line" NL "### reading 'Cyrus SASL authentication is available.'" NL "# use-sasl = true" NL @@ -1180,8 +1180,8 @@ svn_repos_create(svn_repos_t **repos_p, SVN_ERR(lock_repos(repos, FALSE, FALSE, scratch_pool)); /* Create an environment for the filesystem. */ - if ((err = svn_fs_create(&repos->fs, repos->db_path, fs_config, - result_pool))) + if ((err = svn_fs_create2(&repos->fs, repos->db_path, fs_config, + result_pool, scratch_pool))) { /* If there was an error making the filesytem, e.g. unknown/supported * filesystem type. Clean up after ourselves. Yes this is safe because @@ -1504,6 +1504,16 @@ static const char *capability_yes = "yes"; /* Repository does not support the capability. */ static const char *capability_no = "no"; +static svn_error_t * +dummy_mergeinfo_receiver(const char *path, + svn_mergeinfo_t mergeinfo, + void *baton, + apr_pool_t *scratch_pool) +{ + return SVN_NO_ERROR; +} + + svn_error_t * svn_repos_has_capability(svn_repos_t *repos, svn_boolean_t *has, @@ -1525,14 +1535,13 @@ svn_repos_has_capability(svn_repos_t *repos, { svn_error_t *err; svn_fs_root_t *root; - svn_mergeinfo_catalog_t ignored; apr_array_header_t *paths = apr_array_make(pool, 1, sizeof(char *)); SVN_ERR(svn_fs_revision_root(&root, repos->fs, 0, pool)); APR_ARRAY_PUSH(paths, const char *) = ""; - err = svn_fs_get_mergeinfo2(&ignored, root, paths, FALSE, FALSE, - TRUE, pool, pool); + err = svn_fs_get_mergeinfo3(root, paths, FALSE, FALSE, TRUE, + dummy_mergeinfo_receiver, NULL, pool); if (err) { @@ -2061,45 +2070,6 @@ svn_repos_version(void) SVN_VERSION_BODY; } - - -svn_error_t * -svn_repos_stat(svn_dirent_t **dirent, - svn_fs_root_t *root, - const char *path, - apr_pool_t *pool) -{ - svn_node_kind_t kind; - svn_dirent_t *ent; - const char *datestring; - - SVN_ERR(svn_fs_check_path(&kind, root, path, pool)); - - if (kind == svn_node_none) - { - *dirent = NULL; - return SVN_NO_ERROR; - } - - ent = svn_dirent_create(pool); - ent->kind = kind; - - if (kind == svn_node_file) - SVN_ERR(svn_fs_file_length(&(ent->size), root, path, pool)); - - SVN_ERR(svn_fs_node_has_props(&ent->has_props, root, path, pool)); - - SVN_ERR(svn_repos_get_committed_info(&(ent->created_rev), - &datestring, - &(ent->last_author), - root, path, pool)); - if (datestring) - SVN_ERR(svn_time_from_cstring(&(ent->time), datestring, pool)); - - *dirent = ent; - return SVN_NO_ERROR; -} - svn_error_t * svn_repos_remember_client_capabilities(svn_repos_t *repos, const apr_array_header_t *capabilities) diff --git a/subversion/libsvn_repos/repos.h b/subversion/libsvn_repos/repos.h index b1039acd8d9f..2274032dd769 100644 --- a/subversion/libsvn_repos/repos.h +++ b/subversion/libsvn_repos/repos.h @@ -27,6 +27,7 @@ #include #include "svn_fs.h" +#include "svn_config.h" #ifdef __cplusplus extern "C" { @@ -361,46 +362,9 @@ svn_repos__hooks_post_unlock(svn_repos_t *repos, const char *username, apr_pool_t *pool); - -/*** Authz Functions ***/ - -/* Read authz configuration data from PATH into *AUTHZ_P, allocated - in POOL. If GROUPS_PATH is set, use the global groups parsed from it. - - PATH and GROUPS_PATH may be a dirent or a registry path and iff ACCEPT_URLS - is set it may also be an absolute file url. - - If PATH or GROUPS_PATH is not a valid authz rule file, then return - SVN_AUTHZ_INVALID_CONFIG. The contents of *AUTHZ_P is then - undefined. If MUST_EXIST is TRUE, a missing authz or global groups file - is also an error. */ -svn_error_t * -svn_repos__authz_read(svn_authz_t **authz_p, - const char *path, - const char *groups_path, - svn_boolean_t must_exist, - svn_boolean_t accept_urls, - apr_pool_t *pool); - -/* Walk the configuration in AUTHZ looking for any errors. */ -svn_error_t * -svn_repos__authz_validate(svn_authz_t *authz, - apr_pool_t *pool); - /*** Utility Functions ***/ -/* Set *CHANGED_P to TRUE if ROOT1/PATH1 and ROOT2/PATH2 have - different contents, FALSE if they have the same contents. - Use POOL for temporary allocation. */ -svn_error_t * -svn_repos__compare_files(svn_boolean_t *changed_p, - svn_fs_root_t *root1, - const char *path1, - svn_fs_root_t *root2, - const char *path2, - apr_pool_t *pool); - /* Set *PREV_PATH and *PREV_REV to the path and revision which represent the location at which PATH in FS was located immediately prior to REVISION iff there was a copy operation (to PATH or one of diff --git a/subversion/libsvn_repos/rev_hunt.c b/subversion/libsvn_repos/rev_hunt.c index d6cc49576d12..558d691b9bfe 100644 --- a/subversion/libsvn_repos/rev_hunt.c +++ b/subversion/libsvn_repos/rev_hunt.c @@ -44,7 +44,7 @@ /* Note: this binary search assumes that the datestamp properties on each revision are in chronological order. That is if revision A > - revision B, then A's datestamp is younger then B's datestamp. + revision B, then A's datestamp is younger than B's datestamp. If someone comes along and sets a bogus datestamp, this routine might not work right. @@ -65,8 +65,8 @@ get_time(apr_time_t *tm, { svn_string_t *date_str; - SVN_ERR(svn_fs_revision_prop(&date_str, fs, rev, SVN_PROP_REVISION_DATE, - pool)); + SVN_ERR(svn_fs_revision_prop2(&date_str, fs, rev, SVN_PROP_REVISION_DATE, + FALSE, pool, pool)); if (! date_str) return svn_error_createf (SVN_ERR_FS_GENERAL, NULL, @@ -88,6 +88,7 @@ svn_repos_dated_revision(svn_revnum_t *revision, /* Initialize top and bottom values of binary search. */ SVN_ERR(svn_fs_youngest_rev(&rev_latest, fs, pool)); + SVN_ERR(svn_fs_refresh_revision_props(fs, pool)); rev_bot = 0; rev_top = rev_latest; @@ -170,7 +171,8 @@ svn_repos_get_committed_info(svn_revnum_t *committed_rev, SVN_ERR(svn_fs_node_created_rev(committed_rev, root, path, pool)); /* Get the revision properties of this revision. */ - SVN_ERR(svn_fs_revision_proplist(&revprops, fs, *committed_rev, pool)); + SVN_ERR(svn_fs_revision_proplist2(&revprops, fs, *committed_rev, TRUE, + pool, pool)); /* Extract date and author from these revprops. */ committed_date_s = svn_hash_gets(revprops, SVN_PROP_REVISION_DATE); @@ -669,8 +671,7 @@ svn_repos_trace_node_locations(svn_fs_t *fs, /* First - let's sort the array of the revisions from the greatest revision * downward, so it will be easier to search on. */ location_revisions = apr_array_copy(pool, location_revisions_orig); - qsort(location_revisions->elts, location_revisions->nelts, - sizeof(*revision_ptr), svn_sort_compare_revisions); + svn_sort__array(location_revisions, svn_sort_compare_revisions); revision_ptr = (svn_revnum_t *)location_revisions->elts; revision_ptr_end = revision_ptr + location_revisions->nelts; @@ -835,27 +836,32 @@ svn_repos_node_location_segments(svn_repos_t *repos, { svn_fs_t *fs = svn_repos_fs(repos); svn_stringbuf_t *current_path; - svn_revnum_t youngest_rev = SVN_INVALID_REVNUM, current_rev; + svn_revnum_t youngest_rev, current_rev; apr_pool_t *subpool; + SVN_ERR(svn_fs_youngest_rev(&youngest_rev, fs, pool)); + /* No PEG_REVISION? We'll use HEAD. */ if (! SVN_IS_VALID_REVNUM(peg_revision)) - { - SVN_ERR(svn_fs_youngest_rev(&youngest_rev, fs, pool)); - peg_revision = youngest_rev; - } + peg_revision = youngest_rev; - /* No START_REV? We'll use HEAD (which we may have already fetched). */ + if (peg_revision > youngest_rev) + return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL, + _("No such revision %ld"), peg_revision); + + /* No START_REV? We'll use peg rev. */ if (! SVN_IS_VALID_REVNUM(start_rev)) - { - if (SVN_IS_VALID_REVNUM(youngest_rev)) - start_rev = youngest_rev; - else - SVN_ERR(svn_fs_youngest_rev(&start_rev, fs, pool)); - } + start_rev = peg_revision; + else if (start_rev > peg_revision) + return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL, + _("No such revision %ld"), start_rev); /* No END_REV? We'll use 0. */ - end_rev = SVN_IS_VALID_REVNUM(end_rev) ? end_rev : 0; + if (! SVN_IS_VALID_REVNUM(end_rev)) + end_rev = 0; + else if (end_rev > start_rev) + return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL, + _("No such revision %ld"), end_rev); /* Are the revision properly ordered? They better be -- the API demands it. */ @@ -1006,26 +1012,39 @@ get_merged_mergeinfo(apr_hash_t **merged_mergeinfo, apr_hash_t *curr_mergeinfo, *prev_mergeinfo, *deleted, *changed; svn_error_t *err; svn_fs_root_t *root, *prev_root; - apr_hash_t *changed_paths; - const char *path = old_path_rev->path; + const char *start_path = old_path_rev->path; + const char *path = NULL; + + svn_fs_path_change_iterator_t *iterator; + svn_fs_path_change3_t *change; /* Getting/parsing/diffing svn:mergeinfo is expensive, so only do it if there is a property change. */ SVN_ERR(svn_fs_revision_root(&root, repos->fs, old_path_rev->revnum, scratch_pool)); - SVN_ERR(svn_fs_paths_changed2(&changed_paths, root, scratch_pool)); - while (1) + SVN_ERR(svn_fs_paths_changed3(&iterator, root, scratch_pool, scratch_pool)); + SVN_ERR(svn_fs_path_change_get(&change, iterator)); + + /* Find the changed PATH closest to START_PATH which may have a mergeinfo + * change. */ + while (change) { - svn_fs_path_change2_t *changed_path = svn_hash_gets(changed_paths, path); - if (changed_path && changed_path->prop_mod - && changed_path->mergeinfo_mod != svn_tristate_false) - break; - if (svn_fspath__is_root(path, strlen(path))) + if ( change->prop_mod + && change->mergeinfo_mod != svn_tristate_false + && svn_fspath__skip_ancestor(change->path.data, start_path)) { - *merged_mergeinfo = NULL; - return SVN_NO_ERROR; + if (!path || svn_fspath__skip_ancestor(path, change->path.data)) + path = apr_pstrmemdup(scratch_pool, change->path.data, + change->path.len); } - path = svn_fspath__dirname(path, scratch_pool); + + SVN_ERR(svn_fs_path_change_get(&change, iterator)); + } + + if (path == NULL) + { + *merged_mergeinfo = NULL; + return SVN_NO_ERROR; } /* First, find the mergeinfo difference for old_path_rev->revnum, and @@ -1350,22 +1369,48 @@ send_path_revision(struct path_revision *path_rev, void *delta_baton = NULL; apr_pool_t *tmp_pool; /* For swapping */ svn_boolean_t contents_changed; + svn_boolean_t props_changed; svn_pool_clear(sb->iterpool); /* Get the revision properties. */ - SVN_ERR(svn_fs_revision_proplist(&rev_props, repos->fs, - path_rev->revnum, sb->iterpool)); + SVN_ERR(svn_fs_revision_proplist2(&rev_props, repos->fs, + path_rev->revnum, FALSE, + sb->iterpool, sb->iterpool)); /* Open the revision root. */ SVN_ERR(svn_fs_revision_root(&root, repos->fs, path_rev->revnum, sb->iterpool)); - /* Get the file's properties for this revision and compute the diffs. */ - SVN_ERR(svn_fs_node_proplist(&props, root, path_rev->path, + /* Check if the props *may* have changed. */ + if (sb->last_root) + { + /* We don't use svn_fs_props_different() because it's more + * expensive. */ + SVN_ERR(svn_fs_props_changed(&props_changed, + sb->last_root, sb->last_path, + root, path_rev->path, sb->iterpool)); + } + else + { + props_changed = TRUE; + } + + /* Calculate actual difference between last and current properties. */ + if (props_changed) + { + /* Get the file's properties for this revision and compute the diffs. */ + SVN_ERR(svn_fs_node_proplist(&props, root, path_rev->path, sb->iterpool)); - SVN_ERR(svn_prop_diffs(&prop_diffs, props, sb->last_props, - sb->iterpool)); + SVN_ERR(svn_prop_diffs(&prop_diffs, props, sb->last_props, + sb->iterpool)); + } + else + { + /* Properties didn't change: copy LAST_PROPS to current POOL. */ + props = svn_prop_hash_dup(sb->last_props, sb->iterpool); + prop_diffs = apr_array_make(sb->iterpool, 0, sizeof(svn_prop_t)); + } /* Check if the contents *may* have changed. */ if (! sb->last_root) @@ -1590,6 +1635,10 @@ svn_repos_get_file_revs2(svn_repos_t *repos, end = youngest_rev; } + /* Make sure we catch up on the latest revprop changes. This is the only + * time we will refresh the revprop data in this query. */ + SVN_ERR(svn_fs_refresh_revision_props(repos->fs, scratch_pool)); + if (end < start) { if (include_merged_revisions) diff --git a/subversion/libsvn_subr/atomic.c b/subversion/libsvn_subr/atomic.c index b760da4fe156..401d3d9d7e16 100644 --- a/subversion/libsvn_subr/atomic.c +++ b/subversion/libsvn_subr/atomic.c @@ -20,8 +20,13 @@ * ==================================================================== */ +#include #include + +#include "svn_pools.h" + #include "private/svn_atomic.h" +#include "private/svn_mutex.h" /* Magic values for atomic initialization */ #define SVN_ATOMIC_UNINITIALIZED 0 @@ -29,11 +34,21 @@ #define SVN_ATOMIC_INIT_FAILED 2 #define SVN_ATOMIC_INITIALIZED 3 -svn_error_t* -svn_atomic__init_once(volatile svn_atomic_t *global_status, - svn_error_t *(*init_func)(void*,apr_pool_t*), - void *baton, - apr_pool_t* pool) + +/* Baton used by init_funct_t and init_once(). */ +typedef struct init_baton_t init_baton_t; + +/* Initialization function wrapper. Hides API details from init_once(). + The implementation must return FALSE on failure. */ +typedef svn_boolean_t (*init_func_t)(init_baton_t *init_baton); + +/* + * This is the actual atomic initialization driver. + * Returns FALSE on failure. + */ +static svn_boolean_t +init_once(volatile svn_atomic_t *global_status, + init_func_t init_func, init_baton_t *init_baton) { /* !! Don't use localizable strings in this function, because these !! might cause deadlocks. This function can be used to initialize @@ -42,44 +57,162 @@ svn_atomic__init_once(volatile svn_atomic_t *global_status, /* We have to call init_func exactly once. Because APR doesn't have statically-initialized mutexes, we implement a poor man's spinlock using svn_atomic_cas. */ + svn_atomic_t status = svn_atomic_cas(global_status, SVN_ATOMIC_START_INIT, SVN_ATOMIC_UNINITIALIZED); - if (status == SVN_ATOMIC_UNINITIALIZED) + for (;;) { - svn_error_t *err = init_func(baton, pool); - if (err) + switch (status) { -#if APR_HAS_THREADS - /* Tell other threads that the initialization failed. */ - svn_atomic_cas(global_status, - SVN_ATOMIC_INIT_FAILED, - SVN_ATOMIC_START_INIT); -#endif - return svn_error_create(SVN_ERR_ATOMIC_INIT_FAILURE, err, - "Couldn't perform atomic initialization"); + case SVN_ATOMIC_UNINITIALIZED: + { + const svn_boolean_t result = init_func(init_baton); + const svn_atomic_t init_state = (result + ? SVN_ATOMIC_INITIALIZED + : SVN_ATOMIC_INIT_FAILED); + + svn_atomic_cas(global_status, init_state, + SVN_ATOMIC_START_INIT); + return result; + } + + case SVN_ATOMIC_START_INIT: + /* Wait for the init function to complete. */ + apr_sleep(APR_USEC_PER_SEC / 1000); + status = svn_atomic_cas(global_status, + SVN_ATOMIC_UNINITIALIZED, + SVN_ATOMIC_UNINITIALIZED); + continue; + + case SVN_ATOMIC_INIT_FAILED: + return FALSE; + + case SVN_ATOMIC_INITIALIZED: + return TRUE; + + default: + /* Something went seriously wrong with the atomic operations. */ + abort(); } - svn_atomic_cas(global_status, - SVN_ATOMIC_INITIALIZED, - SVN_ATOMIC_START_INIT); } -#if APR_HAS_THREADS - /* Wait for whichever thread is performing initialization to finish. */ - /* XXX FIXME: Should we have a maximum wait here, like we have in - the Windows file IO spinner? */ - else while (status != SVN_ATOMIC_INITIALIZED) - { - if (status == SVN_ATOMIC_INIT_FAILED) - return svn_error_create(SVN_ERR_ATOMIC_INIT_FAILURE, NULL, - "Couldn't perform atomic initialization"); +} - apr_sleep(APR_USEC_PER_SEC / 1000); - status = svn_atomic_cas(global_status, - SVN_ATOMIC_UNINITIALIZED, - SVN_ATOMIC_UNINITIALIZED); - } -#endif /* APR_HAS_THREADS */ +/* This baton structure is used by the two flavours of init-once APIs + to hide their differences from the init_once() driver. Each private + API uses only selected parts of the baton. + + No part of this structure changes unless a wrapped init function is + actually invoked by init_once(). +*/ +struct init_baton_t +{ + /* Used only by svn_atomic__init_once()/err_init_func_wrapper() */ + svn_atomic__err_init_func_t err_init_func; + svn_error_t *err; + apr_pool_t *pool; + + /* Used only by svn_atomic__init_no_error()/str_init_func_wrapper() */ + svn_atomic__str_init_func_t str_init_func; + const char *errstr; + + /* Used by both pairs of functions */ + void *baton; +}; + +/* Wrapper for the svn_atomic__init_once init function. */ +static svn_boolean_t err_init_func_wrapper(init_baton_t *init_baton) +{ + init_baton->err = init_baton->err_init_func(init_baton->baton, + init_baton->pool); + return (init_baton->err == SVN_NO_ERROR); +} + +svn_error_t * +svn_atomic__init_once(volatile svn_atomic_t *global_status, + svn_atomic__err_init_func_t err_init_func, + void *baton, + apr_pool_t* pool) +{ + init_baton_t init_baton; + init_baton.err_init_func = err_init_func; + init_baton.err = NULL; + init_baton.pool = pool; + init_baton.baton = baton; + + if (init_once(global_status, err_init_func_wrapper, &init_baton)) + return SVN_NO_ERROR; + + return svn_error_create(SVN_ERR_ATOMIC_INIT_FAILURE, init_baton.err, + "Couldn't perform atomic initialization"); +} + + +/* Wrapper for the svn_atomic__init_no_error init function. */ +static svn_boolean_t str_init_func_wrapper(init_baton_t *init_baton) +{ + init_baton->errstr = init_baton->str_init_func(init_baton->baton); + return (init_baton->errstr == NULL); +} + +const char * +svn_atomic__init_once_no_error(volatile svn_atomic_t *global_status, + svn_atomic__str_init_func_t str_init_func, + void *baton) +{ + init_baton_t init_baton; + init_baton.str_init_func = str_init_func; + init_baton.errstr = NULL; + init_baton.baton = baton; + + if (init_once(global_status, str_init_func_wrapper, &init_baton)) + return NULL; + + /* Our init function wrapper may not have been called; make sure + that we return generic error message in that case. */ + if (!init_baton.errstr) + return "Couldn't perform atomic initialization"; + else + return init_baton.errstr; +} + +/* The process-global counter that we use to produce process-wide unique + * values. Since APR has no 64 bit atomics, all access to this will be + * serialized through COUNTER_MUTEX. */ +static apr_uint64_t uniqiue_counter = 0; + +/* The corresponding mutex and initialization state. */ +static volatile svn_atomic_t counter_status = SVN_ATOMIC_UNINITIALIZED; +static svn_mutex__t *counter_mutex = NULL; + +/* svn_atomic__err_init_func_t implementation that initializes COUNTER_MUTEX. + * Note that neither argument will be used and should be NULL. */ +static svn_error_t * +init_unique_counter(void *null_baton, + apr_pool_t *null_pool) +{ + /* COUNTER_MUTEX is global, so it needs to live in a global pool. + * APR also makes those thread-safe by default. */ + SVN_ERR(svn_mutex__init(&counter_mutex, TRUE, svn_pool_create(NULL))); + return SVN_NO_ERROR; +} + +/* Read and increment UNIQIUE_COUNTER. Return the new value in *VALUE. + * Call this function only while having acquired the COUNTER_MUTEX. */ +static svn_error_t * +read_unique_counter(apr_uint64_t *value) +{ + *value = ++uniqiue_counter; + return SVN_NO_ERROR; +} + +svn_error_t * +svn_atomic__unique_counter(apr_uint64_t *value) +{ + SVN_ERR(svn_atomic__init_once(&counter_status, init_unique_counter, NULL, + NULL)); + SVN_MUTEX__WITH_LOCK(counter_mutex, read_unique_counter(value)); return SVN_NO_ERROR; } diff --git a/subversion/libsvn_subr/auth.c b/subversion/libsvn_subr/auth.c index 303c41e5cc05..9d58c7319437 100644 --- a/subversion/libsvn_subr/auth.c +++ b/subversion/libsvn_subr/auth.c @@ -207,8 +207,7 @@ svn_auth_get_parameter(svn_auth_baton_t *auth_baton, value = svn_hash_gets(auth_baton->slave_parameters, name); if (value) - return (value == &auth_NULL) ? NULL - : value; + return (value == &auth_NULL ? NULL : value); return svn_hash_gets(auth_baton->parameters, name); } @@ -394,13 +393,11 @@ svn_auth_save_credentials(svn_auth_iterstate_t *state, svn_auth_provider_object_t *provider; svn_boolean_t save_succeeded = FALSE; const char *no_auth_cache; - svn_auth_baton_t *auth_baton; void *creds; if (! state || state->table->providers->nelts <= state->provider_idx) return SVN_NO_ERROR; - auth_baton = state->auth_baton; creds = svn_hash_gets(state->auth_baton->creds_cache, state->cache_key); if (! creds) return SVN_NO_ERROR; @@ -505,7 +502,7 @@ svn_auth_get_platform_specific_provider(svn_auth_provider_object_t **provider, if (apr_strnatcmp(provider_name, "gnome_keyring") == 0 || apr_strnatcmp(provider_name, "kwallet") == 0) { -#if defined(SVN_HAVE_GNOME_KEYRING) || defined(SVN_HAVE_KWALLET) +#if defined(SVN_HAVE_GNOME_KEYRING) || defined(SVN_HAVE_KWALLET) || defined (SVN_HAVE_LIBSECRET) apr_dso_handle_t *dso; apr_dso_handle_sym_t provider_function_symbol, version_function_symbol; const char *library_label, *library_name; @@ -770,12 +767,10 @@ svn_auth__make_session_auth(svn_auth_baton_t **session_auth_baton, * "store-auth-creds = yes" -- they'll get the expected behaviour. */ - if (svn_auth_get_parameter(ab, - SVN_AUTH_PARAM_DONT_STORE_PASSWORDS) != NULL) + if (svn_auth_get_parameter(ab, SVN_AUTH_PARAM_DONT_STORE_PASSWORDS) != NULL) store_passwords = FALSE; - if (svn_auth_get_parameter(ab, - SVN_AUTH_PARAM_NO_AUTH_CACHE) != NULL) + if (svn_auth_get_parameter(ab, SVN_AUTH_PARAM_NO_AUTH_CACHE) != NULL) store_auth_creds = FALSE; /* All the svn_auth_set_parameter() calls below this not only affect the @@ -860,8 +855,7 @@ svn_auth__make_session_auth(svn_auth_baton_t **session_auth_baton, /* Save auth caching parameters in the auth parameter hash. */ if (! store_passwords) - svn_auth_set_parameter(ab, - SVN_AUTH_PARAM_DONT_STORE_PASSWORDS, ""); + svn_auth_set_parameter(ab, SVN_AUTH_PARAM_DONT_STORE_PASSWORDS, ""); svn_auth_set_parameter(ab, SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSWORDS, @@ -877,8 +871,7 @@ svn_auth__make_session_auth(svn_auth_baton_t **session_auth_baton, store_pp_plaintext); if (! store_auth_creds) - svn_auth_set_parameter(ab, - SVN_AUTH_PARAM_NO_AUTH_CACHE, ""); + svn_auth_set_parameter(ab, SVN_AUTH_PARAM_NO_AUTH_CACHE, ""); if (server_group) svn_auth_set_parameter(ab, diff --git a/subversion/libsvn_subr/base64.c b/subversion/libsvn_subr/base64.c index 97ee3d285c50..61774a72abd9 100644 --- a/subversion/libsvn_subr/base64.c +++ b/subversion/libsvn_subr/base64.c @@ -58,6 +58,7 @@ struct encode_baton { unsigned char buf[3]; /* Bytes waiting to be encoded */ size_t buflen; /* Number of bytes waiting */ size_t linelen; /* Bytes output so far on this line */ + svn_boolean_t break_lines; apr_pool_t *scratch_pool; }; @@ -140,7 +141,7 @@ encode_bytes(svn_stringbuf_t *str, const void *data, apr_size_t len, svn_stringbuf_ensure(str, str->len + buflen); /* Keep encoding three-byte groups until we run out. */ - while (*inbuflen + (end - p) >= 3) + while ((end - p) >= (3 - *inbuflen)) { /* May we encode BYTES_PER_LINE bytes without caring about line breaks, data in the temporary INBUF or running out @@ -214,7 +215,8 @@ encode_data(void *baton, const char *data, apr_size_t *len) svn_error_t *err = SVN_NO_ERROR; /* Encode this block of data and write it out. */ - encode_bytes(encoded, data, *len, eb->buf, &eb->buflen, &eb->linelen, TRUE); + encode_bytes(encoded, data, *len, eb->buf, &eb->buflen, &eb->linelen, + eb->break_lines); enclen = encoded->len; if (enclen != 0) err = svn_stream_write(eb->output, encoded->data, &enclen); @@ -233,7 +235,8 @@ finish_encoding_data(void *baton) svn_error_t *err = SVN_NO_ERROR; /* Encode a partial group at the end if necessary, and write it out. */ - encode_partial_group(encoded, eb->buf, eb->buflen, eb->linelen, TRUE); + encode_partial_group(encoded, eb->buf, eb->buflen, eb->linelen, + eb->break_lines); enclen = encoded->len; if (enclen != 0) err = svn_stream_write(eb->output, encoded->data, &enclen); @@ -247,7 +250,9 @@ finish_encoding_data(void *baton) svn_stream_t * -svn_base64_encode(svn_stream_t *output, apr_pool_t *pool) +svn_base64_encode2(svn_stream_t *output, + svn_boolean_t break_lines, + apr_pool_t *pool) { struct encode_baton *eb = apr_palloc(pool, sizeof(*eb)); svn_stream_t *stream; @@ -255,6 +260,7 @@ svn_base64_encode(svn_stream_t *output, apr_pool_t *pool) eb->output = output; eb->buflen = 0; eb->linelen = 0; + eb->break_lines = break_lines; eb->scratch_pool = svn_pool_create(pool); stream = svn_stream_create(eb, pool); svn_stream_set_write(stream, encode_data); @@ -424,7 +430,7 @@ decode_bytes(svn_stringbuf_t *str, const char *data, apr_size_t len, /* If no data is left in temporary INBUF and there is at least one line-sized chunk left to decode, we may use the optimized code path. */ - if ((*inbuflen == 0) && (p + BASE64_LINELEN <= end)) + if ((*inbuflen == 0) && (end - p >= BASE64_LINELEN)) if (decode_line(str, &p)) continue; diff --git a/subversion/libsvn_subr/cache-inprocess.c b/subversion/libsvn_subr/cache-inprocess.c index a0e0bbff4708..7799ce007e09 100644 --- a/subversion/libsvn_subr/cache-inprocess.c +++ b/subversion/libsvn_subr/cache-inprocess.c @@ -23,8 +23,6 @@ #include -#include - #include "svn_pools.h" #include "svn_private_config.h" diff --git a/subversion/libsvn_subr/cache-membuffer.c b/subversion/libsvn_subr/cache-membuffer.c index 87ac96168b0f..889c65a2c336 100644 --- a/subversion/libsvn_subr/cache-membuffer.c +++ b/subversion/libsvn_subr/cache-membuffer.c @@ -28,12 +28,14 @@ #include "svn_pools.h" #include "svn_checksum.h" #include "svn_private_config.h" +#include "svn_hash.h" #include "svn_string.h" #include "svn_sorts.h" /* get the MIN macro */ #include "private/svn_atomic.h" #include "private/svn_dep_compat.h" #include "private/svn_mutex.h" +#include "private/svn_subr_private.h" #include "private/svn_string_private.h" #include "cache.h" @@ -117,6 +119,12 @@ * key length stored in the entry acts as an additional offset to find the * actual item. * + * Most keys are 16 bytes or less. We use the prefix indexes returned by + * a prefix_pool_t instance to uniquely identify the prefix in that case. + * Then the combination of prefix index and key stored in the fingerprint + * is then unique, too, and can never conflict. No full key construction, + * storage and comparison is needed in that case. + * * All access to the cached data needs to be serialized. Because we want * to scale well despite that bottleneck, we simply segment the cache into * a number of independent caches (segments). Items will be multiplexed based @@ -193,6 +201,10 @@ * entries with the same entry key. However unlikely, though, two different * full keys (see full_key_t) may have the same entry key. That is a * collision and at most one of them can be stored in the cache at any time. + * + * If the prefix is shared, which implies that the variable key part is no + * longer than 16 bytes, then there is a 1:1 mapping between full key and + * entry key. */ typedef struct entry_key_t { @@ -200,24 +212,185 @@ typedef struct entry_key_t apr_uint64_t fingerprint[2]; /* Length of the full key. This value is aligned to ITEM_ALIGNMENT to - * make sure the subsequent item content is properly aligned. */ + * make sure the subsequent item content is properly aligned. If 0, + * PREFIX_KEY is implied to be != NO_INDEX. */ apr_size_t key_len; + + /* Unique index of the shared key prefix, i.e. it's index within the + * prefix pool (see prefix_pool_t). NO_INDEX if the key prefix is not + * shared, otherwise KEY_LEN==0 is implied. */ + apr_uint32_t prefix_idx; } entry_key_t; /* A full key, i.e. the combination of the cache's key prefix with some * dynamic part appended to it. It also contains its ENTRY_KEY. + * + * If the ENTRY_KEY has a 1:1 mapping to the FULL_KEY, then the latter + * will be empty and remains unused. */ typedef struct full_key_t { /* Reduced form identifying the cache entry (if such an entry exists). */ entry_key_t entry_key; - /* This contains the full combination. Note that the SIZE element may - * be larger than ENTRY_KEY.KEY_LEN, but only the latter determines the - * valid key size. */ + /* If ENTRY_KEY is not a 1:1 mapping of the prefix + dynamic key + * combination, then this contains the full combination. Note that the + * SIZE element may be larger than ENTRY_KEY.KEY_LEN, but only the latter + * determines the valid key size. */ svn_membuf_t full_key; } full_key_t; +/* A limited capacity, thread-safe pool of unique C strings. Operations on + * this data structure are defined by prefix_pool_* functions. The only + * "public" member is VALUES (r/o access only). + */ +typedef struct prefix_pool_t +{ + /* Map C string to a pointer into VALUES with the same contents. */ + apr_hash_t *map; + + /* Pointer to an array of strings. These are the contents of this pool + * and each one of them is referenced by MAP. Valid indexes are 0 to + * VALUES_USED - 1. May be NULL if VALUES_MAX is 0. */ + const char **values; + + /* Number of used entries that VALUES may have. */ + apr_uint32_t values_max; + + /* Number of used entries in VALUES. Never exceeds VALUES_MAX. */ + apr_uint32_t values_used; + + /* Maximum number of bytes to allocate. */ + apr_size_t bytes_max; + + /* Number of bytes currently allocated. Should not exceed BYTES_MAX but + * the implementation may . */ + apr_size_t bytes_used; + + /* The serialization object. */ + svn_mutex__t *mutex; +} prefix_pool_t; + +/* Set *PREFIX_POOL to a new instance that tries to limit allocation to + * BYTES_MAX bytes. If MUTEX_REQUIRED is set and multi-threading is + * supported, serialize all access to the new instance. Allocate the + * object from *RESULT_POOL. */ +static svn_error_t * +prefix_pool_create(prefix_pool_t **prefix_pool, + apr_size_t bytes_max, + svn_boolean_t mutex_required, + apr_pool_t *result_pool) +{ + enum + { + /* With 56 byes of overhead under 64 bits, we will probably never get + * substantially below this. If we accidentally do, we will simply + * run out of entries in the VALUES array before running out of + * allocated memory. */ + ESTIMATED_BYTES_PER_ENTRY = 120 + }; + + /* Number of entries we are going to support. */ + apr_size_t capacity = MIN(APR_UINT32_MAX, + bytes_max / ESTIMATED_BYTES_PER_ENTRY); + + /* Construct the result struct. */ + prefix_pool_t *result = apr_pcalloc(result_pool, sizeof(*result)); + result->map = svn_hash__make(result_pool); + + result->values = capacity + ? apr_pcalloc(result_pool, capacity * sizeof(const char *)) + : NULL; + result->values_max = (apr_uint32_t)capacity; + result->values_used = 0; + + result->bytes_max = bytes_max; + result->bytes_used = capacity * sizeof(svn_membuf_t); + + SVN_ERR(svn_mutex__init(&result->mutex, mutex_required, result_pool)); + + /* Done. */ + *prefix_pool = result; + return SVN_NO_ERROR; +} + +/* Set *PREFIX_IDX to the offset in PREFIX_POOL->VALUES that contains the + * value PREFIX. If none exists, auto-insert it. If we can't due to + * capacity exhaustion, set *PREFIX_IDX to NO_INDEX. + * To be called by prefix_pool_get() only. */ +static svn_error_t * +prefix_pool_get_internal(apr_uint32_t *prefix_idx, + prefix_pool_t *prefix_pool, + const char *prefix) +{ + enum + { + /* Size of an hash entry plus (max.) APR alignment loss. + * + * This may be slightly off if e.g. APR changes its internal data + * structures but that will translate in just a few percent (~10%) + * over-allocation. Memory consumption will still be capped. + */ + OVERHEAD = 40 + 8 + }; + + const char **value; + apr_size_t prefix_len = strlen(prefix); + apr_size_t bytes_needed; + apr_pool_t *pool; + + /* Lookup. If we already know that prefix, return its index. */ + value = apr_hash_get(prefix_pool->map, prefix, prefix_len); + if (value != NULL) + { + const apr_size_t idx = value - prefix_pool->values; + SVN_ERR_ASSERT(idx < prefix_pool->values_used); + *prefix_idx = (apr_uint32_t) idx; + return SVN_NO_ERROR; + } + + /* Capacity checks. */ + if (prefix_pool->values_used == prefix_pool->values_max) + { + *prefix_idx = NO_INDEX; + return SVN_NO_ERROR; + } + + bytes_needed = prefix_len + 1 + OVERHEAD; + assert(prefix_pool->bytes_max >= prefix_pool->bytes_used); + if (prefix_pool->bytes_max - prefix_pool->bytes_used < bytes_needed) + { + *prefix_idx = NO_INDEX; + return SVN_NO_ERROR; + } + + /* Add new entry. */ + pool = apr_hash_pool_get(prefix_pool->map); + + value = &prefix_pool->values[prefix_pool->values_used]; + *value = apr_pstrndup(pool, prefix, prefix_len + 1); + apr_hash_set(prefix_pool->map, *value, prefix_len, value); + + *prefix_idx = prefix_pool->values_used; + ++prefix_pool->values_used; + prefix_pool->bytes_used += bytes_needed; + + return SVN_NO_ERROR; +} + +/* Thread-safe wrapper around prefix_pool_get_internal. */ +static svn_error_t * +prefix_pool_get(apr_uint32_t *prefix_idx, + prefix_pool_t *prefix_pool, + const char *prefix) +{ + SVN_MUTEX__WITH_LOCK(prefix_pool->mutex, + prefix_pool_get_internal(prefix_idx, prefix_pool, + prefix)); + + return SVN_NO_ERROR; +} + /* Debugging / corruption detection support. * If you define this macro, the getter functions will performed expensive * checks on the item data, requested keys and entry types. If there is @@ -267,13 +440,12 @@ typedef struct entry_tag_t /* Initialize all members of TAG except for the content hash. */ static svn_error_t *store_key_part(entry_tag_t *tag, - const full_key_t *prefix_key, + const char *prefix, const void *key, apr_size_t key_len, - apr_pool_t *pool) + apr_pool_t *scratch_pool) { svn_checksum_t *checksum; - const char *prefix = prefix_key->full_key.data; apr_size_t prefix_len = strlen(prefix); if (prefix_len > sizeof(tag->prefix_tail)) @@ -282,14 +454,18 @@ static svn_error_t *store_key_part(entry_tag_t *tag, prefix_len = sizeof(tag->prefix_tail) - 1; } + SVN_ERR(svn_checksum(&checksum, + svn_checksum_md5, + prefix, + strlen(prefix), + scratch_pool)); + memcpy(tag->prefix_hash, checksum->digest, sizeof(tag->prefix_hash)); + SVN_ERR(svn_checksum(&checksum, svn_checksum_md5, key, key_len, - pool)); - - memcpy(tag->prefix_hash, prefix_key->entry_key.fingerprint, - sizeof(tag->prefix_hash)); + scratch_pool)); memcpy(tag->key_hash, checksum->digest, sizeof(tag->key_hash)); memset(tag->prefix_tail, 0, sizeof(tag->key_hash)); @@ -350,7 +526,7 @@ static svn_error_t* assert_equal_tags(const entry_tag_t *lhs, entry_tag_t *tag = &_tag; \ if (key) \ SVN_ERR(store_key_part(tag, \ - &cache->prefix, \ + get_prefix_key(cache), \ key, \ cache->key_len == APR_HASH_KEY_STRING \ ? strlen((const char *) key) \ @@ -525,6 +701,12 @@ struct svn_membuffer_t and that all segments must / will report the same values here. */ apr_uint32_t segment_count; + /* Collection of prefixes shared among all instances accessing the + * same membuffer cache backend. If a prefix is contained in this + * pool then all cache instances using an equal prefix must actually + * use the one stored in this pool. */ + prefix_pool_t *prefix_pool; + /* The dictionary, GROUP_SIZE * (group_count + spare_group_count) * entries long. Never NULL. */ @@ -630,6 +812,11 @@ struct svn_membuffer_t */ svn_boolean_t allow_blocking_writes; #endif + + /* A write lock counter, must be either 0 or 1. + * This one is only used in debug assertions to verify that you used + * the correct multi-threading settings. */ + svn_atomic_t write_lock_count; }; /* Align integer VALUE to the next ITEM_ALIGNMENT boundary. @@ -1186,6 +1373,7 @@ entry_keys_match(const entry_key_t *lhs, { return (lhs->fingerprint[0] == rhs->fingerprint[0]) && (lhs->fingerprint[1] == rhs->fingerprint[1]) + && (lhs->prefix_idx == rhs->prefix_idx) && (lhs->key_len == rhs->key_len); } @@ -1248,7 +1436,8 @@ find_entry(svn_membuffer_t *cache, /* If we want to preserve it, check that it is actual a match. */ if (!find_empty) { - /* If there is no full key to compare, we are done. */ + /* If the full key is fully defined in prefix_id & mangeled + * key, we are done. */ if (!entry->key.key_len) return entry; @@ -1347,7 +1536,7 @@ find_entry(svn_membuffer_t *cache, */ for (i = 0; i < GROUP_SIZE; ++i) if (entry != &to_shrink->entries[i]) - let_entry_age(cache, entry); + let_entry_age(cache, &to_shrink->entries[i]); drop_entry(cache, entry); } @@ -1447,7 +1636,7 @@ ensure_data_insertable_l2(svn_membuffer_t *cache, /* accumulated size of the entries that have been removed to make * room for the new one. */ - apr_size_t moved_size = 0; + apr_uint64_t moved_size = 0; /* count the number of entries that got moved. A single large entry * being moved is not enough to reject an insertion. @@ -1481,15 +1670,15 @@ ensure_data_insertable_l2(svn_membuffer_t *cache, /* leave function as soon as the insertion window is large enough */ - if (end >= to_fit_in->size + cache->l2.current_data) + if (end - cache->l2.current_data >= to_fit_in->size) return TRUE; /* Don't be too eager to cache data. If a lot of data has been moved * around, the current item has probably a relatively low priority. - * We must also limit the effort spent here (if even in case of faulty + * We must also limit the effort spent here (even in case of faulty * heuristics). Therefore, give up after some time. */ - if (moved_size > 4 * to_fit_in->size && moved_count > 7) + if (moved_size / 4 > to_fit_in->size && moved_count > 7) return FALSE; /* if the net worth (in weighted hits) of items removed is already @@ -1606,7 +1795,7 @@ ensure_data_insertable_l1(svn_membuffer_t *cache, apr_size_t size) /* leave function as soon as the insertion window is large enough */ - if (end >= size + cache->l1.current_data) + if (end - cache->l1.current_data >= size) return TRUE; /* Enlarge the insertion window @@ -1653,6 +1842,7 @@ svn_cache__membuffer_cache_create(svn_membuffer_t **cache, apr_pool_t *pool) { svn_membuffer_t *c; + prefix_pool_t *prefix_pool; apr_uint32_t seg; apr_uint32_t group_count; @@ -1662,6 +1852,12 @@ svn_cache__membuffer_cache_create(svn_membuffer_t **cache, apr_uint64_t data_size; apr_uint64_t max_entry_size; + /* Allocate 1% of the cache capacity to the prefix string pool. + */ + SVN_ERR(prefix_pool_create(&prefix_pool, total_size / 100, thread_safe, + pool)); + total_size -= total_size / 100; + /* Limit the total size (only relevant if we can address > 4GB) */ #if APR_SIZEOF_VOIDP > 4 @@ -1751,7 +1947,7 @@ svn_cache__membuffer_cache_create(svn_membuffer_t **cache, : data_size / 8; /* to keep the entries small, we use 32 bit indexes only - * -> we need to ensure that no more then 4G entries exist. + * -> we need to ensure that no more than 4G entries exist. * * Note, that this limit could only be exceeded in a very * theoretical setup with about 1EB of cache. @@ -1772,14 +1968,18 @@ svn_cache__membuffer_cache_create(svn_membuffer_t **cache, /* allocate buffers and initialize cache members */ c[seg].segment_count = (apr_uint32_t)segment_count; + c[seg].prefix_pool = prefix_pool; c[seg].group_count = main_group_count; c[seg].spare_group_count = spare_group_count; c[seg].first_spare_group = NO_INDEX; c[seg].max_spare_used = 0; - c[seg].directory = apr_pcalloc(pool, - group_count * sizeof(entry_group_t)); + /* Allocate but don't clear / zero the directory because it would add + significantly to the server start-up time if the caches are large. + Group initialization will take care of that in stead. */ + c[seg].directory = apr_palloc(pool, + group_count * sizeof(entry_group_t)); /* Allocate and initialize directory entries as "not initialized", hence "unused" */ @@ -1844,6 +2044,8 @@ svn_cache__membuffer_cache_create(svn_membuffer_t **cache, */ c[seg].allow_blocking_writes = allow_blocking_writes; #endif + /* No writers at the moment. */ + c[seg].write_lock_count = 0; } /* done here @@ -1998,14 +2200,28 @@ membuffer_cache_set_internal(svn_membuffer_t *cache, apr_pool_t *scratch_pool) { cache_level_t *level; - apr_size_t size = item_size + to_find->entry_key.key_len; + apr_size_t size; /* first, look for a previous entry for the given key */ entry_t *entry = find_entry(cache, group_index, to_find, FALSE); + /* If this one fails, you are using multiple threads but created the + * membuffer in single-threaded mode. */ + assert(0 == svn_atomic_inc(&cache->write_lock_count)); + + /* Quick check make sure arithmetics will work further down the road. */ + size = item_size + to_find->entry_key.key_len; + if (size < item_size) + { + /* Arithmetic overflow, so combination of serialized ITEM and KEY + * cannot not fit into the cache. Setting BUFFER to NULL will cause + * the removal of any entry if that exists without writing new data. */ + buffer = NULL; + } + /* if there is an old version of that entry and the new data fits into * the old spot, just re-use that space. */ - if (entry && ALIGN_VALUE(entry->size) >= size && buffer) + if (entry && buffer && ALIGN_VALUE(entry->size) >= size) { /* Careful! We need to cast SIZE to the full width of CACHE->DATA_USED * lest we run into trouble with 32 bit underflow *not* treated as a @@ -2032,6 +2248,10 @@ membuffer_cache_set_internal(svn_membuffer_t *cache, item_size); cache->total_writes++; + + /* Putting the decrement into an assert() to make it disappear + * in production code. */ + assert(0 == svn_atomic_dec(&cache->write_lock_count)); return SVN_NO_ERROR; } @@ -2084,6 +2304,9 @@ membuffer_cache_set_internal(svn_membuffer_t *cache, drop_entry(cache, entry); } + /* Putting the decrement into an assert() to make it disappear + * in production code. */ + assert(0 == svn_atomic_dec(&cache->write_lock_count)); return SVN_NO_ERROR; } @@ -2212,7 +2435,7 @@ membuffer_cache_get_internal(svn_membuffer_t *cache, /* Look for the *ITEM identified by KEY. If no item has been stored * for KEY, *ITEM will be NULL. Otherwise, the DESERIALIZER is called - * re-construct the proper object from the serialized data. + * to re-construct the proper object from the serialized data. * Allocations will be done in POOL. */ static svn_error_t * @@ -2463,9 +2686,11 @@ membuffer_cache_set_partial_internal(svn_membuffer_t *cache, if (item_data != orig_data) { /* Remove the old entry and try to make space for the new one. + * Note that the key has already been stored in the past, i.e. + * it is shorter than the MAX_ENTRY_SIZE. */ drop_entry(cache, entry); - if ( (cache->max_entry_size >= item_size + key_len) + if ( (cache->max_entry_size - key_len >= item_size) && ensure_data_insertable_l1(cache, item_size + key_len)) { /* Write the new entry. @@ -2560,11 +2785,11 @@ typedef struct svn_membuffer_cache_t */ svn_cache__deserialize_func_t deserializer; - /* Prepend this byte sequence to any key passed to us. + /* Prepend this to any key passed to us. * This makes our keys different from all keys used by svn_membuffer_cache_t * instances that we don't want to share cached data with. */ - full_key_t prefix; + entry_key_t prefix; /* length of the keys that will be passed to us through the * svn_cache_t interface. May be APR_HASH_KEY_STRING. @@ -2583,10 +2808,14 @@ typedef struct svn_membuffer_cache_t svn_mutex__t *mutex; } svn_membuffer_cache_t; -/* After an estimated ALLOCATIONS_PER_POOL_CLEAR allocations, we should - * clear the svn_membuffer_cache_t.pool to keep memory consumption in check. - */ -#define ALLOCATIONS_PER_POOL_CLEAR 10 +/* Return the prefix key used by CACHE. */ +static const char * +get_prefix_key(const svn_membuffer_cache_t *cache) +{ + return (cache->prefix.prefix_idx == NO_INDEX + ? cache->combined_key.full_key.data + : cache->membuffer->prefix_pool->values[cache->prefix.prefix_idx]); +} /* Basically calculate a hash value for KEY of length KEY_LEN, combine it * with the CACHE->PREFIX and write the result in CACHE->COMBINED_KEY. @@ -2600,7 +2829,7 @@ combine_long_key(svn_membuffer_cache_t *cache, { apr_uint32_t *digest_buffer; char *key_copy; - apr_size_t prefix_len = cache->prefix.entry_key.key_len; + apr_size_t prefix_len = cache->prefix.key_len; apr_size_t aligned_key_len; /* handle variable-length keys */ @@ -2624,9 +2853,9 @@ combine_long_key(svn_membuffer_cache_t *cache, /* Combine with prefix. */ cache->combined_key.entry_key.fingerprint[0] - ^= cache->prefix.entry_key.fingerprint[0]; + ^= cache->prefix.fingerprint[0]; cache->combined_key.entry_key.fingerprint[1] - ^= cache->prefix.entry_key.fingerprint[1]; + ^= cache->prefix.fingerprint[1]; } /* Basically calculate a hash value for KEY of length KEY_LEN, combine it @@ -2637,40 +2866,55 @@ combine_key(svn_membuffer_cache_t *cache, const void *key, apr_ssize_t key_len) { - /* short, fixed-size keys are the most common case */ - if (key_len != APR_HASH_KEY_STRING && key_len <= 16) + /* copy of *key, padded with 0 */ + apr_uint64_t data[2]; + + /* Do we have to compare full keys? */ + if (cache->prefix.prefix_idx == NO_INDEX) { - const apr_size_t prefix_len = cache->prefix.entry_key.key_len; + combine_long_key(cache, key, key_len); + return; + } - /* Copy of *key, padded with 0. - * We put it just behind the prefix already copied into the COMBINED_KEY. - * The buffer space has been allocated when the cache was created. */ - apr_uint64_t *data = (void *)((char *)cache->combined_key.full_key.data + - prefix_len); - assert(prefix_len <= cache->combined_key.full_key.size - 16); - cache->combined_key.entry_key.key_len = prefix_len + 16; - - data[0] = 0; + /* short, fixed-size keys are the most common case */ + if (key_len == 16) + { + memcpy(data, key, 16); + } + else if (key_len == 8) + { + memcpy(data, key, 8); data[1] = 0; - memcpy(data, key, key_len); - - /* scramble key DATA. All of this must be reversible to prevent key - * collisions. So, we limit ourselves to xor and permutations. */ - data[1] = (data[1] << 27) | (data[1] >> 37); - data[1] ^= data[0] & 0xffff; - data[0] ^= data[1] & APR_UINT64_C(0xffffffffffff0000); - - /* combine with this cache's namespace */ - cache->combined_key.entry_key.fingerprint[0] - = data[0] ^ cache->prefix.entry_key.fingerprint[0]; - cache->combined_key.entry_key.fingerprint[1] - = data[1] ^ cache->prefix.entry_key.fingerprint[1]; } else { - /* longer or variably sized keys */ - combine_long_key(cache, key, key_len); + assert(key_len != APR_HASH_KEY_STRING && key_len < 16); + data[0] = 0; + data[1] = 0; + memcpy(data, key, key_len); } + + /* Scramble key DATA to spread the key space more evenly across the + * cache segments and entry buckets. All of this shall be reversible + * to prevent key collisions. So, we limit ourselves to xor and + * permutations. + * + * Since the entry key must preserve the full key (prefix and KEY), + * the scramble must not introduce KEY collisions. + */ + data[1] = (data[1] << 27) | (data[1] >> 37); + data[1] ^= data[0] & 0xffff; + data[0] ^= data[1] & APR_UINT64_C(0xffffffffffff0000); + + /* Combine with this cache's prefix. This is reversible because the + * prefix is known through to the respective entry_key element. So, + * knowing entry_key.prefix_id, we can still reconstruct KEY (and the + * prefix key). + */ + cache->combined_key.entry_key.fingerprint[0] + = data[0] ^ cache->prefix.fingerprint[0]; + cache->combined_key.entry_key.fingerprint[1] + = data[1] ^ cache->prefix.fingerprint[1]; } /* Implement svn_cache__vtable_t.get (not thread-safe) @@ -2917,7 +3161,7 @@ svn_membuffer_cache_get_info(void *cache_void, /* cache front-end specific data */ - info->id = apr_pstrdup(result_pool, cache->prefix.full_key.data); + info->id = apr_pstrdup(result_pool, get_prefix_key(cache)); /* collect info from shared cache back-end */ @@ -3106,6 +3350,7 @@ svn_cache__create_membuffer_cache(svn_cache__t **cache_p, const char *prefix, apr_uint32_t priority, svn_boolean_t thread_safe, + svn_boolean_t short_lived, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { @@ -3136,10 +3381,10 @@ svn_cache__create_membuffer_cache(svn_cache__t **cache_p, prefix_orig_len = strlen(prefix) + 1; prefix_len = ALIGN_VALUE(prefix_orig_len); - svn_membuf__create(&cache->prefix.full_key, prefix_len, result_pool); - memcpy((char *)cache->prefix.full_key.data, prefix, prefix_orig_len); - memset((char *)cache->prefix.full_key.data + prefix_orig_len, 0, - prefix_len - prefix_orig_len); + /* Paranoia check to ensure pointer arithmetics work as expected. */ + if (prefix_orig_len >= SVN_MAX_OBJECT_SIZE) + return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL, + _("Prefix too long")); /* Construct the folded prefix key. */ SVN_ERR(svn_checksum(&checksum, @@ -3147,17 +3392,44 @@ svn_cache__create_membuffer_cache(svn_cache__t **cache_p, prefix, strlen(prefix), scratch_pool)); - memcpy(cache->prefix.entry_key.fingerprint, checksum->digest, - sizeof(cache->prefix.entry_key.fingerprint)); - cache->prefix.entry_key.key_len = prefix_len; + memcpy(cache->prefix.fingerprint, checksum->digest, + sizeof(cache->prefix.fingerprint)); + cache->prefix.key_len = prefix_len; - /* Initialize the combined key. Pre-allocate some extra room in the full - * key such that we probably don't need to re-alloc. */ - cache->combined_key.entry_key = cache->prefix.entry_key; - svn_membuf__create(&cache->combined_key.full_key, prefix_len + 200, - result_pool); - memcpy(cache->combined_key.full_key.data, cache->prefix.full_key.data, - prefix_len); + /* Fix-length keys of up to 16 bytes may be handled without storing the + * full key separately for each item. */ + if ( (klen != APR_HASH_KEY_STRING) + && (klen <= sizeof(cache->combined_key.entry_key.fingerprint)) + && !short_lived) + SVN_ERR(prefix_pool_get(&cache->prefix.prefix_idx, + membuffer->prefix_pool, + prefix)); + else + cache->prefix.prefix_idx = NO_INDEX; + + /* If key combining is not guaranteed to produce unique results, we have + * to handle full keys. Otherwise, leave it NULL. */ + if (cache->prefix.prefix_idx == NO_INDEX) + { + /* Initialize the combined key. Pre-allocate some extra room in the + * full key such that we probably don't need to re-alloc. */ + cache->combined_key.entry_key = cache->prefix; + svn_membuf__create(&cache->combined_key.full_key, prefix_len + 200, + result_pool); + memcpy((char *)cache->combined_key.full_key.data, prefix, + prefix_orig_len); + memset((char *)cache->combined_key.full_key.data + prefix_orig_len, 0, + prefix_len - prefix_orig_len); + } + else + { + /* Initialize the combined key. We will never have the full combined + * key, so leave it NULL and set its length to 0 to prevent access to + * it. Keep the fingerprint 0 as well b/c it will always be set anew + * by combine_key(). */ + cache->combined_key.entry_key.prefix_idx = cache->prefix.prefix_idx; + cache->combined_key.entry_key.key_len = 0; + } /* initialize the generic cache wrapper */ diff --git a/subversion/libsvn_subr/cache-null.c b/subversion/libsvn_subr/cache-null.c new file mode 100644 index 000000000000..3b7ee12d0a1d --- /dev/null +++ b/subversion/libsvn_subr/cache-null.c @@ -0,0 +1,157 @@ +/* + * cache-null.c: dummy caching object for Subversion + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#include "svn_private_config.h" +#include "cache.h" + +/* There is no dedicated cache data structure. Instead, we store the + * cache ID directly in svn_cache__t.cache_internal . + */ + +static svn_error_t * +null_cache_get(void **value_p, + svn_boolean_t *found, + void *cache_void, + const void *key, + apr_pool_t *result_pool) +{ + /* We know there is nothing to be found in this cache. */ + *value_p = NULL; + *found = FALSE; + + return SVN_NO_ERROR; +} + +static svn_error_t * +null_cache_has_key(svn_boolean_t *found, + void *cache_void, + const void *key, + apr_pool_t *scratch_pool) +{ + /* We know there is nothing to be found in this cache. */ + *found = FALSE; + return SVN_NO_ERROR; +} + +static svn_error_t * +null_cache_set(void *cache_void, + const void *key, + void *value, + apr_pool_t *scratch_pool) +{ + /* We won't cache anything. */ + return SVN_NO_ERROR; +} + +static svn_error_t * +null_cache_iter(svn_boolean_t *completed, + void *cache_void, + svn_iter_apr_hash_cb_t user_cb, + void *user_baton, + apr_pool_t *scratch_pool) +{ + /* Iteration over an empty set is a no-op. */ + if (completed) + *completed = TRUE; + + return SVN_NO_ERROR; +} + +static svn_error_t * +null_cache_get_partial(void **value_p, + svn_boolean_t *found, + void *cache_void, + const void *key, + svn_cache__partial_getter_func_t func, + void *baton, + apr_pool_t *result_pool) +{ + /* We know there is nothing to be found in this cache. */ + *found = FALSE; + return SVN_NO_ERROR; +} + +static svn_error_t * +null_cache_set_partial(void *cache_void, + const void *key, + svn_cache__partial_setter_func_t func, + void *baton, + apr_pool_t *scratch_pool) +{ + /* We know there is nothing to update in this cache. */ + return SVN_NO_ERROR; +} + +static svn_boolean_t +null_cache_is_cachable(void *cache_void, + apr_size_t size) +{ + /* We won't cache anything */ + return FALSE; +} + +static svn_error_t * +null_cache_get_info(void *cache_void, + svn_cache__info_t *info, + svn_boolean_t reset, + apr_pool_t *result_pool) +{ + const char *id = cache_void; + + info->id = apr_pstrdup(result_pool, id); + + info->used_entries = 0; + info->total_entries = 0; + + info->used_size = 0; + info->data_size = 0; + info->total_size = 0; + + return SVN_NO_ERROR; +} + +static svn_cache__vtable_t null_cache_vtable = { + null_cache_get, + null_cache_has_key, + null_cache_set, + null_cache_iter, + null_cache_is_cachable, + null_cache_get_partial, + null_cache_set_partial, + null_cache_get_info +}; + +svn_error_t * +svn_cache__create_null(svn_cache__t **cache_p, + const char *id, + apr_pool_t *result_pool) +{ + svn_cache__t *cache = apr_pcalloc(result_pool, sizeof(*cache)); + cache->vtable = &null_cache_vtable; + cache->cache_internal = apr_pstrdup(result_pool, id); + cache->pretend_empty = FALSE; /* There is no point in pretending -- + this cache _is_ empty. */ + + *cache_p = cache; + return SVN_NO_ERROR; +} diff --git a/subversion/libsvn_subr/checksum.c b/subversion/libsvn_subr/checksum.c index 6b195f8a5ecc..0d6a0c6ee334 100644 --- a/subversion/libsvn_subr/checksum.c +++ b/subversion/libsvn_subr/checksum.c @@ -86,6 +86,7 @@ static const char *ckind_str[] = { "$sha1$", "$fnv1$", "$fnvm$", + /* ### svn_checksum_deserialize() assumes all these have the same strlen() */ }; /* Returns the digest size of it's argument. */ @@ -373,26 +374,42 @@ svn_checksum_parse_hex(svn_checksum_t **checksum, apr_pool_t *pool) { apr_size_t i, len; - char is_nonzero = '\0'; - char *digest; - static const char xdigitval[256] = + unsigned char is_nonzero = 0; + unsigned char *digest; + static const unsigned char xdigitval[256] = { - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1, /* 0-9 */ - -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* A-F */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* a-f */ - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, /* 0-7 */ + 0x08,0x09,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* 8-9 */ + 0xFF,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0xFF, /* A-F */ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0xFF, /* a-f */ + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, }; if (hex == NULL) @@ -404,18 +421,18 @@ svn_checksum_parse_hex(svn_checksum_t **checksum, SVN_ERR(validate_kind(kind)); *checksum = svn_checksum_create(kind, pool); - digest = (char *)(*checksum)->digest; + digest = (unsigned char *)(*checksum)->digest; len = DIGESTSIZE(kind); for (i = 0; i < len; i++) { - char x1 = xdigitval[(unsigned char)hex[i * 2]]; - char x2 = xdigitval[(unsigned char)hex[i * 2 + 1]]; - if (x1 == (char)-1 || x2 == (char)-1) + unsigned char x1 = xdigitval[(unsigned char)hex[i * 2]]; + unsigned char x2 = xdigitval[(unsigned char)hex[i * 2 + 1]]; + if (x1 == 0xFF || x2 == 0xFF) return svn_error_create(SVN_ERR_BAD_CHECKSUM_PARSE, NULL, NULL); - digest[i] = (char)((x1 << 4) | x2); - is_nonzero |= (char)((x1 << 4) | x2); + digest[i] = (x1 << 4) | x2; + is_nonzero |= digest[i]; } if (!is_nonzero) @@ -552,6 +569,36 @@ svn_checksum_ctx_create(svn_checksum_kind_t kind, return ctx; } +svn_error_t * +svn_checksum_ctx_reset(svn_checksum_ctx_t *ctx) +{ + switch (ctx->kind) + { + case svn_checksum_md5: + memset(ctx->apr_ctx, 0, sizeof(apr_md5_ctx_t)); + apr_md5_init(ctx->apr_ctx); + break; + + case svn_checksum_sha1: + memset(ctx->apr_ctx, 0, sizeof(apr_sha1_ctx_t)); + apr_sha1_init(ctx->apr_ctx); + break; + + case svn_checksum_fnv1a_32: + svn_fnv1a_32__context_reset(ctx->apr_ctx); + break; + + case svn_checksum_fnv1a_32x4: + svn_fnv1a_32x4__context_reset(ctx->apr_ctx); + break; + + default: + SVN_ERR_MALFUNCTION(); + } + + return SVN_NO_ERROR; +} + svn_error_t * svn_checksum_update(svn_checksum_ctx_t *ctx, const void *data, diff --git a/subversion/libsvn_subr/cmdline.c b/subversion/libsvn_subr/cmdline.c index 9e97bf71f713..2255952189ff 100644 --- a/subversion/libsvn_subr/cmdline.c +++ b/subversion/libsvn_subr/cmdline.c @@ -42,6 +42,7 @@ #include /* for apr_initialize/apr_terminate */ #include /* for apr_snprintf */ #include +#include #include "svn_cmdline.h" #include "svn_ctype.h" @@ -341,6 +342,23 @@ svn_cmdline_path_local_style_from_utf8(const char **dest, pool); } +svn_error_t * +svn_cmdline__stdin_readline(const char **result, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_stringbuf_t *buf = NULL; + svn_stream_t *stdin_stream = NULL; + svn_boolean_t oob = FALSE; + + SVN_ERR(svn_stream_for_stdin2(&stdin_stream, TRUE, scratch_pool)); + SVN_ERR(svn_stream_readline(stdin_stream, &buf, APR_EOL_STR, &oob, result_pool)); + + *result = buf->data; + + return SVN_NO_ERROR; +} + svn_error_t * svn_cmdline_printf(apr_pool_t *pool, const char *fmt, ...) { @@ -821,7 +839,7 @@ most_similar(const char *needle_cstr, apr_size_t haystack_len, apr_pool_t *scratch_pool) { - const char *max_similar; + const char *max_similar = NULL; apr_size_t max_score = 0; apr_size_t i; svn_membuf_t membuf; @@ -846,10 +864,7 @@ most_similar(const char *needle_cstr, } } - if (max_score) - return max_similar; - else - return NULL; + return max_similar; } /* Verify that NEEDLE is in HAYSTACK, which contains HAYSTACK_LEN elements. */ @@ -883,7 +898,7 @@ string_in_array(const char *needle, #include "config_keys.inc" /* Validate the FILE, SECTION, and OPTION components of CONFIG_OPTION are - * known. Warn to stderr if not. (An unknown value may be either a typo + * known. Return an error if not. (An unknown value may be either a typo * or added in a newer minor version of Subversion.) */ static svn_error_t * validate_config_option(svn_cmdline__config_argument_t *config_option, @@ -1170,6 +1185,36 @@ svn_cmdline__print_xml_prop_hash(svn_stringbuf_t **outstr, return SVN_NO_ERROR; } +svn_boolean_t +svn_cmdline__stdin_is_a_terminal(void) +{ +#ifdef WIN32 + return (_isatty(STDIN_FILENO) != 0); +#else + return (isatty(STDIN_FILENO) != 0); +#endif +} + +svn_boolean_t +svn_cmdline__stdout_is_a_terminal(void) +{ +#ifdef WIN32 + return (_isatty(STDOUT_FILENO) != 0); +#else + return (isatty(STDOUT_FILENO) != 0); +#endif +} + +svn_boolean_t +svn_cmdline__stderr_is_a_terminal(void) +{ +#ifdef WIN32 + return (_isatty(STDERR_FILENO) != 0); +#else + return (isatty(STDERR_FILENO) != 0); +#endif +} + svn_boolean_t svn_cmdline__be_interactive(svn_boolean_t non_interactive, svn_boolean_t force_interactive) @@ -1179,11 +1224,7 @@ svn_cmdline__be_interactive(svn_boolean_t non_interactive, * If --force-interactive was passed, always be interactive. */ if (!force_interactive && !non_interactive) { -#ifdef WIN32 - return (_isatty(STDIN_FILENO) != 0); -#else - return (isatty(STDIN_FILENO) != 0); -#endif + return svn_cmdline__stdin_is_a_terminal(); } else if (force_interactive) return TRUE; @@ -1325,12 +1366,12 @@ svn_cmdline__edit_string_externally(svn_string_t **edited_contents /* UTF-8! */, apr_file_t *tmp_file; const char *tmpfile_name; const char *tmpfile_native; - const char *tmpfile_apr, *base_dir_apr; + const char *base_dir_apr; svn_string_t *translated_contents; - apr_status_t apr_err, apr_err2; + apr_status_t apr_err; apr_size_t written; apr_finfo_t finfo_before, finfo_after; - svn_error_t *err = SVN_NO_ERROR, *err2; + svn_error_t *err = SVN_NO_ERROR; char *old_cwd; int sys_err; svn_boolean_t remove_file = TRUE; @@ -1413,49 +1454,36 @@ svn_cmdline__edit_string_externally(svn_string_t **edited_contents /* UTF-8! */, the file we just created!! ***/ /* Dump initial CONTENTS to TMP_FILE. */ - apr_err = apr_file_write_full(tmp_file, translated_contents->data, - translated_contents->len, &written); + err = svn_io_file_write_full(tmp_file, translated_contents->data, + translated_contents->len, &written, + pool); - apr_err2 = apr_file_close(tmp_file); - if (! apr_err) - apr_err = apr_err2; + err = svn_error_compose_create(err, svn_io_file_close(tmp_file, pool)); /* Make sure the whole CONTENTS were written, else return an error. */ - if (apr_err) - { - err = svn_error_wrap_apr(apr_err, _("Can't write to '%s'"), - tmpfile_name); - goto cleanup; - } - - err = svn_path_cstring_from_utf8(&tmpfile_apr, tmpfile_name, pool); if (err) goto cleanup; /* Get information about the temporary file before the user has been allowed to edit its contents. */ - apr_err = apr_stat(&finfo_before, tmpfile_apr, - APR_FINFO_MTIME, pool); - if (apr_err) - { - err = svn_error_wrap_apr(apr_err, _("Can't stat '%s'"), tmpfile_name); - goto cleanup; - } + err = svn_io_stat(&finfo_before, tmpfile_name, APR_FINFO_MTIME, pool); + if (err) + goto cleanup; /* Backdate the file a little bit in case the editor is very fast and doesn't change the size. (Use two seconds, since some filesystems have coarse granularity.) It's OK if this call fails, so we don't check its return value.*/ - apr_file_mtime_set(tmpfile_apr, finfo_before.mtime - 2000, pool); + err = svn_io_set_file_affected_time(finfo_before.mtime + - apr_time_from_sec(2), + tmpfile_name, pool); + svn_error_clear(err); /* Stat it again to get the mtime we actually set. */ - apr_err = apr_stat(&finfo_before, tmpfile_apr, - APR_FINFO_MTIME | APR_FINFO_SIZE, pool); - if (apr_err) - { - err = svn_error_wrap_apr(apr_err, _("Can't stat '%s'"), tmpfile_name); - goto cleanup; - } + err = svn_io_stat(&finfo_before, tmpfile_name, + APR_FINFO_MTIME | APR_FINFO_SIZE, pool); + if (err) + goto cleanup; /* Prepare the editor command line. */ err = svn_utf_cstring_from_utf8(&tmpfile_native, tmpfile_name, pool); @@ -1483,13 +1511,10 @@ svn_cmdline__edit_string_externally(svn_string_t **edited_contents /* UTF-8! */, } /* Get information about the temporary file after the assumed editing. */ - apr_err = apr_stat(&finfo_after, tmpfile_apr, - APR_FINFO_MTIME | APR_FINFO_SIZE, pool); - if (apr_err) - { - err = svn_error_wrap_apr(apr_err, _("Can't stat '%s'"), tmpfile_name); - goto cleanup; - } + err = svn_io_stat(&finfo_after, tmpfile_name, + APR_FINFO_MTIME | APR_FINFO_SIZE, pool); + if (err) + goto cleanup; /* If the file looks changed... */ if ((finfo_before.mtime != finfo_after.mtime) || @@ -1527,13 +1552,9 @@ svn_cmdline__edit_string_externally(svn_string_t **edited_contents /* UTF-8! */, if (remove_file) { /* Remove the file from disk. */ - err2 = svn_io_remove_file2(tmpfile_name, FALSE, pool); - - /* Only report remove error if there was no previous error. */ - if (! err && err2) - err = err2; - else - svn_error_clear(err2); + err = svn_error_compose_create( + err, + svn_io_remove_file2(tmpfile_name, FALSE, pool)); } cleanup2: @@ -1596,3 +1617,99 @@ svn_cmdline__parse_trust_options( return SVN_NO_ERROR; } + +/* Flags to see if we've been cancelled by the client or not. */ +static volatile sig_atomic_t cancelled = FALSE; +static volatile sig_atomic_t signum_cancelled = 0; + +/* The signals we handle. */ +static int signal_map [] = { + SIGINT +#ifdef SIGBREAK + /* SIGBREAK is a Win32 specific signal generated by ctrl-break. */ + , SIGBREAK +#endif +#ifdef SIGHUP + , SIGHUP +#endif +#ifdef SIGTERM + , SIGTERM +#endif +}; + +/* A signal handler to support cancellation. */ +static void +signal_handler(int signum) +{ + int i; + + apr_signal(signum, SIG_IGN); + cancelled = TRUE; + for (i = 0; i < sizeof(signal_map)/sizeof(signal_map[0]); ++i) + if (signal_map[i] == signum) + { + signum_cancelled = i + 1; + break; + } +} + +/* An svn_cancel_func_t callback. */ +static svn_error_t * +check_cancel(void *baton) +{ + /* Cancel baton should be always NULL in command line client. */ + SVN_ERR_ASSERT(baton == NULL); + if (cancelled) + return svn_error_create(SVN_ERR_CANCELLED, NULL, _("Caught signal")); + else + return SVN_NO_ERROR; +} + +svn_cancel_func_t +svn_cmdline__setup_cancellation_handler(void) +{ + int i; + + for (i = 0; i < sizeof(signal_map)/sizeof(signal_map[0]); ++i) + apr_signal(signal_map[i], signal_handler); + +#ifdef SIGPIPE + /* Disable SIGPIPE generation for the platforms that have it. */ + apr_signal(SIGPIPE, SIG_IGN); +#endif + +#ifdef SIGXFSZ + /* Disable SIGXFSZ generation for the platforms that have it, otherwise + * working with large files when compiled against an APR that doesn't have + * large file support will crash the program, which is uncool. */ + apr_signal(SIGXFSZ, SIG_IGN); +#endif + + return check_cancel; +} + +void +svn_cmdline__disable_cancellation_handler(void) +{ + int i; + + for (i = 0; i < sizeof(signal_map)/sizeof(signal_map[0]); ++i) + apr_signal(signal_map[i], SIG_DFL); +} + +void +svn_cmdline__cancellation_exit(void) +{ + int signum = 0; + + if (cancelled && signum_cancelled) + signum = signal_map[signum_cancelled - 1]; + if (signum) + { +#ifndef WIN32 + apr_signal(signum, SIG_DFL); + /* No APR support for getpid() so cannot use apr_proc_kill(). */ + kill(getpid(), signum); +#endif + } +} diff --git a/subversion/libsvn_subr/compress_lz4.c b/subversion/libsvn_subr/compress_lz4.c new file mode 100644 index 000000000000..d700b3215566 --- /dev/null +++ b/subversion/libsvn_subr/compress_lz4.c @@ -0,0 +1,144 @@ +/* + * compress_lz4.c: LZ4 data compression routines + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#include + +#include "private/svn_subr_private.h" + +#include "svn_private_config.h" + +#if SVN_INTERNAL_LZ4 +#include "lz4/lz4internal.h" +#else +#include +#endif + +svn_error_t * +svn__compress_lz4(const void *data, apr_size_t len, + svn_stringbuf_t *out) +{ + apr_size_t hdrlen; + unsigned char buf[SVN__MAX_ENCODED_UINT_LEN]; + unsigned char *p; + int compressed_data_len; + int max_compressed_data_len; + + assert(len <= LZ4_MAX_INPUT_SIZE); + + p = svn__encode_uint(buf, (apr_uint64_t)len); + hdrlen = p - buf; + max_compressed_data_len = LZ4_compressBound((int)len); + svn_stringbuf_setempty(out); + svn_stringbuf_ensure(out, max_compressed_data_len + hdrlen); + svn_stringbuf_appendbytes(out, (const char *)buf, hdrlen); + compressed_data_len = LZ4_compress_default(data, out->data + out->len, + (int)len, max_compressed_data_len); + if (!compressed_data_len) + return svn_error_create(SVN_ERR_LZ4_COMPRESSION_FAILED, NULL, NULL); + + if (compressed_data_len >= (int)len) + { + /* Compression didn't help :(, just append the original text */ + svn_stringbuf_appendbytes(out, data, len); + } + else + { + out->len += compressed_data_len; + out->data[out->len] = 0; + } + + return SVN_NO_ERROR; +} + +svn_error_t * +svn__decompress_lz4(const void *data, apr_size_t len, + svn_stringbuf_t *out, + apr_size_t limit) +{ + apr_size_t hdrlen; + int compressed_data_len; + int decompressed_data_len; + apr_uint64_t u64; + const unsigned char *p = data; + int rv; + + assert(len <= INT_MAX); + assert(limit <= INT_MAX); + + /* First thing in the string is the original length. */ + p = svn__decode_uint(&u64, p, p + len); + if (p == NULL) + return svn_error_create(SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA, NULL, + _("Decompression of compressed data failed: " + "no size")); + if (u64 > limit) + return svn_error_create(SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA, NULL, + _("Decompression of compressed data failed: " + "size too large")); + decompressed_data_len = (int)u64; + hdrlen = p - (const unsigned char *)data; + compressed_data_len = (int)(len - hdrlen); + + svn_stringbuf_setempty(out); + svn_stringbuf_ensure(out, decompressed_data_len); + + if (compressed_data_len == decompressed_data_len) + { + /* Data is in the original, uncompressed form. */ + memcpy(out->data, p, decompressed_data_len); + } + else + { + rv = LZ4_decompress_safe((const char *)p, out->data, compressed_data_len, + decompressed_data_len); + if (rv < 0) + return svn_error_create(SVN_ERR_LZ4_DECOMPRESSION_FAILED, NULL, NULL); + + if (rv != decompressed_data_len) + return svn_error_create(SVN_ERR_SVNDIFF_INVALID_COMPRESSED_DATA, + NULL, + _("Size of uncompressed data " + "does not match stored original length")); + } + + out->data[decompressed_data_len] = 0; + out->len = decompressed_data_len; + + return SVN_NO_ERROR; +} + +const char * +svn_lz4__compiled_version(void) +{ + static const char lz4_version_str[] = APR_STRINGIFY(LZ4_VERSION_MAJOR) "." \ + APR_STRINGIFY(LZ4_VERSION_MINOR) "." \ + APR_STRINGIFY(LZ4_VERSION_RELEASE); + + return lz4_version_str; +} + +int +svn_lz4__runtime_version(void) +{ + return LZ4_versionNumber(); +} diff --git a/subversion/libsvn_subr/compress.c b/subversion/libsvn_subr/compress_zlib.c similarity index 81% rename from subversion/libsvn_subr/compress.c rename to subversion/libsvn_subr/compress_zlib.c index 004e443628bd..ec42b360a475 100644 --- a/subversion/libsvn_subr/compress.c +++ b/subversion/libsvn_subr/compress_zlib.c @@ -1,5 +1,5 @@ /* - * compress.c: various data compression routines + * compress_zlib.c: zlib data compression routines * * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one @@ -22,8 +22,6 @@ */ -#include -#include #include #include "private/svn_subr_private.h" @@ -57,60 +55,6 @@ svn_zlib__runtime_version(void) be compressed using zlib as a secondary compressor. */ #define MIN_COMPRESS_SIZE 512 -unsigned char * -svn__encode_uint(unsigned char *p, apr_uint64_t val) -{ - int n; - apr_uint64_t v; - - /* Figure out how many bytes we'll need. */ - v = val >> 7; - n = 1; - while (v > 0) - { - v = v >> 7; - n++; - } - - /* Encode the remaining bytes; n is always the number of bytes - coming after the one we're encoding. */ - while (--n >= 1) - *p++ = (unsigned char)(((val >> (n * 7)) | 0x80) & 0xff); - - *p++ = (unsigned char)(val & 0x7f); - - return p; -} - -const unsigned char * -svn__decode_uint(apr_uint64_t *val, - const unsigned char *p, - const unsigned char *end) -{ - apr_uint64_t temp = 0; - - if (p + SVN__MAX_ENCODED_UINT_LEN < end) - end = p + SVN__MAX_ENCODED_UINT_LEN; - - /* Decode bytes until we're done. */ - while (SVN__PREDICT_TRUE(p < end)) - { - unsigned int c = *p++; - - if (c < 0x80) - { - *val = (temp << 7) | c; - return p; - } - else - { - temp = (temp << 7) | (c & 0x7f); - } - } - - return NULL; -} - /* If IN is a string that is >= MIN_COMPRESS_SIZE and the COMPRESSION_LEVEL is not SVN_DELTA_COMPRESSION_LEVEL_NONE, zlib compress it and places the result in OUT, with an integer prepended specifying the original size. @@ -235,9 +179,9 @@ zlib_decode(const unsigned char *in, apr_size_t inLen, svn_stringbuf_t *out, } svn_error_t * -svn__compress(svn_stringbuf_t *in, - svn_stringbuf_t *out, - int compression_method) +svn__compress_zlib(const void *data, apr_size_t len, + svn_stringbuf_t *out, + int compression_method) { if ( compression_method < SVN__COMPRESSION_NONE || compression_method > SVN__COMPRESSION_ZLIB_MAX) @@ -245,13 +189,13 @@ svn__compress(svn_stringbuf_t *in, _("Unsupported compression method %d"), compression_method); - return zlib_encode(in->data, in->len, out, compression_method); + return zlib_encode(data, len, out, compression_method); } svn_error_t * -svn__decompress(svn_stringbuf_t *in, - svn_stringbuf_t *out, - apr_size_t limit) +svn__decompress_zlib(const void *data, apr_size_t len, + svn_stringbuf_t *out, + apr_size_t limit) { - return zlib_decode((const unsigned char*)in->data, in->len, out, limit); + return zlib_decode(data, len, out, limit); } diff --git a/subversion/libsvn_subr/config.c b/subversion/libsvn_subr/config.c index 770d699ef020..5c3cf440a208 100644 --- a/subversion/libsvn_subr/config.c +++ b/subversion/libsvn_subr/config.c @@ -33,12 +33,15 @@ #include #include "svn_hash.h" #include "svn_error.h" +#include "svn_string.h" #include "svn_pools.h" #include "config_impl.h" -#include "svn_private_config.h" #include "private/svn_dep_compat.h" #include "private/svn_subr_private.h" +#include "private/svn_config_private.h" + +#include "svn_private_config.h" @@ -55,6 +58,27 @@ struct cfg_section_t }; +/* States that a config option value can assume. */ +typedef enum option_state_t +{ + /* Value still needs to be expanded. + This is the initial state for *all* values. */ + option_state_needs_expanding, + + /* Value is currently being expanded. + This transitional state allows for detecting cyclic dependencies. */ + option_state_expanding, + + /* Expanded value is available. + Values that never needed expanding directly go into that state + skipping option_state_expanding. */ + option_state_expanded, + + /* The value expansion is cyclic which results in "undefined" behavior. + This is to return a defined value ("") in that case. */ + option_state_cyclic +} option_state_t; + /* Option table entries. */ typedef struct cfg_option_t cfg_option_t; struct cfg_option_t @@ -71,10 +95,10 @@ struct cfg_option_t /* The expanded option value. */ const char *x_value; - /* Expansion flag. If this is TRUE, this value has already been expanded. - In this case, if x_value is NULL, no expansions were necessary, - and value should be used directly. */ - svn_boolean_t expanded; + /* Expansion state. If this is option_state_expanded, VALUE has already + been expanded. In this case, if x_value is NULL, no expansions were + necessary, and value should be used directly. */ + option_state_t state; }; @@ -87,7 +111,7 @@ svn_config_create2(svn_config_t **cfgp, { svn_config_t *cfg = apr_palloc(result_pool, sizeof(*cfg)); - cfg->sections = apr_hash_make(result_pool); + cfg->sections = svn_hash__make(result_pool); cfg->pool = result_pool; cfg->x_pool = svn_pool_create(result_pool); cfg->x_values = FALSE; @@ -137,6 +161,18 @@ svn_config_read3(svn_config_t **cfgp, const char *file, return SVN_NO_ERROR; } +svn_error_t * +svn_config__default_add_value_fn(void *baton, + svn_stringbuf_t *section, + svn_stringbuf_t *option, + svn_stringbuf_t *value) +{ + /* FIXME: We may as well propagate the known string sizes here. */ + svn_config_set((svn_config_t *)baton, section->data, + option->data, value->data); + return SVN_NO_ERROR; +} + svn_error_t * svn_config_parse(svn_config_t **cfgp, svn_stream_t *stream, svn_boolean_t section_names_case_sensitive, @@ -153,7 +189,12 @@ svn_config_parse(svn_config_t **cfgp, svn_stream_t *stream, result_pool); if (err == SVN_NO_ERROR) - err = svn_config__parse_stream(cfg, stream, result_pool, scratch_pool); + err = svn_config__parse_stream(stream, + svn_config__constructor_create( + NULL, NULL, + svn_config__default_add_value_fn, + scratch_pool), + cfg, scratch_pool); if (err == SVN_NO_ERROR) *cfgp = cfg; @@ -294,7 +335,7 @@ svn_config_get_config(apr_hash_t **cfg_hash, apr_pool_t *pool) { svn_config_t *cfg; - *cfg_hash = apr_hash_make(pool); + *cfg_hash = svn_hash__make(pool); SVN_ERR(get_category_config(&cfg, config_dir, SVN_CONFIG_CATEGORY_SERVERS, pool)); @@ -312,7 +353,7 @@ svn_config__get_default_config(apr_hash_t **cfg_hash, apr_pool_t *pool) { svn_config_t *empty_cfg; - *cfg_hash = apr_hash_make(pool); + *cfg_hash = svn_hash__make(pool); SVN_ERR(svn_config_create2(&empty_cfg, FALSE, FALSE, pool)); svn_hash_sets(*cfg_hash, SVN_CONFIG_CATEGORY_CONFIG, empty_cfg); @@ -338,22 +379,14 @@ for_each_option(svn_config_t *cfg, void *baton, apr_pool_t *pool, sec_ndx != NULL; sec_ndx = apr_hash_next(sec_ndx)) { - void *sec_ptr; - cfg_section_t *sec; + cfg_section_t *sec = apr_hash_this_val(sec_ndx); apr_hash_index_t *opt_ndx; - apr_hash_this(sec_ndx, NULL, NULL, &sec_ptr); - sec = sec_ptr; - for (opt_ndx = apr_hash_first(pool, sec->options); opt_ndx != NULL; opt_ndx = apr_hash_next(opt_ndx)) { - void *opt_ptr; - cfg_option_t *opt; - - apr_hash_this(opt_ndx, NULL, NULL, &opt_ptr); - opt = opt_ptr; + cfg_option_t *opt = apr_hash_this_val(opt_ndx); if (callback(baton, sec, opt)) return; @@ -396,12 +429,13 @@ svn_config_merge(svn_config_t *cfg, const char *file, static svn_boolean_t rmex_callback(void *baton, cfg_section_t *section, cfg_option_t *option) { - /* Only clear the `expanded' flag if the value actually contains + /* Only reset the expansion state if the value actually contains variable expansions. */ - if (option->expanded && option->x_value != NULL) + if ( (option->state == option_state_expanded && option->x_value != NULL) + || option->state == option_state_cyclic) { option->x_value = NULL; - option->expanded = FALSE; + option->state = option_state_needs_expanding; } return FALSE; @@ -482,7 +516,7 @@ find_option(svn_config_t *cfg, const char *section, const char *option, /* Has a bi-directional dependency with make_string_from_option(). */ -static void +static svn_boolean_t expand_option_value(svn_config_t *cfg, cfg_section_t *section, const char *opt_value, const char **opt_x_valuep, apr_pool_t *x_pool); @@ -496,7 +530,20 @@ make_string_from_option(const char **valuep, svn_config_t *cfg, apr_pool_t* x_pool) { /* Expand the option value if necessary. */ - if (!opt->expanded) + if ( opt->state == option_state_expanding + || opt->state == option_state_cyclic) + { + /* Recursion is not supported. Since we can't produce an error + * nor should we abort the process, the next best thing is to + * report the recursive part as an empty string. */ + *valuep = ""; + + /* Go into "value undefined" state. */ + opt->state = option_state_cyclic; + + return; + } + else if (opt->state == option_state_needs_expanding) { /* before attempting to expand an option, check for the placeholder. * If none is there, there is no point in calling expand_option_value. @@ -511,9 +558,16 @@ make_string_from_option(const char **valuep, svn_config_t *cfg, tmp_pool = (x_pool ? x_pool : svn_pool_create(cfg->x_pool)); - expand_option_value(cfg, section, opt->value, &opt->x_value, tmp_pool); - opt->expanded = TRUE; + /* Expand the value. During that process, have the option marked + * as "expanding" to detect cycles. */ + opt->state = option_state_expanding; + if (expand_option_value(cfg, section, opt->value, &opt->x_value, + tmp_pool)) + opt->state = option_state_expanded; + else + opt->state = option_state_cyclic; + /* Ensure the expanded value is allocated in a permanent pool. */ if (x_pool != cfg->x_pool) { /* Grab the fully expanded value from tmp_pool before its @@ -527,7 +581,7 @@ make_string_from_option(const char **valuep, svn_config_t *cfg, } else { - opt->expanded = TRUE; + opt->state = option_state_expanded; } } @@ -549,8 +603,9 @@ make_string_from_option(const char **valuep, svn_config_t *cfg, /* Expand OPT_VALUE (which may be NULL) in SECTION into *OPT_X_VALUEP. If no variable replacements are done, set *OPT_X_VALUEP to - NULL. Allocate from X_POOL. */ -static void + NULL. Return TRUE if the expanded value is defined and FALSE + for recursive definitions. Allocate from X_POOL. */ +static svn_boolean_t expand_option_value(svn_config_t *cfg, cfg_section_t *section, const char *opt_value, const char **opt_x_valuep, apr_pool_t *x_pool) @@ -587,6 +642,18 @@ expand_option_value(svn_config_t *cfg, cfg_section_t *section, should terminate. */ make_string_from_option(&cstring, cfg, section, x_opt, x_pool); + /* Values depending on cyclic values must also be marked as + * "undefined" because they might themselves form cycles with + * the one cycle we just detected. Due to the early abort of + * the recursion, we won't follow and thus detect dependent + * cycles anymore. + */ + if (x_opt->state == option_state_cyclic) + { + *opt_x_valuep = ""; + return FALSE; + } + /* Append the plain text preceding the expansion. */ len = name_start - FMT_START_LEN - copy_from; if (buf == NULL) @@ -625,6 +692,9 @@ expand_option_value(svn_config_t *cfg, cfg_section_t *section, } else *opt_x_valuep = NULL; + + /* Expansion has a well-defined answer. */ + return TRUE; } static cfg_section_t * @@ -640,7 +710,8 @@ svn_config_addsection(svn_config_t *cfg, hash_key = s->name; else hash_key = make_hash_key(apr_pstrdup(cfg->pool, section)); - s->options = apr_hash_make(cfg->pool); + s->options = svn_hash__make(cfg->pool); + svn_hash_sets(cfg->sections, hash_key, s); return s; @@ -664,7 +735,7 @@ svn_config_create_option(cfg_option_t **opt, o->value = apr_pstrdup(pool, value); o->x_value = NULL; - o->expanded = FALSE; + o->state = option_state_needs_expanding; *opt = o; } @@ -685,7 +756,8 @@ svn_config__is_expanded(svn_config_t *cfg, return FALSE; /* already expanded? */ - if (opt->expanded) + if ( opt->state == option_state_expanded + || opt->state == option_state_cyclic) return TRUE; /* needs expansion? */ @@ -719,8 +791,14 @@ svn_config_get(svn_config_t *cfg, const char **valuep, { apr_pool_t *tmp_pool = svn_pool_create(cfg->pool); const char *x_default; - expand_option_value(cfg, sec, default_value, &x_default, tmp_pool); - if (x_default) + if (!expand_option_value(cfg, sec, default_value, &x_default, + tmp_pool)) + { + /* Recursive definitions are not supported. + Normalize the answer in that case. */ + *valuep = ""; + } + else if (x_default) { svn_stringbuf_set(cfg->tmp_value, x_default); *valuep = cfg->tmp_value->data; @@ -758,7 +836,7 @@ svn_config_set(svn_config_t *cfg, { /* Replace the option's value. */ opt->value = apr_pstrdup(cfg->pool, value); - opt->expanded = FALSE; + opt->state = option_state_needs_expanding; return; } @@ -965,11 +1043,8 @@ svn_config_enumerate_sections2(svn_config_t *cfg, sec_ndx != NULL; sec_ndx = apr_hash_next(sec_ndx)) { - void *sec_ptr; - cfg_section_t *sec; + cfg_section_t *sec = apr_hash_this_val(sec_ndx); - apr_hash_this(sec_ndx, NULL, NULL, &sec_ptr); - sec = sec_ptr; ++count; svn_pool_clear(iteration_pool); if (!callback(sec->name, baton, iteration_pool)) @@ -1001,13 +1076,9 @@ svn_config_enumerate(svn_config_t *cfg, const char *section, opt_ndx != NULL; opt_ndx = apr_hash_next(opt_ndx)) { - void *opt_ptr; - cfg_option_t *opt; + cfg_option_t *opt = apr_hash_this_val(opt_ndx); const char *temp_value; - apr_hash_this(opt_ndx, NULL, NULL, &opt_ptr); - opt = opt_ptr; - ++count; make_string_from_option(&temp_value, cfg, sec, opt, NULL); if (!callback(opt->name, temp_value, baton)) @@ -1039,13 +1110,9 @@ svn_config_enumerate2(svn_config_t *cfg, const char *section, opt_ndx != NULL; opt_ndx = apr_hash_next(opt_ndx)) { - void *opt_ptr; - cfg_option_t *opt; + cfg_option_t *opt = apr_hash_this_val(opt_ndx); const char *temp_value; - apr_hash_this(opt_ndx, NULL, NULL, &opt_ptr); - opt = opt_ptr; - ++count; make_string_from_option(&temp_value, cfg, sec, opt, NULL); svn_pool_clear(iteration_pool); @@ -1171,7 +1238,7 @@ svn_config_dup(svn_config_t **cfgp, destopt->value = apr_pstrdup(pool, srcopt->value); destopt->x_value = apr_pstrdup(pool, srcopt->x_value); - destopt->expanded = srcopt->expanded; + destopt->state = srcopt->state; apr_hash_set(destsec->options, apr_pstrdup(pool, (const char*)optkey), optkeyLength, destopt); @@ -1188,7 +1255,7 @@ svn_config_copy_config(apr_hash_t **cfg_hash, { apr_hash_index_t *cidx; - *cfg_hash = apr_hash_make(pool); + *cfg_hash = svn_hash__make(pool); for (cidx = apr_hash_first(pool, src_hash); cidx != NULL; cidx = apr_hash_next(cidx)) @@ -1265,3 +1332,40 @@ svn_config_has_section(svn_config_t *cfg, const char *section) return NULL != get_hash_value(cfg->sections, cfg->tmp_key, section, cfg->section_names_case_sensitive); } + +svn_error_t * +svn_config__write(svn_stream_t *stream, + const struct svn_config_t *cfg, + apr_pool_t *scratch_pool) +{ + apr_hash_index_t *section_i; + apr_hash_index_t *options_i; + apr_pool_t *section_pool = svn_pool_create(scratch_pool); + apr_pool_t *options_pool = svn_pool_create(scratch_pool); + + for (section_i = apr_hash_first(scratch_pool, cfg->sections); + section_i != NULL; + section_i = apr_hash_next(section_i)) + { + cfg_section_t *section = apr_hash_this_val(section_i); + svn_pool_clear(section_pool); + SVN_ERR(svn_stream_printf(stream, section_pool, "\n[%s]\n", + section->name)); + + for (options_i = apr_hash_first(section_pool, section->options); + options_i != NULL; + options_i = apr_hash_next(options_i)) + { + cfg_option_t *option = apr_hash_this_val(options_i); + svn_pool_clear(options_pool); + SVN_ERR(svn_stream_printf(stream, options_pool, "%s=%s\n", + option->name, option->value)); + } + } + + svn_pool_destroy(section_pool); + svn_pool_destroy(options_pool); + + return SVN_NO_ERROR; +} + diff --git a/subversion/libsvn_subr/config_auth.c b/subversion/libsvn_subr/config_auth.c index 90670f9d7519..7461b912a732 100644 --- a/subversion/libsvn_subr/config_auth.c +++ b/subversion/libsvn_subr/config_auth.c @@ -144,7 +144,7 @@ svn_config_write_auth_data(apr_hash_t *hash, apr_psprintf(pool, _("Error writing hash to '%s'"), svn_dirent_local_style(auth_path, pool))); SVN_ERR(svn_stream_close(stream)); - SVN_ERR(svn_io_file_rename(tmp_path, auth_path, pool)); + SVN_ERR(svn_io_file_rename2(tmp_path, auth_path, FALSE, pool)); /* To be nice, remove the realmstring from the hash again, just in case the caller wants their hash unchanged. diff --git a/subversion/libsvn_subr/config_file.c b/subversion/libsvn_subr/config_file.c index e4a5936d7834..bd2ec828a542 100644 --- a/subversion/libsvn_subr/config_file.c +++ b/subversion/libsvn_subr/config_file.c @@ -25,6 +25,8 @@ #include #include +#include + #include "config_impl.h" #include "svn_io.h" #include "svn_types.h" @@ -37,8 +39,9 @@ #include "svn_user.h" #include "svn_ctype.h" -#include "svn_private_config.h" +#include "private/svn_config_private.h" #include "private/svn_subr_private.h" +#include "svn_private_config.h" #ifdef __HAIKU__ # include @@ -52,8 +55,9 @@ /* File parsing context */ typedef struct parse_context_t { - /* This config struct */ - svn_config_t *cfg; + /* The configuration constructor. */ + svn_config__constructor_t *constructor; + void *constructor_baton; /* The stream struct */ svn_stream_t *stream; @@ -64,10 +68,14 @@ typedef struct parse_context_t /* Emulate an ungetc */ int ungotten_char; + /* We're currently parsing a section */ + svn_boolean_t in_section; + /* Temporary strings */ svn_stringbuf_t *section; svn_stringbuf_t *option; svn_stringbuf_t *value; + svn_stringbuf_t *line_read; /* Parser buffer for getc() to avoid call overhead into several libraries for every character */ @@ -80,6 +88,109 @@ typedef struct parse_context_t } parse_context_t; +/* Config representation constructor */ +struct svn_config__constructor_t +{ + /* Constructor callbacks; see docs for svn_config__constructor_create. */ + svn_config__open_section_fn open_section; + svn_config__close_section_fn close_section; + svn_config__add_value_fn add_value; +}; + +svn_config__constructor_t * +svn_config__constructor_create( + svn_config__open_section_fn open_section_callback, + svn_config__close_section_fn close_section_callback, + svn_config__add_value_fn add_value_callback, + apr_pool_t *result_pool) +{ + svn_config__constructor_t *ctor = apr_palloc(result_pool, sizeof(*ctor)); + ctor->open_section = open_section_callback; + ctor->close_section = close_section_callback; + ctor->add_value = add_value_callback; + return ctor; +} + +/* Called after we've parsed a section name and before we start + parsing any options within that section. */ +static APR_INLINE svn_error_t * +open_section(parse_context_t *ctx, svn_boolean_t *stop) +{ + if (ctx->constructor->open_section) + { + svn_error_t *err = ctx->constructor->open_section( + ctx->constructor_baton, ctx->section); + if (err) + { + if (err->apr_err == SVN_ERR_CEASE_INVOCATION) + { + *stop = TRUE; + svn_error_clear(err); + return SVN_NO_ERROR; + } + else + return svn_error_trace(err); + } + } + + *stop = FALSE; + ctx->in_section = TRUE; + return SVN_NO_ERROR; +} + +/* Called after we've parsed all options within a section and before + we start parsing the next section. */ +static APR_INLINE svn_error_t * +close_section(parse_context_t *ctx, svn_boolean_t *stop) +{ + ctx->in_section = FALSE; + if (ctx->constructor->close_section) + { + svn_error_t *err = ctx->constructor->close_section( + ctx->constructor_baton, ctx->section); + if (err) + { + if (err->apr_err == SVN_ERR_CEASE_INVOCATION) + { + *stop = TRUE; + svn_error_clear(err); + return SVN_NO_ERROR; + } + else + return svn_error_trace(err); + } + } + + *stop = FALSE; + return SVN_NO_ERROR; +} + +/* Called every tyme we've parsed a complete (option, value) pair. */ +static APR_INLINE svn_error_t * +add_value(parse_context_t *ctx, svn_boolean_t *stop) +{ + if (ctx->constructor->add_value) + { + svn_error_t *err = ctx->constructor->add_value( + ctx->constructor_baton, ctx->section, + ctx->option, ctx->value); + if (err) + { + if (err->apr_err == SVN_ERR_CEASE_INVOCATION) + { + *stop = TRUE; + svn_error_clear(err); + return SVN_NO_ERROR; + } + else + return svn_error_trace(err); + } + } + + *stop = FALSE; + return SVN_NO_ERROR; +} + /* Emulate getc() because streams don't support it. * @@ -161,6 +272,57 @@ parser_ungetc(parse_context_t *ctx, int c) return SVN_NO_ERROR; } +/* Read from CTX to the end of the line (or file) and write the data + into LINE. Previous contents of *LINE will be overwritten. + Returns the char that ended the line in *C; the char is either + EOF or newline. */ +static svn_error_t * +parser_get_line(parse_context_t *ctx, svn_stringbuf_t *line, int *c) +{ + int ch; + svn_stringbuf_setempty(line); + + /* Loop until EOF of newline. There is one extra iteration per + * parser buffer refill. The initial parser_getc() also ensures + * that the unget buffer is emptied. */ + SVN_ERR(parser_getc(ctx, &ch)); + while (ch != '\n' && ch != EOF) + { + const char *start, *newline; + + /* Save the char we just read. */ + svn_stringbuf_appendbyte(line, ch); + + /* Scan the parser buffer for NL. */ + start = ctx->parser_buffer + ctx->buffer_pos; + newline = memchr(start, '\n', ctx->buffer_size - ctx->buffer_pos); + if (newline) + { + /* NL found before the end of the of the buffer. */ + svn_stringbuf_appendbytes(line, start, newline - start); + ch = '\n'; + ctx->buffer_pos = newline - ctx->parser_buffer + 1; + break; + } + else + { + /* Hit the end of the buffer. This may be either due to + * buffer size or EOF. In any case, all (remaining) current + * buffer data is part of the line to read. */ + const char *end = ctx->parser_buffer + ctx->buffer_size; + ctx->buffer_pos = ctx->buffer_size; + + svn_stringbuf_appendbytes(line, start, end - start); + } + + /* refill buffer, check for EOF */ + SVN_ERR(parser_getc_plain(ctx, &ch)); + } + + *c = ch; + return SVN_NO_ERROR; +} + /* Eat chars from STREAM until encounter non-whitespace, newline, or EOF. Set *PCOUNT to the number of characters eaten, not counting the last one, and return the last char read (the one that caused the @@ -245,23 +407,16 @@ skip_bom(parse_context_t *ctx) return SVN_NO_ERROR; } -/* Parse a single option value */ +/* Parse continuation lines of single option value if they exist. Append + * their contents, including *PCH, to CTX->VALUE. Return the first char + * of the next line or EOF in *PCH. */ static svn_error_t * -parse_value(int *pch, parse_context_t *ctx) +parse_value_continuation_lines(int *pch, parse_context_t *ctx) { svn_boolean_t end_of_val = FALSE; - int ch; + svn_boolean_t stop; + int ch = *pch; - /* Read the first line of the value */ - svn_stringbuf_setempty(ctx->value); - SVN_ERR(parser_getc(ctx, &ch)); - while (ch != EOF && ch != '\n') - /* last ch seen was ':' or '=' in parse_option. */ - { - const char char_from_int = (char)ch; - svn_stringbuf_appendbyte(ctx->value, char_from_int); - SVN_ERR(parser_getc(ctx, &ch)); - } /* Leading and trailing whitespace is ignored. */ svn_stringbuf_strip_whitespace(ctx->value); @@ -273,8 +428,9 @@ parse_value(int *pch, parse_context_t *ctx) { /* At end of file. The value is complete, there can't be any continuation lines. */ - svn_config_set(ctx->cfg, ctx->section->data, - ctx->option->data, ctx->value->data); + SVN_ERR(add_value(ctx, &stop)); + if (stop) + return SVN_NO_ERROR; break; } else @@ -310,16 +466,15 @@ parse_value(int *pch, parse_context_t *ctx) else { /* This is a continuation line. Read it. */ - svn_stringbuf_appendbyte(ctx->value, ' '); + SVN_ERR(parser_ungetc(ctx, ch)); + SVN_ERR(parser_get_line(ctx, ctx->line_read, &ch)); - while (ch != EOF && ch != '\n') - { - const char char_from_int = (char)ch; - svn_stringbuf_appendbyte(ctx->value, char_from_int); - SVN_ERR(parser_getc(ctx, &ch)); - } /* Trailing whitespace is ignored. */ - svn_stringbuf_strip_whitespace(ctx->value); + svn_stringbuf_strip_whitespace(ctx->line_read); + + svn_stringbuf_appendbyte(ctx->value, ' '); + svn_stringbuf_appendbytes(ctx->value, ctx->line_read->data, + ctx->line_read->len); } } } @@ -336,17 +491,33 @@ parse_option(int *pch, parse_context_t *ctx, apr_pool_t *scratch_pool) { svn_error_t *err = SVN_NO_ERROR; int ch; + char *equals, *separator; - svn_stringbuf_setempty(ctx->option); - ch = *pch; /* Yes, the first char is relevant. */ - while (ch != EOF && ch != ':' && ch != '=' && ch != '\n') + /* Read the first line. */ + parser_ungetc(ctx, *pch); /* Yes, the first char is relevant. */ + SVN_ERR(parser_get_line(ctx, ctx->line_read, &ch)); + + /* Extract the option name from it. */ + equals = strchr(ctx->line_read->data, '='); + if (equals) { - const char char_from_int = (char)ch; - svn_stringbuf_appendbyte(ctx->option, char_from_int); - SVN_ERR(parser_getc(ctx, &ch)); + /* Efficiently look for a colon separator prior to the equals sign. + * Since there is no strnchr, we limit the search by temporarily + * limiting the string. */ + char *colon; + *equals = 0; + colon = strchr(ctx->line_read->data, ':'); + *equals = '='; + + separator = colon ? colon : equals; + } + else + { + /* No '=' separator so far. Look for colon. */ + separator = strchr(ctx->line_read->data, ':'); } - if (ch != ':' && ch != '=') + if (!separator) { ch = EOF; err = svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL, @@ -356,8 +527,22 @@ parse_option(int *pch, parse_context_t *ctx, apr_pool_t *scratch_pool) else { /* Whitespace around the name separator is ignored. */ - svn_stringbuf_strip_whitespace(ctx->option); - err = parse_value(&ch, ctx); + const char *end = separator; + while (svn_ctype_isspace(*--end)) + ; + while (svn_ctype_isspace(*++separator)) + ; + + /* Extract the option. It can't contain whitespace chars. */ + svn_stringbuf_setempty(ctx->option); + svn_stringbuf_appendbytes(ctx->option, ctx->line_read->data, + end + 1 - ctx->line_read->data); + + /* Extract the first line of the value. */ + end = ctx->line_read->data + ctx->line_read->len; + svn_stringbuf_setempty(ctx->value); + svn_stringbuf_appendbytes(ctx->value, separator, end - separator); + err = parse_value_continuation_lines(&ch, ctx); } *pch = ch; @@ -379,17 +564,12 @@ parse_section_name(int *pch, parse_context_t *ctx, { svn_error_t *err = SVN_NO_ERROR; int ch; + char *terminal; - svn_stringbuf_setempty(ctx->section); - SVN_ERR(parser_getc(ctx, &ch)); - while (ch != EOF && ch != ']' && ch != '\n') - { - const char char_from_int = (char)ch; - svn_stringbuf_appendbyte(ctx->section, char_from_int); - SVN_ERR(parser_getc(ctx, &ch)); - } + SVN_ERR(parser_get_line(ctx, ctx->section, &ch)); + terminal = strchr(ctx->section->data, ']'); - if (ch != ']') + if (!terminal) { ch = EOF; err = svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL, @@ -399,9 +579,8 @@ parse_section_name(int *pch, parse_context_t *ctx, else { /* Everything from the ']' to the end of the line is ignored. */ - SVN_ERR(skip_to_eoln(ctx, &ch)); - if (ch != EOF) - ++ctx->line; + *terminal = 0; + ctx->section->len = terminal - ctx->section->data; } *pch = ch; @@ -531,6 +710,7 @@ svn_config__shallow_replace_section(svn_config_t *target, } + svn_error_t * svn_config__parse_file(svn_config_t *cfg, const char *file, svn_boolean_t must_exist, apr_pool_t *result_pool) @@ -554,7 +734,12 @@ svn_config__parse_file(svn_config_t *cfg, const char *file, SVN_ERR(err); stream = svn_stream_from_aprfile2(apr_file, FALSE, scratch_pool); - err = svn_config__parse_stream(cfg, stream, result_pool, scratch_pool); + err = svn_config__parse_stream(stream, + svn_config__constructor_create( + NULL, NULL, + svn_config__default_add_value_fn, + scratch_pool), + cfg, scratch_pool); if (err != SVN_NO_ERROR) { @@ -571,21 +756,27 @@ svn_config__parse_file(svn_config_t *cfg, const char *file, } svn_error_t * -svn_config__parse_stream(svn_config_t *cfg, svn_stream_t *stream, - apr_pool_t *result_pool, apr_pool_t *scratch_pool) +svn_config__parse_stream(svn_stream_t *stream, + svn_config__constructor_t *constructor, + void *constructor_baton, + apr_pool_t *scratch_pool) { parse_context_t *ctx; + svn_boolean_t stop; int ch, count; ctx = apr_palloc(scratch_pool, sizeof(*ctx)); - ctx->cfg = cfg; + ctx->constructor = constructor; + ctx->constructor_baton = constructor_baton; ctx->stream = stream; ctx->line = 1; ctx->ungotten_char = EOF; + ctx->in_section = FALSE; ctx->section = svn_stringbuf_create_empty(scratch_pool); ctx->option = svn_stringbuf_create_empty(scratch_pool); ctx->value = svn_stringbuf_create_empty(scratch_pool); + ctx->line_read = svn_stringbuf_create_empty(scratch_pool); ctx->buffer_pos = 0; ctx->buffer_size = 0; ctx->hit_stream_eof = FALSE; @@ -599,13 +790,23 @@ svn_config__parse_stream(svn_config_t *cfg, svn_stream_t *stream, switch (ch) { case '[': /* Start of section header */ - if (count == 0) - SVN_ERR(parse_section_name(&ch, ctx, scratch_pool)); - else + if (count != 0) return svn_error_createf(SVN_ERR_MALFORMED_FILE, NULL, _("line %d: Section header" " must start in the first column"), ctx->line); + + /* Close the previous section before starting a new one. */ + if (ctx->in_section) + { + SVN_ERR(close_section(ctx, &stop)); + if (stop) + return SVN_NO_ERROR; + } + SVN_ERR(parse_section_name(&ch, ctx, scratch_pool)); + SVN_ERR(open_section(ctx, &stop)); + if (stop) + return SVN_NO_ERROR; break; case '#': /* Comment */ @@ -644,6 +845,9 @@ svn_config__parse_stream(svn_config_t *cfg, svn_stream_t *stream, } while (ch != EOF); + /* Emit the last close-section call to wrap up. */ + if (ctx->in_section) + SVN_ERR(close_section(ctx, &stop)); return SVN_NO_ERROR; } @@ -945,12 +1149,12 @@ svn_config_ensure(const char *config_dir, apr_pool_t *pool) "### http-timeout Timeout for HTTP requests in seconds" NL "### http-compression Whether to compress HTTP requests" NL + "### (yes/no/auto)." NL "### http-max-connections Maximum number of parallel server" NL "### connections to use for any given" NL "### HTTP operation." NL "### http-chunked-requests Whether to use chunked transfer" NL "### encoding for HTTP requests body." NL - "### neon-debug-mask Debug mask for Neon HTTP library" NL "### ssl-authority-files List of files, each of a trusted CA" NL "### ssl-trust-default-ca Trust the system 'default' CAs" NL @@ -1043,7 +1247,6 @@ svn_config_ensure(const char *config_dir, apr_pool_t *pool) "### Most users will not need to explicitly set the http-library" NL "### option, but valid values for the option include:" NL "### 'serf': Serf-based module (Subversion 1.5 - present)" NL - "### 'neon': Neon-based module (Subversion 1.0 - 1.7)" NL "### Availability of these modules may depend on your specific" NL "### Subversion distribution." NL "###" NL @@ -1068,7 +1271,6 @@ svn_config_ensure(const char *config_dir, apr_pool_t *pool) "# http-proxy-username = blah" NL "# http-proxy-password = doubleblah" NL "# http-timeout = 60" NL - "# neon-debug-mask = 130" NL #ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE "# store-plaintext-passwords = no" NL #endif @@ -1107,9 +1309,8 @@ svn_config_ensure(const char *config_dir, apr_pool_t *pool) "# http-proxy-port = 7000" NL "# http-proxy-username = defaultusername" NL "# http-proxy-password = defaultpassword" NL - "# http-compression = no" NL + "# http-compression = auto" NL "# No http-timeout, so just use the builtin default." NL - "# No neon-debug-mask, so neon debugging is disabled." NL "# ssl-authority-files = /path/to/CAcert.pem;/path/to/CAcert2.pem" NL "#" NL "# Password / passphrase caching parameters:" NL @@ -1421,7 +1622,7 @@ svn_config_get_user_config_path(const char **path, if (! homedir) return SVN_NO_ERROR; *path = svn_dirent_join_many(pool, - svn_dirent_canonicalize(homedir, pool), + homedir, SVN_CONFIG__USR_DIRECTORY, fname, SVN_VA_NULL); } #endif /* WIN32 */ diff --git a/subversion/libsvn_subr/config_impl.h b/subversion/libsvn_subr/config_impl.h index 529d7d5d1aca..899dd2a65d96 100644 --- a/subversion/libsvn_subr/config_impl.h +++ b/subversion/libsvn_subr/config_impl.h @@ -76,18 +76,18 @@ struct svn_config_t svn_boolean_t read_only; }; +/* The default add-value constructor callback, used by the default + config parser that populates an svn_config_t. */ +svn_error_t *svn_config__default_add_value_fn( + void *baton, svn_stringbuf_t *section, + svn_stringbuf_t *option, svn_stringbuf_t *value); + /* Read sections and options from a file. */ svn_error_t *svn_config__parse_file(svn_config_t *cfg, const char *file, svn_boolean_t must_exist, apr_pool_t *pool); -/* Read sections and options from a stream. */ -svn_error_t *svn_config__parse_stream(svn_config_t *cfg, - svn_stream_t *stream, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool); - /* The name of the magic [DEFAULT] section. */ #define SVN_CONFIG__DEFAULT_SECTION "DEFAULT" diff --git a/subversion/libsvn_subr/config_win.c b/subversion/libsvn_subr/config_win.c index 77f7ce43994b..aeab0d6b1af8 100644 --- a/subversion/libsvn_subr/config_win.c +++ b/subversion/libsvn_subr/config_win.c @@ -201,10 +201,14 @@ svn_config__parse_registry(svn_config_t *cfg, const char *file, svn_boolean_t is_enoent = APR_STATUS_IS_ENOENT(apr_err) || (err == ERROR_INVALID_HANDLE); - if (must_exist || !is_enoent) + if (!is_enoent) return svn_error_createf(SVN_ERR_BAD_FILENAME, - is_enoent ? NULL - : svn_error_wrap_apr(apr_err, NULL), + svn_error_wrap_apr(apr_err, NULL), + _("Can't open registry key '%s'"), + svn_dirent_local_style(file, pool)); + else if (must_exist) + return svn_error_createf(SVN_ERR_BAD_FILENAME, + NULL, _("Can't open registry key '%s'"), svn_dirent_local_style(file, pool)); else @@ -269,4 +273,11 @@ svn_config__parse_registry(svn_config_t *cfg, const char *file, return svn_err; } +#else /* !WIN32 */ + +/* Silence OSX ranlib warnings about object files with no symbols. */ +#include +extern const apr_uint32_t svn__fake__config_win; +const apr_uint32_t svn__fake__config_win = 0xdeadbeef; + #endif /* WIN32 */ diff --git a/subversion/libsvn_subr/deprecated.c b/subversion/libsvn_subr/deprecated.c index 68e3bd2cb3f9..1110d994bb79 100644 --- a/subversion/libsvn_subr/deprecated.c +++ b/subversion/libsvn_subr/deprecated.c @@ -46,6 +46,7 @@ #include "svn_utf.h" #include "svn_xml.h" #include "svn_auth.h" +#include "svn_base64.h" #include "opt.h" #include "auth.h" @@ -889,6 +890,26 @@ svn_io_stat_dirent(const svn_io_dirent2_t **dirent_p, scratch_pool)); } +svn_error_t * +svn_io_file_rename(const char *from_path, const char *to_path, + apr_pool_t *pool) +{ + return svn_error_trace(svn_io_file_rename2(from_path, to_path, + FALSE, pool)); +} + +svn_error_t * +svn_io_write_atomic(const char *final_path, + const void *buf, + apr_size_t nbytes, + const char *copy_perms_path, + apr_pool_t *scratch_pool) +{ + return svn_error_trace(svn_io_write_atomic2(final_path, buf, nbytes, + copy_perms_path, TRUE, + scratch_pool)); +} + /*** From constructors.c ***/ svn_log_changed_path_t * svn_log_changed_path_dup(const svn_log_changed_path_t *changed_path, @@ -1057,6 +1078,12 @@ svn_stream_from_aprfile(apr_file_t *file, apr_pool_t *pool) return svn_stream_from_aprfile2(file, TRUE, pool); } +svn_error_t * +svn_stream_for_stdin(svn_stream_t **in, apr_pool_t *pool) +{ + return svn_error_trace(svn_stream_for_stdin2(in, FALSE, pool)); +} + svn_error_t * svn_stream_contents_same(svn_boolean_t *same, svn_stream_t *stream1, @@ -1183,6 +1210,16 @@ svn_stream_checksummed(svn_stream_t *stream, return s; } +svn_error_t * +svn_string_from_stream(svn_string_t **result, + svn_stream_t *stream, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + return svn_error_trace(svn_string_from_stream2(result, stream, 0, + result_pool)); +} + /*** From path.c ***/ const char * @@ -1251,7 +1288,7 @@ svn_rangelist_merge(svn_rangelist_t **rangelist, pool, pool)); return svn_error_trace( - svn_rangelist__combine_adjacent_ranges(*rangelist, pool)); + svn_rangelist__canonicalize(*rangelist, pool)); } svn_error_t * @@ -1548,3 +1585,19 @@ svn_cmdline_create_auth_baton(svn_auth_baton_t **ab, cancel_baton, pool)); } + +/*** From base64.c ***/ +svn_stream_t * +svn_base64_encode(svn_stream_t *output, apr_pool_t *pool) +{ + return svn_base64_encode2(output, TRUE, pool); +} + +/*** From string.c ***/ +char * +svn_cstring_join(const apr_array_header_t *strings, + const char *separator, + apr_pool_t *pool) +{ + return svn_cstring_join2(strings, separator, TRUE, pool); +} diff --git a/subversion/libsvn_subr/dirent_uri.c b/subversion/libsvn_subr/dirent_uri.c index a009145eb946..b53f3508fd2d 100644 --- a/subversion/libsvn_subr/dirent_uri.c +++ b/subversion/libsvn_subr/dirent_uri.c @@ -495,14 +495,20 @@ canonicalize(path_type_t type, const char *path, apr_pool_t *pool) #ifdef SVN_USE_DOS_PATHS /* If this is the first path segment of a file:// URI and it contains a windows drive letter, convert the drive letter to upper case. */ - else if (url && canon_segments == 1 && seglen == 2 && + else if (url && canon_segments == 1 && seglen >= 2 && (strncmp(canon, "file:", 5) == 0) && src[0] >= 'a' && src[0] <= 'z' && src[1] == ':') { *(dst++) = canonicalize_to_upper(src[0]); *(dst++) = ':'; - if (*next) - *(dst++) = *next; + if (seglen > 2) /* drive relative path */ + { + memcpy(dst, src + 2, seglen - 2); + dst += seglen - 2; + } + + if (slash_len) + *(dst++) = '/'; canon_segments++; } #endif /* SVN_USE_DOS_PATHS */ @@ -1856,18 +1862,18 @@ svn_uri_is_canonical(const char *uri, apr_pool_t *scratch_pool) ptr++; } - if (ptr == schema_data) + if (ptr == schema_data && (*ptr == '/' || *ptr == '\0')) return FALSE; /* Fail on "http://host:" */ - if (*ptr && *ptr != '/') - return FALSE; /* Not a port number */ - if (port == 80 && strncmp(uri, "http:", 5) == 0) return FALSE; else if (port == 443 && strncmp(uri, "https:", 6) == 0) return FALSE; else if (port == 3690 && strncmp(uri, "svn:", 4) == 0) return FALSE; + + while (*ptr && *ptr != '/') + ++ptr; /* Allow "http://host:stuff" */ } schema_data = ptr; @@ -2398,8 +2404,11 @@ svn_uri_get_dirent_from_file_url(const char **dirent, if (dup_path[1] == '|') dup_path[1] = ':'; - if (dup_path[2] == '/' || dup_path[2] == '\0') + if (dup_path[2] == '/' || dup_path[2] == '\\' || dup_path[2] == '\0') { + /* Dirents have upper case drive letters in their canonical form */ + dup_path[0] = canonicalize_to_upper(dup_path[0]); + if (dup_path[2] == '\0') { /* A valid dirent for the driveroot must be like "C:/" instead of @@ -2412,6 +2421,8 @@ svn_uri_get_dirent_from_file_url(const char **dirent, new_path[3] = '\0'; dup_path = new_path; } + else + dup_path[2] = '/'; /* Ensure not relative for '\' after drive! */ } } if (hostname) diff --git a/subversion/libsvn_subr/dso.c b/subversion/libsvn_subr/dso.c index 46af5499ff51..681b8f6958db 100644 --- a/subversion/libsvn_subr/dso.c +++ b/subversion/libsvn_subr/dso.c @@ -19,7 +19,6 @@ * ==================================================================== */ -#include #include #include "svn_hash.h" diff --git a/subversion/libsvn_subr/encode.c b/subversion/libsvn_subr/encode.c new file mode 100644 index 000000000000..503277cd9e2f --- /dev/null +++ b/subversion/libsvn_subr/encode.c @@ -0,0 +1,107 @@ +/* + * encode.c: various data encoding routines + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +#include "private/svn_subr_private.h" + +#include "svn_private_config.h" + +unsigned char * +svn__encode_uint(unsigned char *p, apr_uint64_t val) +{ + int n; + apr_uint64_t v; + + /* Figure out how many bytes we'll need. */ + v = val >> 7; + n = 1; + while (v > 0) + { + v = v >> 7; + n++; + } + + /* Encode the remaining bytes; n is always the number of bytes + coming after the one we're encoding. */ + while (--n >= 1) + *p++ = (unsigned char)(((val >> (n * 7)) | 0x80) & 0xff); + + *p++ = (unsigned char)(val & 0x7f); + + return p; +} + +unsigned char * +svn__encode_int(unsigned char *p, apr_int64_t val) +{ + apr_uint64_t value = val; + value = value & APR_UINT64_C(0x8000000000000000) + ? APR_UINT64_MAX - (2 * value) + : 2 * value; + + return svn__encode_uint(p, value); +} + +const unsigned char * +svn__decode_uint(apr_uint64_t *val, + const unsigned char *p, + const unsigned char *end) +{ + apr_uint64_t temp = 0; + + if (end - p > SVN__MAX_ENCODED_UINT_LEN) + end = p + SVN__MAX_ENCODED_UINT_LEN; + + /* Decode bytes until we're done. */ + while (SVN__PREDICT_TRUE(p < end)) + { + unsigned int c = *p++; + + if (c < 0x80) + { + *val = (temp << 7) | c; + return p; + } + else + { + temp = (temp << 7) | (c & 0x7f); + } + } + + return NULL; +} + +const unsigned char * +svn__decode_int(apr_int64_t *val, + const unsigned char *p, + const unsigned char *end) +{ + apr_uint64_t value; + const unsigned char *result = svn__decode_uint(&value, p, end); + + value = value & 1 + ? (APR_UINT64_MAX - value / 2) + : value / 2; + *val = (apr_int64_t)value; + + return result; +} diff --git a/subversion/libsvn_subr/eol.c b/subversion/libsvn_subr/eol.c index e63cf1113577..d04afd71c2e3 100644 --- a/subversion/libsvn_subr/eol.c +++ b/subversion/libsvn_subr/eol.c @@ -38,25 +38,25 @@ svn_eol__find_eol_start(char *buf, apr_size_t len) /* Scan the input one machine word at a time. */ for (; len > sizeof(apr_uintptr_t) ; buf += sizeof(apr_uintptr_t), len -= sizeof(apr_uintptr_t)) - { - /* This is a variant of the well-known strlen test: */ - apr_uintptr_t chunk = *(const apr_uintptr_t *)buf; + { + /* This is a variant of the well-known strlen test: */ + apr_uintptr_t chunk = *(const apr_uintptr_t *)buf; - /* A byte in SVN__R_TEST is \0, iff it was \r in *BUF. - * Similarly, SVN__N_TEST is an indicator for \n. */ - apr_uintptr_t r_test = chunk ^ SVN__R_MASK; - apr_uintptr_t n_test = chunk ^ SVN__N_MASK; + /* A byte in SVN__R_TEST is \0, iff it was \r in *BUF. + * Similarly, SVN__N_TEST is an indicator for \n. */ + apr_uintptr_t r_test = chunk ^ SVN__R_MASK; + apr_uintptr_t n_test = chunk ^ SVN__N_MASK; - /* A byte in SVN__R_TEST can only be < 0x80, iff it has been \0 before - * (i.e. \r in *BUF). Ditto for SVN__N_TEST. */ - r_test |= (r_test & SVN__LOWER_7BITS_SET) + SVN__LOWER_7BITS_SET; - n_test |= (n_test & SVN__LOWER_7BITS_SET) + SVN__LOWER_7BITS_SET; + /* A byte in SVN__R_TEST can only be < 0x80, iff it has been \0 before + * (i.e. \r in *BUF). Ditto for SVN__N_TEST. */ + r_test |= (r_test & SVN__LOWER_7BITS_SET) + SVN__LOWER_7BITS_SET; + n_test |= (n_test & SVN__LOWER_7BITS_SET) + SVN__LOWER_7BITS_SET; - /* Check whether at least one of the words contains a byte <0x80 - * (if one is detected, there was a \r or \n in CHUNK). */ - if ((r_test & n_test & SVN__BIT_7_SET) != SVN__BIT_7_SET) - break; - } + /* Check whether at least one of the words contains a byte <0x80 + * (if one is detected, there was a \r or \n in CHUNK). */ + if ((r_test & n_test & SVN__BIT_7_SET) != SVN__BIT_7_SET) + break; + } #endif diff --git a/subversion/libsvn_subr/error.c b/subversion/libsvn_subr/error.c index ffb2495f4cc5..1b2e7357e1fa 100644 --- a/subversion/libsvn_subr/error.c +++ b/subversion/libsvn_subr/error.c @@ -28,6 +28,10 @@ #include #include +#if defined(SVN_DEBUG) && APR_HAS_THREADS +#include +#endif + #include #ifndef SVN_ERR__TRACING @@ -38,12 +42,57 @@ #include "svn_pools.h" #include "svn_utf.h" -#ifdef SVN_DEBUG -/* XXX FIXME: These should be protected by a thread mutex. - svn_error__locate and make_error_internal should cooperate - in locking and unlocking it. */ +#include "private/svn_error_private.h" +#include "svn_private_config.h" -/* XXX TODO: Define mutex here #if APR_HAS_THREADS */ +#if defined(SVN_DEBUG) && APR_HAS_THREADS +#include "private/svn_atomic.h" +#include "pools.h" +#endif + + +#ifdef SVN_DEBUG +# if APR_HAS_THREADS +static apr_threadkey_t *error_file_key = NULL; +static apr_threadkey_t *error_line_key = NULL; + +/* No-op destructor for apr_threadkey_private_create(). */ +static void null_threadkey_dtor(void *stuff) {} + +/* Implements svn_atomic__str_init_func_t. + Callback used by svn_error__locate to initialize the thread-local + error location storage. This function will never return an + error string. */ +static const char * +locate_init_once(void *ignored_baton) +{ + /* Strictly speaking, this is a memory leak, since we're creating an + unmanaged, top-level pool and never destroying it. We do this + because this pool controls the lifetime of the thread-local + storage for error locations, and that storage must always be + available. */ + apr_pool_t *threadkey_pool = svn_pool__create_unmanaged(TRUE); + apr_status_t status; + + status = apr_threadkey_private_create(&error_file_key, + null_threadkey_dtor, + threadkey_pool); + if (status == APR_SUCCESS) + status = apr_threadkey_private_create(&error_line_key, + null_threadkey_dtor, + threadkey_pool); + + /* If anything went wrong with the creation of the thread-local + storage, we'll revert to the old, thread-agnostic behaviour */ + if (status != APR_SUCCESS) + error_file_key = error_line_key = NULL; + + return NULL; +} +# endif /* APR_HAS_THREADS */ + +/* These location variables will be used in no-threads mode or if + thread-local storage is not available. */ static const char * volatile error_file = NULL; static long volatile error_line = -1; @@ -51,9 +100,6 @@ static long volatile error_line = -1; static const char SVN_FILE_LINE_UNDEFINED[] = "svn:"; #endif /* SVN_DEBUG */ -#include "svn_private_config.h" -#include "private/svn_error_private.h" - /* * Undefine the helpers for creating errors. @@ -76,11 +122,25 @@ static const char SVN_FILE_LINE_UNDEFINED[] = "svn:"; void svn_error__locate(const char *file, long line) { -#if defined(SVN_DEBUG) - /* XXX TODO: Lock mutex here */ +#ifdef SVN_DEBUG +# if APR_HAS_THREADS + static volatile svn_atomic_t init_status = 0; + svn_atomic__init_once_no_error(&init_status, locate_init_once, NULL); + + if (error_file_key && error_line_key) + { + apr_status_t status; + status = apr_threadkey_private_set((char*)file, error_file_key); + if (status == APR_SUCCESS) + status = apr_threadkey_private_set((void*)line, error_line_key); + if (status == APR_SUCCESS) + return; + } +# endif /* APR_HAS_THREADS */ + error_file = file; error_line = line; -#endif +#endif /* SVN_DEBUG */ } @@ -103,6 +163,9 @@ make_error_internal(apr_status_t apr_err, { apr_pool_t *pool; svn_error_t *new_error; +#ifdef SVN_DEBUG + apr_status_t status = APR_ENOTIMPL; +#endif /* Reuse the child's pool, or create our own. */ if (child) @@ -121,16 +184,34 @@ make_error_internal(apr_status_t apr_err, new_error->apr_err = apr_err; new_error->child = child; new_error->pool = pool; -#if defined(SVN_DEBUG) - new_error->file = error_file; - new_error->line = error_line; - /* XXX TODO: Unlock mutex here */ + +#ifdef SVN_DEBUG +#if APR_HAS_THREADS + if (error_file_key && error_line_key) + { + void *item; + status = apr_threadkey_private_get(&item, error_file_key); + if (status == APR_SUCCESS) + { + new_error->file = item; + status = apr_threadkey_private_get(&item, error_line_key); + if (status == APR_SUCCESS) + new_error->line = (long)item; + } + } +# endif /* APR_HAS_THREADS */ + + if (status != APR_SUCCESS) + { + new_error->file = error_file; + new_error->line = error_line; + } if (! child) apr_pool_cleanup_register(pool, new_error, err_abort, apr_pool_cleanup_null); -#endif +#endif /* SVN_DEBUG */ return new_error; } diff --git a/subversion/libsvn_subr/errorcode.inc b/subversion/libsvn_subr/errorcode.inc index a02cd4ed0b3d..009b4b43bf80 100644 --- a/subversion/libsvn_subr/errorcode.inc +++ b/subversion/libsvn_subr/errorcode.inc @@ -4,126 +4,7 @@ static struct { int errcode; const char *errname; } svn__errno[] = { - { 1, "EPERM" }, - { 2, "ENOENT" }, - { 3, "ESRCH" }, - { 4, "EINTR" }, - { 5, "EIO" }, - { 6, "ENXIO" }, - { 7, "E2BIG" }, - { 8, "ENOEXEC" }, - { 9, "EBADF" }, - { 10, "ECHILD" }, - { 11, "EAGAIN" }, - { 12, "ENOMEM" }, - { 13, "EACCES" }, - { 14, "EFAULT" }, - { 15, "ENOTBLK" }, - { 16, "EBUSY" }, - { 17, "EEXIST" }, - { 18, "EXDEV" }, - { 19, "ENODEV" }, - { 20, "ENOTDIR" }, - { 21, "EISDIR" }, - { 22, "EINVAL" }, - { 23, "ENFILE" }, - { 24, "EMFILE" }, - { 25, "ENOTTY" }, - { 26, "ETXTBSY" }, - { 27, "EFBIG" }, - { 28, "ENOSPC" }, - { 29, "ESPIPE" }, - { 30, "EROFS" }, - { 31, "EMLINK" }, - { 32, "EPIPE" }, - { 33, "EDOM" }, - { 34, "ERANGE" }, - { 35, "EDEADLOCK" }, - { 36, "ENAMETOOLONG" }, - { 37, "ENOLCK" }, - { 38, "ENOSYS" }, - { 39, "ENOTEMPTY" }, - { 40, "ELOOP" }, - { 42, "ENOMSG" }, - { 43, "EIDRM" }, - { 44, "ECHRNG" }, - { 45, "EL2NSYNC" }, - { 46, "EL3HLT" }, - { 47, "EL3RST" }, - { 48, "ELNRNG" }, - { 49, "EUNATCH" }, - { 50, "ENOCSI" }, - { 51, "EL2HLT" }, - { 52, "EBADE" }, - { 53, "EBADR" }, - { 54, "EXFULL" }, - { 55, "ENOANO" }, - { 56, "EBADRQC" }, - { 57, "EBADSLT" }, - { 59, "EBFONT" }, - { 60, "ENOSTR" }, - { 61, "ENODATA" }, - { 62, "ETIME" }, - { 63, "ENOSR" }, - { 64, "ENONET" }, - { 65, "ENOPKG" }, - { 66, "EREMOTE" }, - { 67, "ENOLINK" }, - { 68, "EADV" }, - { 69, "ESRMNT" }, - { 70, "ECOMM" }, - { 71, "EPROTO" }, - { 72, "EMULTIHOP" }, - { 73, "EDOTDOT" }, - { 74, "EBADMSG" }, - { 75, "EOVERFLOW" }, - { 76, "ENOTUNIQ" }, - { 77, "EBADFD" }, - { 78, "EREMCHG" }, - { 79, "ELIBACC" }, - { 80, "ELIBBAD" }, - { 81, "ELIBSCN" }, - { 82, "ELIBMAX" }, - { 83, "ELIBEXEC" }, - { 84, "EILSEQ" }, - { 85, "ERESTART" }, - { 86, "ESTRPIPE" }, - { 87, "EUSERS" }, - { 88, "ENOTSOCK" }, - { 89, "EDESTADDRREQ" }, - { 90, "EMSGSIZE" }, - { 91, "EPROTOTYPE" }, - { 92, "ENOPROTOOPT" }, - { 93, "EPROTONOSUPPORT" }, - { 94, "ESOCKTNOSUPPORT" }, - { 95, "ENOTSUP" }, - { 96, "EPFNOSUPPORT" }, - { 97, "EAFNOSUPPORT" }, - { 98, "EADDRINUSE" }, - { 99, "EADDRNOTAVAIL" }, - { 100, "ENETDOWN" }, - { 101, "ENETUNREACH" }, - { 102, "ENETRESET" }, - { 103, "ECONNABORTED" }, - { 104, "ECONNRESET" }, - { 105, "ENOBUFS" }, - { 106, "EISCONN" }, - { 107, "ENOTCONN" }, - { 108, "ESHUTDOWN" }, - { 109, "ETOOMANYREFS" }, - { 110, "ETIMEDOUT" }, - { 111, "ECONNREFUSED" }, - { 112, "EHOSTDOWN" }, - { 113, "EHOSTUNREACH" }, - { 114, "EALREADY" }, - { 115, "EINPROGRESS" }, - { 116, "ESTALE" }, - { 117, "EUCLEAN" }, - { 118, "ENOTNAM" }, - { 119, "ENAVAIL" }, - { 120, "EISNAM" }, - { 121, "EREMOTEIO" }, - { 122, "EDQUOT" } + { 0, "success" } }; static struct { diff --git a/subversion/libsvn_subr/fnv1a.c b/subversion/libsvn_subr/fnv1a.c index 458bdd25ebcd..5a8f57c6b7eb 100644 --- a/subversion/libsvn_subr/fnv1a.c +++ b/subversion/libsvn_subr/fnv1a.c @@ -165,6 +165,12 @@ svn_fnv1a_32__context_create(apr_pool_t *pool) return context; } +void +svn_fnv1a_32__context_reset(svn_fnv1a_32__context_t *context) +{ + context->hash = FNV1_BASE_32; +} + void svn_fnv1a_32__update(svn_fnv1a_32__context_t *context, const void *data, @@ -202,6 +208,17 @@ svn_fnv1a_32x4__context_create(apr_pool_t *pool) return context; } +void +svn_fnv1a_32x4__context_reset(svn_fnv1a_32x4__context_t *context) +{ + context->hashes[0] = FNV1_BASE_32; + context->hashes[1] = FNV1_BASE_32; + context->hashes[2] = FNV1_BASE_32; + context->hashes[3] = FNV1_BASE_32; + + context->buffered = 0; +} + void svn_fnv1a_32x4__update(svn_fnv1a_32x4__context_t *context, const void *data, diff --git a/subversion/libsvn_subr/fnv1a.h b/subversion/libsvn_subr/fnv1a.h index 4bb0b1275463..fa13bcbe6467 100644 --- a/subversion/libsvn_subr/fnv1a.h +++ b/subversion/libsvn_subr/fnv1a.h @@ -41,6 +41,11 @@ typedef struct svn_fnv1a_32__context_t svn_fnv1a_32__context_t; svn_fnv1a_32__context_t * svn_fnv1a_32__context_create(apr_pool_t *pool); +/* Reset the FNV-1a checksum CONTEXT to initial state. + */ +void +svn_fnv1a_32__context_reset(svn_fnv1a_32__context_t *context); + /* Feed LEN bytes from DATA into the FNV-1a checksum creation CONTEXT. */ void @@ -63,6 +68,11 @@ typedef struct svn_fnv1a_32x4__context_t svn_fnv1a_32x4__context_t; svn_fnv1a_32x4__context_t * svn_fnv1a_32x4__context_create(apr_pool_t *pool); +/* Reset the modified FNV-1a checksum CONTEXT to initial state. + */ +void +svn_fnv1a_32x4__context_reset(svn_fnv1a_32x4__context_t *context); + /* Feed LEN bytes from DATA into the modified FNV-1a checksum creation * CONTEXT. */ diff --git a/subversion/libsvn_subr/gpg_agent.c b/subversion/libsvn_subr/gpg_agent.c index 36fe30ddb8fe..e851cb059bc2 100644 --- a/subversion/libsvn_subr/gpg_agent.c +++ b/subversion/libsvn_subr/gpg_agent.c @@ -65,9 +65,12 @@ #include #include +#include +#include #include "svn_auth.h" #include "svn_config.h" #include "svn_error.h" +#include "svn_io.h" #include "svn_pools.h" #include "svn_cmdline.h" #include "svn_checksum.h" @@ -225,30 +228,31 @@ bye_gpg_agent(int sd) close(sd); } -/* Locate a running GPG Agent, and return an open file descriptor - * for communication with the agent in *NEW_SD. If no running agent - * can be found, set *NEW_SD to -1. */ -static svn_error_t * -find_running_gpg_agent(int *new_sd, apr_pool_t *pool) +/* This implements a method of finding the socket which is a mix of the + * description from GPG 1.x's gpg-agent man page under the + * --use-standard-socket option and the logic from GPG 2.x's socket discovery + * code in common/homedir.c. + * + * The man page says the standard socket is "named 'S.gpg-agent' located + * in the home directory." GPG's home directory is either the directory + * specified by $GNUPGHOME or ~/.gnupg. GPG >= 2.1.13 will check for a + * socket under (/var)/run/UID/gnupg before ~/.gnupg if no environment + * variables are set. + * + * $GPG_AGENT_INFO takes precedence, if set, otherwise $GNUPGHOME will be + * used. For GPG >= 2.1.13, $GNUPGHOME will be used directly only if it + * refers to the canonical home -- ~/.gnupg. Otherwise, the path specified + * by $GNUPGHOME is hashed (SHA1 + z-base-32) and the socket is expected to + * be present under (/var)/run/UID/gnupg/d.HASH. This last mechanism is not + * yet supported here. */ +static const char * +find_gpg_agent_socket(apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - char *buffer; char *gpg_agent_info = NULL; char *gnupghome = NULL; const char *socket_name = NULL; - const char *request = NULL; - const char *p = NULL; - char *ep = NULL; - int sd; - *new_sd = -1; - - /* This implements the method of finding the socket as described in - * the gpg-agent man page under the --use-standard-socket option. - * The manage page says the standard socket is "named 'S.gpg-agent' located - * in the home directory." GPG's home directory is either the directory - * specified by $GNUPGHOME or ~/.gnupg. */ - gpg_agent_info = getenv("GPG_AGENT_INFO"); - if (gpg_agent_info != NULL) + if ((gpg_agent_info = getenv("GPG_AGENT_INFO")) != NULL) { apr_array_header_t *socket_details; @@ -256,26 +260,78 @@ find_running_gpg_agent(int *new_sd, apr_pool_t *pool) * The path to the socket, the pid of the gpg-agent process and * finally the version of the protocol the agent talks. */ socket_details = svn_cstring_split(gpg_agent_info, ":", TRUE, - pool); + scratch_pool); socket_name = APR_ARRAY_IDX(socket_details, 0, const char *); } else if ((gnupghome = getenv("GNUPGHOME")) != NULL) { - const char *homedir = svn_dirent_canonicalize(gnupghome, pool); - socket_name = svn_dirent_join(homedir, "S.gpg-agent", pool); + const char *homedir = svn_dirent_canonicalize(gnupghome, scratch_pool); + socket_name = svn_dirent_join(homedir, "S.gpg-agent", scratch_pool); } else { - const char *homedir = svn_user_get_homedir(pool); + int i = 0; + const char *maybe_socket[] = {NULL, NULL, NULL, NULL}; + const char *homedir; - if (!homedir) - return SVN_NO_ERROR; +#ifdef APR_HAS_USER + apr_uid_t uid; + apr_gid_t gid; - homedir = svn_dirent_canonicalize(homedir, pool); - socket_name = svn_dirent_join_many(pool, homedir, ".gnupg", - "S.gpg-agent", SVN_VA_NULL); + if (apr_uid_current(&uid, &gid, scratch_pool) == APR_SUCCESS) + { + const char *uidbuf = apr_psprintf(scratch_pool, "%lu", + (unsigned long)uid); + maybe_socket[i++] = svn_dirent_join_many(scratch_pool, "/run/user", + uidbuf, "gnupg", + "S.gpg-agent", + SVN_VA_NULL); + maybe_socket[i++] = svn_dirent_join_many(scratch_pool, + "/var/run/user", + uidbuf, "gnupg", + "S.gpg-agent", + SVN_VA_NULL); + } +#endif + + homedir = svn_user_get_homedir(scratch_pool); + if (homedir) + maybe_socket[i++] = svn_dirent_join_many(scratch_pool, homedir, + ".gnupg", "S.gpg-agent", + SVN_VA_NULL); + + for (i = 0; !socket_name && maybe_socket[i]; i++) + { + apr_finfo_t finfo; + svn_error_t *err = svn_io_stat(&finfo, maybe_socket[i], + APR_FINFO_TYPE, scratch_pool); + if (!err && finfo.filetype == APR_SOCK) + socket_name = maybe_socket[i]; + svn_error_clear(err); + } } + if (socket_name) + socket_name = apr_pstrdup(result_pool, socket_name); + + return socket_name; +} + +/* Locate a running GPG Agent, and return an open file descriptor + * for communication with the agent in *NEW_SD. If no running agent + * can be found, set *NEW_SD to -1. */ +static svn_error_t * +find_running_gpg_agent(int *new_sd, apr_pool_t *pool) +{ + char *buffer; + const char *socket_name = find_gpg_agent_socket(pool, pool); + const char *request = NULL; + const char *p = NULL; + char *ep = NULL; + int sd; + + *new_sd = -1; + if (socket_name != NULL) { struct sockaddr_un addr; diff --git a/subversion/libsvn_subr/hash.c b/subversion/libsvn_subr/hash.c index f58c43c40336..28874f42cc15 100644 --- a/subversion/libsvn_subr/hash.c +++ b/subversion/libsvn_subr/hash.c @@ -31,10 +31,14 @@ #include #include +#ifndef SVN_HASH__GETS_SETS +#define SVN_HASH__GETS_SETS +#endif +#include "svn_hash.h" + #include "svn_types.h" #include "svn_string.h" #include "svn_error.h" -#include "svn_hash.h" #include "svn_sorts.h" #include "svn_io.h" #include "svn_pools.h" @@ -45,7 +49,6 @@ #include "svn_private_config.h" - /* @@ -560,6 +563,20 @@ svn_hash_from_cstring_keys(apr_hash_t **hash_p, } +void * +svn_hash__gets_debug(apr_hash_t *ht, const char *key) +{ + return apr_hash_get(ht, key, APR_HASH_KEY_STRING); +} + + +void +svn_hash__sets_debug(apr_hash_t *ht, const char *key, const void *val) +{ + apr_hash_set(ht, key, APR_HASH_KEY_STRING, val); +} + + /*** Specialized getter APIs ***/ diff --git a/subversion/libsvn_subr/internal_statements.h b/subversion/libsvn_subr/internal_statements.h index 1d0a3f8e9399..5f8095fb2f2a 100644 --- a/subversion/libsvn_subr/internal_statements.h +++ b/subversion/libsvn_subr/internal_statements.h @@ -1,4 +1,4 @@ -/* This file is automatically generated from internal_statements.sql and .dist_sandbox/subversion-1.9.7/subversion/libsvn_subr/token-map.h. +/* This file is automatically generated from internal_statements.sql and subversion/libsvn_subr/token-map.h. * Do not edit this file -- edit the source and rerun gen-make.py */ #define STMT_INTERNAL_SAVEPOINT_SVN 0 diff --git a/subversion/libsvn_subr/io.c b/subversion/libsvn_subr/io.c index 468dd1723804..8c4f26760507 100644 --- a/subversion/libsvn_subr/io.c +++ b/subversion/libsvn_subr/io.c @@ -578,10 +578,8 @@ svn_io_open_uniquely_named(apr_file_t **file, continue; #ifdef WIN32 - apr_err_2 = APR_TO_OS_ERROR(apr_err); - - if (apr_err_2 == ERROR_ACCESS_DENIED || - apr_err_2 == ERROR_SHARING_VIOLATION) + if (apr_err == APR_FROM_OS_ERROR(ERROR_ACCESS_DENIED) || + apr_err == APR_FROM_OS_ERROR(ERROR_SHARING_VIOLATION)) { /* The file is in use by another process or is hidden; create a new name, but don't do this 99999 times in @@ -773,7 +771,7 @@ svn_io_copy_link(const char *src, ".tmp", pool)); /* Move the tmp-link to link. */ - return svn_io_file_rename(dst_tmp, dst, pool); + return svn_io_file_rename2(dst_tmp, dst, FALSE, pool); #else return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL, @@ -942,7 +940,7 @@ svn_io_copy_file(const char *src, if (copy_perms) SVN_ERR(svn_io_copy_perms(src, dst_tmp, pool)); - return svn_error_trace(svn_io_file_rename(dst_tmp, dst, pool)); + return svn_error_trace(svn_io_file_rename2(dst_tmp, dst, FALSE, pool)); } #if !defined(WIN32) && !defined(__OS2__) @@ -1480,18 +1478,14 @@ svn_io_file_checksum2(svn_checksum_t **checksum, apr_pool_t *pool) { svn_stream_t *file_stream; - svn_stream_t *checksum_stream; apr_file_t* f; SVN_ERR(svn_io_file_open(&f, file, APR_READ, APR_OS_DEFAULT, pool)); file_stream = svn_stream_from_aprfile2(f, FALSE, pool); - checksum_stream = svn_stream_checksummed2(file_stream, checksum, NULL, kind, - TRUE, pool); + SVN_ERR(svn_stream_contents_checksum(checksum, file_stream, kind, + pool, pool)); - /* Because the checksummed stream will force the reading (and - checksumming) of all the file's bytes, we can just close the stream - and let its magic work. */ - return svn_stream_close(checksum_stream); + return SVN_NO_ERROR; } @@ -1527,20 +1521,23 @@ reown_file(const char *path, SVN_ERR(svn_io_open_unique_file3(NULL, &unique_name, svn_dirent_dirname(path, pool), svn_io_file_del_none, pool, pool)); - SVN_ERR(svn_io_file_rename(path, unique_name, pool)); + SVN_ERR(svn_io_file_rename2(path, unique_name, FALSE, pool)); SVN_ERR(svn_io_copy_file(unique_name, path, TRUE, pool)); return svn_error_trace(svn_io_remove_file2(unique_name, FALSE, pool)); } /* Determine what the PERMS for a new file should be by looking at the - permissions of a temporary file that we create. + permissions of a temporary file that we create in DIRECTORY. + DIRECTORY can be NULL in which case the system temporary dir is used. Unfortunately, umask() as defined in POSIX provides no thread-safe way to get at the current value of the umask, so what we're doing here is the only way we have to determine which combination of write bits (User/Group/World) should be set by default. Make temporary allocations in SCRATCH_POOL. */ static svn_error_t * -get_default_file_perms(apr_fileperms_t *perms, apr_pool_t *scratch_pool) +get_default_file_perms(apr_fileperms_t *perms, + const char *directory, + apr_pool_t *scratch_pool) { /* the default permissions as read from the temp folder */ static apr_fileperms_t default_perms = 0; @@ -1567,12 +1564,18 @@ get_default_file_perms(apr_fileperms_t *perms, apr_pool_t *scratch_pool) Using svn_io_open_uniquely_named() here because other tempfile creation functions tweak the permission bits of files they create. + + Note that APR pool structures are allocated as the first item + in their first memory page (with e.g. 4kB granularity), i.e. the + lower bits tend to be identical between pool instances. That is + particularly true for the MMAPed allocator. */ randomish = ((apr_uint32_t)(apr_uintptr_t)scratch_pool + + (apr_uint32_t)((apr_uintptr_t)scratch_pool / 4096) + (apr_uint32_t)apr_time_now()); fname_base = apr_psprintf(scratch_pool, "svn-%08x", randomish); - SVN_ERR(svn_io_open_uniquely_named(&fd, &fname, NULL, fname_base, + SVN_ERR(svn_io_open_uniquely_named(&fd, &fname, directory, fname_base, NULL, svn_io_file_del_none, scratch_pool, scratch_pool)); err = svn_io_file_info_get(&finfo, APR_FINFO_PROT, fd, scratch_pool); @@ -1590,16 +1593,19 @@ get_default_file_perms(apr_fileperms_t *perms, apr_pool_t *scratch_pool) } /* OR together permission bits of the file FD and the default permissions - of a file as determined by get_default_file_perms(). Do temporary + of a file as determined by get_default_file_perms(). DIRECTORY is used + to create temporary files, DIRECTORY can be NULL. Do temporary allocations in SCRATCH_POOL. */ static svn_error_t * -merge_default_file_perms(apr_file_t *fd, apr_fileperms_t *perms, +merge_default_file_perms(apr_file_t *fd, + apr_fileperms_t *perms, + const char *directory, apr_pool_t *scratch_pool) { apr_finfo_t finfo; apr_fileperms_t default_perms; - SVN_ERR(get_default_file_perms(&default_perms, scratch_pool)); + SVN_ERR(get_default_file_perms(&default_perms, directory, scratch_pool)); SVN_ERR(svn_io_file_info_get(&finfo, APR_FINFO_PROT, fd, scratch_pool)); /* Glom the perms together. */ @@ -1768,7 +1774,7 @@ svn_io__utf8_to_unicode_longpath(const WCHAR **result, * than the original number of utf-8 narrow chars. */ const WCHAR *prefix = NULL; - const int srclen = strlen(source); + const size_t srclen = strlen(source); WCHAR *buffer; if (srclen > 248) @@ -1879,12 +1885,12 @@ io_win_file_attrs_set(const char *fname, _("Can't set attributes of file '%s'"), svn_dirent_local_style(fname, pool)); - return SVN_NO_ERROR;; + return SVN_NO_ERROR; } static svn_error_t *win_init_dynamic_imports(void *baton, apr_pool_t *pool) { - HMODULE kernel32 = GetModuleHandleA("kernel32.dll"); + HMODULE kernel32 = GetModuleHandleW(L"kernel32.dll"); if (kernel32) { @@ -2274,7 +2280,6 @@ svn_io_is_file_executable(svn_boolean_t *executable, /*** File locking. ***/ -#if !defined(WIN32) && !defined(__OS2__) /* Clear all outstanding locks on ARG, an open apr_file_t *. */ static apr_status_t file_clear_locks(void *arg) @@ -2289,7 +2294,6 @@ file_clear_locks(void *arg) return 0; } -#endif svn_error_t * svn_io_lock_open_file(apr_file_t *lockfile_handle, @@ -2347,13 +2351,14 @@ svn_io_lock_open_file(apr_file_t *lockfile_handle, } } -/* On Windows and OS/2 file locks are automatically released when - the file handle closes */ -#if !defined(WIN32) && !defined(__OS2__) + /* On Windows, a process may not release file locks before closing the + handle, and in this case the outstanding locks are unlocked by the OS. + However, this is not recommended, because the actual unlocking may be + postponed depending on available system resources. We explicitly unlock + the file as a part of the pool cleanup handler. */ apr_pool_cleanup_register(pool, lockfile_handle, file_clear_locks, apr_pool_cleanup_null); -#endif return SVN_NO_ERROR; } @@ -2377,11 +2382,7 @@ svn_io_unlock_open_file(apr_file_t *lockfile_handle, return svn_error_wrap_apr(apr_err, _("Can't unlock file '%s'"), try_utf8_from_internal_style(fname, pool)); -/* On Windows and OS/2 file locks are automatically released when - the file handle closes */ -#if !defined(WIN32) && !defined(__OS2__) apr_pool_cleanup_kill(pool, lockfile_handle, file_clear_locks); -#endif return SVN_NO_ERROR; } @@ -2455,6 +2456,14 @@ svn_error_t *svn_io_file_flush_to_disk(apr_file_t *file, apr_pool_t *pool) { apr_os_file_t filehand; + const char *fname; + apr_status_t apr_err; + + /* We need this only in case of an error but this is cheap to get - + * so we do it here for clarity. */ + apr_err = apr_file_name_get(&fname, file); + if (apr_err) + return svn_error_wrap_apr(apr_err, _("Can't get file name")); /* ### In apr 1.4+ we could delegate most of this function to apr_file_sync(). The only major difference is that this doesn't @@ -2472,7 +2481,8 @@ svn_error_t *svn_io_file_flush_to_disk(apr_file_t *file, if (! FlushFileBuffers(filehand)) return svn_error_wrap_apr(apr_get_os_error(), - _("Can't flush file to disk")); + _("Can't flush file '%s' to disk"), + try_utf8_from_internal_style(fname, pool)); #else int rv; @@ -2493,7 +2503,8 @@ svn_error_t *svn_io_file_flush_to_disk(apr_file_t *file, if (rv == -1) return svn_error_wrap_apr(apr_get_os_error(), - _("Can't flush file to disk")); + _("Can't flush file '%s' to disk"), + try_utf8_from_internal_style(fname, pool)); #endif } @@ -2640,9 +2651,6 @@ svn_io_remove_file2(const char *path, allow us to delete when path is read-only */ SVN_ERR(svn_io_set_file_read_write(path, ignore_enoent, scratch_pool)); apr_err = apr_file_remove(path_apr, scratch_pool); - - if (!apr_err) - return SVN_NO_ERROR; } /* Check to make sure we aren't trying to delete a directory */ @@ -2721,7 +2729,7 @@ svn_io_remove_dir2(const char *path, svn_boolean_t ignore_enoent, If we need to bail out, do so early. */ if (cancel_func) - SVN_ERR((*cancel_func)(cancel_baton)); + SVN_ERR(cancel_func(cancel_baton)); subpool = svn_pool_create(pool); @@ -2754,7 +2762,7 @@ svn_io_remove_dir2(const char *path, svn_boolean_t ignore_enoent, else { if (cancel_func) - SVN_ERR((*cancel_func)(cancel_baton)); + SVN_ERR(cancel_func(cancel_baton)); err = svn_io_remove_file2(fullpath, FALSE, subpool); if (err) @@ -3736,6 +3744,32 @@ svn_io_file_info_get(apr_finfo_t *finfo, apr_int32_t wanted, pool); } +svn_error_t * +svn_io_file_size_get(svn_filesize_t *filesize_p, apr_file_t *file, + apr_pool_t *pool) +{ + apr_finfo_t finfo; + SVN_ERR(svn_io_file_info_get(&finfo, APR_FINFO_SIZE, file, pool)); + + *filesize_p = finfo.size; + return SVN_NO_ERROR; +} + +svn_error_t * +svn_io_file_get_offset(apr_off_t *offset_p, + apr_file_t *file, + apr_pool_t *pool) +{ + apr_off_t offset; + + /* Note that, for buffered files, one (possibly surprising) side-effect + of this call is to flush any unwritten data to disk. */ + offset = 0; + SVN_ERR(svn_io_file_seek(file, APR_CUR, &offset, pool)); + *offset_p = offset; + + return SVN_NO_ERROR; +} svn_error_t * svn_io_file_read(apr_file_t *file, void *buf, @@ -3906,21 +3940,20 @@ svn_io_file_write_full(apr_file_t *file, const void *buf, apr_size_t nbytes, apr_size_t *bytes_written, apr_pool_t *pool) { - /* We cannot simply call apr_file_write_full on Win32 as it may fail - for larger values of NBYTES. In that case, we have to emulate the - "_full" part here. Thus, always call apr_file_write directly on - Win32 as this minimizes overhead for small data buffers. */ #ifdef WIN32 #define MAXBUFSIZE 30*1024 apr_size_t bw = nbytes; apr_size_t to_write = nbytes; + apr_status_t rv; - /* try a simple "write everything at once" first */ - apr_status_t rv = apr_file_write(file, buf, &bw); + rv = apr_file_write_full(file, buf, nbytes, &bw); buf = (char *)buf + bw; to_write -= bw; - /* if the OS cannot handle that, use smaller chunks */ + /* Issue #1789: On Windows, writing may fail for large values of NBYTES. + If that is the case, keep track of how many bytes have been written + by the apr_file_write_full() call, and attempt to write the remaining + part in smaller chunks. */ if (rv == APR_FROM_OS_ERROR(ERROR_NOT_ENOUGH_MEMORY) && nbytes > MAXBUFSIZE) { @@ -3981,11 +4014,12 @@ svn_io_write_unique(const char **tmp_path, } svn_error_t * -svn_io_write_atomic(const char *final_path, - const void *buf, - apr_size_t nbytes, - const char *copy_perms_path, - apr_pool_t *scratch_pool) +svn_io_write_atomic2(const char *final_path, + const void *buf, + apr_size_t nbytes, + const char *copy_perms_path, + svn_boolean_t flush_to_disk, + apr_pool_t *scratch_pool) { apr_file_t *tmp_file; const char *tmp_path; @@ -3998,7 +4032,7 @@ svn_io_write_atomic(const char *final_path, err = svn_io_file_write_full(tmp_file, buf, nbytes, NULL, scratch_pool); - if (!err) + if (!err && flush_to_disk) err = svn_io_file_flush_to_disk(tmp_file, scratch_pool); err = svn_error_compose_create(err, @@ -4008,7 +4042,8 @@ svn_io_write_atomic(const char *final_path, err = svn_io_copy_perms(copy_perms_path, tmp_path, scratch_pool); if (!err) - err = svn_io_file_rename(tmp_path, final_path, scratch_pool); + err = svn_io_file_rename2(tmp_path, final_path, flush_to_disk, + scratch_pool); if (err) { @@ -4022,22 +4057,6 @@ svn_io_write_atomic(const char *final_path, scratch_pool)); } -#ifdef __linux__ - { - /* Linux has the unusual feature that fsync() on a file is not - enough to ensure that a file's directory entries have been - flushed to disk; you have to fsync the directory as well. - On other operating systems, we'd only be asking for trouble - by trying to open and fsync a directory. */ - apr_file_t *file; - - SVN_ERR(svn_io_file_open(&file, dirname, APR_READ, APR_OS_DEFAULT, - scratch_pool)); - SVN_ERR(svn_io_file_flush_to_disk(file, scratch_pool)); - SVN_ERR(svn_io_file_close(file, scratch_pool)); - } -#endif - return SVN_NO_ERROR; } @@ -4052,7 +4071,7 @@ svn_io_file_trunc(apr_file_t *file, apr_off_t offset, apr_pool_t *pool) To prevent this, write 1 dummy byte just after the OFFSET at which we will trunc it. That will force the APR file into write mode - internally and the flush() work-around below becomes affective. */ + internally and the flush() work-around below becomes effective. */ apr_off_t position = 0; /* A frequent usage is OFFSET==0, in which case we don't need to preserve @@ -4186,20 +4205,53 @@ svn_io_stat(apr_finfo_t *finfo, const char *fname, return SVN_NO_ERROR; } +#if defined(WIN32) +/* Platform specific implementation of apr_file_rename() to workaround + APR problems on Windows. */ +static apr_status_t +win32_file_rename(const WCHAR *from_path_w, + const WCHAR *to_path_w, + svn_boolean_t flush_to_disk) +{ + /* APR calls MoveFileExW() with MOVEFILE_COPY_ALLOWED, while we rely + * that rename is atomic operation. Call MoveFileEx directly on Windows + * without MOVEFILE_COPY_ALLOWED flag to workaround it. + */ + + DWORD flags = MOVEFILE_REPLACE_EXISTING; + + if (flush_to_disk) + { + /* Do not return until the file has actually been moved on the disk. */ + flags |= MOVEFILE_WRITE_THROUGH; + } + + if (!MoveFileExW(from_path_w, to_path_w, flags)) + return apr_get_os_error(); + + return APR_SUCCESS; +} +#endif svn_error_t * -svn_io_file_rename(const char *from_path, const char *to_path, - apr_pool_t *pool) +svn_io_file_rename2(const char *from_path, const char *to_path, + svn_boolean_t flush_to_disk, apr_pool_t *pool) { apr_status_t status = APR_SUCCESS; const char *from_path_apr, *to_path_apr; +#if defined(WIN32) + WCHAR *from_path_w; + WCHAR *to_path_w; +#endif SVN_ERR(cstring_from_utf8(&from_path_apr, from_path, pool)); SVN_ERR(cstring_from_utf8(&to_path_apr, to_path, pool)); - status = apr_file_rename(from_path_apr, to_path_apr, pool); +#if defined(WIN32) + SVN_ERR(svn_io__utf8_to_unicode_longpath(&from_path_w, from_path_apr, pool)); + SVN_ERR(svn_io__utf8_to_unicode_longpath(&to_path_w, to_path_apr, pool)); + status = win32_file_rename(from_path_w, to_path_w, flush_to_disk); -#if defined(WIN32) || defined(__OS2__) /* If the target file is read only NTFS reports EACCESS and FAT/FAT32 reports EEXIST */ if (APR_STATUS_IS_EACCES(status) || APR_STATUS_IS_EEXIST(status)) @@ -4209,9 +4261,25 @@ svn_io_file_rename(const char *from_path, const char *to_path, allow renaming when from_path is read only. */ SVN_ERR(svn_io_set_file_read_write(to_path, TRUE, pool)); + status = win32_file_rename(from_path_w, to_path_w, flush_to_disk); + } + WIN32_RETRY_LOOP(status, win32_file_rename(from_path_w, to_path_w, + flush_to_disk)); +#elif defined(__OS2__) + status = apr_file_rename(from_path_apr, to_path_apr, pool); + /* If the target file is read only NTFS reports EACCESS and + FAT/FAT32 reports EEXIST */ + if (APR_STATUS_IS_EACCES(status) || APR_STATUS_IS_EEXIST(status)) + { + /* Set the destination file writable because OS/2 will not + allow us to rename when to_path is read-only, but will + allow renaming when from_path is read only. */ + SVN_ERR(svn_io_set_file_read_write(to_path, TRUE, pool)); + status = apr_file_rename(from_path_apr, to_path_apr, pool); } - WIN32_RETRY_LOOP(status, apr_file_rename(from_path_apr, to_path_apr, pool)); +#else + status = apr_file_rename(from_path_apr, to_path_apr, pool); #endif /* WIN32 || __OS2__ */ if (status) @@ -4219,6 +4287,34 @@ svn_io_file_rename(const char *from_path, const char *to_path, svn_dirent_local_style(from_path, pool), svn_dirent_local_style(to_path, pool)); +#if defined(SVN_ON_POSIX) + if (flush_to_disk) + { + /* On POSIX, the file name is stored in the file's directory entry. + Hence, we need to fsync() that directory as well. + On other operating systems, we'd only be asking for trouble + by trying to open and fsync a directory. */ + const char *dirname; + apr_file_t *file; + + dirname = svn_dirent_dirname(to_path, pool); + SVN_ERR(svn_io_file_open(&file, dirname, APR_READ, APR_OS_DEFAULT, + pool)); + SVN_ERR(svn_io_file_flush_to_disk(file, pool)); + SVN_ERR(svn_io_file_close(file, pool)); + } +#elif !defined(WIN32) + /* Flush the target of the rename to disk. */ + if (flush_to_disk) + { + apr_file_t *file; + SVN_ERR(svn_io_file_open(&file, to_path, APR_WRITE, + APR_OS_DEFAULT, pool)); + SVN_ERR(svn_io_file_flush_to_disk(file, pool)); + SVN_ERR(svn_io_file_close(file, pool)); + } +#endif + return SVN_NO_ERROR; } @@ -4227,37 +4323,16 @@ svn_error_t * svn_io_file_move(const char *from_path, const char *to_path, apr_pool_t *pool) { - svn_error_t *err = svn_io_file_rename(from_path, to_path, pool); + svn_error_t *err = svn_error_trace(svn_io_file_rename2(from_path, to_path, + FALSE, pool)); if (err && APR_STATUS_IS_EXDEV(err->apr_err)) { - const char *tmp_to_path; - svn_error_clear(err); - SVN_ERR(svn_io_open_unique_file3(NULL, &tmp_to_path, - svn_dirent_dirname(to_path, pool), - svn_io_file_del_none, - pool, pool)); - - err = svn_io_copy_file(from_path, tmp_to_path, TRUE, pool); - if (err) - goto failed_tmp; - - err = svn_io_file_rename(tmp_to_path, to_path, pool); - if (err) - goto failed_tmp; - - err = svn_io_remove_file2(from_path, FALSE, pool); - if (! err) - return SVN_NO_ERROR; - - svn_error_clear(svn_io_remove_file2(to_path, FALSE, pool)); - - return err; - - failed_tmp: - svn_error_clear(svn_io_remove_file2(tmp_to_path, FALSE, pool)); + /* svn_io_copy_file() performs atomic copy via temporary file. */ + err = svn_error_trace(svn_io_copy_file(from_path, to_path, TRUE, + pool)); } return err; @@ -4409,8 +4484,8 @@ svn_io_dir_remove_nonrecursive(const char *dirname, apr_pool_t *pool) { svn_boolean_t retry = TRUE; - if (APR_TO_OS_ERROR(status) == ERROR_DIR_NOT_EMPTY) - { + if (status == APR_FROM_OS_ERROR(ERROR_DIR_NOT_EMPTY)) + { apr_status_t empty_status = dir_is_empty(dirname_apr, pool); if (APR_STATUS_IS_ENOTEMPTY(empty_status)) @@ -4689,7 +4764,7 @@ svn_io_write_version_file(const char *path, #endif /* WIN32 || __OS2__ */ /* rename the temp file as the real destination */ - SVN_ERR(svn_io_file_rename(path_tmp, path, pool)); + SVN_ERR(svn_io_file_rename2(path_tmp, path, FALSE, pool)); /* And finally remove the perms to make it read only */ return svn_io_set_file_read_only(path, FALSE, pool); @@ -5086,7 +5161,7 @@ temp_file_create(apr_file_t **new_file, /* Generate a number that should be unique for this application and usually for the entire computer to reduce the number of cycles - through this loop. (A bit of calculation is much cheaper then + through this loop. (A bit of calculation is much cheaper than disk io) */ unique_nr = baseNr + 3 * i; @@ -5117,10 +5192,8 @@ temp_file_create(apr_file_t **new_file, if (!apr_err_2 && finfo.filetype == APR_DIR) continue; - apr_err_2 = APR_TO_OS_ERROR(apr_err); - - if (apr_err_2 == ERROR_ACCESS_DENIED || - apr_err_2 == ERROR_SHARING_VIOLATION) + if (apr_err == APR_FROM_OS_ERROR(ERROR_ACCESS_DENIED) || + apr_err == APR_FROM_OS_ERROR(ERROR_SHARING_VIOLATION)) { /* The file is in use by another process or is hidden; create a new name, but don't do this 99999 times in @@ -5254,7 +5327,8 @@ svn_io_open_unique_file3(apr_file_t **file, { svn_error_t *err; - SVN_ERR(merge_default_file_perms(tempfile, &perms, scratch_pool)); + SVN_ERR(merge_default_file_perms(tempfile, &perms, dirpath, + scratch_pool)); err = file_perms_set2(tempfile, perms, scratch_pool); if (err) { @@ -5334,8 +5408,7 @@ svn_io_file_readline(apr_file_t *file, apr_off_t pos; /* Check for "\r\n" by peeking at the next byte. */ - pos = 0; - SVN_ERR(svn_io_file_seek(file, APR_CUR, &pos, scratch_pool)); + SVN_ERR(svn_io_file_get_offset(&pos, file, scratch_pool)); SVN_ERR(svn_io_file_read_full2(file, &c, sizeof(c), &numbytes, &found_eof, scratch_pool)); if (numbytes == 1 && c == '\n') diff --git a/subversion/libsvn_subr/libsvn_subr.pc.in b/subversion/libsvn_subr/libsvn_subr.pc.in index 309b697bf765..81ae97df433e 100644 --- a/subversion/libsvn_subr/libsvn_subr.pc.in +++ b/subversion/libsvn_subr/libsvn_subr.pc.in @@ -8,5 +8,5 @@ Description: Subversion General Utility Library Version: @PACKAGE_VERSION@ Requires: apr-util-@SVN_APR_MAJOR_VERSION@ apr-@SVN_APR_MAJOR_VERSION@ Requires.private: sqlite3 -Libs: -L${libdir} -lsvn_subr @SVN_XML_LIBS@ @SVN_ZLIB_LIBS@ @SVN_APR_MEMCACHE_LIBS@ @SVN_MAGIC_LIBS@ @SVN_INTL_LIBS@ +Libs: -L${libdir} -lsvn_subr @SVN_XML_LIBS@ @SVN_ZLIB_LIBS@ @SVN_APR_MEMCACHE_LIBS@ @SVN_MAGIC_LIBS@ @SVN_INTL_LIBS@ @SVN_LZ4_LIBS@ @SVN_UTF8PROC_LIBS@ Cflags: -I${includedir} diff --git a/subversion/libsvn_subr/log.c b/subversion/libsvn_subr/log.c index be6d77a8030a..8dd4cfbf22ec 100644 --- a/subversion/libsvn_subr/log.c +++ b/subversion/libsvn_subr/log.c @@ -105,7 +105,7 @@ svn_log__get_file(const char *path, svn_revnum_t rev, const char * svn_log__get_dir(const char *path, svn_revnum_t rev, svn_boolean_t want_contents, svn_boolean_t want_props, - apr_uint64_t dirent_fields, + apr_uint32_t dirent_fields, apr_pool_t *pool) { return apr_psprintf(pool, "get-dir %s r%ld%s%s", @@ -395,3 +395,35 @@ svn_log__get_inherited_props(const char *path, log_path = "/"; return apr_psprintf(pool, "get-inherited-props %s r%ld", log_path, rev); } + +const char * +svn_log__list(const char *path, svn_revnum_t revision, + apr_array_header_t *patterns, svn_depth_t depth, + apr_uint32_t dirent_fields, apr_pool_t *pool) +{ + svn_stringbuf_t *pattern_text = svn_stringbuf_create_empty(pool); + const char *log_path; + int i; + + if (path && path[0] != '\0') + log_path = svn_path_uri_encode(path, pool); + else + log_path = "/"; + + if (patterns) + { + for (i = 0; i < patterns->nelts; ++i) + { + const char *pattern = APR_ARRAY_IDX(patterns, i, const char *); + svn_stringbuf_appendbyte(pattern_text, ' '); + svn_stringbuf_appendcstr(pattern_text, pattern); + } + } + else + { + svn_stringbuf_appendcstr(pattern_text, " "); + } + + return apr_psprintf(pool, "list %s r%ld%s%s", log_path, revision, + log_depth(depth, pool), pattern_text->data); +} diff --git a/subversion/libsvn_subr/lz4/LICENSE b/subversion/libsvn_subr/lz4/LICENSE new file mode 100644 index 000000000000..74c2cdd7d50b --- /dev/null +++ b/subversion/libsvn_subr/lz4/LICENSE @@ -0,0 +1,24 @@ +LZ4 Library +Copyright (c) 2011-2016, Yann Collet +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/subversion/libsvn_subr/lz4/lz4.c b/subversion/libsvn_subr/lz4/lz4.c new file mode 100644 index 000000000000..d329064b9edc --- /dev/null +++ b/subversion/libsvn_subr/lz4/lz4.c @@ -0,0 +1,1481 @@ +#include "svn_private_config.h" +#if SVN_INTERNAL_LZ4 +/* + LZ4 - Fast LZ compression algorithm + Copyright (C) 2011-2016, Yann Collet. + + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - LZ4 homepage : http://www.lz4.org + - LZ4 source repository : https://github.com/lz4/lz4 +*/ + + +/*-************************************ +* Tuning parameters +**************************************/ +/* + * HEAPMODE : + * Select how default compression functions will allocate memory for their hash table, + * in memory stack (0:default, fastest), or in memory heap (1:requires malloc()). + */ +#ifndef HEAPMODE +# define HEAPMODE 0 +#endif + +/* + * ACCELERATION_DEFAULT : + * Select "acceleration" for LZ4_compress_fast() when parameter value <= 0 + */ +#define ACCELERATION_DEFAULT 1 + + +/*-************************************ +* CPU Feature Detection +**************************************/ +/* LZ4_FORCE_MEMORY_ACCESS + * By default, access to unaligned memory is controlled by `memcpy()`, which is safe and portable. + * Unfortunately, on some target/compiler combinations, the generated assembly is sub-optimal. + * The below switch allow to select different access method for improved performance. + * Method 0 (default) : use `memcpy()`. Safe and portable. + * Method 1 : `__packed` statement. It depends on compiler extension (ie, not portable). + * This method is safe if your compiler supports it, and *generally* as fast or faster than `memcpy`. + * Method 2 : direct access. This method is portable but violate C standard. + * It can generate buggy code on targets which generate assembly depending on alignment. + * But in some circumstances, it's the only known way to get the most performance (ie GCC + ARMv6) + * See https://fastcompression.blogspot.fr/2015/08/accessing-unaligned-memory.html for details. + * Prefer these methods in priority order (0 > 1 > 2) + */ +#ifndef LZ4_FORCE_MEMORY_ACCESS /* can be defined externally, on command line for example */ +# if defined(__GNUC__) && ( defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) ) +# define LZ4_FORCE_MEMORY_ACCESS 2 +# elif defined(__INTEL_COMPILER) || \ + (defined(__GNUC__) && ( defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) )) +# define LZ4_FORCE_MEMORY_ACCESS 1 +# endif +#endif + +/* + * LZ4_FORCE_SW_BITCOUNT + * Define this parameter if your target system or compiler does not support hardware bit count + */ +#if defined(_MSC_VER) && defined(_WIN32_WCE) /* Visual Studio for Windows CE does not support Hardware bit count */ +# define LZ4_FORCE_SW_BITCOUNT +#endif + + +/*-************************************ +* Dependency +**************************************/ +#include "lz4internal.h" +/* see also "memory routines" below */ + +/* Silence GCC's -Wmissing-prototypes warning. */ +int LZ4_compress_fast_force(const char*, char*, int, int, int); +int LZ4_compress_forceExtDict (LZ4_stream_t*, const char*, char*, int); +int LZ4_decompress_safe_forceExtDict(const char*, char*, int, int, const char*, int); +int LZ4_uncompress (const char*, char*, int); +int LZ4_uncompress_unknownOutputSize (const char*, char*, int, int); + +/*-************************************ +* Compiler Options +**************************************/ +#ifdef _MSC_VER /* Visual Studio */ +# define FORCE_INLINE static __forceinline +# include +# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ +# pragma warning(disable : 4293) /* disable: C4293: too large shift (32-bits) */ +#else +# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */ +# if defined(__GNUC__) || defined(__clang__) +# define FORCE_INLINE static inline __attribute__((always_inline)) +# else +# define FORCE_INLINE static inline +# endif +# else +# define FORCE_INLINE static +# endif /* __STDC_VERSION__ */ +#endif /* _MSC_VER */ + +#if (defined(__GNUC__) && (__GNUC__ >= 3)) || (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 800)) || defined(__clang__) +# define expect(expr,value) (__builtin_expect ((expr),(value)) ) +#else +# define expect(expr,value) (expr) +#endif + +#define likely(expr) expect((expr) != 0, 1) +#define unlikely(expr) expect((expr) != 0, 0) + + +/*-************************************ +* Memory routines +**************************************/ +#include /* malloc, calloc, free */ +#define ALLOCATOR(n,s) calloc(n,s) +#define FREEMEM free +#include /* memset, memcpy */ +#define MEM_INIT memset + + +/*-************************************ +* Basic Types +**************************************/ +#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) +# include + typedef uint8_t BYTE; + typedef uint16_t U16; + typedef uint32_t U32; + typedef int32_t S32; + typedef uint64_t U64; + typedef uintptr_t uptrval; +#else + typedef unsigned char BYTE; + typedef unsigned short U16; + typedef unsigned int U32; + typedef signed int S32; + typedef unsigned long long U64; + typedef size_t uptrval; /* generally true, except OpenVMS-64 */ +#endif + +#if defined(__x86_64__) + typedef U64 reg_t; /* 64-bits in x32 mode */ +#else + typedef size_t reg_t; /* 32-bits in x32 mode */ +#endif + +/*-************************************ +* Reading and writing into memory +**************************************/ +static unsigned LZ4_isLittleEndian(void) +{ + const union { U32 u; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */ + return one.c[0]; +} + + +#if defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==2) +/* lie to the compiler about data alignment; use with caution */ + +static U16 LZ4_read16(const void* memPtr) { return *(const U16*) memPtr; } +static U32 LZ4_read32(const void* memPtr) { return *(const U32*) memPtr; } +static reg_t LZ4_read_ARCH(const void* memPtr) { return *(const reg_t*) memPtr; } + +static void LZ4_write16(void* memPtr, U16 value) { *(U16*)memPtr = value; } +static void LZ4_write32(void* memPtr, U32 value) { *(U32*)memPtr = value; } + +#elif defined(LZ4_FORCE_MEMORY_ACCESS) && (LZ4_FORCE_MEMORY_ACCESS==1) + +/* __pack instructions are safer, but compiler specific, hence potentially problematic for some compilers */ +/* currently only defined for gcc and icc */ +typedef union { U16 u16; U32 u32; reg_t uArch; } __attribute__((packed)) unalign; + +static U16 LZ4_read16(const void* ptr) { return ((const unalign*)ptr)->u16; } +static U32 LZ4_read32(const void* ptr) { return ((const unalign*)ptr)->u32; } +static reg_t LZ4_read_ARCH(const void* ptr) { return ((const unalign*)ptr)->uArch; } + +static void LZ4_write16(void* memPtr, U16 value) { ((unalign*)memPtr)->u16 = value; } +static void LZ4_write32(void* memPtr, U32 value) { ((unalign*)memPtr)->u32 = value; } + +#else /* safe and portable access through memcpy() */ + +static U16 LZ4_read16(const void* memPtr) +{ + U16 val; memcpy(&val, memPtr, sizeof(val)); return val; +} + +static U32 LZ4_read32(const void* memPtr) +{ + U32 val; memcpy(&val, memPtr, sizeof(val)); return val; +} + +static reg_t LZ4_read_ARCH(const void* memPtr) +{ + reg_t val; memcpy(&val, memPtr, sizeof(val)); return val; +} + +static void LZ4_write16(void* memPtr, U16 value) +{ + memcpy(memPtr, &value, sizeof(value)); +} + +static void LZ4_write32(void* memPtr, U32 value) +{ + memcpy(memPtr, &value, sizeof(value)); +} + +#endif /* LZ4_FORCE_MEMORY_ACCESS */ + + +static U16 LZ4_readLE16(const void* memPtr) +{ + if (LZ4_isLittleEndian()) { + return LZ4_read16(memPtr); + } else { + const BYTE* p = (const BYTE*)memPtr; + return (U16)((U16)p[0] + (p[1]<<8)); + } +} + +static void LZ4_writeLE16(void* memPtr, U16 value) +{ + if (LZ4_isLittleEndian()) { + LZ4_write16(memPtr, value); + } else { + BYTE* p = (BYTE*)memPtr; + p[0] = (BYTE) value; + p[1] = (BYTE)(value>>8); + } +} + +static void LZ4_copy8(void* dst, const void* src) +{ + memcpy(dst,src,8); +} + +/* customized variant of memcpy, which can overwrite up to 8 bytes beyond dstEnd */ +static void LZ4_wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd) +{ + BYTE* d = (BYTE*)dstPtr; + const BYTE* s = (const BYTE*)srcPtr; + BYTE* const e = (BYTE*)dstEnd; + + do { LZ4_copy8(d,s); d+=8; s+=8; } while (d>3); +# elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT) + return (__builtin_ctzll((U64)val) >> 3); +# else + static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 }; + return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58]; +# endif + } else /* 32 bits */ { +# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) + unsigned long r; + _BitScanForward( &r, (U32)val ); + return (int)(r>>3); +# elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT) + return (__builtin_ctz((U32)val) >> 3); +# else + static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 }; + return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27]; +# endif + } + } else /* Big Endian CPU */ { + if (sizeof(val)==8) { +# if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT) + unsigned long r = 0; + _BitScanReverse64( &r, val ); + return (unsigned)(r>>3); +# elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT) + return (__builtin_clzll((U64)val) >> 3); +# else + unsigned r; + if (!(val>>32)) { r=4; } else { r=0; val>>=32; } + if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; } + r += (!val); + return r; +# endif + } else /* 32 bits */ { +# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) + unsigned long r = 0; + _BitScanReverse( &r, (unsigned long)val ); + return (unsigned)(r>>3); +# elif (defined(__clang__) || (defined(__GNUC__) && (__GNUC__>=3))) && !defined(LZ4_FORCE_SW_BITCOUNT) + return (__builtin_clz((U32)val) >> 3); +# else + unsigned r; + if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; } + r += (!val); + return r; +# endif + } + } +} + +#define STEPSIZE sizeof(reg_t) +static unsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit) +{ + const BYTE* const pStart = pIn; + + while (likely(pIn compression run slower on incompressible data */ + + +/*-************************************ +* Local Structures and types +**************************************/ +typedef enum { notLimited = 0, limitedOutput = 1 } limitedOutput_directive; +typedef enum { byPtr, byU32, byU16 } tableType_t; + +typedef enum { noDict = 0, withPrefix64k, usingExtDict } dict_directive; +typedef enum { noDictIssue = 0, dictSmall } dictIssue_directive; + +typedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive; +typedef enum { full = 0, partial = 1 } earlyEnd_directive; + + +/*-************************************ +* Local Utils +**************************************/ +int LZ4_versionNumber (void) { return LZ4_VERSION_NUMBER; } +const char* LZ4_versionString(void) { return LZ4_VERSION_STRING; } +int LZ4_compressBound(int isize) { return LZ4_COMPRESSBOUND(isize); } +int LZ4_sizeofState(void) { return LZ4_STREAMSIZE; } + + +/*-****************************** +* Compression functions +********************************/ +static U32 LZ4_hash4(U32 sequence, tableType_t const tableType) +{ + if (tableType == byU16) + return ((sequence * 2654435761U) >> ((MINMATCH*8)-(LZ4_HASHLOG+1))); + else + return ((sequence * 2654435761U) >> ((MINMATCH*8)-LZ4_HASHLOG)); +} + +static U32 LZ4_hash5(U64 sequence, tableType_t const tableType) +{ + static const U64 prime5bytes = 889523592379ULL; + static const U64 prime8bytes = 11400714785074694791ULL; + const U32 hashLog = (tableType == byU16) ? LZ4_HASHLOG+1 : LZ4_HASHLOG; + if (LZ4_isLittleEndian()) + return (U32)(((sequence << 24) * prime5bytes) >> (64 - hashLog)); + else + return (U32)(((sequence >> 24) * prime8bytes) >> (64 - hashLog)); +} + +FORCE_INLINE U32 LZ4_hashPosition(const void* const p, tableType_t const tableType) +{ + if ((sizeof(reg_t)==8) && (tableType != byU16)) return LZ4_hash5(LZ4_read_ARCH(p), tableType); + return LZ4_hash4(LZ4_read32(p), tableType); +} + +static void LZ4_putPositionOnHash(const BYTE* p, U32 h, void* tableBase, tableType_t const tableType, const BYTE* srcBase) +{ + switch (tableType) + { + case byPtr: { const BYTE** hashTable = (const BYTE**)tableBase; hashTable[h] = p; return; } + case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = (U32)(p-srcBase); return; } + case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = (U16)(p-srcBase); return; } + } +} + +FORCE_INLINE void LZ4_putPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase) +{ + U32 const h = LZ4_hashPosition(p, tableType); + LZ4_putPositionOnHash(p, h, tableBase, tableType, srcBase); +} + +static const BYTE* LZ4_getPositionOnHash(U32 h, void* tableBase, tableType_t tableType, const BYTE* srcBase) +{ + if (tableType == byPtr) { const BYTE** hashTable = (const BYTE**) tableBase; return hashTable[h]; } + if (tableType == byU32) { const U32* const hashTable = (U32*) tableBase; return hashTable[h] + srcBase; } + { const U16* const hashTable = (U16*) tableBase; return hashTable[h] + srcBase; } /* default, to ensure a return */ +} + +FORCE_INLINE const BYTE* LZ4_getPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase) +{ + U32 const h = LZ4_hashPosition(p, tableType); + return LZ4_getPositionOnHash(h, tableBase, tableType, srcBase); +} + + +/** LZ4_compress_generic() : + inlined, to ensure branches are decided at compilation time */ +FORCE_INLINE int LZ4_compress_generic( + LZ4_stream_t_internal* const cctx, + const char* const source, + char* const dest, + const int inputSize, + const int maxOutputSize, + const limitedOutput_directive outputLimited, + const tableType_t tableType, + const dict_directive dict, + const dictIssue_directive dictIssue, + const U32 acceleration) +{ + const BYTE* ip = (const BYTE*) source; + const BYTE* base; + const BYTE* lowLimit; + const BYTE* const lowRefLimit = ip - cctx->dictSize; + const BYTE* const dictionary = cctx->dictionary; + const BYTE* const dictEnd = dictionary + cctx->dictSize; + const ptrdiff_t dictDelta = dictEnd - (const BYTE*)source; + const BYTE* anchor = (const BYTE*) source; + const BYTE* const iend = ip + inputSize; + const BYTE* const mflimit = iend - MFLIMIT; + const BYTE* const matchlimit = iend - LASTLITERALS; + + BYTE* op = (BYTE*) dest; + BYTE* const olimit = op + maxOutputSize; + + U32 forwardH; + + /* Init conditions */ + if ((U32)inputSize > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported inputSize, too large (or negative) */ + switch(dict) + { + case noDict: + default: + base = (const BYTE*)source; + lowLimit = (const BYTE*)source; + break; + case withPrefix64k: + base = (const BYTE*)source - cctx->currentOffset; + lowLimit = (const BYTE*)source - cctx->dictSize; + break; + case usingExtDict: + base = (const BYTE*)source - cctx->currentOffset; + lowLimit = (const BYTE*)source; + break; + } + if ((tableType == byU16) && (inputSize>=LZ4_64Klimit)) return 0; /* Size too large (not within 64K limit) */ + if (inputSizehashTable, tableType, base); + ip++; forwardH = LZ4_hashPosition(ip, tableType); + + /* Main Loop */ + for ( ; ; ) { + ptrdiff_t refDelta = 0; + const BYTE* match; + BYTE* token; + + /* Find a match */ + { const BYTE* forwardIp = ip; + unsigned step = 1; + unsigned searchMatchNb = acceleration << LZ4_skipTrigger; + do { + U32 const h = forwardH; + ip = forwardIp; + forwardIp += step; + step = (searchMatchNb++ >> LZ4_skipTrigger); + + if (unlikely(forwardIp > mflimit)) goto _last_literals; + + match = LZ4_getPositionOnHash(h, cctx->hashTable, tableType, base); + if (dict==usingExtDict) { + if (match < (const BYTE*)source) { + refDelta = dictDelta; + lowLimit = dictionary; + } else { + refDelta = 0; + lowLimit = (const BYTE*)source; + } } + forwardH = LZ4_hashPosition(forwardIp, tableType); + LZ4_putPositionOnHash(ip, h, cctx->hashTable, tableType, base); + + } while ( ((dictIssue==dictSmall) ? (match < lowRefLimit) : 0) + || ((tableType==byU16) ? 0 : (match + MAX_DISTANCE < ip)) + || (LZ4_read32(match+refDelta) != LZ4_read32(ip)) ); + } + + /* Catch up */ + while (((ip>anchor) & (match+refDelta > lowLimit)) && (unlikely(ip[-1]==match[refDelta-1]))) { ip--; match--; } + + /* Encode Literals */ + { unsigned const litLength = (unsigned)(ip - anchor); + token = op++; + if ((outputLimited) && /* Check output buffer overflow */ + (unlikely(op + litLength + (2 + 1 + LASTLITERALS) + (litLength/255) > olimit))) + return 0; + if (litLength >= RUN_MASK) { + int len = (int)litLength-RUN_MASK; + *token = (RUN_MASK<= 255 ; len-=255) *op++ = 255; + *op++ = (BYTE)len; + } + else *token = (BYTE)(litLength< matchlimit) limit = matchlimit; + matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, limit); + ip += MINMATCH + matchCode; + if (ip==limit) { + unsigned const more = LZ4_count(ip, (const BYTE*)source, matchlimit); + matchCode += more; + ip += more; + } + } else { + matchCode = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit); + ip += MINMATCH + matchCode; + } + + if ( outputLimited && /* Check output buffer overflow */ + (unlikely(op + (1 + LASTLITERALS) + (matchCode>>8) > olimit)) ) + return 0; + if (matchCode >= ML_MASK) { + *token += ML_MASK; + matchCode -= ML_MASK; + LZ4_write32(op, 0xFFFFFFFF); + while (matchCode >= 4*255) op+=4, LZ4_write32(op, 0xFFFFFFFF), matchCode -= 4*255; + op += matchCode / 255; + *op++ = (BYTE)(matchCode % 255); + } else + *token += (BYTE)(matchCode); + } + + anchor = ip; + + /* Test end of chunk */ + if (ip > mflimit) break; + + /* Fill table */ + LZ4_putPosition(ip-2, cctx->hashTable, tableType, base); + + /* Test next position */ + match = LZ4_getPosition(ip, cctx->hashTable, tableType, base); + if (dict==usingExtDict) { + if (match < (const BYTE*)source) { + refDelta = dictDelta; + lowLimit = dictionary; + } else { + refDelta = 0; + lowLimit = (const BYTE*)source; + } } + LZ4_putPosition(ip, cctx->hashTable, tableType, base); + if ( ((dictIssue==dictSmall) ? (match>=lowRefLimit) : 1) + && (match+MAX_DISTANCE>=ip) + && (LZ4_read32(match+refDelta)==LZ4_read32(ip)) ) + { token=op++; *token=0; goto _next_match; } + + /* Prepare next loop */ + forwardH = LZ4_hashPosition(++ip, tableType); + } + +_last_literals: + /* Encode Last Literals */ + { size_t const lastRun = (size_t)(iend - anchor); + if ( (outputLimited) && /* Check output buffer overflow */ + ((op - (BYTE*)dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize) ) + return 0; + if (lastRun >= RUN_MASK) { + size_t accumulator = lastRun - RUN_MASK; + *op++ = RUN_MASK << ML_BITS; + for(; accumulator >= 255 ; accumulator-=255) *op++ = 255; + *op++ = (BYTE) accumulator; + } else { + *op++ = (BYTE)(lastRun<internal_donotuse; + LZ4_resetStream((LZ4_stream_t*)state); + if (acceleration < 1) acceleration = ACCELERATION_DEFAULT; + + if (maxOutputSize >= LZ4_compressBound(inputSize)) { + if (inputSize < LZ4_64Klimit) + return LZ4_compress_generic(ctx, source, dest, inputSize, 0, notLimited, byU16, noDict, noDictIssue, acceleration); + else + return LZ4_compress_generic(ctx, source, dest, inputSize, 0, notLimited, (sizeof(void*)==8) ? byU32 : byPtr, noDict, noDictIssue, acceleration); + } else { + if (inputSize < LZ4_64Klimit) + return LZ4_compress_generic(ctx, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration); + else + return LZ4_compress_generic(ctx, source, dest, inputSize, maxOutputSize, limitedOutput, (sizeof(void*)==8) ? byU32 : byPtr, noDict, noDictIssue, acceleration); + } +} + + +int LZ4_compress_fast(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) +{ +#if (HEAPMODE) + void* ctxPtr = ALLOCATOR(1, sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */ +#else + LZ4_stream_t ctx; + void* const ctxPtr = &ctx; +#endif + + int const result = LZ4_compress_fast_extState(ctxPtr, source, dest, inputSize, maxOutputSize, acceleration); + +#if (HEAPMODE) + FREEMEM(ctxPtr); +#endif + return result; +} + + +int LZ4_compress_default(const char* source, char* dest, int inputSize, int maxOutputSize) +{ + return LZ4_compress_fast(source, dest, inputSize, maxOutputSize, 1); +} + + +/* hidden debug function */ +/* strangely enough, gcc generates faster code when this function is uncommented, even if unused */ +int LZ4_compress_fast_force(const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) +{ + LZ4_stream_t ctx; + LZ4_resetStream(&ctx); + + if (inputSize < LZ4_64Klimit) + return LZ4_compress_generic(&ctx.internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue, acceleration); + else + return LZ4_compress_generic(&ctx.internal_donotuse, source, dest, inputSize, maxOutputSize, limitedOutput, sizeof(void*)==8 ? byU32 : byPtr, noDict, noDictIssue, acceleration); +} + + +/*-****************************** +* *_destSize() variant +********************************/ + +static int LZ4_compress_destSize_generic( + LZ4_stream_t_internal* const ctx, + const char* const src, + char* const dst, + int* const srcSizePtr, + const int targetDstSize, + const tableType_t tableType) +{ + const BYTE* ip = (const BYTE*) src; + const BYTE* base = (const BYTE*) src; + const BYTE* lowLimit = (const BYTE*) src; + const BYTE* anchor = ip; + const BYTE* const iend = ip + *srcSizePtr; + const BYTE* const mflimit = iend - MFLIMIT; + const BYTE* const matchlimit = iend - LASTLITERALS; + + BYTE* op = (BYTE*) dst; + BYTE* const oend = op + targetDstSize; + BYTE* const oMaxLit = op + targetDstSize - 2 /* offset */ - 8 /* because 8+MINMATCH==MFLIMIT */ - 1 /* token */; + BYTE* const oMaxMatch = op + targetDstSize - (LASTLITERALS + 1 /* token */); + BYTE* const oMaxSeq = oMaxLit - 1 /* token */; + + U32 forwardH; + + + /* Init conditions */ + if (targetDstSize < 1) return 0; /* Impossible to store anything */ + if ((U32)*srcSizePtr > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size, too large (or negative) */ + if ((tableType == byU16) && (*srcSizePtr>=LZ4_64Klimit)) return 0; /* Size too large (not within 64K limit) */ + if (*srcSizePtrhashTable, tableType, base); + ip++; forwardH = LZ4_hashPosition(ip, tableType); + + /* Main Loop */ + for ( ; ; ) { + const BYTE* match; + BYTE* token; + + /* Find a match */ + { const BYTE* forwardIp = ip; + unsigned step = 1; + unsigned searchMatchNb = 1 << LZ4_skipTrigger; + + do { + U32 h = forwardH; + ip = forwardIp; + forwardIp += step; + step = (searchMatchNb++ >> LZ4_skipTrigger); + + if (unlikely(forwardIp > mflimit)) goto _last_literals; + + match = LZ4_getPositionOnHash(h, ctx->hashTable, tableType, base); + forwardH = LZ4_hashPosition(forwardIp, tableType); + LZ4_putPositionOnHash(ip, h, ctx->hashTable, tableType, base); + + } while ( ((tableType==byU16) ? 0 : (match + MAX_DISTANCE < ip)) + || (LZ4_read32(match) != LZ4_read32(ip)) ); + } + + /* Catch up */ + while ((ip>anchor) && (match > lowLimit) && (unlikely(ip[-1]==match[-1]))) { ip--; match--; } + + /* Encode Literal length */ + { unsigned litLength = (unsigned)(ip - anchor); + token = op++; + if (op + ((litLength+240)/255) + litLength > oMaxLit) { + /* Not enough space for a last match */ + op--; + goto _last_literals; + } + if (litLength>=RUN_MASK) { + unsigned len = litLength - RUN_MASK; + *token=(RUN_MASK<= 255 ; len-=255) *op++ = 255; + *op++ = (BYTE)len; + } + else *token = (BYTE)(litLength< oMaxMatch) { + /* Match description too long : reduce it */ + matchLength = (15-1) + (oMaxMatch-op) * 255; + } + ip += MINMATCH + matchLength; + + if (matchLength>=ML_MASK) { + *token += ML_MASK; + matchLength -= ML_MASK; + while (matchLength >= 255) { matchLength-=255; *op++ = 255; } + *op++ = (BYTE)matchLength; + } + else *token += (BYTE)(matchLength); + } + + anchor = ip; + + /* Test end of block */ + if (ip > mflimit) break; + if (op > oMaxSeq) break; + + /* Fill table */ + LZ4_putPosition(ip-2, ctx->hashTable, tableType, base); + + /* Test next position */ + match = LZ4_getPosition(ip, ctx->hashTable, tableType, base); + LZ4_putPosition(ip, ctx->hashTable, tableType, base); + if ( (match+MAX_DISTANCE>=ip) + && (LZ4_read32(match)==LZ4_read32(ip)) ) + { token=op++; *token=0; goto _next_match; } + + /* Prepare next loop */ + forwardH = LZ4_hashPosition(++ip, tableType); + } + +_last_literals: + /* Encode Last Literals */ + { size_t lastRunSize = (size_t)(iend - anchor); + if (op + 1 /* token */ + ((lastRunSize+240)/255) /* litLength */ + lastRunSize /* literals */ > oend) { + /* adapt lastRunSize to fill 'dst' */ + lastRunSize = (oend-op) - 1; + lastRunSize -= (lastRunSize+240)/255; + } + ip = anchor + lastRunSize; + + if (lastRunSize >= RUN_MASK) { + size_t accumulator = lastRunSize - RUN_MASK; + *op++ = RUN_MASK << ML_BITS; + for(; accumulator >= 255 ; accumulator-=255) *op++ = 255; + *op++ = (BYTE) accumulator; + } else { + *op++ = (BYTE)(lastRunSize<= LZ4_compressBound(*srcSizePtr)) { /* compression success is guaranteed */ + return LZ4_compress_fast_extState(state, src, dst, *srcSizePtr, targetDstSize, 1); + } else { + if (*srcSizePtr < LZ4_64Klimit) + return LZ4_compress_destSize_generic(&state->internal_donotuse, src, dst, srcSizePtr, targetDstSize, byU16); + else + return LZ4_compress_destSize_generic(&state->internal_donotuse, src, dst, srcSizePtr, targetDstSize, sizeof(void*)==8 ? byU32 : byPtr); + } +} + + +int LZ4_compress_destSize(const char* src, char* dst, int* srcSizePtr, int targetDstSize) +{ +#if (HEAPMODE) + LZ4_stream_t* ctx = (LZ4_stream_t*)ALLOCATOR(1, sizeof(LZ4_stream_t)); /* malloc-calloc always properly aligned */ +#else + LZ4_stream_t ctxBody; + LZ4_stream_t* ctx = &ctxBody; +#endif + + int result = LZ4_compress_destSize_extState(ctx, src, dst, srcSizePtr, targetDstSize); + +#if (HEAPMODE) + FREEMEM(ctx); +#endif + return result; +} + + + +/*-****************************** +* Streaming functions +********************************/ + +LZ4_stream_t* LZ4_createStream(void) +{ + LZ4_stream_t* lz4s = (LZ4_stream_t*)ALLOCATOR(8, LZ4_STREAMSIZE_U64); + LZ4_STATIC_ASSERT(LZ4_STREAMSIZE >= sizeof(LZ4_stream_t_internal)); /* A compilation error here means LZ4_STREAMSIZE is not large enough */ + LZ4_resetStream(lz4s); + return lz4s; +} + +void LZ4_resetStream (LZ4_stream_t* LZ4_stream) +{ + MEM_INIT(LZ4_stream, 0, sizeof(LZ4_stream_t)); +} + +int LZ4_freeStream (LZ4_stream_t* LZ4_stream) +{ + FREEMEM(LZ4_stream); + return (0); +} + + +#define HASH_UNIT sizeof(reg_t) +int LZ4_loadDict (LZ4_stream_t* LZ4_dict, const char* dictionary, int dictSize) +{ + LZ4_stream_t_internal* dict = &LZ4_dict->internal_donotuse; + const BYTE* p = (const BYTE*)dictionary; + const BYTE* const dictEnd = p + dictSize; + const BYTE* base; + + if ((dict->initCheck) || (dict->currentOffset > 1 GB)) /* Uninitialized structure, or reuse overflow */ + LZ4_resetStream(LZ4_dict); + + if (dictSize < (int)HASH_UNIT) { + dict->dictionary = NULL; + dict->dictSize = 0; + return 0; + } + + if ((dictEnd - p) > 64 KB) p = dictEnd - 64 KB; + dict->currentOffset += 64 KB; + base = p - dict->currentOffset; + dict->dictionary = p; + dict->dictSize = (U32)(dictEnd - p); + dict->currentOffset += dict->dictSize; + + while (p <= dictEnd-HASH_UNIT) { + LZ4_putPosition(p, dict->hashTable, byU32, base); + p+=3; + } + + return dict->dictSize; +} + + +static void LZ4_renormDictT(LZ4_stream_t_internal* LZ4_dict, const BYTE* src) +{ + if ((LZ4_dict->currentOffset > 0x80000000) || + ((uptrval)LZ4_dict->currentOffset > (uptrval)src)) { /* address space overflow */ + /* rescale hash table */ + U32 const delta = LZ4_dict->currentOffset - 64 KB; + const BYTE* dictEnd = LZ4_dict->dictionary + LZ4_dict->dictSize; + int i; + for (i=0; ihashTable[i] < delta) LZ4_dict->hashTable[i]=0; + else LZ4_dict->hashTable[i] -= delta; + } + LZ4_dict->currentOffset = 64 KB; + if (LZ4_dict->dictSize > 64 KB) LZ4_dict->dictSize = 64 KB; + LZ4_dict->dictionary = dictEnd - LZ4_dict->dictSize; + } +} + + +int LZ4_compress_fast_continue (LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize, int maxOutputSize, int acceleration) +{ + LZ4_stream_t_internal* streamPtr = &LZ4_stream->internal_donotuse; + const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize; + + const BYTE* smallest = (const BYTE*) source; + if (streamPtr->initCheck) return 0; /* Uninitialized structure detected */ + if ((streamPtr->dictSize>0) && (smallest>dictEnd)) smallest = dictEnd; + LZ4_renormDictT(streamPtr, smallest); + if (acceleration < 1) acceleration = ACCELERATION_DEFAULT; + + /* Check overlapping input/dictionary space */ + { const BYTE* sourceEnd = (const BYTE*) source + inputSize; + if ((sourceEnd > streamPtr->dictionary) && (sourceEnd < dictEnd)) { + streamPtr->dictSize = (U32)(dictEnd - sourceEnd); + if (streamPtr->dictSize > 64 KB) streamPtr->dictSize = 64 KB; + if (streamPtr->dictSize < 4) streamPtr->dictSize = 0; + streamPtr->dictionary = dictEnd - streamPtr->dictSize; + } + } + + /* prefix mode : source data follows dictionary */ + if (dictEnd == (const BYTE*)source) { + int result; + if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) + result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, dictSmall, acceleration); + else + result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, withPrefix64k, noDictIssue, acceleration); + streamPtr->dictSize += (U32)inputSize; + streamPtr->currentOffset += (U32)inputSize; + return result; + } + + /* external dictionary mode */ + { int result; + if ((streamPtr->dictSize < 64 KB) && (streamPtr->dictSize < streamPtr->currentOffset)) + result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, dictSmall, acceleration); + else + result = LZ4_compress_generic(streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput, byU32, usingExtDict, noDictIssue, acceleration); + streamPtr->dictionary = (const BYTE*)source; + streamPtr->dictSize = (U32)inputSize; + streamPtr->currentOffset += (U32)inputSize; + return result; + } +} + + +/* Hidden debug function, to force external dictionary mode */ +int LZ4_compress_forceExtDict (LZ4_stream_t* LZ4_dict, const char* source, char* dest, int inputSize) +{ + LZ4_stream_t_internal* streamPtr = &LZ4_dict->internal_donotuse; + int result; + const BYTE* const dictEnd = streamPtr->dictionary + streamPtr->dictSize; + + const BYTE* smallest = dictEnd; + if (smallest > (const BYTE*) source) smallest = (const BYTE*) source; + LZ4_renormDictT(streamPtr, smallest); + + result = LZ4_compress_generic(streamPtr, source, dest, inputSize, 0, notLimited, byU32, usingExtDict, noDictIssue, 1); + + streamPtr->dictionary = (const BYTE*)source; + streamPtr->dictSize = (U32)inputSize; + streamPtr->currentOffset += (U32)inputSize; + + return result; +} + + +/*! LZ4_saveDict() : + * If previously compressed data block is not guaranteed to remain available at its memory location, + * save it into a safer place (char* safeBuffer). + * Note : you don't need to call LZ4_loadDict() afterwards, + * dictionary is immediately usable, you can therefore call LZ4_compress_fast_continue(). + * Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error. + */ +int LZ4_saveDict (LZ4_stream_t* LZ4_dict, char* safeBuffer, int dictSize) +{ + LZ4_stream_t_internal* const dict = &LZ4_dict->internal_donotuse; + const BYTE* const previousDictEnd = dict->dictionary + dict->dictSize; + + if ((U32)dictSize > 64 KB) dictSize = 64 KB; /* useless to define a dictionary > 64 KB */ + if ((U32)dictSize > dict->dictSize) dictSize = dict->dictSize; + + memmove(safeBuffer, previousDictEnd - dictSize, dictSize); + + dict->dictionary = (const BYTE*)safeBuffer; + dict->dictSize = (U32)dictSize; + + return dictSize; +} + + + +/*-***************************** +* Decompression functions +*******************************/ +/*! LZ4_decompress_generic() : + * This generic decompression function cover all use cases. + * It shall be instantiated several times, using different sets of directives + * Note that it is important this generic function is really inlined, + * in order to remove useless branches during compilation optimization. + */ +FORCE_INLINE int LZ4_decompress_generic( + const char* const source, + char* const dest, + int inputSize, + int outputSize, /* If endOnInput==endOnInputSize, this value is the max size of Output Buffer. */ + + int endOnInput, /* endOnOutputSize, endOnInputSize */ + int partialDecoding, /* full, partial */ + int targetOutputSize, /* only used if partialDecoding==partial */ + int dict, /* noDict, withPrefix64k, usingExtDict */ + const BYTE* const lowPrefix, /* == dest when no prefix */ + const BYTE* const dictStart, /* only if dict==usingExtDict */ + const size_t dictSize /* note : = 0 if noDict */ + ) +{ + /* Local Variables */ + const BYTE* ip = (const BYTE*) source; + const BYTE* const iend = ip + inputSize; + + BYTE* op = (BYTE*) dest; + BYTE* const oend = op + outputSize; + BYTE* cpy; + BYTE* oexit = op + targetOutputSize; + const BYTE* const lowLimit = lowPrefix - dictSize; + + const BYTE* const dictEnd = (const BYTE*)dictStart + dictSize; + const unsigned dec32table[] = {0, 1, 2, 1, 4, 4, 4, 4}; + const int dec64table[] = {0, 0, 0, -1, 0, 1, 2, 3}; + + const int safeDecode = (endOnInput==endOnInputSize); + const int checkOffset = ((safeDecode) && (dictSize < (int)(64 KB))); + + + /* Special cases */ + if ((partialDecoding) && (oexit > oend-MFLIMIT)) oexit = oend-MFLIMIT; /* targetOutputSize too high => decode everything */ + if ((endOnInput) && (unlikely(outputSize==0))) return ((inputSize==1) && (*ip==0)) ? 0 : -1; /* Empty output buffer */ + if ((!endOnInput) && (unlikely(outputSize==0))) return (*ip==0?1:-1); + + /* Main Loop : decode sequences */ + while (1) { + size_t length; + const BYTE* match; + size_t offset; + + /* get literal length */ + unsigned const token = *ip++; + if ((length=(token>>ML_BITS)) == RUN_MASK) { + unsigned s; + do { + s = *ip++; + length += s; + } while ( likely(endOnInput ? ip(partialDecoding?oexit:oend-MFLIMIT)) || (ip+length>iend-(2+1+LASTLITERALS))) ) + || ((!endOnInput) && (cpy>oend-WILDCOPYLENGTH)) ) + { + if (partialDecoding) { + if (cpy > oend) goto _output_error; /* Error : write attempt beyond end of output buffer */ + if ((endOnInput) && (ip+length > iend)) goto _output_error; /* Error : read attempt beyond end of input buffer */ + } else { + if ((!endOnInput) && (cpy != oend)) goto _output_error; /* Error : block decoding must stop exactly there */ + if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) goto _output_error; /* Error : input must be consumed */ + } + memcpy(op, ip, length); + ip += length; + op += length; + break; /* Necessarily EOF, due to parsing restrictions */ + } + LZ4_wildCopy(op, ip, cpy); + ip += length; op = cpy; + + /* get offset */ + offset = LZ4_readLE16(ip); ip+=2; + match = op - offset; + if ((checkOffset) && (unlikely(match < lowLimit))) goto _output_error; /* Error : offset outside buffers */ + LZ4_write32(op, (U32)offset); /* costs ~1%; silence an msan warning when offset==0 */ + + /* get matchlength */ + length = token & ML_MASK; + if (length == ML_MASK) { + unsigned s; + do { + s = *ip++; + if ((endOnInput) && (ip > iend-LASTLITERALS)) goto _output_error; + length += s; + } while (s==255); + if ((safeDecode) && unlikely((uptrval)(op)+length<(uptrval)op)) goto _output_error; /* overflow detection */ + } + length += MINMATCH; + + /* check external dictionary */ + if ((dict==usingExtDict) && (match < lowPrefix)) { + if (unlikely(op+length > oend-LASTLITERALS)) goto _output_error; /* doesn't respect parsing restriction */ + + if (length <= (size_t)(lowPrefix-match)) { + /* match can be copied as a single segment from external dictionary */ + memmove(op, dictEnd - (lowPrefix-match), length); + op += length; + } else { + /* match encompass external dictionary and current block */ + size_t const copySize = (size_t)(lowPrefix-match); + size_t const restSize = length - copySize; + memcpy(op, dictEnd - copySize, copySize); + op += copySize; + if (restSize > (size_t)(op-lowPrefix)) { /* overlap copy */ + BYTE* const endOfMatch = op + restSize; + const BYTE* copyFrom = lowPrefix; + while (op < endOfMatch) *op++ = *copyFrom++; + } else { + memcpy(op, lowPrefix, restSize); + op += restSize; + } } + continue; + } + + /* copy match within block */ + cpy = op + length; + if (unlikely(offset<8)) { + const int dec64 = dec64table[offset]; + op[0] = match[0]; + op[1] = match[1]; + op[2] = match[2]; + op[3] = match[3]; + match += dec32table[offset]; + memcpy(op+4, match, 4); + match -= dec64; + } else { LZ4_copy8(op, match); match+=8; } + op += 8; + + if (unlikely(cpy>oend-12)) { + BYTE* const oCopyLimit = oend-(WILDCOPYLENGTH-1); + if (cpy > oend-LASTLITERALS) goto _output_error; /* Error : last LASTLITERALS bytes must be literals (uncompressed) */ + if (op < oCopyLimit) { + LZ4_wildCopy(op, match, oCopyLimit); + match += oCopyLimit - op; + op = oCopyLimit; + } + while (op16) LZ4_wildCopy(op+8, match+8, cpy); + } + op=cpy; /* correction */ + } + + /* end of decoding */ + if (endOnInput) + return (int) (((char*)op)-dest); /* Nb of output bytes decoded */ + else + return (int) (((const char*)ip)-source); /* Nb of input bytes read */ + + /* Overflow error detected */ +_output_error: + return (int) (-(((const char*)ip)-source))-1; +} + + +int LZ4_decompress_safe(const char* source, char* dest, int compressedSize, int maxDecompressedSize) +{ + return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, full, 0, noDict, (BYTE*)dest, NULL, 0); +} + +int LZ4_decompress_safe_partial(const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize) +{ + return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, endOnInputSize, partial, targetOutputSize, noDict, (BYTE*)dest, NULL, 0); +} + +int LZ4_decompress_fast(const char* source, char* dest, int originalSize) +{ + return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, (BYTE*)(dest - 64 KB), NULL, 64 KB); +} + + +/*===== streaming decompression functions =====*/ + +/* + * If you prefer dynamic allocation methods, + * LZ4_createStreamDecode() + * provides a pointer (void*) towards an initialized LZ4_streamDecode_t structure. + */ +LZ4_streamDecode_t* LZ4_createStreamDecode(void) +{ + LZ4_streamDecode_t* lz4s = (LZ4_streamDecode_t*) ALLOCATOR(1, sizeof(LZ4_streamDecode_t)); + return lz4s; +} + +int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream) +{ + FREEMEM(LZ4_stream); + return 0; +} + +/*! + * LZ4_setStreamDecode() : + * Use this function to instruct where to find the dictionary. + * This function is not necessary if previous data is still available where it was decoded. + * Loading a size of 0 is allowed (same effect as no dictionary). + * Return : 1 if OK, 0 if error + */ +int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize) +{ + LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse; + lz4sd->prefixSize = (size_t) dictSize; + lz4sd->prefixEnd = (const BYTE*) dictionary + dictSize; + lz4sd->externalDict = NULL; + lz4sd->extDictSize = 0; + return 1; +} + +/* +*_continue() : + These decoding functions allow decompression of multiple blocks in "streaming" mode. + Previously decoded blocks must still be available at the memory position where they were decoded. + If it's not possible, save the relevant part of decoded data into a safe buffer, + and indicate where it stands using LZ4_setStreamDecode() +*/ +int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxOutputSize) +{ + LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse; + int result; + + if (lz4sd->prefixEnd == (BYTE*)dest) { + result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, + endOnInputSize, full, 0, + usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize); + if (result <= 0) return result; + lz4sd->prefixSize += result; + lz4sd->prefixEnd += result; + } else { + lz4sd->extDictSize = lz4sd->prefixSize; + lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize; + result = LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, + endOnInputSize, full, 0, + usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize); + if (result <= 0) return result; + lz4sd->prefixSize = result; + lz4sd->prefixEnd = (BYTE*)dest + result; + } + + return result; +} + +int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize) +{ + LZ4_streamDecode_t_internal* lz4sd = &LZ4_streamDecode->internal_donotuse; + int result; + + if (lz4sd->prefixEnd == (BYTE*)dest) { + result = LZ4_decompress_generic(source, dest, 0, originalSize, + endOnOutputSize, full, 0, + usingExtDict, lz4sd->prefixEnd - lz4sd->prefixSize, lz4sd->externalDict, lz4sd->extDictSize); + if (result <= 0) return result; + lz4sd->prefixSize += originalSize; + lz4sd->prefixEnd += originalSize; + } else { + lz4sd->extDictSize = lz4sd->prefixSize; + lz4sd->externalDict = lz4sd->prefixEnd - lz4sd->extDictSize; + result = LZ4_decompress_generic(source, dest, 0, originalSize, + endOnOutputSize, full, 0, + usingExtDict, (BYTE*)dest, lz4sd->externalDict, lz4sd->extDictSize); + if (result <= 0) return result; + lz4sd->prefixSize = originalSize; + lz4sd->prefixEnd = (BYTE*)dest + originalSize; + } + + return result; +} + + +/* +Advanced decoding functions : +*_usingDict() : + These decoding functions work the same as "_continue" ones, + the dictionary must be explicitly provided within parameters +*/ + +FORCE_INLINE int LZ4_decompress_usingDict_generic(const char* source, char* dest, int compressedSize, int maxOutputSize, int safe, const char* dictStart, int dictSize) +{ + if (dictSize==0) + return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest, NULL, 0); + if (dictStart+dictSize == dest) { + if (dictSize >= (int)(64 KB - 1)) + return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, withPrefix64k, (BYTE*)dest-64 KB, NULL, 0); + return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, noDict, (BYTE*)dest-dictSize, NULL, 0); + } + return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, safe, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize); +} + +int LZ4_decompress_safe_usingDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize) +{ + return LZ4_decompress_usingDict_generic(source, dest, compressedSize, maxOutputSize, 1, dictStart, dictSize); +} + +int LZ4_decompress_fast_usingDict(const char* source, char* dest, int originalSize, const char* dictStart, int dictSize) +{ + return LZ4_decompress_usingDict_generic(source, dest, 0, originalSize, 0, dictStart, dictSize); +} + +/* debug function */ +int LZ4_decompress_safe_forceExtDict(const char* source, char* dest, int compressedSize, int maxOutputSize, const char* dictStart, int dictSize) +{ + return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, usingExtDict, (BYTE*)dest, (const BYTE*)dictStart, dictSize); +} + + +/*=************************************************* +* Obsolete Functions +***************************************************/ +/* obsolete compression functions */ +int LZ4_compress_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize) { return LZ4_compress_default(source, dest, inputSize, maxOutputSize); } +int LZ4_compress(const char* source, char* dest, int inputSize) { return LZ4_compress_default(source, dest, inputSize, LZ4_compressBound(inputSize)); } +int LZ4_compress_limitedOutput_withState (void* state, const char* src, char* dst, int srcSize, int dstSize) { return LZ4_compress_fast_extState(state, src, dst, srcSize, dstSize, 1); } +int LZ4_compress_withState (void* state, const char* src, char* dst, int srcSize) { return LZ4_compress_fast_extState(state, src, dst, srcSize, LZ4_compressBound(srcSize), 1); } +int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_stream, const char* src, char* dst, int srcSize, int maxDstSize) { return LZ4_compress_fast_continue(LZ4_stream, src, dst, srcSize, maxDstSize, 1); } +int LZ4_compress_continue (LZ4_stream_t* LZ4_stream, const char* source, char* dest, int inputSize) { return LZ4_compress_fast_continue(LZ4_stream, source, dest, inputSize, LZ4_compressBound(inputSize), 1); } + +/* +These function names are deprecated and should no longer be used. +They are only provided here for compatibility with older user programs. +- LZ4_uncompress is totally equivalent to LZ4_decompress_fast +- LZ4_uncompress_unknownOutputSize is totally equivalent to LZ4_decompress_safe +*/ +int LZ4_uncompress (const char* source, char* dest, int outputSize) { return LZ4_decompress_fast(source, dest, outputSize); } +int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize) { return LZ4_decompress_safe(source, dest, isize, maxOutputSize); } + + +/* Obsolete Streaming functions */ + +int LZ4_sizeofStreamState(void) { return LZ4_STREAMSIZE; } + +static void LZ4_init(LZ4_stream_t* lz4ds, BYTE* base) +{ + MEM_INIT(lz4ds, 0, sizeof(LZ4_stream_t)); + lz4ds->internal_donotuse.bufferStart = base; +} + +int LZ4_resetStreamState(void* state, char* inputBuffer) +{ + if ((((uptrval)state) & 3) != 0) return 1; /* Error : pointer is not aligned on 4-bytes boundary */ + LZ4_init((LZ4_stream_t*)state, (BYTE*)inputBuffer); + return 0; +} + +void* LZ4_create (char* inputBuffer) +{ + LZ4_stream_t* lz4ds = (LZ4_stream_t*)ALLOCATOR(8, sizeof(LZ4_stream_t)); + LZ4_init (lz4ds, (BYTE*)inputBuffer); + return lz4ds; +} + +char* LZ4_slideInputBuffer (void* LZ4_Data) +{ + LZ4_stream_t_internal* ctx = &((LZ4_stream_t*)LZ4_Data)->internal_donotuse; + int dictSize = LZ4_saveDict((LZ4_stream_t*)LZ4_Data, (char*)ctx->bufferStart, 64 KB); + return (char*)(ctx->bufferStart + dictSize); +} + +/* Obsolete streaming decompression functions */ + +int LZ4_decompress_safe_withPrefix64k(const char* source, char* dest, int compressedSize, int maxOutputSize) +{ + return LZ4_decompress_generic(source, dest, compressedSize, maxOutputSize, endOnInputSize, full, 0, withPrefix64k, (BYTE*)dest - 64 KB, NULL, 64 KB); +} + +int LZ4_decompress_fast_withPrefix64k(const char* source, char* dest, int originalSize) +{ + return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, (BYTE*)dest - 64 KB, NULL, 64 KB); +} + +#endif /* LZ4_COMMONDEFS_ONLY */ +#else /* !SVN_INTERNAL_LZ4 */ + +/* Silence OSX ranlib warnings about object files with no symbols. */ +#include +extern const apr_uint32_t svn__fake__lz4internal; +const apr_uint32_t svn__fake__lz4internal = 0xdeadbeef; + +#endif /* SVN_INTERNAL_LZ4 */ diff --git a/subversion/libsvn_subr/lz4/lz4internal.h b/subversion/libsvn_subr/lz4/lz4internal.h new file mode 100644 index 000000000000..02ba09d3710f --- /dev/null +++ b/subversion/libsvn_subr/lz4/lz4internal.h @@ -0,0 +1,466 @@ +#include "svn_private_config.h" +#if SVN_INTERNAL_LZ4 +/* + * LZ4 - Fast LZ compression algorithm + * Header File + * Copyright (C) 2011-2016, Yann Collet. + + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - LZ4 homepage : http://www.lz4.org + - LZ4 source repository : https://github.com/lz4/lz4 +*/ +#ifndef LZ4_H_2983827168210 +#define LZ4_H_2983827168210 + +#if defined (__cplusplus) +extern "C" { +#endif + +/* --- Dependency --- */ +#include /* size_t */ + + +/** + Introduction + + LZ4 is lossless compression algorithm, providing compression speed at 400 MB/s per core, + scalable with multi-cores CPU. It features an extremely fast decoder, with speed in + multiple GB/s per core, typically reaching RAM speed limits on multi-core systems. + + The LZ4 compression library provides in-memory compression and decompression functions. + Compression can be done in: + - a single step (described as Simple Functions) + - a single step, reusing a context (described in Advanced Functions) + - unbounded multiple steps (described as Streaming compression) + + lz4.h provides block compression functions. It gives full buffer control to user. + Decompressing an lz4-compressed block also requires metadata (such as compressed size). + Each application is free to encode such metadata in whichever way it wants. + + An additional format, called LZ4 frame specification (doc/lz4_Frame_format.md), + take care of encoding standard metadata alongside LZ4-compressed blocks. + If your application requires interoperability, it's recommended to use it. + A library is provided to take care of it, see lz4frame.h. +*/ + +/*^*************************************************************** +* Export parameters +*****************************************************************/ +/* +* LZ4_DLL_EXPORT : +* Enable exporting of functions when building a Windows DLL +*/ +#if defined(LZ4_DLL_EXPORT) && (LZ4_DLL_EXPORT==1) +# define LZ4LIB_API __declspec(dllexport) +#elif defined(LZ4_DLL_IMPORT) && (LZ4_DLL_IMPORT==1) +# define LZ4LIB_API __declspec(dllimport) /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/ +#else +# define LZ4LIB_API +#endif + + +/*========== Version =========== */ +#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */ +#define LZ4_VERSION_MINOR 7 /* for new (non-breaking) interface capabilities */ +#define LZ4_VERSION_RELEASE 5 /* for tweaks, bug-fixes, or development */ + +#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE) + +#define LZ4_LIB_VERSION LZ4_VERSION_MAJOR.LZ4_VERSION_MINOR.LZ4_VERSION_RELEASE +#define LZ4_QUOTE(str) #str +#define LZ4_EXPAND_AND_QUOTE(str) LZ4_QUOTE(str) +#define LZ4_VERSION_STRING LZ4_EXPAND_AND_QUOTE(LZ4_LIB_VERSION) + +LZ4LIB_API int LZ4_versionNumber (void); +LZ4LIB_API const char* LZ4_versionString (void); + + +/*-************************************ +* Tuning parameter +**************************************/ +/*! + * LZ4_MEMORY_USAGE : + * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.) + * Increasing memory usage improves compression ratio + * Reduced memory usage can improve speed, due to cache effect + * Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache + */ +#define LZ4_MEMORY_USAGE 14 + + +/*-************************************ +* Simple Functions +**************************************/ +/*! LZ4_compress_default() : + Compresses 'sourceSize' bytes from buffer 'source' + into already allocated 'dest' buffer of size 'maxDestSize'. + Compression is guaranteed to succeed if 'maxDestSize' >= LZ4_compressBound(sourceSize). + It also runs faster, so it's a recommended setting. + If the function cannot compress 'source' into a more limited 'dest' budget, + compression stops *immediately*, and the function result is zero. + As a consequence, 'dest' content is not valid. + This function never writes outside 'dest' buffer, nor read outside 'source' buffer. + sourceSize : Max supported value is LZ4_MAX_INPUT_VALUE + maxDestSize : full or partial size of buffer 'dest' (which must be already allocated) + return : the number of bytes written into buffer 'dest' (necessarily <= maxOutputSize) + or 0 if compression fails */ +LZ4LIB_API int LZ4_compress_default(const char* source, char* dest, int sourceSize, int maxDestSize); + +/*! LZ4_decompress_safe() : + compressedSize : is the precise full size of the compressed block. + maxDecompressedSize : is the size of destination buffer, which must be already allocated. + return : the number of bytes decompressed into destination buffer (necessarily <= maxDecompressedSize) + If destination buffer is not large enough, decoding will stop and output an error code (<0). + If the source stream is detected malformed, the function will stop decoding and return a negative result. + This function is protected against buffer overflow exploits, including malicious data packets. + It never writes outside output buffer, nor reads outside input buffer. +*/ +LZ4LIB_API int LZ4_decompress_safe (const char* source, char* dest, int compressedSize, int maxDecompressedSize); + + +/*-************************************ +* Advanced Functions +**************************************/ +#define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */ +#define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16) + +/*! +LZ4_compressBound() : + Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible) + This function is primarily useful for memory allocation purposes (destination buffer size). + Macro LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example). + Note that LZ4_compress_default() compress faster when dest buffer size is >= LZ4_compressBound(srcSize) + inputSize : max supported value is LZ4_MAX_INPUT_SIZE + return : maximum output size in a "worst case" scenario + or 0, if input size is too large ( > LZ4_MAX_INPUT_SIZE) +*/ +LZ4LIB_API int LZ4_compressBound(int inputSize); + +/*! +LZ4_compress_fast() : + Same as LZ4_compress_default(), but allows to select an "acceleration" factor. + The larger the acceleration value, the faster the algorithm, but also the lesser the compression. + It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed. + An acceleration value of "1" is the same as regular LZ4_compress_default() + Values <= 0 will be replaced by ACCELERATION_DEFAULT (see lz4.c), which is 1. +*/ +LZ4LIB_API int LZ4_compress_fast (const char* source, char* dest, int sourceSize, int maxDestSize, int acceleration); + + +/*! +LZ4_compress_fast_extState() : + Same compression function, just using an externally allocated memory space to store compression state. + Use LZ4_sizeofState() to know how much memory must be allocated, + and allocate it on 8-bytes boundaries (using malloc() typically). + Then, provide it as 'void* state' to compression function. +*/ +LZ4LIB_API int LZ4_sizeofState(void); +LZ4LIB_API int LZ4_compress_fast_extState (void* state, const char* source, char* dest, int inputSize, int maxDestSize, int acceleration); + + +/*! +LZ4_compress_destSize() : + Reverse the logic, by compressing as much data as possible from 'source' buffer + into already allocated buffer 'dest' of size 'targetDestSize'. + This function either compresses the entire 'source' content into 'dest' if it's large enough, + or fill 'dest' buffer completely with as much data as possible from 'source'. + *sourceSizePtr : will be modified to indicate how many bytes where read from 'source' to fill 'dest'. + New value is necessarily <= old value. + return : Nb bytes written into 'dest' (necessarily <= targetDestSize) + or 0 if compression fails +*/ +LZ4LIB_API int LZ4_compress_destSize (const char* source, char* dest, int* sourceSizePtr, int targetDestSize); + + +/*! +LZ4_decompress_fast() : + originalSize : is the original and therefore uncompressed size + return : the number of bytes read from the source buffer (in other words, the compressed size) + If the source stream is detected malformed, the function will stop decoding and return a negative result. + Destination buffer must be already allocated. Its size must be a minimum of 'originalSize' bytes. + note : This function fully respect memory boundaries for properly formed compressed data. + It is a bit faster than LZ4_decompress_safe(). + However, it does not provide any protection against intentionally modified data stream (malicious input). + Use this function in trusted environment only (data to decode comes from a trusted source). +*/ +LZ4LIB_API int LZ4_decompress_fast (const char* source, char* dest, int originalSize); + +/*! +LZ4_decompress_safe_partial() : + This function decompress a compressed block of size 'compressedSize' at position 'source' + into destination buffer 'dest' of size 'maxDecompressedSize'. + The function tries to stop decompressing operation as soon as 'targetOutputSize' has been reached, + reducing decompression time. + return : the number of bytes decoded in the destination buffer (necessarily <= maxDecompressedSize) + Note : this number can be < 'targetOutputSize' should the compressed block to decode be smaller. + Always control how many bytes were decoded. + If the source stream is detected malformed, the function will stop decoding and return a negative result. + This function never writes outside of output buffer, and never reads outside of input buffer. It is therefore protected against malicious data packets +*/ +LZ4LIB_API int LZ4_decompress_safe_partial (const char* source, char* dest, int compressedSize, int targetOutputSize, int maxDecompressedSize); + + +/*-********************************************* +* Streaming Compression Functions +***********************************************/ +typedef union LZ4_stream_u LZ4_stream_t; /* incomplete type (defined later) */ + +/*! LZ4_createStream() and LZ4_freeStream() : + * LZ4_createStream() will allocate and initialize an `LZ4_stream_t` structure. + * LZ4_freeStream() releases its memory. + */ +LZ4LIB_API LZ4_stream_t* LZ4_createStream(void); +LZ4LIB_API int LZ4_freeStream (LZ4_stream_t* streamPtr); + +/*! LZ4_resetStream() : + * An LZ4_stream_t structure can be allocated once and re-used multiple times. + * Use this function to init an allocated `LZ4_stream_t` structure and start a new compression. + */ +LZ4LIB_API void LZ4_resetStream (LZ4_stream_t* streamPtr); + +/*! LZ4_loadDict() : + * Use this function to load a static dictionary into LZ4_stream. + * Any previous data will be forgotten, only 'dictionary' will remain in memory. + * Loading a size of 0 is allowed. + * Return : dictionary size, in bytes (necessarily <= 64 KB) + */ +LZ4LIB_API int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize); + +/*! LZ4_compress_fast_continue() : + * Compress buffer content 'src', using data from previously compressed blocks as dictionary to improve compression ratio. + * Important : Previous data blocks are assumed to still be present and unmodified ! + * 'dst' buffer must be already allocated. + * If maxDstSize >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster. + * If not, and if compressed data cannot fit into 'dst' buffer size, compression stops, and function returns a zero. + */ +LZ4LIB_API int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int maxDstSize, int acceleration); + +/*! LZ4_saveDict() : + * If previously compressed data block is not guaranteed to remain available at its memory location, + * save it into a safer place (char* safeBuffer). + * Note : you don't need to call LZ4_loadDict() afterwards, + * dictionary is immediately usable, you can therefore call LZ4_compress_fast_continue(). + * Return : saved dictionary size in bytes (necessarily <= dictSize), or 0 if error. + */ +LZ4LIB_API int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int dictSize); + + +/*-********************************************** +* Streaming Decompression Functions +* Bufferless synchronous API +************************************************/ +typedef union LZ4_streamDecode_u LZ4_streamDecode_t; /* incomplete type (defined later) */ + +/* creation / destruction of streaming decompression tracking structure */ +LZ4LIB_API LZ4_streamDecode_t* LZ4_createStreamDecode(void); +LZ4LIB_API int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream); + +/*! LZ4_setStreamDecode() : + * Use this function to instruct where to find the dictionary. + * Setting a size of 0 is allowed (same effect as reset). + * @return : 1 if OK, 0 if error + */ +LZ4LIB_API int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize); + +/*! +LZ4_decompress_*_continue() : + These decoding functions allow decompression of multiple blocks in "streaming" mode. + Previously decoded blocks *must* remain available at the memory position where they were decoded (up to 64 KB) + In the case of a ring buffers, decoding buffer must be either : + - Exactly same size as encoding buffer, with same update rule (block boundaries at same positions) + In which case, the decoding & encoding ring buffer can have any size, including very small ones ( < 64 KB). + - Larger than encoding buffer, by a minimum of maxBlockSize more bytes. + maxBlockSize is implementation dependent. It's the maximum size you intend to compress into a single block. + In which case, encoding and decoding buffers do not need to be synchronized, + and encoding ring buffer can have any size, including small ones ( < 64 KB). + - _At least_ 64 KB + 8 bytes + maxBlockSize. + In which case, encoding and decoding buffers do not need to be synchronized, + and encoding ring buffer can have any size, including larger than decoding buffer. + Whenever these conditions are not possible, save the last 64KB of decoded data into a safe buffer, + and indicate where it is saved using LZ4_setStreamDecode() +*/ +LZ4LIB_API int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int compressedSize, int maxDecompressedSize); +LZ4LIB_API int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* source, char* dest, int originalSize); + + +/*! LZ4_decompress_*_usingDict() : + * These decoding functions work the same as + * a combination of LZ4_setStreamDecode() followed by LZ4_decompress_*_continue() + * They are stand-alone, and don't need an LZ4_streamDecode_t structure. + */ +LZ4LIB_API int LZ4_decompress_safe_usingDict (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize); +LZ4LIB_API int LZ4_decompress_fast_usingDict (const char* source, char* dest, int originalSize, const char* dictStart, int dictSize); + + +/*^********************************************** + * !!!!!! STATIC LINKING ONLY !!!!!! + ***********************************************/ +/*-************************************ + * Private definitions + ************************************** + * Do not use these definitions. + * They are exposed to allow static allocation of `LZ4_stream_t` and `LZ4_streamDecode_t`. + * Using these definitions will expose code to API and/or ABI break in future versions of the library. + **************************************/ +#define LZ4_HASHLOG (LZ4_MEMORY_USAGE-2) +#define LZ4_HASHTABLESIZE (1 << LZ4_MEMORY_USAGE) +#define LZ4_HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */ + +#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */) +#include + +typedef struct { + uint32_t hashTable[LZ4_HASH_SIZE_U32]; + uint32_t currentOffset; + uint32_t initCheck; + const uint8_t* dictionary; + uint8_t* bufferStart; /* obsolete, used for slideInputBuffer */ + uint32_t dictSize; +} LZ4_stream_t_internal; + +typedef struct { + const uint8_t* externalDict; + size_t extDictSize; + const uint8_t* prefixEnd; + size_t prefixSize; +} LZ4_streamDecode_t_internal; + +#else + +typedef struct { + unsigned int hashTable[LZ4_HASH_SIZE_U32]; + unsigned int currentOffset; + unsigned int initCheck; + const unsigned char* dictionary; + unsigned char* bufferStart; /* obsolete, used for slideInputBuffer */ + unsigned int dictSize; +} LZ4_stream_t_internal; + +typedef struct { + const unsigned char* externalDict; + size_t extDictSize; + const unsigned char* prefixEnd; + size_t prefixSize; +} LZ4_streamDecode_t_internal; + +#endif + +/*! + * LZ4_stream_t : + * information structure to track an LZ4 stream. + * init this structure before first use. + * note : only use in association with static linking ! + * this definition is not API/ABI safe, + * and may change in a future version ! + */ +#define LZ4_STREAMSIZE_U64 ((1 << (LZ4_MEMORY_USAGE-3)) + 4) +#define LZ4_STREAMSIZE (LZ4_STREAMSIZE_U64 * sizeof(unsigned long long)) +union LZ4_stream_u { + unsigned long long table[LZ4_STREAMSIZE_U64]; + LZ4_stream_t_internal internal_donotuse; +} ; /* previously typedef'd to LZ4_stream_t */ + + +/*! + * LZ4_streamDecode_t : + * information structure to track an LZ4 stream during decompression. + * init this structure using LZ4_setStreamDecode (or memset()) before first use + * note : only use in association with static linking ! + * this definition is not API/ABI safe, + * and may change in a future version ! + */ +#define LZ4_STREAMDECODESIZE_U64 4 +#define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U64 * sizeof(unsigned long long)) +union LZ4_streamDecode_u { + unsigned long long table[LZ4_STREAMDECODESIZE_U64]; + LZ4_streamDecode_t_internal internal_donotuse; +} ; /* previously typedef'd to LZ4_streamDecode_t */ + + +/*=************************************ +* Obsolete Functions +**************************************/ +/* Deprecation warnings */ +/* Should these warnings be a problem, + it is generally possible to disable them, + typically with -Wno-deprecated-declarations for gcc + or _CRT_SECURE_NO_WARNINGS in Visual. + Otherwise, it's also possible to define LZ4_DISABLE_DEPRECATE_WARNINGS */ +#ifdef LZ4_DISABLE_DEPRECATE_WARNINGS +# define LZ4_DEPRECATED(message) /* disable deprecation warnings */ +#else +# define LZ4_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) +# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */ +# define LZ4_DEPRECATED(message) [[deprecated(message)]] +# elif (LZ4_GCC_VERSION >= 405) || defined(__clang__) +# define LZ4_DEPRECATED(message) __attribute__((deprecated(message))) +# elif (LZ4_GCC_VERSION >= 301) +# define LZ4_DEPRECATED(message) __attribute__((deprecated)) +# elif defined(_MSC_VER) +# define LZ4_DEPRECATED(message) __declspec(deprecated(message)) +# else +# pragma message("WARNING: You need to implement LZ4_DEPRECATED for this compiler") +# define LZ4_DEPRECATED(message) +# endif +#endif /* LZ4_DISABLE_DEPRECATE_WARNINGS */ + +/* Obsolete compression functions */ +LZ4_DEPRECATED("use LZ4_compress_default() instead") int LZ4_compress (const char* source, char* dest, int sourceSize); +LZ4_DEPRECATED("use LZ4_compress_default() instead") int LZ4_compress_limitedOutput (const char* source, char* dest, int sourceSize, int maxOutputSize); +LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize); +LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize); +LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize); +LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize); + +/* Obsolete decompression functions */ +/* These function names are completely deprecated and must no longer be used. + They are only provided in lz4.c for compatibility with older programs. + - LZ4_uncompress is the same as LZ4_decompress_fast + - LZ4_uncompress_unknownOutputSize is the same as LZ4_decompress_safe + These function prototypes are now disabled; uncomment them only if you really need them. + It is highly recommended to stop using these prototypes and migrate to maintained ones */ +/* int LZ4_uncompress (const char* source, char* dest, int outputSize); */ +/* int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize); */ + +/* Obsolete streaming functions; use new streaming interface whenever possible */ +LZ4_DEPRECATED("use LZ4_createStream() instead") void* LZ4_create (char* inputBuffer); +LZ4_DEPRECATED("use LZ4_createStream() instead") int LZ4_sizeofStreamState(void); +LZ4_DEPRECATED("use LZ4_resetStream() instead") int LZ4_resetStreamState(void* state, char* inputBuffer); +LZ4_DEPRECATED("use LZ4_saveDict() instead") char* LZ4_slideInputBuffer (void* state); + +/* Obsolete streaming decoding functions */ +LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") int LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize); +LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize); + + +#if defined (__cplusplus) +} +#endif + +#endif /* LZ4_H_2983827168210 */ +#endif /* SVN_INTERNAL_LZ4 */ diff --git a/subversion/libsvn_subr/mergeinfo.c b/subversion/libsvn_subr/mergeinfo.c index e46d672347b9..21fa2121635c 100644 --- a/subversion/libsvn_subr/mergeinfo.c +++ b/subversion/libsvn_subr/mergeinfo.c @@ -41,6 +41,14 @@ #include "svn_hash.h" #include "private/svn_dep_compat.h" +/* Return TRUE iff the forward revision range FIRST wholly contains the + * forward revision range SECOND and (if CONSIDER_INHERITANCE is TRUE) has + * the same inheritability. */ +static svn_boolean_t +range_contains(const svn_merge_range_t *first, const svn_merge_range_t *second, + svn_boolean_t consider_inheritance); + + /* Attempt to combine two ranges, IN1 and IN2. If they are adjacent or overlapping, and their inheritability allows them to be combined, put the result in OUTPUT and return TRUE, otherwise return FALSE. @@ -263,197 +271,186 @@ combine_with_lastrange(const svn_merge_range_t *new_range, APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = svn_merge_range_dup(new_range, result_pool); } + else if (combine_ranges(&combined_range, lastrange, new_range, + consider_inheritance)) + { + *lastrange = combined_range; + } else if (!consider_inheritance) { /* We are not considering inheritance so we can merge intersecting ranges of different inheritability. Of course if the ranges don't intersect at all we simply push NEW_RANGE onto RANGELIST. */ - if (combine_ranges(&combined_range, lastrange, new_range, FALSE)) - { - *lastrange = combined_range; - } - else - { - APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = + APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = svn_merge_range_dup(new_range, result_pool); - } } else /* Considering inheritance */ { - if (combine_ranges(&combined_range, lastrange, new_range, TRUE)) - { - /* Even when considering inheritance two intersection ranges - of the same inheritability can simply be combined. */ - *lastrange = combined_range; - } - else - { - /* If we are here then the ranges either don't intersect or do - intersect but have differing inheritability. Check for the - first case as that is easy to handle. */ - intersection_type_t intersection_type; - svn_boolean_t sorted = FALSE; + /* If we are here then the ranges either don't intersect or do + intersect but have differing inheritability. Check for the + first case as that is easy to handle. */ + intersection_type_t intersection_type; + svn_boolean_t sorted = FALSE; - SVN_ERR(get_type_of_intersection(new_range, lastrange, - &intersection_type)); + SVN_ERR(get_type_of_intersection(new_range, lastrange, + &intersection_type)); - switch (intersection_type) + switch (intersection_type) + { + case svn__no_intersection: + /* NEW_RANGE and *LASTRANGE *really* don't intersect so + just push NEW_RANGE onto RANGELIST. */ + APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = + svn_merge_range_dup(new_range, result_pool); + sorted = (svn_sort_compare_ranges(&lastrange, + &new_range) < 0); + break; + + case svn__equal_intersection: + /* They range are equal so all we do is force the + inheritability of lastrange to true. */ + lastrange->inheritable = TRUE; + sorted = TRUE; + break; + + case svn__adjoining_intersection: + /* They adjoin but don't overlap so just push NEW_RANGE + onto RANGELIST. */ + APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = + svn_merge_range_dup(new_range, result_pool); + sorted = (svn_sort_compare_ranges(&lastrange, + &new_range) < 0); + break; + + case svn__overlapping_intersection: + /* They ranges overlap but neither is a proper subset of + the other. We'll end up pusing two new ranges onto + RANGELIST, the intersecting part and the part unique to + NEW_RANGE.*/ { - case svn__no_intersection: - /* NEW_RANGE and *LASTRANGE *really* don't intersect so - just push NEW_RANGE onto RANGELIST. */ - APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = - svn_merge_range_dup(new_range, result_pool); - sorted = (svn_sort_compare_ranges(&lastrange, - &new_range) < 0); - break; + svn_merge_range_t *r1 = svn_merge_range_dup(lastrange, + result_pool); + svn_merge_range_t *r2 = svn_merge_range_dup(new_range, + result_pool); - case svn__equal_intersection: - /* They range are equal so all we do is force the - inheritability of lastrange to true. */ - lastrange->inheritable = TRUE; - sorted = TRUE; - break; + /* Pop off *LASTRANGE to make our manipulations + easier. */ + apr_array_pop(rangelist); - case svn__adjoining_intersection: - /* They adjoin but don't overlap so just push NEW_RANGE - onto RANGELIST. */ - APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = - svn_merge_range_dup(new_range, result_pool); - sorted = (svn_sort_compare_ranges(&lastrange, - &new_range) < 0); - break; - - case svn__overlapping_intersection: - /* They ranges overlap but neither is a proper subset of - the other. We'll end up pusing two new ranges onto - RANGELIST, the intersecting part and the part unique to - NEW_RANGE.*/ + /* Ensure R1 is the older range. */ + if (r2->start < r1->start) { - svn_merge_range_t *r1 = svn_merge_range_dup(lastrange, - result_pool); - svn_merge_range_t *r2 = svn_merge_range_dup(new_range, - result_pool); + /* Swap R1 and R2. */ + *r2 = *r1; + *r1 = *new_range; + } - /* Pop off *LASTRANGE to make our manipulations - easier. */ - apr_array_pop(rangelist); + /* Absorb the intersecting ranges into the + inheritable range. */ + if (r1->inheritable) + r2->start = r1->end; + else + r1->end = r2->start; - /* Ensure R1 is the older range. */ - if (r2->start < r1->start) - { - /* Swap R1 and R2. */ - *r2 = *r1; - *r1 = *new_range; - } + /* Push everything back onto RANGELIST. */ + APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = r1; + sorted = (svn_sort_compare_ranges(&lastrange, + &r1) < 0); + APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = r2; + if (sorted) + sorted = (svn_sort_compare_ranges(&r1, &r2) < 0); + break; + } - /* Absorb the intersecting ranges into the - inheritable range. */ - if (r1->inheritable) - r2->start = r1->end; - else - r1->end = r2->start; + default: /* svn__proper_subset_intersection */ + { + /* One range is a proper subset of the other. */ + svn_merge_range_t *r1 = svn_merge_range_dup(lastrange, + result_pool); + svn_merge_range_t *r2 = svn_merge_range_dup(new_range, + result_pool); + svn_merge_range_t *r3 = NULL; - /* Push everything back onto RANGELIST. */ - APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = r1; - sorted = (svn_sort_compare_ranges(&lastrange, - &r1) < 0); + /* Pop off *LASTRANGE to make our manipulations + easier. */ + apr_array_pop(rangelist); + + /* Ensure R1 is the superset. */ + if (r2->start < r1->start || r2->end > r1->end) + { + /* Swap R1 and R2. */ + *r2 = *r1; + *r1 = *new_range; + } + + if (r1->inheritable) + { + /* The simple case: The superset is inheritable, so + just combine r1 and r2. */ + r1->start = MIN(r1->start, r2->start); + r1->end = MAX(r1->end, r2->end); + r2 = NULL; + } + else if (r1->start == r2->start) + { + svn_revnum_t tmp_revnum; + + /* *LASTRANGE and NEW_RANGE share an end point. */ + tmp_revnum = r1->end; + r1->end = r2->end; + r2->inheritable = r1->inheritable; + r1->inheritable = TRUE; + r2->start = r1->end; + r2->end = tmp_revnum; + } + else if (r1->end == r2->end) + { + /* *LASTRANGE and NEW_RANGE share an end point. */ + r1->end = r2->start; + r2->inheritable = TRUE; + } + else + { + /* NEW_RANGE and *LASTRANGE share neither start + nor end points. */ + r3 = apr_pcalloc(result_pool, sizeof(*r3)); + r3->start = r2->end; + r3->end = r1->end; + r3->inheritable = r1->inheritable; + r2->inheritable = TRUE; + r1->end = r2->start; + } + + /* Push everything back onto RANGELIST. */ + APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = r1; + sorted = (svn_sort_compare_ranges(&lastrange, &r1) < 0); + if (r2) + { APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = r2; if (sorted) sorted = (svn_sort_compare_ranges(&r1, &r2) < 0); - break; } - - default: /* svn__proper_subset_intersection */ + if (r3) { - /* One range is a proper subset of the other. */ - svn_merge_range_t *r1 = svn_merge_range_dup(lastrange, - result_pool); - svn_merge_range_t *r2 = svn_merge_range_dup(new_range, - result_pool); - svn_merge_range_t *r3 = NULL; - - /* Pop off *LASTRANGE to make our manipulations - easier. */ - apr_array_pop(rangelist); - - /* Ensure R1 is the superset. */ - if (r2->start < r1->start || r2->end > r1->end) + APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = r3; + if (sorted) { - /* Swap R1 and R2. */ - *r2 = *r1; - *r1 = *new_range; + if (r2) + sorted = (svn_sort_compare_ranges(&r2, + &r3) < 0); + else + sorted = (svn_sort_compare_ranges(&r1, + &r3) < 0); } - - if (r1->inheritable) - { - /* The simple case: The superset is inheritable, so - just combine r1 and r2. */ - r1->start = MIN(r1->start, r2->start); - r1->end = MAX(r1->end, r2->end); - r2 = NULL; - } - else if (r1->start == r2->start) - { - svn_revnum_t tmp_revnum; - - /* *LASTRANGE and NEW_RANGE share an end point. */ - tmp_revnum = r1->end; - r1->end = r2->end; - r2->inheritable = r1->inheritable; - r1->inheritable = TRUE; - r2->start = r1->end; - r2->end = tmp_revnum; - } - else if (r1->end == r2->end) - { - /* *LASTRANGE and NEW_RANGE share an end point. */ - r1->end = r2->start; - r2->inheritable = TRUE; - } - else - { - /* NEW_RANGE and *LASTRANGE share neither start - nor end points. */ - r3 = apr_pcalloc(result_pool, sizeof(*r3)); - r3->start = r2->end; - r3->end = r1->end; - r3->inheritable = r1->inheritable; - r2->inheritable = TRUE; - r1->end = r2->start; - } - - /* Push everything back onto RANGELIST. */ - APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = r1; - sorted = (svn_sort_compare_ranges(&lastrange, &r1) < 0); - if (r2) - { - APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = r2; - if (sorted) - sorted = (svn_sort_compare_ranges(&r1, &r2) < 0); - } - if (r3) - { - APR_ARRAY_PUSH(rangelist, svn_merge_range_t *) = r3; - if (sorted) - { - if (r2) - sorted = (svn_sort_compare_ranges(&r2, - &r3) < 0); - else - sorted = (svn_sort_compare_ranges(&r1, - &r3) < 0); - } - } - break; } + break; } - - /* Some of the above cases might have put *RANGELIST out of - order, so re-sort.*/ - if (!sorted) - svn_sort__array(rangelist, svn_sort_compare_ranges); } + + /* Some of the above cases might have put *RANGELIST out of + order, so re-sort.*/ + if (!sorted) + svn_sort__array(rangelist, svn_sort_compare_ranges); } return SVN_NO_ERROR; @@ -608,49 +605,48 @@ svn_rangelist__parse(svn_rangelist_t **rangelist, return SVN_NO_ERROR; } -/* Return TRUE, if all ranges in RANGELIST are in ascending order and do - * not overlap and are not adjacent. - * - * ### Can yield false negatives: ranges of differing inheritance are - * allowed to be adjacent. - * - * If this returns FALSE, you probaly want to qsort() the - * ranges and then call svn_rangelist__combine_adjacent_ranges(). - */ -static svn_boolean_t -is_rangelist_normalized(svn_rangelist_t *rangelist) +svn_boolean_t +svn_rangelist__is_canonical(const svn_rangelist_t *rangelist) { int i; svn_merge_range_t **ranges = (svn_merge_range_t **)rangelist->elts; - for (i = 0; i < rangelist->nelts-1; ++i) - if (ranges[i]->end >= ranges[i+1]->start) - return FALSE; + /* Check for reversed and empty ranges */ + for (i = 0; i < rangelist->nelts; ++i) + { + if (ranges[i]->start >= ranges[i]->end) + return FALSE; + } + + /* Check for overlapping ranges */ + for (i = 0; i < rangelist->nelts - 1; ++i) + { + if (ranges[i]->end > ranges[i + 1]->start) + return FALSE; /* Overlapping range */ + else if (ranges[i]->end == ranges[i+1]->start + && ranges[i]->inheritable == ranges[i + 1]->inheritable) + { + return FALSE; /* Ranges should have been combined */ + } + } return TRUE; } +/* In-place combines adjacent ranges in a rangelist. + SCRATCH_POOL is just used for providing error messages. */ svn_error_t * svn_rangelist__canonicalize(svn_rangelist_t *rangelist, apr_pool_t *scratch_pool) -{ - if (! is_rangelist_normalized(rangelist)) - { - svn_sort__array(rangelist, svn_sort_compare_ranges); - - SVN_ERR(svn_rangelist__combine_adjacent_ranges(rangelist, scratch_pool)); - } - - return SVN_NO_ERROR; -} - -svn_error_t * -svn_rangelist__combine_adjacent_ranges(svn_rangelist_t *rangelist, - apr_pool_t *scratch_pool) { int i; svn_merge_range_t *range, *lastrange; + if (svn_rangelist__is_canonical(rangelist)) + return SVN_NO_ERROR; /* Nothing to do */ + + svn_sort__array(rangelist, svn_sort_compare_ranges); + lastrange = APR_ARRAY_IDX(rangelist, 0, svn_merge_range_t *); for (i = 1; i < rangelist->nelts; i++) @@ -895,7 +891,7 @@ adjust_remaining_ranges(svn_rangelist_t *rangelist, new_modified_range->end = modified_range->end; new_modified_range->inheritable = FALSE; modified_range->end = next_range->start; - (*range_index)+=2; + (*range_index) += 2 + elements_to_delete; svn_sort__array_insert(rangelist, &new_modified_range, *range_index); /* Recurse with the new range. */ @@ -955,25 +951,99 @@ adjust_remaining_ranges(svn_rangelist_t *rangelist, svn_sort__array_delete(rangelist, starting_index, elements_to_delete); } +#if 0 /* Temporary debug helper code */ +static svn_error_t * +dual_dump(const char *prefix, + const svn_rangelist_t *rangelist, + const svn_rangelist_t *changes, + apr_pool_t *scratch_pool) +{ + svn_string_t *rls, *chg; + + SVN_ERR(svn_rangelist_to_string(&rls, rangelist, scratch_pool)); + SVN_ERR(svn_rangelist_to_string(&chg, changes, scratch_pool)); + + SVN_DBG(("%s: %s / %s", prefix, rls->data, chg->data)); + return SVN_NO_ERROR; +} +#endif + svn_error_t * svn_rangelist_merge2(svn_rangelist_t *rangelist, - const svn_rangelist_t *changes, + const svn_rangelist_t *chg, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { + svn_rangelist_t *changes; int i = 0; - int j = 0; + int j; + + SVN_ERR(svn_rangelist__canonicalize(rangelist, scratch_pool)); /* We may modify CHANGES, so make a copy in SCRATCH_POOL. */ - changes = svn_rangelist_dup(changes, scratch_pool); + changes = svn_rangelist_dup(chg, scratch_pool); + SVN_ERR(svn_rangelist__canonicalize(changes, scratch_pool)); - while (i < rangelist->nelts && j < changes->nelts) + for (j = 0; j < changes->nelts; j++) { - svn_merge_range_t *range = - APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *); + svn_merge_range_t *range; svn_merge_range_t *change = APR_ARRAY_IDX(changes, j, svn_merge_range_t *); - int res = svn_sort_compare_ranges(&range, &change); + int res; + + range = (i < rangelist->nelts) + ? APR_ARRAY_IDX(rangelist, i, svn_merge_range_t *) + : NULL; + + if (!range || change->end < range->start) + { + /* No overlap, nor adjoin, copy change to result range */ + svn_merge_range_t *chg_copy = svn_merge_range_dup(change, + result_pool); + svn_sort__array_insert(rangelist, &chg_copy, i++); + continue; + } + else if ((change->start > range->end) + || (change->start == range->end + && change->inheritable != range->inheritable)) + { + /* No overlap, nor adjoin. Check next range item against change */ + i++; + j--; + continue; + } + + if (change->start < range->start + && range->inheritable != change->inheritable + && ! (change->inheritable && range_contains(change, range, FALSE)) + && ! (range->inheritable && range_contains(range, change, FALSE))) + { + /* Can't fold change into existing range. + Insert new range before range */ + + svn_merge_range_t *chg_copy = svn_merge_range_dup(change, + result_pool); + + chg_copy->start = MIN(change->start, range->start); + if (! change->inheritable) + chg_copy->end = range->start; + else + range->start = change->end; + + svn_sort__array_insert(rangelist, &chg_copy, i++); + + change->start = chg_copy->end; + if (change->start >= change->end) + continue; /* No overlap with range left */ + } + else + { + range->start = MIN(range->start, change->start); + } + + SVN_ERR_ASSERT(change->start >= range->start); + + res = svn_sort_compare_ranges(&range, &change); if (res == 0) { @@ -983,17 +1053,11 @@ svn_rangelist_merge2(svn_rangelist_t *rangelist, if (range->inheritable || change->inheritable) range->inheritable = TRUE; i++; - j++; + continue; } else if (res < 0) /* CHANGE is younger than RANGE */ { - if (range->end < change->start) - { - /* RANGE is older than CHANGE and the two do not - adjoin or overlap */ - i++; - } - else if (range->end == change->start) + if (range->end == change->start) { /* RANGE and CHANGE adjoin */ if (range->inheritable == change->inheritable) @@ -1002,14 +1066,14 @@ svn_rangelist_merge2(svn_rangelist_t *rangelist, RANGE expands to absord CHANGE. */ range->end = change->end; adjust_remaining_ranges(rangelist, &i, result_pool); - j++; + continue; } else { /* RANGE and CHANGE adjoin, but have different inheritability. Since RANGE is older, just move on to the next RANGE. */ - i++; + SVN_ERR_MALFUNCTION(); } } else @@ -1022,9 +1086,13 @@ svn_rangelist_merge2(svn_rangelist_t *rangelist, with no adjustment otherwise only the intersection is absorbed and CHANGE is truncated. */ if (range->end >= change->end) - j++; + continue; else - change->start = range->end; + { + change->start = range->end; + j--; + continue; + } } else { @@ -1038,6 +1106,8 @@ svn_rangelist_merge2(svn_rangelist_t *rangelist, range_copy->end = change->start; range->start = change->start; svn_sort__array_insert(rangelist, &range_copy, i++); + j--; + continue; } else { @@ -1046,23 +1116,15 @@ svn_rangelist_merge2(svn_rangelist_t *rangelist, is older. */ range->inheritable = TRUE; change->start = range->end; + j--; + continue; } } } } else /* res > 0, CHANGE is older than RANGE */ { - if (change->end < range->start) - { - /* CHANGE is older than RANGE and the two do not - adjoin or overlap, so insert a copy of CHANGE - into RANGELIST. */ - svn_merge_range_t *change_copy = - svn_merge_range_dup(change, result_pool); - svn_sort__array_insert(rangelist, &change_copy, i++); - j++; - } - else if (change->end == range->start) + if (change->end == range->start) { /* RANGE and CHANGE adjoin */ if (range->inheritable == change->inheritable) @@ -1070,16 +1132,13 @@ svn_rangelist_merge2(svn_rangelist_t *rangelist, /* RANGE and CHANGE have the same inheritability so we can simply combine the two in place. */ range->start = change->start; - j++; + continue; } else { /* RANGE and CHANGE have different inheritability so insert a copy of CHANGE into RANGELIST. */ - svn_merge_range_t *change_copy = - svn_merge_range_dup(change, result_pool); - svn_sort__array_insert(rangelist, &change_copy, i); - j++; + SVN_ERR_MALFUNCTION(); /* Already handled */ } } else @@ -1097,7 +1156,7 @@ svn_rangelist_merge2(svn_rangelist_t *rangelist, range->end = change->end; adjust_remaining_ranges(rangelist, &i, result_pool); } - j++; + continue; } else if (range->inheritable) { @@ -1106,18 +1165,14 @@ svn_rangelist_merge2(svn_rangelist_t *rangelist, /* RANGE is inheritable so absorbs any part of CHANGE it overlaps. CHANGE is truncated and the remainder inserted into RANGELIST. */ - svn_merge_range_t *change_copy = - svn_merge_range_dup(change, result_pool); - change_copy->end = range->start; - change->start = range->start; - svn_sort__array_insert(rangelist, &change_copy, i++); + SVN_ERR_MALFUNCTION(); /* Already handled */ } else { /* CHANGE and RANGE share the same start rev, but CHANGE is considered older because CHANGE->END is older than RANGE->END. */ - j++; + continue; } } else @@ -1131,7 +1186,7 @@ svn_rangelist_merge2(svn_rangelist_t *rangelist, same end revision, so set RANGE equal to CHANGE. */ range->start = change->start; range->inheritable = TRUE; - j++; + continue; } else if (change->end > range->end) { @@ -1141,6 +1196,8 @@ svn_rangelist_merge2(svn_rangelist_t *rangelist, range->start = change->start; range->inheritable = TRUE; change->start = range->end; + j--; + continue; } else { @@ -1154,7 +1211,7 @@ svn_rangelist_merge2(svn_rangelist_t *rangelist, range->end = change->end; range->inheritable = TRUE; svn_sort__array_insert(rangelist, &range_copy, ++i); - j++; + continue; } } else @@ -1172,22 +1229,17 @@ svn_rangelist_merge2(svn_rangelist_t *rangelist, range_copy->inheritable = TRUE; range->start = change->end; svn_sort__array_insert(rangelist, &range_copy, i++); - j++; + continue; } } } } + SVN_ERR_MALFUNCTION(); /* Unreachable */ } - /* Copy any remaining elements in CHANGES into RANGELIST. */ - for (; j < (changes)->nelts; j++) - { - svn_merge_range_t *change = - APR_ARRAY_IDX(changes, j, svn_merge_range_t *); - svn_merge_range_t *change_copy = svn_merge_range_dup(change, - result_pool); - svn_sort__array_insert(rangelist, &change_copy, rangelist->nelts); - } +#ifdef SVN_DEBUG + SVN_ERR_ASSERT(svn_rangelist__is_canonical(rangelist)); +#endif return SVN_NO_ERROR; } @@ -2306,8 +2358,7 @@ svn_rangelist_dup(const svn_rangelist_t *rangelist, apr_pool_t *pool) svn_merge_range_t * svn_merge_range_dup(const svn_merge_range_t *range, apr_pool_t *pool) { - svn_merge_range_t *new_range = apr_palloc(pool, sizeof(*new_range)); - memcpy(new_range, range, sizeof(*new_range)); + svn_merge_range_t *new_range = apr_pmemdup(pool, range, sizeof(*new_range)); return new_range; } @@ -2360,7 +2411,7 @@ svn_mergeinfo__catalog_to_formatted_string(svn_string_t **output, svn_stringbuf_appendcstr(output_buf, "\n"); } } -#if SVN_DEBUG +#ifdef SVN_DEBUG else if (!catalog) { output_buf = svn_stringbuf_create(key_prefix ? key_prefix : "", pool); diff --git a/subversion/libsvn_subr/mutex.c b/subversion/libsvn_subr/mutex.c index 3c348dfedaaa..44e9addbd43e 100644 --- a/subversion/libsvn_subr/mutex.c +++ b/subversion/libsvn_subr/mutex.c @@ -105,3 +105,13 @@ svn_mutex__unlock(svn_mutex__t *mutex, return err; } + +#if APR_HAS_THREADS + +apr_thread_mutex_t * +svn_mutex__get(svn_mutex__t *mutex) +{ + return mutex->mutex; +} + +#endif diff --git a/subversion/libsvn_subr/object_pool.c b/subversion/libsvn_subr/object_pool.c index 782ffa27fa89..0f41feaf4b04 100644 --- a/subversion/libsvn_subr/object_pool.c +++ b/subversion/libsvn_subr/object_pool.c @@ -1,5 +1,5 @@ /* - * config_pool.c : pool of configuration objects + * object_pool.c : generic pool of reference-counted objects * * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one @@ -49,7 +49,7 @@ typedef struct object_ref_t svn_membuf_t key; /* User provided object. Usually a wrapper. */ - void *wrapper; + void *object; /* private pool. This instance and its other members got allocated in it. * Will be destroyed when this instance is cleaned up. */ @@ -85,10 +85,6 @@ struct svn_object_pool__t /* the root pool owning this structure */ apr_pool_t *pool; - - /* extractor and updater for the user object wrappers */ - svn_object_pool__getter_t getter; - svn_object_pool__setter_t setter; }; @@ -176,9 +172,11 @@ add_object_ref(object_ref_t *object_ref, if (svn_atomic_inc(&object_ref->ref_count) == 0) svn_atomic_dec(&object_ref->object_pool->unused_count); - /* make sure the reference gets released automatically */ - apr_pool_cleanup_register(pool, object_ref, object_ref_cleanup, - apr_pool_cleanup_null); + /* Make sure the reference gets released automatically. + Since POOL might be a parent pool of OBJECT_REF->OBJECT_POOL, + to the reference counting update before destroing any of the + pool hierarchy. */ + apr_pool_pre_cleanup_register(pool, object_ref, object_ref_cleanup); } /* Actual implementation of svn_object_pool__lookup. @@ -189,7 +187,6 @@ static svn_error_t * lookup(void **object, svn_object_pool__t *object_pool, svn_membuf_t *key, - void *baton, apr_pool_t *result_pool) { object_ref_t *object_ref @@ -197,7 +194,7 @@ lookup(void **object, if (object_ref) { - *object = object_pool->getter(object_ref->wrapper, baton, result_pool); + *object = object_ref->object; add_object_ref(object_ref, result_pool); } else @@ -216,57 +213,28 @@ static svn_error_t * insert(void **object, svn_object_pool__t *object_pool, const svn_membuf_t *key, - void *wrapper, - void *baton, - apr_pool_t *wrapper_pool, + void *item, + apr_pool_t *item_pool, apr_pool_t *result_pool) { object_ref_t *object_ref = apr_hash_get(object_pool->objects, key->data, key->size); if (object_ref) { - /* entry already exists (e.g. race condition) */ - svn_error_t *err = object_pool->setter(&object_ref->wrapper, - wrapper, baton, - object_ref->pool); - if (err) - { - /* if we had an issue in the setter, then OBJECT_REF is in an - * unknown state now. Keep it around for the current users - * (i.e. don't clean the pool) but remove it from the list of - * available ones. - */ - apr_hash_set(object_pool->objects, key->data, key->size, NULL); - svn_atomic_dec(&object_pool->object_count); - - /* for the unlikely case that the object got created _and_ - * already released since we last checked: */ - if (svn_atomic_read(&object_ref->ref_count) == 0) - svn_atomic_dec(&object_pool->unused_count); - - /* cleanup the new data as well because it's not safe to use - * either. - */ - svn_pool_destroy(wrapper_pool); - - /* propagate error */ - return svn_error_trace(err); - } - /* Destroy the new one and return a reference to the existing one * because the existing one may already have references on it. */ - svn_pool_destroy(wrapper_pool); + svn_pool_destroy(item_pool); } else { /* add new index entry */ - object_ref = apr_pcalloc(wrapper_pool, sizeof(*object_ref)); + object_ref = apr_pcalloc(item_pool, sizeof(*object_ref)); object_ref->object_pool = object_pool; - object_ref->wrapper = wrapper; - object_ref->pool = wrapper_pool; + object_ref->object = item; + object_ref->pool = item_pool; - svn_membuf__create(&object_ref->key, key->size, wrapper_pool); + svn_membuf__create(&object_ref->key, key->size, item_pool); object_ref->key.size = key->size; memcpy(object_ref->key.data, key->data, key->size); @@ -281,7 +249,7 @@ insert(void **object, } /* return a reference to the object we just added */ - *object = object_pool->getter(object_ref->wrapper, baton, result_pool); + *object = object_ref->object; add_object_ref(object_ref, result_pool); /* limit memory usage */ @@ -292,34 +260,11 @@ insert(void **object, return SVN_NO_ERROR; } -/* Implement svn_object_pool__getter_t as no-op. - */ -static void * -default_getter(void *object, - void *baton, - apr_pool_t *pool) -{ - return object; -} - -/* Implement svn_object_pool__setter_t as no-op. - */ -static svn_error_t * -default_setter(void **target, - void *source, - void *baton, - apr_pool_t *pool) -{ - return SVN_NO_ERROR; -} - /* API implementation */ svn_error_t * svn_object_pool__create(svn_object_pool__t **object_pool, - svn_object_pool__getter_t getter, - svn_object_pool__setter_t setter, svn_boolean_t thread_safe, apr_pool_t *pool) { @@ -333,8 +278,6 @@ svn_object_pool__create(svn_object_pool__t **object_pool, result->pool = pool; result->objects = svn_hash__make(result->pool); - result->getter = getter ? getter : default_getter; - result->setter = setter ? setter : default_setter; /* make sure we clean up nicely. * We need two cleanup functions of which exactly one will be run @@ -351,33 +294,20 @@ svn_object_pool__create(svn_object_pool__t **object_pool, } apr_pool_t * -svn_object_pool__new_wrapper_pool(svn_object_pool__t *object_pool) +svn_object_pool__new_item_pool(svn_object_pool__t *object_pool) { return svn_pool_create(object_pool->pool); } -svn_mutex__t * -svn_object_pool__mutex(svn_object_pool__t *object_pool) -{ - return object_pool->mutex; -} - -unsigned -svn_object_pool__count(svn_object_pool__t *object_pool) -{ - return svn_atomic_read(&object_pool->object_count); -} - svn_error_t * svn_object_pool__lookup(void **object, svn_object_pool__t *object_pool, svn_membuf_t *key, - void *baton, apr_pool_t *result_pool) { *object = NULL; SVN_MUTEX__WITH_LOCK(object_pool->mutex, - lookup(object, object_pool, key, baton, result_pool)); + lookup(object, object_pool, key, result_pool)); return SVN_NO_ERROR; } @@ -385,14 +315,13 @@ svn_error_t * svn_object_pool__insert(void **object, svn_object_pool__t *object_pool, const svn_membuf_t *key, - void *wrapper, - void *baton, - apr_pool_t *wrapper_pool, + void *item, + apr_pool_t *item_pool, apr_pool_t *result_pool) { *object = NULL; SVN_MUTEX__WITH_LOCK(object_pool->mutex, - insert(object, object_pool, key, wrapper, baton, - wrapper_pool, result_pool)); + insert(object, object_pool, key, item, + item_pool, result_pool)); return SVN_NO_ERROR; } diff --git a/subversion/libsvn_subr/opt.c b/subversion/libsvn_subr/opt.c index 7b108e5a572a..fd8c73a273b2 100644 --- a/subversion/libsvn_subr/opt.c +++ b/subversion/libsvn_subr/opt.c @@ -350,6 +350,38 @@ print_command_info2(const svn_opt_subcommand_desc2_t *cmd, return SVN_NO_ERROR; } +/* The body for svn_opt_print_generic_help2() function with standard error + * handling semantic. Handling of errors implemented at caller side. */ +static svn_error_t * +print_generic_help_body(const char *header, + const svn_opt_subcommand_desc2_t *cmd_table, + const apr_getopt_option_t *opt_table, + const char *footer, + apr_pool_t *pool, FILE *stream) +{ + int i = 0; + + if (header) + SVN_ERR(svn_cmdline_fputs(header, stream, pool)); + + while (cmd_table[i].name) + { + SVN_ERR(svn_cmdline_fputs(" ", stream, pool)); + SVN_ERR(print_command_info2(cmd_table + i, opt_table, + NULL, FALSE, + pool, stream)); + SVN_ERR(svn_cmdline_fputs("\n", stream, pool)); + i++; + } + + SVN_ERR(svn_cmdline_fputs("\n", stream, pool)); + + if (footer) + SVN_ERR(svn_cmdline_fputs(footer, stream, pool)); + + return SVN_NO_ERROR; +} + void svn_opt_print_generic_help2(const char *header, const svn_opt_subcommand_desc2_t *cmd_table, @@ -357,34 +389,11 @@ svn_opt_print_generic_help2(const char *header, const char *footer, apr_pool_t *pool, FILE *stream) { - int i = 0; svn_error_t *err; - if (header) - if ((err = svn_cmdline_fputs(header, stream, pool))) - goto print_error; + err = print_generic_help_body(header, cmd_table, opt_table, footer, pool, + stream); - while (cmd_table[i].name) - { - if ((err = svn_cmdline_fputs(" ", stream, pool)) - || (err = print_command_info2(cmd_table + i, opt_table, - NULL, FALSE, - pool, stream)) - || (err = svn_cmdline_fputs("\n", stream, pool))) - goto print_error; - i++; - } - - if ((err = svn_cmdline_fputs("\n", stream, pool))) - goto print_error; - - if (footer) - if ((err = svn_cmdline_fputs(footer, stream, pool))) - goto print_error; - - return; - - print_error: /* Issue #3014: * Don't print anything on broken pipes. The pipe was likely * closed by the process at the other end. We expect that @@ -392,7 +401,7 @@ svn_opt_print_generic_help2(const char *header, * * ### This assumes that there is only one error in a chain for * ### SVN_ERR_IO_PIPE_WRITE_ERROR. See svn_cmdline_fputs(). */ - if (err->apr_err != SVN_ERR_IO_PIPE_WRITE_ERROR) + if (err && err->apr_err != SVN_ERR_IO_PIPE_WRITE_ERROR) svn_handle_error2(err, stderr, FALSE, "svn: "); svn_error_clear(err); } diff --git a/subversion/libsvn_subr/packed_data.c b/subversion/libsvn_subr/packed_data.c index 27651ff9a0ad..88c66e6bb421 100644 --- a/subversion/libsvn_subr/packed_data.c +++ b/subversion/libsvn_subr/packed_data.c @@ -308,7 +308,7 @@ unmap_uint(apr_uint64_t value) * are no sub-streams). */ static void -svn_packed__data_flush_buffer(svn_packed__int_stream_t *stream) +data_flush_buffer(svn_packed__int_stream_t *stream) { packed_int_private_t *private_data = stream->private_data; apr_size_t i; @@ -382,7 +382,7 @@ svn_packed__add_uint(svn_packed__int_stream_t *stream, { stream->buffer[stream->buffer_used] = value; if (++stream->buffer_used == SVN__PACKED_DATA_BUFFER_SIZE) - svn_packed__data_flush_buffer(stream); + data_flush_buffer(stream); } void @@ -435,7 +435,7 @@ write_int_stream_structure(svn_stringbuf_t* tree_struct, + (private_data->is_signed ? 2 : 0)); /* store item count and length their of packed representation */ - svn_packed__data_flush_buffer(stream); + data_flush_buffer(stream); write_packed_uint(tree_struct, private_data->item_count); write_packed_uint(tree_struct, private_data->packed @@ -561,9 +561,9 @@ write_stream_data(svn_stream_t *stream, svn_stringbuf_t *uncompressed, svn_stringbuf_t *compressed) { - SVN_ERR(svn__compress(uncompressed, - compressed, - SVN_DELTA_COMPRESSION_LEVEL_DEFAULT)); + SVN_ERR(svn__compress_zlib(uncompressed->data, uncompressed->len, + compressed, + SVN_DELTA_COMPRESSION_LEVEL_DEFAULT)); SVN_ERR(write_stream_uint(stream, compressed->len)); SVN_ERR(svn_stream_write(stream, compressed->data, &compressed->len)); @@ -676,6 +676,12 @@ svn_packed__byte_count(svn_packed__byte_stream_t *stream) return stream->packed->len; } +apr_size_t +svn_packed__byte_block_count(svn_packed__byte_stream_t *stream) +{ + return svn_packed__int_count(stream->lengths_stream); +} + /* Read one 7b/8b encoded value from *P and return it in *RESULT. Returns * the first position after the parsed data. * @@ -972,7 +978,8 @@ read_stream_data(svn_stream_t *stream, SVN_ERR(svn_stream_read_full(stream, compressed->data, &compressed->len)); compressed->data[compressed_len] = '\0'; - SVN_ERR(svn__decompress(compressed, uncompressed, uncompressed_len)); + SVN_ERR(svn__decompress_zlib(compressed->data, compressed->len, + uncompressed, uncompressed_len)); return SVN_NO_ERROR; } diff --git a/subversion/libsvn_subr/path.c b/subversion/libsvn_subr/path.c index aaeee757a270..50a67debb0cd 100644 --- a/subversion/libsvn_subr/path.c +++ b/subversion/libsvn_subr/path.c @@ -506,7 +506,7 @@ get_path_ancestor_length(const char *path1, else if (last_dirsep == 0 && path1[0] == '/' && path2[0] == '/') return 1; - return last_dirsep; + return last_dirsep; } @@ -910,9 +910,24 @@ uri_escape(const char *path, const char table[], apr_pool_t *pool) svn_stringbuf_t *retstr; apr_size_t i, copied = 0; int c; + apr_size_t len; + const char *p; - retstr = svn_stringbuf_create_ensure(strlen(path), pool); - for (i = 0; path[i]; i++) + /* To terminate our scanning loop, table[NUL] must report "invalid". */ + assert(table[0] == 0); + + /* Quick check: Does any character need escaping? */ + for (p = path; table[(unsigned char)*p]; ++p) + {} + + /* No char to escape before EOS? */ + if (*p == '\0') + return path; + + /* We need to escape at least one character. */ + len = strlen(p) + (p - path); + retstr = svn_stringbuf_create_ensure(len, pool); + for (i = p - path; i < len; i++) { c = (unsigned char)path[i]; if (table[c]) @@ -941,10 +956,6 @@ uri_escape(const char *path, const char table[], apr_pool_t *pool) copied = i + 1; } - /* If we didn't encode anything, we don't need to duplicate the string. */ - if (retstr->len == 0) - return path; - /* Anything left to copy? */ if (i - copied) svn_stringbuf_appendbytes(retstr, path + copied, i - copied); @@ -971,7 +982,7 @@ svn_path_uri_encode(const char *path, apr_pool_t *pool) } static const char iri_escape_chars[256] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -998,7 +1009,7 @@ svn_path_uri_from_iri(const char *iri, apr_pool_t *pool) } static const char uri_autoescape_chars[256] = { - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, diff --git a/subversion/libsvn_subr/pool.c b/subversion/libsvn_subr/pool.c index db57a6e9f981..5fd80a7a83cc 100644 --- a/subversion/libsvn_subr/pool.c +++ b/subversion/libsvn_subr/pool.c @@ -26,12 +26,14 @@ #include #include +#include +#include #include #include -#include #include "svn_pools.h" +#include "pools.h" #if APR_POOL_DEBUG /* file_line for the non-debug case. */ @@ -52,6 +54,13 @@ abort_on_pool_failure(int retcode) /* Don't translate this string! It requires memory allocation to do so! And we don't have any of it... */ printf("libsvn: Out of memory - terminating application.\n"); + +#ifdef WIN32 + /* Provide a way to distinguish the out-of-memory error from abort(). */ + if (retcode == APR_ENOMEM) + RaiseException(STATUS_NO_MEMORY, EXCEPTION_NONCONTINUABLE, 0, NULL); +#endif + abort(); return 0; /* not reached */ } @@ -140,3 +149,24 @@ svn_pool_create_allocator(svn_boolean_t thread_safe) return allocator; } + + +/* + * apr_pool_create_core_ex was introduced in APR 1.3.0, then + * deprecated and renamed to apr_pool_create_unmanaged_ex in 1.3.3. + * Since our minimum requirement is APR 1.3.0, one or the other of + * these functions will always be available. + */ +#if !APR_VERSION_AT_LEAST(1,3,3) +#define apr_pool_create_unmanaged_ex apr_pool_create_core_ex +#endif + +/* Private function that creates an unmanaged pool. */ +apr_pool_t * +svn_pool__create_unmanaged(svn_boolean_t thread_safe) +{ + apr_pool_t *pool; + apr_pool_create_unmanaged_ex(&pool, abort_on_pool_failure, + svn_pool_create_allocator(thread_safe)); + return pool; +} diff --git a/subversion/libsvn_delta/debug_editor.h b/subversion/libsvn_subr/pools.h similarity index 57% rename from subversion/libsvn_delta/debug_editor.h rename to subversion/libsvn_subr/pools.h index 63c90d32fb12..903dff009171 100644 --- a/subversion/libsvn_delta/debug_editor.h +++ b/subversion/libsvn_subr/pools.h @@ -1,4 +1,6 @@ /* + * pools.h: private pool functions + * * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -19,36 +21,23 @@ * ==================================================================== */ - -#ifndef SVN_DEBUG_EDITOR_H -#define SVN_DEBUG_EDITOR_H +#ifndef SVN_LIBSVN_SUBR_POOLS_H +#define SVN_LIBSVN_SUBR_POOLS_H -#include "svn_delta.h" +#include "svn_pools.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -/* Return a debug editor that wraps @a wrapped_editor. - * - * The debug editor simply prints an indication of what callbacks are being - * called to @c stdout, and is only intended for use in debugging subversion - * editors. - * - * @a prefix, if non-null, is printed between "DBG: " and each indication. - * - * Note: Our test suite generally ignores stdout lines starting with "DBG:". - */ -svn_error_t * -svn_delta__get_debug_editor(const svn_delta_editor_t **editor, - void **edit_baton, - const svn_delta_editor_t *wrapped_editor, - void *wrapped_baton, - const char *prefix, - apr_pool_t *pool); +/* Create an unmanaged, global pool with a new allocator. + THREAD_SAFE indicates whether the pool's allocator should be + thread-safe or not. */ +apr_pool_t * +svn_pool__create_unmanaged(svn_boolean_t thread_safe); #ifdef __cplusplus } #endif /* __cplusplus */ -#endif /* SVN_DEBUG_EDITOR_H */ +#endif /* SVN_LIBSVN_SUBR_POOLS_H */ diff --git a/subversion/libsvn_subr/prefix_string.c b/subversion/libsvn_subr/prefix_string.c index fcf11bd2bf73..8e64ace1c338 100644 --- a/subversion/libsvn_subr/prefix_string.c +++ b/subversion/libsvn_subr/prefix_string.c @@ -49,7 +49,12 @@ struct svn_prefix_string__t /* mandatory prefix */ node_t *prefix; - /* 0 ..7 chars to add the the prefix. NUL-terminated. */ + /* 0 ..7 chars to add the prefix. + * + * NUL-terminated, if this is indeed a tree leaf. We use the same struct + * within node_t for inner tree nodes, too. There, DATA[7] is not NUL, + * meaning DATA may or may not be NUL terminated. The actual length is + * provided by the node_t.length field (minus parent node length). */ char data[8]; }; @@ -94,6 +99,12 @@ struct svn_prefix_tree__t static svn_boolean_t is_leaf(node_t *node) { + /* If this NOT a leaf node and this node has ... + * ... 8 chars, data[7] will not be NUL because we only support + * NUL-*terminated* strings. + * ... less than 8 chars, this will be set to 0xff + * (any other non-NUL would do as well but this is not valid UTF8 + * making it easy to recognize during debugging etc.) */ return node->key.data[7] == 0; } @@ -154,7 +165,7 @@ svn_prefix_tree__create(apr_pool_t *pool) tree->pool = pool; tree->root = apr_pcalloc(pool, sizeof(*tree->root)); - tree->root->key.data[7] = '\xff'; + tree->root->key.data[7] = '\xff'; /* This is not a leaf. See is_leaf(). */ return tree; } @@ -188,6 +199,7 @@ svn_prefix_string__create(svn_prefix_tree__t *tree, || node->sub_nodes[idx]->key.data[0] != s[node->length]) break; + /* Yes, it matches - at least the first character does. */ sub_node = node->sub_nodes[idx]; /* fully matching sub-node? */ @@ -198,6 +210,11 @@ svn_prefix_string__create(svn_prefix_tree__t *tree, } else { + /* The string formed by the path from the root down to + * SUB_NODE differs from S. + * + * Is it a prefix? In that case, the chars added by SUB_NODE + * must fully match the respective chars in S. */ apr_size_t sub_node_len = sub_node->length - node->length; if (strncmp(sub_node->key.data, s + node->length, sub_node_len) == 0) @@ -207,14 +224,24 @@ svn_prefix_string__create(svn_prefix_tree__t *tree, } } - /* partial match -> split */ + /* partial match -> split + * + * At this point, S may either be a prefix to the string represented + * by SUB_NODE, or they may diverge at some offset with + * SUB_NODE->KEY.DATA . + * + * MATCH starts with 1 here b/c we already know that at least one + * char matches. Also, the loop will terminate because the strings + * differ before SUB_NODE->KEY.DATA - either at the NUL terminator + * of S or some char before that. + */ while (sub_node->key.data[match] == s[node->length + match]) ++match; new_node = apr_pcalloc(tree->pool, sizeof(*new_node)); new_node->key = sub_node->key; new_node->length = node->length + match; - new_node->key.data[7] = '\xff'; + new_node->key.data[7] = '\xff'; /* This is not a leaf. See is_leaf(). */ new_node->sub_node_count = 1; new_node->sub_nodes = apr_palloc(tree->pool, sizeof(node_t *)); new_node->sub_nodes[0] = sub_node; @@ -228,7 +255,7 @@ svn_prefix_string__create(svn_prefix_tree__t *tree, } /* add sub-node(s) and final string */ - while (node->length + 7 < len) + while (len - node->length > 7) { new_node = apr_pcalloc(tree->pool, sizeof(*new_node)); new_node->key.prefix = node; diff --git a/subversion/libsvn_subr/prompt.c b/subversion/libsvn_subr/prompt.c index 8f24b424042a..086ff197f593 100644 --- a/subversion/libsvn_subr/prompt.c +++ b/subversion/libsvn_subr/prompt.c @@ -814,6 +814,8 @@ plaintext_prompt_helper(svn_boolean_t *may_save_plaintext, const char *config_path = NULL; terminal_handle_t *terminal; + *may_save_plaintext = FALSE; /* de facto API promise */ + if (pb) SVN_ERR(svn_config_get_user_config_path(&config_path, pb->config_dir, SVN_CONFIG_CATEGORY_SERVERS, pool)); @@ -826,17 +828,7 @@ plaintext_prompt_helper(svn_boolean_t *may_save_plaintext, do { - svn_error_t *err = prompt(&answer, prompt_string, FALSE, pb, pool); - if (err) - { - if (err->apr_err == SVN_ERR_CANCELLED) - { - *may_save_plaintext = FALSE; - return err; - } - else - return err; - } + SVN_ERR(prompt(&answer, prompt_string, FALSE, pb, pool)); if (apr_strnatcasecmp(answer, _("yes")) == 0 || apr_strnatcasecmp(answer, _("y")) == 0) { diff --git a/subversion/libsvn_subr/properties.c b/subversion/libsvn_subr/properties.c index 738d00f16682..4ccc5cd4b1ea 100644 --- a/subversion/libsvn_subr/properties.c +++ b/subversion/libsvn_subr/properties.c @@ -131,7 +131,6 @@ svn_boolean_t svn_prop_has_svn_prop(const apr_hash_t *props, apr_pool_t *pool) { apr_hash_index_t *hi; - const void *prop_name; if (! props) return FALSE; @@ -139,8 +138,9 @@ svn_prop_has_svn_prop(const apr_hash_t *props, apr_pool_t *pool) for (hi = apr_hash_first(pool, (apr_hash_t *)props); hi; hi = apr_hash_next(hi)) { - apr_hash_this(hi, &prop_name, NULL, NULL); - if (svn_prop_is_svn_prop((const char *) prop_name)) + const char *prop_name = apr_hash_this_key(hi); + + if (svn_prop_is_svn_prop(prop_name)) return TRUE; } diff --git a/subversion/libsvn_subr/skel.c b/subversion/libsvn_subr/skel.c index ed12db094ad0..567440a0504b 100644 --- a/subversion/libsvn_subr/skel.c +++ b/subversion/libsvn_subr/skel.c @@ -380,7 +380,7 @@ explicit_atom(const char *data, data++; /* Check the length. */ - if (data + size > end) + if (end - data < size) return NULL; /* Allocate the skel representing this string. */ diff --git a/subversion/libsvn_subr/sorts.c b/subversion/libsvn_subr/sorts.c index 06a4964e1a44..613c93b288a4 100644 --- a/subversion/libsvn_subr/sorts.c +++ b/subversion/libsvn_subr/sorts.c @@ -333,7 +333,7 @@ svn_sort__array_delete(apr_array_header_t *arr, if (delete_index >= 0 && delete_index < arr->nelts && elements_to_delete > 0 - && (elements_to_delete + delete_index) <= arr->nelts) + && (arr->nelts - delete_index) >= elements_to_delete) { /* If we are not deleting a block of elements that extends to the end of the array, then we need to move the remaining elements to keep diff --git a/subversion/libsvn_subr/spillbuf.c b/subversion/libsvn_subr/spillbuf.c index 6b8d15b587f4..c28780bab16d 100644 --- a/subversion/libsvn_subr/spillbuf.c +++ b/subversion/libsvn_subr/spillbuf.c @@ -242,7 +242,7 @@ svn_spillbuf__write(svn_spillbuf_t *buf, will grow too large. Create the file and place the pending data into the temporary file. */ if (buf->spill == NULL - && (buf->memory_size + len) > buf->maxsize) + && ((buf->maxsize - buf->memory_size) < len)) { SVN_ERR(svn_io_open_unique_file3(&buf->spill, &buf->filename, @@ -265,10 +265,10 @@ svn_spillbuf__write(svn_spillbuf_t *buf, /* Adjust the start offset for reading from the spill file. - ### FIXME: Instead, we should simply discard the memory - buffers; but currently some tests expect to read data in - the same chunk sizes as were written, so we'll leave this - change for later.*/ + This way, the first `buf->memory_size` bytes of data will + be read from the existing in-memory buffers, which makes + more sense than discarding the buffers and re-reading + data from the file. */ buf->spill_start = buf->memory_size; } } diff --git a/subversion/libsvn_subr/sqlite.c b/subversion/libsvn_subr/sqlite.c index 18124a3508e6..43c49e30cd23 100644 --- a/subversion/libsvn_subr/sqlite.c +++ b/subversion/libsvn_subr/sqlite.c @@ -65,8 +65,8 @@ extern int (*const svn_sqlite3__api_config)(int, ...); # include #endif -#if !SQLITE_VERSION_AT_LEAST(3,7,12) -#error SQLite is too old -- version 3.7.12 is the minimum required version +#if !SQLITE_VERSION_AT_LEAST(3,8,2) +#error SQLite is too old -- version 3.8.2 is the minimum required version #endif #ifndef SQLITE_DETERMINISTIC @@ -213,13 +213,6 @@ struct svn_sqlite__value_t sqlite_err__temp, msg); \ } while (0) -#define SVN_ERR_CLOSE(x, db) do \ -{ \ - svn_error_t *svn__err = (x); \ - if (svn__err) \ - return svn_error_compose_create(svn__err, svn_sqlite__close(db)); \ -} while (0) - /* Time (in milliseconds) to wait for sqlite locks before giving up. */ #define BUSY_TIMEOUT 10000 @@ -1141,7 +1134,7 @@ svn_sqlite__open(svn_sqlite__db_t **db, const char *path, sqlite3_profile((*db)->db3, sqlite_profiler, (*db)->db3); #endif - SVN_ERR_CLOSE(exec_sql(*db, + SVN_SQLITE__ERR_CLOSE(exec_sql(*db, /* The default behavior of the LIKE operator is to ignore case for ASCII characters. Hence, by default 'a' LIKE 'A' is true. The case_sensitive_like pragma installs a new application- @@ -1180,8 +1173,8 @@ svn_sqlite__open(svn_sqlite__db_t **db, const char *path, /* When running in debug mode, enable the checking of foreign key constraints. This has possible performance implications, so we don't bother to do it for production...for now. */ - SVN_ERR_CLOSE(exec_sql(*db, "PRAGMA foreign_keys=ON;"), - *db); + SVN_SQLITE__ERR_CLOSE(exec_sql(*db, "PRAGMA foreign_keys=ON;"), + *db); #endif #ifdef SVN_SQLITE_REVERSE_UNORDERED_SELECTS @@ -1189,8 +1182,8 @@ svn_sqlite__open(svn_sqlite__db_t **db, const char *path, clause to emit their results in the reverse order of what they normally would. This can help detecting invalid assumptions about the result order.*/ - SVN_ERR_CLOSE(exec_sql(*db, "PRAGMA reverse_unordered_selects=ON;"), - *db); + SVN_SQLITE__ERR_CLOSE(exec_sql(*db, "PRAGMA reverse_unordered_selects=ON;"), + *db); #endif /* Store temporary tables in RAM instead of in temporary files, but don't @@ -1303,8 +1296,7 @@ rollback_transaction(svn_sqlite__db_t *db, if (err) { /* Rollback failed, use a specific error code. */ - err = svn_error_create(SVN_SQLITE__ERR_ROLLBACK_FAILED, err, - _("SQLite transaction rollback failed")); + err = svn_error_create(SVN_ERR_SQLITE_ROLLBACK_FAILED, err, NULL); } return svn_error_compose_create(error_to_wrap, err); @@ -1407,7 +1399,7 @@ svn_sqlite__finish_savepoint(svn_sqlite__db_t *db, /* Ok, we have a major problem. Some statement is still open, which makes it impossible to release this savepoint. - ### See huge comment in svn_sqlite__finish_transaction for + ### See huge comment in rollback_transaction() for further details */ err2 = svn_error_trace(reset_all_statements(db, err2)); @@ -1430,6 +1422,8 @@ svn_sqlite__finish_savepoint(svn_sqlite__db_t *db, SVN_ERR(get_internal_statement(&stmt, db, STMT_INTERNAL_RELEASE_SAVEPOINT_SVN)); + /* ### Releasing a savepoint can fail and leave the db connection + unusable; see svn_sqlite__finish_transaction(). */ return svn_error_trace(svn_sqlite__step_done(stmt)); } diff --git a/subversion/libsvn_subr/sqlite3wrapper.c b/subversion/libsvn_subr/sqlite3wrapper.c index 76e182ff564f..95e42d138268 100644 --- a/subversion/libsvn_subr/sqlite3wrapper.c +++ b/subversion/libsvn_subr/sqlite3wrapper.c @@ -58,4 +58,12 @@ const sqlite3_api_routines *const svn_sqlite3__api_funcs = &sqlite3Apis; int (*const svn_sqlite3__api_initialize)(void) = sqlite3_initialize; int (*const svn_sqlite3__api_config)(int, ...) = sqlite3_config; -#endif + +#else /* !SVN_SQLITE_INLINE */ + +/* Silence OSX ranlib warnings about object files with no symbols. */ +#include +extern const apr_uint32_t svn__fake__sqlite3wrapper; +const apr_uint32_t svn__fake__sqlite3wrapper = 0xdeadbeef; + +#endif /* SVN_SQLITE_INLINE */ diff --git a/subversion/libsvn_subr/stream.c b/subversion/libsvn_subr/stream.c index 2f803b87219f..609d7af72c94 100644 --- a/subversion/libsvn_subr/stream.c +++ b/subversion/libsvn_subr/stream.c @@ -42,6 +42,7 @@ #include "svn_checksum.h" #include "svn_path.h" #include "svn_private_config.h" +#include "svn_sorts.h" #include "private/svn_atomic.h" #include "private/svn_error_private.h" #include "private/svn_eol_private.h" @@ -60,7 +61,7 @@ struct svn_stream_t { svn_stream_mark_fn_t mark_fn; svn_stream_seek_fn_t seek_fn; svn_stream_data_available_fn_t data_available_fn; - svn_stream__is_buffered_fn_t is_buffered_fn; + svn_stream_readline_fn_t readline_fn; apr_file_t *file; /* Maybe NULL */ }; @@ -138,10 +139,10 @@ svn_stream_set_data_available(svn_stream_t *stream, } void -svn_stream__set_is_buffered(svn_stream_t *stream, - svn_stream__is_buffered_fn_t is_buffered_fn) +svn_stream_set_readline(svn_stream_t *stream, + svn_stream_readline_fn_t readline_fn) { - stream->is_buffered_fn = is_buffered_fn; + stream->readline_fn = readline_fn; } /* Standard implementation for svn_stream_read_full() based on @@ -197,8 +198,15 @@ svn_error_t * svn_stream_skip(svn_stream_t *stream, apr_size_t len) { if (stream->skip_fn == NULL) - return svn_error_trace( - skip_default_handler(stream->baton, len, stream->read_full_fn)); + { + svn_read_fn_t read_fn = stream->read_full_fn ? stream->read_full_fn + : stream->read_fn; + if (read_fn == NULL) + return svn_error_create(SVN_ERR_STREAM_NOT_SUPPORTED, NULL, NULL); + + return svn_error_trace(skip_default_handler(stream->baton, len, + read_fn)); + } return svn_error_trace(stream->skip_fn(stream->baton, len)); } @@ -227,6 +235,12 @@ svn_stream_supports_mark(svn_stream_t *stream) return stream->mark_fn != NULL; } +svn_boolean_t +svn_stream_supports_reset(svn_stream_t *stream) +{ + return stream->seek_fn != NULL; +} + svn_error_t * svn_stream_mark(svn_stream_t *stream, svn_stream_mark_t **mark, apr_pool_t *pool) @@ -257,15 +271,6 @@ svn_stream_data_available(svn_stream_t *stream, data_available)); } -svn_boolean_t -svn_stream__is_buffered(svn_stream_t *stream) -{ - if (stream->is_buffered_fn == NULL) - return FALSE; - - return stream->is_buffered_fn(stream->baton); -} - svn_error_t * svn_stream_close(svn_stream_t *stream) { @@ -320,11 +325,9 @@ svn_stream_printf_from_utf8(svn_stream_t *stream, return svn_error_trace(svn_stream_puts(stream, translated)); } -/* Guts of svn_stream_readline(). +/* Default implementation for svn_stream_readline(). * Returns the line read from STREAM in *STRINGBUF, and indicates - * end-of-file in *EOF. If DETECT_EOL is TRUE, the end-of-line indicator - * is detected automatically and returned in *EOL. - * If DETECT_EOL is FALSE, *EOL must point to the desired end-of-line + * end-of-file in *EOF. EOL must point to the desired end-of-line * indicator. STRINGBUF is allocated in POOL. */ static svn_error_t * stream_readline_bytewise(svn_stringbuf_t **stringbuf, @@ -373,150 +376,6 @@ stream_readline_bytewise(svn_stringbuf_t **stringbuf, return SVN_NO_ERROR; } -static svn_error_t * -stream_readline_chunky(svn_stringbuf_t **stringbuf, - svn_boolean_t *eof, - const char *eol, - svn_stream_t *stream, - apr_pool_t *pool) -{ - /* Read larger chunks of data at once into this buffer and scan - * that for EOL. A good chunk size should be about 80 chars since - * most text lines will be shorter. However, don't use a much - * larger value because filling the buffer from the stream takes - * time as well. - */ - char buffer[SVN__LINE_CHUNK_SIZE+1]; - - /* variables */ - svn_stream_mark_t *mark; - apr_size_t numbytes; - const char *eol_pos; - apr_size_t total_parsed = 0; - - /* invariant for this call */ - const size_t eol_len = strlen(eol); - - /* Remember the line start so this plus the line length will be - * the position to move to at the end of this function. - */ - SVN_ERR(svn_stream_mark(stream, &mark, pool)); - - /* Read the first chunk. */ - numbytes = SVN__LINE_CHUNK_SIZE; - SVN_ERR(svn_stream_read_full(stream, buffer, &numbytes)); - buffer[numbytes] = '\0'; - - /* Look for the EOL in this first chunk. If we find it, we are done here. - */ - eol_pos = strstr(buffer, eol); - if (eol_pos != NULL) - { - *stringbuf = svn_stringbuf_ncreate(buffer, eol_pos - buffer, pool); - total_parsed = eol_pos - buffer + eol_len; - } - else if (numbytes < SVN__LINE_CHUNK_SIZE) - { - /* We hit EOF but not EOL. - */ - *stringbuf = svn_stringbuf_ncreate(buffer, numbytes, pool); - *eof = TRUE; - return SVN_NO_ERROR; - } - else - { - /* A larger buffer for the string is needed. */ - svn_stringbuf_t *str; - str = svn_stringbuf_create_ensure(2*SVN__LINE_CHUNK_SIZE, pool); - svn_stringbuf_appendbytes(str, buffer, numbytes); - *stringbuf = str; - - /* Loop reading chunks until an EOL was found. If we hit EOF, fall - * back to the standard implementation. */ - do - { - /* Append the next chunk to the string read so far. - */ - svn_stringbuf_ensure(str, str->len + SVN__LINE_CHUNK_SIZE); - numbytes = SVN__LINE_CHUNK_SIZE; - SVN_ERR(svn_stream_read_full(stream, str->data + str->len, &numbytes)); - str->len += numbytes; - str->data[str->len] = '\0'; - - /* Look for the EOL in the new data plus the last part of the - * previous chunk because the EOL may span over the boundary - * between both chunks. - */ - eol_pos = strstr(str->data + str->len - numbytes - (eol_len-1), eol); - - if ((numbytes < SVN__LINE_CHUNK_SIZE) && (eol_pos == NULL)) - { - /* We hit EOF instead of EOL. */ - *eof = TRUE; - return SVN_NO_ERROR; - } - } - while (eol_pos == NULL); - - /* Number of bytes we actually consumed (i.e. line + EOF). - * We need to "return" the rest to the stream by moving its - * read pointer. - */ - total_parsed = eol_pos - str->data + eol_len; - - /* Terminate the string at the EOL postion and return it. */ - str->len = eol_pos - str->data; - str->data[str->len] = 0; - } - - /* Move the stream read pointer to the first position behind the EOL. - */ - SVN_ERR(svn_stream_seek(stream, mark)); - return svn_error_trace(svn_stream_skip(stream, total_parsed)); -} - -/* Guts of svn_stream_readline(). - * Returns the line read from STREAM in *STRINGBUF, and indicates - * end-of-file in *EOF. EOL must point to the desired end-of-line - * indicator. STRINGBUF is allocated in POOL. */ -static svn_error_t * -stream_readline(svn_stringbuf_t **stringbuf, - svn_boolean_t *eof, - const char *eol, - svn_stream_t *stream, - apr_pool_t *pool) -{ - *eof = FALSE; - - /* Often, we operate on APR file or string-based streams and know what - * EOL we are looking for. Optimize that common case. - */ - if (svn_stream_supports_mark(stream) && - svn_stream__is_buffered(stream)) - { - /* We can efficiently read chunks speculatively and reposition the - * stream pointer to the end of the line once we found that. - */ - SVN_ERR(stream_readline_chunky(stringbuf, - eof, - eol, - stream, - pool)); - } - else - { - /* Use the standard byte-byte implementation. - */ - SVN_ERR(stream_readline_bytewise(stringbuf, - eof, - eol, - stream, - pool)); - } - - return SVN_NO_ERROR; -} - svn_error_t * svn_stream_readline(svn_stream_t *stream, svn_stringbuf_t **stringbuf, @@ -524,8 +383,18 @@ svn_stream_readline(svn_stream_t *stream, svn_boolean_t *eof, apr_pool_t *pool) { - return svn_error_trace(stream_readline(stringbuf, eof, eol, stream, - pool)); + if (stream->readline_fn) + { + /* Use the specific implementation when it's available. */ + SVN_ERR(stream->readline_fn(stream->baton, stringbuf, eol, eof, pool)); + } + else + { + /* Use the default implementation. */ + SVN_ERR(stream_readline_bytewise(stringbuf, eof, eol, stream, pool)); + } + + return SVN_NO_ERROR; } svn_error_t *svn_stream_copy3(svn_stream_t *from, svn_stream_t *to, @@ -656,11 +525,6 @@ seek_handler_empty(void *baton, const svn_stream_mark_t *mark) return SVN_NO_ERROR; } -static svn_boolean_t -is_buffered_handler_empty(void *baton) -{ - return FALSE; -} svn_stream_t * @@ -673,7 +537,6 @@ svn_stream_empty(apr_pool_t *pool) svn_stream_set_write(stream, write_handler_empty); svn_stream_set_mark(stream, mark_handler_empty); svn_stream_set_seek(stream, seek_handler_empty); - svn_stream__set_is_buffered(stream, is_buffered_handler_empty); return stream; } @@ -780,10 +643,15 @@ data_available_disown(void *baton, svn_boolean_t *data_available) return svn_error_trace(svn_stream_data_available(baton, data_available)); } -static svn_boolean_t -is_buffered_handler_disown(void *baton) +static svn_error_t * +readline_handler_disown(void *baton, + svn_stringbuf_t **stringbuf, + const char *eol, + svn_boolean_t *eof, + apr_pool_t *pool) { - return svn_stream__is_buffered(baton); + return svn_error_trace(svn_stream_readline(baton, stringbuf, eol, + eof, pool)); } svn_stream_t * @@ -797,7 +665,7 @@ svn_stream_disown(svn_stream_t *stream, apr_pool_t *pool) svn_stream_set_mark(s, mark_handler_disown); svn_stream_set_seek(s, seek_handler_disown); svn_stream_set_data_available(s, data_available_disown); - svn_stream__set_is_buffered(s, is_buffered_handler_disown); + svn_stream_set_readline(s, readline_handler_disown); return s; } @@ -808,6 +676,7 @@ svn_stream_disown(svn_stream_t *stream, apr_pool_t *pool) struct baton_apr { apr_file_t *file; apr_pool_t *pool; + svn_boolean_t truncate_on_seek; }; /* svn_stream_mark_t for streams backed by APR files. */ @@ -917,8 +786,7 @@ mark_handler_apr(void *baton, svn_stream_mark_t **mark, apr_pool_t *pool) struct mark_apr *mark_apr; mark_apr = apr_palloc(pool, sizeof(*mark_apr)); - mark_apr->off = 0; - SVN_ERR(svn_io_file_seek(btn->file, APR_CUR, &mark_apr->off, btn->pool)); + SVN_ERR(svn_io_file_get_offset(&mark_apr->off, btn->file, btn->pool)); *mark = (svn_stream_mark_t *)mark_apr; return SVN_NO_ERROR; } @@ -929,7 +797,16 @@ seek_handler_apr(void *baton, const svn_stream_mark_t *mark) struct baton_apr *btn = baton; apr_off_t offset = (mark != NULL) ? ((const struct mark_apr *)mark)->off : 0; - SVN_ERR(svn_io_file_seek(btn->file, APR_SET, &offset, btn->pool)); + if (btn->truncate_on_seek) + { + /* The apr_file_trunc() function always does seek + trunc, + * and this is documented, so don't seek when truncating. */ + SVN_ERR(svn_io_file_trunc(btn->file, offset, btn->pool)); + } + else + { + SVN_ERR(svn_io_file_seek(btn->file, APR_SET, &offset, btn->pool)); + } return SVN_NO_ERROR; } @@ -990,11 +867,146 @@ data_available_handler_apr(void *baton, svn_boolean_t *data_available) #endif } -static svn_boolean_t -is_buffered_handler_apr(void *baton) +static svn_error_t * +readline_apr_lf(apr_file_t *file, + svn_stringbuf_t **stringbuf, + svn_boolean_t *eof, + apr_pool_t *pool) +{ + svn_stringbuf_t *buf; + + buf = svn_stringbuf_create_ensure(SVN__LINE_CHUNK_SIZE, pool); + while (1) + { + apr_status_t status; + + status = apr_file_gets(buf->data + buf->len, + (int) (buf->blocksize - buf->len), + file); + buf->len += strlen(buf->data + buf->len); + + if (APR_STATUS_IS_EOF(status)) + { + /* apr_file_gets() keeps the newline; strip it if necessary. */ + if (buf->len > 0 && buf->data[buf->len - 1] == '\n') + svn_stringbuf_chop(buf, 1); + + *eof = TRUE; + *stringbuf = buf; + return SVN_NO_ERROR; + } + else if (status != APR_SUCCESS) + { + const char *fname; + svn_error_t *err = svn_io_file_name_get(&fname, file, pool); + if (err) + fname = NULL; + svn_error_clear(err); + + if (fname) + return svn_error_wrap_apr(status, + _("Can't read a line from file '%s'"), + svn_dirent_local_style(fname, pool)); + else + return svn_error_wrap_apr(status, + _("Can't read a line from stream")); + } + + /* Do we have the EOL? If yes, strip it and return. */ + if (buf->len > 0 && buf->data[buf->len - 1] == '\n') + { + svn_stringbuf_chop(buf, 1); + *eof = FALSE; + *stringbuf = buf; + return SVN_NO_ERROR; + } + + /* Otherwise, prepare to read the next chunk. */ + svn_stringbuf_ensure(buf, buf->blocksize + SVN__LINE_CHUNK_SIZE); + } +} + +static svn_error_t * +readline_apr_generic(apr_file_t *file, + svn_stringbuf_t **stringbuf, + const char *eol, + svn_boolean_t *eof, + apr_pool_t *pool) +{ + apr_size_t eol_len = strlen(eol); + apr_off_t offset; + svn_stringbuf_t *buf; + + SVN_ERR(svn_io_file_get_offset(&offset, file, pool)); + + buf = svn_stringbuf_create_ensure(SVN__LINE_CHUNK_SIZE, pool); + while (1) + { + apr_size_t bytes_read; + svn_boolean_t hit_eof; + const char *search_start; + const char *eol_pos; + + /* We look for the EOL in the new data plus the last part of the + previous chunk because the EOL may span over the boundary + between both chunks. */ + if (buf->len < eol_len) + search_start = buf->data; + else + search_start = buf->data + buf->len - eol_len; + + SVN_ERR(svn_io_file_read_full2(file, buf->data + buf->len, + buf->blocksize - buf->len - 1, + &bytes_read, &hit_eof, pool)); + buf->len += bytes_read; + buf->data[buf->len] = '\0'; + + /* Do we have the EOL now? */ + eol_pos = strstr(search_start, eol); + if (eol_pos) + { + svn_stringbuf_chop(buf, buf->data + buf->len - eol_pos); + /* Seek to the first position behind the EOL. */ + offset += (buf->len + eol_len); + SVN_ERR(svn_io_file_seek(file, APR_SET, &offset, pool)); + + *eof = FALSE; + *stringbuf = buf; + return SVN_NO_ERROR; + } + else if (eol_pos == NULL && hit_eof) + { + *eof = TRUE; + *stringbuf = buf; + return SVN_NO_ERROR; + } + + /* Prepare to read the next chunk. */ + svn_stringbuf_ensure(buf, buf->blocksize + SVN__LINE_CHUNK_SIZE); + } +} + +static svn_error_t * +readline_handler_apr(void *baton, + svn_stringbuf_t **stringbuf, + const char *eol, + svn_boolean_t *eof, + apr_pool_t *pool) { struct baton_apr *btn = baton; - return (apr_file_flags_get(btn->file) & APR_BUFFERED) != 0; + + if (eol[0] == '\n' && eol[1] == '\0') + { + /* Optimize the common case when we're looking for an LF ("\n") + end-of-line sequence by using apr_file_gets(). */ + return svn_error_trace(readline_apr_lf(btn->file, stringbuf, + eof, pool)); + } + else + { + return svn_error_trace(readline_apr_generic(btn->file, stringbuf, + eol, eof, pool)); + } } svn_error_t * @@ -1056,6 +1068,7 @@ static svn_stream_t * make_stream_from_apr_file(apr_file_t *file, svn_boolean_t disown, svn_boolean_t supports_seek, + svn_boolean_t truncate_on_seek, apr_pool_t *pool) { struct baton_apr *baton; @@ -1067,6 +1080,7 @@ make_stream_from_apr_file(apr_file_t *file, baton = apr_palloc(pool, sizeof(*baton)); baton->file = file; baton->pool = pool; + baton->truncate_on_seek = truncate_on_seek; stream = svn_stream_create(baton, pool); svn_stream_set_read2(stream, read_handler_apr, read_full_handler_apr); svn_stream_set_write(stream, write_handler_apr); @@ -1076,10 +1090,10 @@ make_stream_from_apr_file(apr_file_t *file, svn_stream_set_skip(stream, skip_handler_apr); svn_stream_set_mark(stream, mark_handler_apr); svn_stream_set_seek(stream, seek_handler_apr); + svn_stream_set_readline(stream, readline_handler_apr); } svn_stream_set_data_available(stream, data_available_handler_apr); - svn_stream__set_is_buffered(stream, is_buffered_handler_apr); stream->file = file; if (! disown) @@ -1088,12 +1102,21 @@ make_stream_from_apr_file(apr_file_t *file, return stream; } +svn_stream_t * +svn_stream__from_aprfile(apr_file_t *file, + svn_boolean_t disown, + svn_boolean_t truncate_on_seek, + apr_pool_t *pool) +{ + return make_stream_from_apr_file(file, disown, TRUE, truncate_on_seek, pool); +} + svn_stream_t * svn_stream_from_aprfile2(apr_file_t *file, svn_boolean_t disown, apr_pool_t *pool) { - return make_stream_from_apr_file(file, disown, TRUE, pool); + return make_stream_from_apr_file(file, disown, TRUE, FALSE, pool); } apr_file_t * @@ -1431,6 +1454,31 @@ close_handler_checksum(void *baton) return svn_error_trace(svn_stream_close(btn->proxy)); } +static svn_error_t * +seek_handler_checksum(void *baton, const svn_stream_mark_t *mark) +{ + struct checksum_stream_baton *btn = baton; + + /* Only reset support. */ + if (mark) + { + return svn_error_create(SVN_ERR_STREAM_SEEK_NOT_SUPPORTED, + NULL, NULL); + } + else + { + if (btn->read_ctx) + svn_checksum_ctx_reset(btn->read_ctx); + + if (btn->write_ctx) + svn_checksum_ctx_reset(btn->write_ctx); + + SVN_ERR(svn_stream_reset(btn->proxy)); + } + + return SVN_NO_ERROR; +} + svn_stream_t * svn_stream_checksummed2(svn_stream_t *stream, @@ -1468,37 +1516,96 @@ svn_stream_checksummed2(svn_stream_t *stream, svn_stream_set_write(s, write_handler_checksum); svn_stream_set_data_available(s, data_available_handler_checksum); svn_stream_set_close(s, close_handler_checksum); + if (svn_stream_supports_reset(stream)) + svn_stream_set_seek(s, seek_handler_checksum); return s; } +/* Helper for svn_stream_contents_checksum() to compute checksum of + * KIND of STREAM. This function doesn't close source stream. */ +static svn_error_t * +compute_stream_checksum(svn_checksum_t **checksum, + svn_stream_t *stream, + svn_checksum_kind_t kind, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_checksum_ctx_t *ctx = svn_checksum_ctx_create(kind, scratch_pool); + char *buf = apr_palloc(scratch_pool, SVN__STREAM_CHUNK_SIZE); + + while (1) + { + apr_size_t len = SVN__STREAM_CHUNK_SIZE; + + SVN_ERR(svn_stream_read_full(stream, buf, &len)); + + if (len > 0) + SVN_ERR(svn_checksum_update(ctx, buf, len)); + + if (len != SVN__STREAM_CHUNK_SIZE) + break; + } + SVN_ERR(svn_checksum_final(checksum, ctx, result_pool)); + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_stream_contents_checksum(svn_checksum_t **checksum, + svn_stream_t *stream, + svn_checksum_kind_t kind, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_error_t *err; + + err = compute_stream_checksum(checksum, stream, kind, + result_pool, scratch_pool); + + /* Close source stream in all cases. */ + return svn_error_compose_create(err, svn_stream_close(stream)); +} + /* Miscellaneous stream functions. */ +/* + * [JAF] By considering the buffer size doubling algorithm we use, I think + * the performance characteristics of this implementation are as follows: + * + * When the effective hint is big enough for the actual data, it uses + * minimal time and allocates space roughly equal to the effective hint. + * Otherwise, it incurs a time overhead for copying an additional 1x to 2x + * the actual length of data, and a space overhead of an additional 2x to + * 3x the actual length. + */ svn_error_t * -svn_stringbuf_from_stream(svn_stringbuf_t **str, +svn_stringbuf_from_stream(svn_stringbuf_t **result, svn_stream_t *stream, apr_size_t len_hint, apr_pool_t *result_pool) { #define MIN_READ_SIZE 64 - - apr_size_t to_read = 0; svn_stringbuf_t *text - = svn_stringbuf_create_ensure(len_hint ? len_hint : MIN_READ_SIZE, + = svn_stringbuf_create_ensure(MAX(len_hint + 1, MIN_READ_SIZE), result_pool); - do + while(TRUE) { - to_read = text->blocksize - 1 - text->len; - SVN_ERR(svn_stream_read_full(stream, text->data + text->len, &to_read)); - text->len += to_read; + apr_size_t to_read = text->blocksize - 1 - text->len; + apr_size_t actually_read = to_read; - if (to_read && text->blocksize < text->len + MIN_READ_SIZE) + SVN_ERR(svn_stream_read_full(stream, text->data + text->len, &actually_read)); + text->len += actually_read; + + if (actually_read < to_read) + break; + + if (text->blocksize - text->len < MIN_READ_SIZE) svn_stringbuf_ensure(text, text->blocksize * 2); } - while (to_read); text->data[text->len] = '\0'; - *str = text; + *result = text; return SVN_NO_ERROR; } @@ -1587,10 +1694,35 @@ data_available_handler_stringbuf(void *baton, svn_boolean_t *data_available) return SVN_NO_ERROR; } -static svn_boolean_t -is_buffered_handler_stringbuf(void *baton) +static svn_error_t * +readline_handler_stringbuf(void *baton, + svn_stringbuf_t **stringbuf, + const char *eol, + svn_boolean_t *eof, + apr_pool_t *pool) { - return TRUE; + struct stringbuf_stream_baton *btn = baton; + const char *pos = btn->str->data + btn->amt_read; + const char *eol_pos; + + eol_pos = strstr(pos, eol); + if (eol_pos) + { + apr_size_t eol_len = strlen(eol); + + *eof = FALSE; + *stringbuf = svn_stringbuf_ncreate(pos, eol_pos - pos, pool); + btn->amt_read += (eol_pos - pos + eol_len); + } + else + { + *eof = TRUE; + *stringbuf = svn_stringbuf_ncreate(pos, btn->str->len - btn->amt_read, + pool); + btn->amt_read = btn->str->len; + } + + return SVN_NO_ERROR; } svn_stream_t * @@ -1613,7 +1745,7 @@ svn_stream_from_stringbuf(svn_stringbuf_t *str, svn_stream_set_mark(stream, mark_handler_stringbuf); svn_stream_set_seek(stream, seek_handler_stringbuf); svn_stream_set_data_available(stream, data_available_handler_stringbuf); - svn_stream__set_is_buffered(stream, is_buffered_handler_stringbuf); + svn_stream_set_readline(stream, readline_handler_stringbuf); return stream; } @@ -1692,10 +1824,35 @@ data_available_handler_string(void *baton, svn_boolean_t *data_available) return SVN_NO_ERROR; } -static svn_boolean_t -is_buffered_handler_string(void *baton) +static svn_error_t * +readline_handler_string(void *baton, + svn_stringbuf_t **stringbuf, + const char *eol, + svn_boolean_t *eof, + apr_pool_t *pool) { - return TRUE; + struct string_stream_baton *btn = baton; + const char *pos = btn->str->data + btn->amt_read; + const char *eol_pos; + + eol_pos = strstr(pos, eol); + if (eol_pos) + { + apr_size_t eol_len = strlen(eol); + + *eof = FALSE; + *stringbuf = svn_stringbuf_ncreate(pos, eol_pos - pos, pool); + btn->amt_read += (eol_pos - pos + eol_len); + } + else + { + *eof = TRUE; + *stringbuf = svn_stringbuf_ncreate(pos, btn->str->len - btn->amt_read, + pool); + btn->amt_read = btn->str->len; + } + + return SVN_NO_ERROR; } svn_stream_t * @@ -1717,18 +1874,21 @@ svn_stream_from_string(const svn_string_t *str, svn_stream_set_seek(stream, seek_handler_string); svn_stream_set_skip(stream, skip_handler_string); svn_stream_set_data_available(stream, data_available_handler_string); - svn_stream__set_is_buffered(stream, is_buffered_handler_string); + svn_stream_set_readline(stream, readline_handler_string); return stream; } svn_error_t * -svn_stream_for_stdin(svn_stream_t **in, apr_pool_t *pool) +svn_stream_for_stdin2(svn_stream_t **in, + svn_boolean_t buffered, + apr_pool_t *pool) { apr_file_t *stdin_file; apr_status_t apr_err; - apr_err = apr_file_open_stdin(&stdin_file, pool); + apr_uint32_t flags = buffered ? APR_BUFFERED : 0; + apr_err = apr_file_open_flags_stdin(&stdin_file, flags, pool); if (apr_err) return svn_error_wrap_apr(apr_err, "Can't open stdin"); @@ -1736,7 +1896,7 @@ svn_stream_for_stdin(svn_stream_t **in, apr_pool_t *pool) it does not, or the behavior is implementation-specific. Hence, we cannot safely advertise mark(), seek() and non-default skip() support. */ - *in = make_stream_from_apr_file(stdin_file, TRUE, FALSE, pool); + *in = make_stream_from_apr_file(stdin_file, TRUE, FALSE, FALSE, pool); return SVN_NO_ERROR; } @@ -1756,7 +1916,7 @@ svn_stream_for_stdout(svn_stream_t **out, apr_pool_t *pool) it does not, or the behavior is implementation-specific. Hence, we cannot safely advertise mark(), seek() and non-default skip() support. */ - *out = make_stream_from_apr_file(stdout_file, TRUE, FALSE, pool); + *out = make_stream_from_apr_file(stdout_file, TRUE, FALSE, FALSE, pool); return SVN_NO_ERROR; } @@ -1776,39 +1936,25 @@ svn_stream_for_stderr(svn_stream_t **err, apr_pool_t *pool) it does not, or the behavior is implementation-specific. Hence, we cannot safely advertise mark(), seek() and non-default skip() support. */ - *err = make_stream_from_apr_file(stderr_file, TRUE, FALSE, pool); + *err = make_stream_from_apr_file(stderr_file, TRUE, FALSE, FALSE, pool); return SVN_NO_ERROR; } svn_error_t * -svn_string_from_stream(svn_string_t **result, - svn_stream_t *stream, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) +svn_string_from_stream2(svn_string_t **result, + svn_stream_t *stream, + apr_size_t len_hint, + apr_pool_t *result_pool) { - svn_stringbuf_t *work = svn_stringbuf_create_ensure(SVN__STREAM_CHUNK_SIZE, - result_pool); - char *buffer = apr_palloc(scratch_pool, SVN__STREAM_CHUNK_SIZE); + svn_stringbuf_t *buf; - while (1) - { - apr_size_t len = SVN__STREAM_CHUNK_SIZE; - - SVN_ERR(svn_stream_read_full(stream, buffer, &len)); - svn_stringbuf_appendbytes(work, buffer, len); - - if (len < SVN__STREAM_CHUNK_SIZE) - break; - } + SVN_ERR(svn_stringbuf_from_stream(&buf, stream, len_hint, result_pool)); + *result = svn_stringbuf__morph_into_string(buf); SVN_ERR(svn_stream_close(stream)); - *result = apr_palloc(result_pool, sizeof(**result)); - (*result)->data = work->data; - (*result)->len = work->len; - return SVN_NO_ERROR; } @@ -1977,17 +2123,19 @@ data_available_handler_lazyopen(void *baton, data_available)); } -/* Implements svn_stream__is_buffered_fn_t */ -static svn_boolean_t -is_buffered_lazyopen(void *baton) +/* Implements svn_stream_readline_fn_t */ +static svn_error_t * +readline_handler_lazyopen(void *baton, + svn_stringbuf_t **stringbuf, + const char *eol, + svn_boolean_t *eof, + apr_pool_t *pool) { lazyopen_baton_t *b = baton; - /* No lazy open as we cannot handle an open error. */ - if (!b->real_stream) - return FALSE; - - return svn_stream__is_buffered(b->real_stream); + SVN_ERR(lazyopen_if_unopened(b)); + return svn_error_trace(svn_stream_readline(b->real_stream, stringbuf, + eol, eof, pool)); } svn_stream_t * @@ -2014,7 +2162,7 @@ svn_stream_lazyopen_create(svn_stream_lazyopen_func_t open_func, svn_stream_set_mark(stream, mark_handler_lazyopen); svn_stream_set_seek(stream, seek_handler_lazyopen); svn_stream_set_data_available(stream, data_available_handler_lazyopen); - svn_stream__set_is_buffered(stream, is_buffered_lazyopen); + svn_stream_set_readline(stream, readline_handler_lazyopen); return stream; } @@ -2096,6 +2244,8 @@ create_tempfile(HANDLE *hFile, return SVN_NO_ERROR; } +#endif /* WIN32 */ + /* Implements svn_close_fn_t */ static svn_error_t * install_close(void *baton) @@ -2108,8 +2258,6 @@ install_close(void *baton) return SVN_NO_ERROR; } -#endif /* WIN32 */ - svn_error_t * svn_stream__create_for_install(svn_stream_t **install_stream, const char *tmp_abspath, @@ -2132,8 +2280,8 @@ svn_stream__create_for_install(svn_stream_t **install_stream, /* Wrap as a standard APR file to allow sharing implementation. But do note that some file functions (such as retrieving the name) - don't work on this wrapper. */ - /* ### Buffered, or not? */ + don't work on this wrapper. + Use buffered mode to match svn_io_open_unique_file3() behavior. */ status = apr_os_file_put(&file, &hInstall, APR_WRITE | APR_BINARY | APR_BUFFERED, result_pool); @@ -2153,7 +2301,9 @@ svn_stream__create_for_install(svn_stream_t **install_stream, svn_io_file_del_none, result_pool, scratch_pool)); #endif - *install_stream = svn_stream_from_aprfile2(file, FALSE, result_pool); + /* Set the temporary file to be truncated on seeks. */ + *install_stream = svn_stream__from_aprfile(file, FALSE, TRUE, + result_pool); ib = apr_pcalloc(result_pool, sizeof(*ib)); ib->baton_apr = *(struct baton_apr*)(*install_stream)->baton; @@ -2164,12 +2314,8 @@ svn_stream__create_for_install(svn_stream_t **install_stream, ib->tmp_path = tmp_path; -#ifdef WIN32 /* Don't close the file on stream close; flush instead */ svn_stream_set_close(*install_stream, install_close); -#else - /* ### Install pool cleanup handler for tempfile? */ -#endif return SVN_NO_ERROR; } @@ -2214,8 +2360,6 @@ svn_stream__install_stream(svn_stream_t *install_stream, svn_io_file_rename2(). */ svn_error_clear(err); err = SVN_NO_ERROR; - - SVN_ERR(svn_io_file_close(ib->baton_apr.file, scratch_pool)); } else { @@ -2225,7 +2369,10 @@ svn_stream__install_stream(svn_stream_t *install_stream, } #endif - err = svn_io_file_rename(ib->tmp_path, final_abspath, scratch_pool); + /* Close temporary file. */ + SVN_ERR(svn_io_file_close(ib->baton_apr.file, scratch_pool)); + + err = svn_io_file_rename2(ib->tmp_path, final_abspath, FALSE, scratch_pool); /* A missing directory is too common to not cover here. */ if (make_parents && err && APR_STATUS_IS_ENOENT(err->apr_err)) @@ -2243,7 +2390,7 @@ svn_stream__install_stream(svn_stream_t *install_stream, /* We could create a directory: retry install */ svn_error_clear(err); - SVN_ERR(svn_io_file_rename(ib->tmp_path, final_abspath, scratch_pool)); + SVN_ERR(svn_io_file_rename2(ib->tmp_path, final_abspath, FALSE, scratch_pool)); } else SVN_ERR(err); @@ -2258,19 +2405,12 @@ svn_stream__install_get_info(apr_finfo_t *finfo, apr_pool_t *scratch_pool) { struct install_baton_t *ib = install_stream->baton; - -#ifdef WIN32 - /* On WIN32 the file is still open, so we can obtain the information - from the handle without race conditions */ apr_status_t status; status = apr_file_info_get(finfo, wanted, ib->baton_apr.file); if (status) return svn_error_wrap_apr(status, NULL); -#else - SVN_ERR(svn_io_stat(finfo, ib->tmp_path, wanted, scratch_pool)); -#endif return SVN_NO_ERROR; } @@ -2297,9 +2437,10 @@ svn_stream__install_delete(svn_stream_t *install_stream, /* Deleting file on close may be unsupported, so ignore errors and fallback to svn_io_remove_file2(). */ svn_error_clear(err); - SVN_ERR(svn_io_file_close(ib->baton_apr.file, scratch_pool)); #endif + SVN_ERR(svn_io_file_close(ib->baton_apr.file, scratch_pool)); + return svn_error_trace(svn_io_remove_file2(ib->tmp_path, FALSE, scratch_pool)); } diff --git a/subversion/libsvn_subr/string.c b/subversion/libsvn_subr/string.c index 43a1a4ec1802..243e4b555c71 100644 --- a/subversion/libsvn_subr/string.c +++ b/subversion/libsvn_subr/string.c @@ -479,7 +479,7 @@ svn_stringbuf_set(svn_stringbuf_t *str, const char *value) { apr_size_t amt = strlen(value); - svn_stringbuf_ensure(str, amt); + membuf_ensure((void**) &str->data, &str->blocksize, amt + 1, str->pool); memcpy(str->data, value, amt + 1); str->len = amt; } @@ -487,9 +487,7 @@ svn_stringbuf_set(svn_stringbuf_t *str, const char *value) void svn_stringbuf_setempty(svn_stringbuf_t *str) { - if (str->len > 0) - str->data[0] = '\0'; - + str->data[0] = '\0'; str->len = 0; } @@ -505,6 +503,27 @@ svn_stringbuf_chop(svn_stringbuf_t *str, apr_size_t nbytes) str->data[str->len] = '\0'; } +void +svn_stringbuf_leftchop(svn_stringbuf_t *str, apr_size_t nbytes) +{ + if (str->len == 0) + return; + + if (nbytes >= str->len) + { + str->len = 0; + *str->data = '\0'; + } + else + { + /* Note: This will irretrievably waste nbytes of space in the + stringbuf's pool, but unlike the alternative of memmoving the + data, it's a constant-time operation. */ + str->data += nbytes; + str->len -= nbytes; + str->blocksize -= nbytes; + } +} svn_boolean_t svn_stringbuf_isempty(const svn_stringbuf_t *str) @@ -723,6 +742,71 @@ svn_stringbuf_replace(svn_stringbuf_t *str, } +apr_size_t +svn_stringbuf_replace_all(svn_stringbuf_t *str, + const char *to_find, + const char *replacement) +{ + apr_size_t replacements = 0; + + apr_size_t current = 0; + apr_size_t original_length = str->len; + + apr_size_t to_copy; + apr_size_t to_find_len; + apr_size_t replacement_len; + apr_size_t new_length; + + /* Early exit. */ + const char *pos = strstr(str->data, to_find); + if (pos == NULL) + return 0; + + to_find_len = strlen(to_find); + replacement_len = strlen(replacement); + + /* We will store the new contents behind the NUL terminator of the current + * data and track the total length in STR->LEN to make the reallocation + * code preserve both bits. However, we need to keep the NUL between them + * to make strstr stop at that boundary. */ + ++str->len; + + /* Find all occurrences of TO_FIND, copy the bits in between to the target, + * separated by REPLACEMENT. */ + for ( ; pos; pos = strstr(str->data + current, to_find), ++replacements) + { + to_copy = pos - str->data - current; + svn_stringbuf_ensure(str, str->len + to_copy + replacement_len); + + if (to_copy) + memcpy(str->data + str->len, str->data + current, to_copy); + current += to_copy + to_find_len; + + str->len += to_copy; + memcpy(str->data + str->len, replacement, replacement_len); + str->len += replacement_len; + } + + /* Copy remainder. */ + to_copy = original_length - current; + if (to_copy) + { + svn_stringbuf_ensure(str, str->len + to_copy); + memcpy(str->data + str->len, str->data + current, to_copy); + str->len += to_copy; + } + + /* Move new contents to the start of the buffer and terminate it. */ + new_length = str->len - original_length - 1; + memmove(str->data, str->data + original_length + 1, new_length); + str->len = new_length; + str->data[new_length] = 0; + + /* Done. */ + return replacements; +} + + svn_stringbuf_t * svn_stringbuf_dup(const svn_stringbuf_t *original_string, apr_pool_t *pool) { @@ -751,13 +835,18 @@ svn_stringbuf_first_non_whitespace(const svn_stringbuf_t *str) void svn_stringbuf_strip_whitespace(svn_stringbuf_t *str) { - /* Find first non-whitespace character */ - apr_size_t offset = svn_stringbuf_first_non_whitespace(str); + /* Skip (hide) whitespace at the beginning of the string. */ + if (svn_ctype_isspace(str->data[0])) + { + /* Find first non-whitespace character */ + apr_size_t offset = string_first_non_whitespace(str->data + 1, + str->len - 1) + 1; - /* Go ahead! Waste some RAM, we've got pools! :) */ - str->data += offset; - str->len -= offset; - str->blocksize -= offset; + /* Go ahead! Waste some RAM, we've got pools! :) */ + str->data += offset; + str->len -= offset; + str->blocksize -= offset; + } /* Now that we've trimmed the front, trim the end, wasting more RAM. */ while ((str->len > 0) && svn_ctype_isspace(str->data[str->len - 1])) @@ -932,9 +1021,10 @@ int svn_cstring_count_newlines(const char *msg) } char * -svn_cstring_join(const apr_array_header_t *strings, - const char *separator, - apr_pool_t *pool) +svn_cstring_join2(const apr_array_header_t *strings, + const char *separator, + svn_boolean_t trailing_separator, + apr_pool_t *pool) { svn_stringbuf_t *new_str = svn_stringbuf_create_empty(pool); size_t sep_len = strlen(separator); @@ -943,9 +1033,14 @@ svn_cstring_join(const apr_array_header_t *strings, for (i = 0; i < strings->nelts; i++) { const char *string = APR_ARRAY_IDX(strings, i, const char *); + if (i > 0) + svn_stringbuf_appendbytes(new_str, separator, sep_len); svn_stringbuf_appendbytes(new_str, string, strlen(string)); - svn_stringbuf_appendbytes(new_str, separator, sep_len); } + + if (strings->nelts > 0 && trailing_separator) + svn_stringbuf_appendbytes(new_str, separator, sep_len); + return new_str->data; } @@ -1421,7 +1516,7 @@ svn_cstring__match_length(const char *a, * because A and B will probably have different alignment. So, skipping * the first few chars until alignment is reached is not an option. */ - for (; pos + sizeof(apr_size_t) <= max_len; pos += sizeof(apr_size_t)) + for (; max_len - pos >= sizeof(apr_size_t); pos += sizeof(apr_size_t)) if (*(const apr_size_t*)(a + pos) != *(const apr_size_t*)(b + pos)) break; diff --git a/subversion/libsvn_subr/subst.c b/subversion/libsvn_subr/subst.c index 388c31a8fddd..c8c3018d8d6a 100644 --- a/subversion/libsvn_subr/subst.c +++ b/subversion/libsvn_subr/subst.c @@ -1127,7 +1127,7 @@ translate_chunk(svn_stream_t *dst, { /* Check 4 bytes at once to allow for efficient pipelining and to reduce loop condition overhead. */ - while ((p + len + 4) <= end) + while ((end - p) >= (len + 4)) { if (interesting[(unsigned char)p[len]] || interesting[(unsigned char)p[len+1]] @@ -1157,7 +1157,7 @@ translate_chunk(svn_stream_t *dst, } while (b->nl_translation_skippable == svn_tristate_true && /* can potentially skip EOLs */ - p + len + 2 < end && /* not too close to EOF */ + (end - p) > (len + 2) && /* not too close to EOF */ eol_unchanged(b, p + len)); /* EOL format already ok */ while ((p + len) < end && !interesting[(unsigned char)p[len]]) @@ -1431,14 +1431,6 @@ translated_stream_seek(void *baton, const svn_stream_mark_t *mark) return SVN_NO_ERROR; } -/* Implements svn_stream__is_buffered_fn_t. */ -static svn_boolean_t -translated_stream_is_buffered(void *baton) -{ - struct translated_stream_baton *b = baton; - return svn_stream__is_buffered(b->stream); -} - svn_error_t * svn_subst_read_specialfile(svn_stream_t **stream, const char *path, @@ -1546,9 +1538,11 @@ stream_translated(svn_stream_t *stream, translated_stream_read); svn_stream_set_write(s, translated_stream_write); svn_stream_set_close(s, translated_stream_close); - svn_stream_set_mark(s, translated_stream_mark); - svn_stream_set_seek(s, translated_stream_seek); - svn_stream__set_is_buffered(s, translated_stream_is_buffered); + if (svn_stream_supports_mark(stream)) + { + svn_stream_set_mark(s, translated_stream_mark); + svn_stream_set_seek(s, translated_stream_seek); + } return s; } @@ -1649,7 +1643,7 @@ detranslate_special_file(const char *src, const char *dst, cancel_func, cancel_baton, scratch_pool)); /* Do the atomic rename from our temporary location. */ - return svn_error_trace(svn_io_file_rename(dst_tmp, dst, scratch_pool)); + return svn_error_trace(svn_io_file_rename2(dst_tmp, dst, FALSE, scratch_pool)); } /* Creates a special file DST from the "normal form" located in SOURCE. @@ -1691,17 +1685,16 @@ create_special_file_from_stream(svn_stream_t *source, const char *dst, ".tmp", pool); /* If we had an error, check to see if it was because symlinks are - not supported on the platform. If so, fall back - to using the internal representation. */ - if (err) + not supported on the platform. If so, fall back to using the + internal representation. */ + if (err && err->apr_err == SVN_ERR_UNSUPPORTED_FEATURE) { - if (err->apr_err == SVN_ERR_UNSUPPORTED_FEATURE) - { - svn_error_clear(err); - create_using_internal_representation = TRUE; - } - else - return err; + svn_error_clear(err); + create_using_internal_representation = TRUE; + } + else if (err) + { + return svn_error_trace(err); } } else @@ -1733,7 +1726,7 @@ create_special_file_from_stream(svn_stream_t *source, const char *dst, } /* Do the atomic rename from our temporary location. */ - return svn_error_trace(svn_io_file_rename(dst_tmp, dst, pool)); + return svn_error_trace(svn_io_file_rename2(dst_tmp, dst, FALSE, pool)); } @@ -1824,7 +1817,7 @@ svn_subst_copy_and_translate4(const char *src, } /* Now that dst_tmp contains the translated data, do the atomic rename. */ - SVN_ERR(svn_io_file_rename(dst_tmp, dst, pool)); + SVN_ERR(svn_io_file_rename2(dst_tmp, dst, FALSE, pool)); /* Preserve the source file's permission bits. */ SVN_ERR(svn_io_copy_perms(src, dst, pool)); diff --git a/subversion/libsvn_subr/sysinfo.c b/subversion/libsvn_subr/sysinfo.c index 4ac923c0551b..a5c302d1e2b7 100644 --- a/subversion/libsvn_subr/sysinfo.c +++ b/subversion/libsvn_subr/sysinfo.c @@ -127,7 +127,8 @@ const apr_array_header_t * svn_sysinfo__linked_libs(apr_pool_t *pool) { svn_version_ext_linked_lib_t *lib; - apr_array_header_t *array = apr_array_make(pool, 6, sizeof(*lib)); + apr_array_header_t *array = apr_array_make(pool, 7, sizeof(*lib)); + int lz4_version = svn_lz4__runtime_version(); lib = &APR_ARRAY_PUSH(array, svn_version_ext_linked_lib_t); lib->name = "APR"; @@ -167,6 +168,15 @@ svn_sysinfo__linked_libs(apr_pool_t *pool) lib->compiled_version = apr_pstrdup(pool, svn_zlib__compiled_version()); lib->runtime_version = apr_pstrdup(pool, svn_zlib__runtime_version()); + lib = &APR_ARRAY_PUSH(array, svn_version_ext_linked_lib_t); + lib->name = "LZ4"; + lib->compiled_version = apr_pstrdup(pool, svn_lz4__compiled_version()); + + lib->runtime_version = apr_psprintf(pool, "%d.%d.%d", + lz4_version / 100 / 100, + (lz4_version / 100) % 100, + lz4_version % 100); + return array; } @@ -666,7 +676,7 @@ system_info(SYSTEM_INFO *sysinfo, SYSTEM_INFO *local_sysinfo) { FNGETNATIVESYSTEMINFO GetNativeSystemInfo_ = (FNGETNATIVESYSTEMINFO) - GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetNativeSystemInfo"); + GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "GetNativeSystemInfo"); memset(sysinfo, 0, sizeof *sysinfo); if (local_sysinfo) @@ -875,12 +885,12 @@ enum_loaded_modules(apr_pool_t *pool) DWORD size; FNENUMPROCESSMODULES EnumProcessModules_; - psapi_dll = GetModuleHandleA("psapi.dll"); + psapi_dll = GetModuleHandleW(L"psapi.dll"); if (!psapi_dll) { /* Load and never unload, just like static linking */ - psapi_dll = LoadLibraryA("psapi.dll"); + psapi_dll = LoadLibraryW(L"psapi.dll"); } if (!psapi_dll) @@ -1145,6 +1155,7 @@ release_name_from_version(const char *osver) case 10: return "Yosemite"; case 11: return "El Capitan"; case 12: return "Sierra"; + case 13: return "High Sierra"; } return NULL; diff --git a/subversion/libsvn_subr/temp_serializer.c b/subversion/libsvn_subr/temp_serializer.c index c6286a65d3a5..48d3d71ebdce 100644 --- a/subversion/libsvn_subr/temp_serializer.c +++ b/subversion/libsvn_subr/temp_serializer.c @@ -366,7 +366,7 @@ svn_temp_serializer__get(svn_temp_serializer__context_t *context) * proper pointer value. */ void -svn_temp_deserializer__resolve(void *buffer, void **ptr) +svn_temp_deserializer__resolve(const void *buffer, void **ptr) { /* All pointers are stored as offsets to the buffer start * (of the respective serialized sub-struct). */ diff --git a/subversion/libsvn_subr/user.c b/subversion/libsvn_subr/user.c index 7d6d0bf0e115..12d688707e03 100644 --- a/subversion/libsvn_subr/user.c +++ b/subversion/libsvn_subr/user.c @@ -28,6 +28,7 @@ #include "svn_user.h" #include "svn_utf.h" +#include "svn_dirent_uri.h" /* Get the current user's name from the OS */ static const char * @@ -68,8 +69,11 @@ svn_user_get_name(apr_pool_t *pool) return utf8_or_nothing(username, pool); } -const char * -svn_user_get_homedir(apr_pool_t *pool) +/* Most of the guts of svn_user_get_homedir(): everything except + * canonicalizing the path. + */ +static const char * +user_get_homedir(apr_pool_t *pool) { const char *username; char *homedir; @@ -84,3 +88,14 @@ svn_user_get_homedir(apr_pool_t *pool) return NULL; } + +const char * +svn_user_get_homedir(apr_pool_t *pool) +{ + const char *homedir = user_get_homedir(pool); + + if (homedir) + return svn_dirent_canonicalize(homedir, pool); + + return NULL; +} diff --git a/subversion/libsvn_subr/utf.c b/subversion/libsvn_subr/utf.c index 7d20d24db3c0..a0b0dc784d62 100644 --- a/subversion/libsvn_subr/utf.c +++ b/subversion/libsvn_subr/utf.c @@ -190,9 +190,7 @@ static APR_INLINE void* atomic_swap(void * volatile * mem, void *new_value) { #if APR_HAS_THREADS - /* Cast is necessary because of APR bug: - https://issues.apache.org/bugzilla/show_bug.cgi?id=50731 */ - return apr_atomic_xchgptr((volatile void **)mem, new_value); + return svn_atomic_xchgptr(mem, new_value); #else /* no threads - no sync. necessary */ void *old_value = (void*)*mem; @@ -860,7 +858,6 @@ svn_utf_string_from_utf8(const svn_string_t **dest, const svn_string_t *src, apr_pool_t *pool) { - svn_stringbuf_t *dbuf; xlate_handle_node_t *node; svn_error_t *err; @@ -870,10 +867,15 @@ svn_utf_string_from_utf8(const svn_string_t **dest, { err = check_utf8(src->data, src->len, pool); if (! err) - err = convert_to_stringbuf(node, src->data, src->len, - &dbuf, pool); - if (! err) - *dest = svn_stringbuf__morph_into_string(dbuf); + { + svn_stringbuf_t *dbuf; + + err = convert_to_stringbuf(node, src->data, src->len, + &dbuf, pool); + + if (! err) + *dest = svn_stringbuf__morph_into_string(dbuf); + } } else { @@ -991,7 +993,6 @@ svn_utf_cstring_from_utf8_string(const char **dest, const svn_string_t *src, apr_pool_t *pool) { - svn_stringbuf_t *dbuf; xlate_handle_node_t *node; svn_error_t *err; @@ -1001,10 +1002,14 @@ svn_utf_cstring_from_utf8_string(const char **dest, { err = check_utf8(src->data, src->len, pool); if (! err) - err = convert_to_stringbuf(node, src->data, src->len, - &dbuf, pool); - if (! err) - *dest = dbuf->data; + { + svn_stringbuf_t *dbuf; + + err = convert_to_stringbuf(node, src->data, src->len, + &dbuf, pool); + if (! err) + *dest = dbuf->data; + } } else { diff --git a/subversion/libsvn_subr/utf8proc.c b/subversion/libsvn_subr/utf8proc.c index 1e705f5f24a1..0e22af8d94ae 100644 --- a/subversion/libsvn_subr/utf8proc.c +++ b/subversion/libsvn_subr/utf8proc.c @@ -29,12 +29,16 @@ #include "private/svn_utf_private.h" #include "svn_private_config.h" +#if SVN_INTERNAL_UTF8PROC #define UTF8PROC_INLINE /* Somehow utf8proc thinks it is nice to use strlen as an argument name, while this function is already defined via apr.h */ #define strlen svn__strlen_var #include "utf8proc/utf8proc.c" #undef strlen +#else +#include +#endif @@ -52,6 +56,14 @@ const char * svn_utf__utf8proc_runtime_version(void) { /* Unused static function warning removal hack. */ + SVN_UNUSED(utf8proc_grapheme_break); + SVN_UNUSED(utf8proc_tolower); + SVN_UNUSED(utf8proc_toupper); +#if UTF8PROC_VERSION_MAJOR >= 2 + SVN_UNUSED(utf8proc_totitle); +#endif + SVN_UNUSED(utf8proc_charwidth); + SVN_UNUSED(utf8proc_category_string); SVN_UNUSED(utf8proc_NFD); SVN_UNUSED(utf8proc_NFC); SVN_UNUSED(utf8proc_NFKD); @@ -73,7 +85,7 @@ svn_utf__utf8proc_runtime_version(void) * that STRING contains invalid UTF-8 or was so long that an overflow * occurred. */ -static ssize_t +static apr_ssize_t unicode_decomposition(int transform_flags, const char *string, apr_size_t length, svn_membuf_t *buffer) @@ -84,8 +96,8 @@ unicode_decomposition(int transform_flags, for (;;) { apr_int32_t *const ucs4buf = buffer->data; - const ssize_t ucs4len = buffer->size / sizeof(*ucs4buf); - const ssize_t result = + const apr_ssize_t ucs4len = buffer->size / sizeof(*ucs4buf); + const apr_ssize_t result = utf8proc_decompose((const void*) string, length, ucs4buf, ucs4len, UTF8PROC_DECOMPOSE | UTF8PROC_STABLE | transform_flags | nullterm); @@ -112,7 +124,7 @@ decompose_normalized(apr_size_t *result_length, const char *string, apr_size_t length, svn_membuf_t *buffer) { - ssize_t result = unicode_decomposition(0, string, length, buffer); + apr_ssize_t result = unicode_decomposition(0, string, length, buffer); if (result < 0) return svn_error_create(SVN_ERR_UTF8PROC_ERROR, NULL, gettext(utf8proc_errmsg(result))); @@ -126,15 +138,30 @@ decompose_normalized(apr_size_t *result_length, * STRING. Upon return, BUFFER->data points at a NUL-terminated string * of UTF-8 characters. * + * If CASEFOLD is non-zero, perform Unicode case folding, e.g., for + * case-insensitive string comparison. If STRIPMARK is non-zero, strip + * all diacritical marks (e.g., accents) from the string. + * * A returned error may indicate that STRING contains invalid UTF-8 or * invalid Unicode codepoints. Any error message comes from utf8proc. */ static svn_error_t * normalize_cstring(apr_size_t *result_length, const char *string, apr_size_t length, + svn_boolean_t casefold, + svn_boolean_t stripmark, svn_membuf_t *buffer) { - ssize_t result = unicode_decomposition(0, string, length, buffer); + int flags = 0; + apr_ssize_t result; + + if (casefold) + flags |= UTF8PROC_CASEFOLD; + + if (stripmark) + flags |= UTF8PROC_STRIPMARK; + + result = unicode_decomposition(flags, string, length, buffer); if (result >= 0) { svn_membuf__resize(buffer, result * sizeof(apr_int32_t) + 1); @@ -202,11 +229,55 @@ svn_utf__normalize(const char **result, svn_membuf_t *buf) { apr_size_t result_length; - SVN_ERR(normalize_cstring(&result_length, str, len, buf)); + SVN_ERR(normalize_cstring(&result_length, str, len, FALSE, FALSE, buf)); *result = (const char*)(buf->data); return SVN_NO_ERROR; } +svn_error_t * +svn_utf__xfrm(const char **result, + const char *str, apr_size_t len, + svn_boolean_t case_insensitive, + svn_boolean_t accent_insensitive, + svn_membuf_t *buf) +{ + apr_size_t result_length; + SVN_ERR(normalize_cstring(&result_length, str, len, + case_insensitive, accent_insensitive, buf)); + *result = (const char*)(buf->data); + return SVN_NO_ERROR; +} + +svn_boolean_t +svn_utf__fuzzy_glob_match(const char *str, + const apr_array_header_t *patterns, + svn_membuf_t *buf) +{ + const char *normalized; + svn_error_t *err; + int i; + + /* Try to normalize case and accents in STR. + * + * If that should fail for some reason, consider STR a mismatch. */ + err = svn_utf__xfrm(&normalized, str, strlen(str), TRUE, TRUE, buf); + if (err) + { + svn_error_clear(err); + return FALSE; + } + + /* Now see whether it matches any/all of the patterns. */ + for (i = 0; i < patterns->nelts; ++i) + { + const char *pattern = APR_ARRAY_IDX(patterns, i, const char *); + if (apr_fnmatch(pattern, normalized, 0) == APR_SUCCESS) + return TRUE; + } + + return FALSE; +} + /* Decode a single UCS-4 code point to UTF-8, appending the result to BUFFER. * Assume BUFFER is already filled to *LENGTH and return the new size there. * This function does *not* nul-terminate the stringbuf! @@ -221,7 +292,7 @@ encode_ucs4(svn_membuf_t *buffer, apr_int32_t ucs4chr, apr_size_t *length) if (buffer->size - *length < 4) svn_membuf__resize(buffer, buffer->size + 4); - utf8len = utf8proc_encode_char(ucs4chr, ((uint8_t*)buffer->data + *length)); + utf8len = utf8proc_encode_char(ucs4chr, ((apr_byte_t*)buffer->data + *length)); if (!utf8len) return svn_error_createf(SVN_ERR_UTF8PROC_ERROR, NULL, _("Invalid Unicode character U+%04lX"), @@ -284,7 +355,7 @@ svn_utf__glob(svn_boolean_t *match, { const int nullterm = (escape_len == SVN_UTF__UNKNOWN_LENGTH ? UTF8PROC_NULLTERM : 0); - ssize_t result = + apr_ssize_t result = utf8proc_decompose((const void*) escape, escape_len, &ucs4esc, 1, UTF8PROC_DECOMPOSE | UTF8PROC_STABLE | nullterm); if (result < 0) @@ -359,7 +430,8 @@ svn_utf__is_normalized(const char *string, apr_pool_t *scratch_pool) apr_size_t result_length; const apr_size_t length = strlen(string); svn_membuf__create(&buffer, length * sizeof(apr_int32_t), scratch_pool); - err = normalize_cstring(&result_length, string, length, &buffer); + err = normalize_cstring(&result_length, string, length, + FALSE, FALSE, &buffer); if (err) { svn_error_clear(err); @@ -381,8 +453,8 @@ svn_utf__fuzzy_escape(const char *src, apr_size_t length, apr_pool_t *pool) svn_stringbuf_t *result; svn_membuf_t buffer; - ssize_t decomp_length; - ssize_t len; + apr_ssize_t decomp_length; + apr_ssize_t len; /* Decompose to a non-reversible compatibility format. */ svn_membuf__create(&buffer, length * sizeof(apr_int32_t), pool); @@ -411,7 +483,7 @@ svn_utf__fuzzy_escape(const char *src, apr_size_t length, apr_pool_t *pool) while (done < length) { - len = utf8proc_iterate((uint8_t*)src + done, length - done, &uc); + len = utf8proc_iterate((apr_byte_t*)src + done, length - done, &uc); if (len < 0) break; done += len; @@ -439,7 +511,7 @@ svn_utf__fuzzy_escape(const char *src, apr_size_t length, apr_pool_t *pool) /* Determine the length of the UTF-8 sequence */ const char *const p = src + done; - len = utf8proc_utf8class[(uint8_t)*p]; + len = utf8proc_utf8class[(apr_byte_t)*p]; /* Check if the multi-byte sequence is valid UTF-8. */ if (len > 1 && len <= (apr_ssize_t)(length - done)) diff --git a/subversion/libsvn_subr/utf8proc/LICENSE b/subversion/libsvn_subr/utf8proc/LICENSE.md similarity index 63% rename from subversion/libsvn_subr/utf8proc/LICENSE rename to subversion/libsvn_subr/utf8proc/LICENSE.md index 504e4c5c06be..86279fc07cd0 100644 --- a/subversion/libsvn_subr/utf8proc/LICENSE +++ b/subversion/libsvn_subr/utf8proc/LICENSE.md @@ -1,5 +1,13 @@ +## utf8proc license ## -Copyright (c) 2009 Public Software Group e. V., Berlin, Germany +**utf8proc** is a software package originally developed +by Jan Behrens and the rest of the Public Software Group, who +deserve nearly all of the credit for this library, that is now maintained by the Julia-language developers. Like the original utf8proc, +whose copyright and license statements are reproduced below, all new +work on the utf8proc library is licensed under the [MIT "expat" +license](http://opensource.org/licenses/MIT): + +*Copyright © 2014-2015 by Steven G. Johnson, Jiahao Chen, Tony Kelman, Jonas Fonseca, and other contributors listed in the git history.* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -19,14 +27,37 @@ 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. +## Original utf8proc license ## + +*Copyright (c) 2009, 2013 Public Software Group e. V., Berlin, Germany* + +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. + +## Unicode data license ## This software distribution contains derived data from a modified version of the Unicode data files. The following license applies to that data: -COPYRIGHT AND PERMISSION NOTICE +**COPYRIGHT AND PERMISSION NOTICE** -Copyright (c) 1991-2007 Unicode, Inc. All rights reserved. Distributed -under the Terms of Use in http://www.unicode.org/copyright.html. +*Copyright (c) 1991-2007 Unicode, Inc. All rights reserved. Distributed +under the Terms of Use in http://www.unicode.org/copyright.html.* Permission is hereby granted, free of charge, to any person obtaining a copy of the Unicode data files and any associated documentation (the "Data @@ -57,8 +88,6 @@ not be used in advertising or otherwise to promote the sale, use or other dealings in these Data Files or Software without prior written authorization of the copyright holder. - Unicode and the Unicode logo are trademarks of Unicode, Inc., and may be registered in some jurisdictions. All other trademarks and registered trademarks mentioned herein are the property of their respective owners. - diff --git a/subversion/libsvn_subr/utf8proc/NEWS.md b/subversion/libsvn_subr/utf8proc/NEWS.md new file mode 100644 index 000000000000..22eff0ec06ee --- /dev/null +++ b/subversion/libsvn_subr/utf8proc/NEWS.md @@ -0,0 +1,303 @@ +# utf8proc release history # + +## Version 2.1 ## + +2016-12-16: + +- New functions `utf8proc_map_custom` and `utf8proc_decompose_custom` + to allow user-supplied transformations of codepoints, in conjunction + with other transformations ([#89]). + +- New function `utf8proc_normalize_utf32` to apply normalizations + directly to UTF-32 data (not just UTF-8) ([#88]). + +- Fixed stack overflow that could occur due to incorrect definition + of `UINT16_MAX` with some compilers ([#84]). + +- Fixed conflict with `stdbool.h` in Visual Studio ([#90]). + +- Updated font metrics to use Unifont 9.0.04. + +## Version 2.0.2 ## + +2016-07-27: + +- Move `-Wmissing-prototypes` warning flag from `Makefile` to `.travis.yml` + since MSVC does not understand this flag and it is occasionally useful to + build using MSVC through the `Makefile` ([#79]). + +- Use a different variable name for a nested loop in `bench/bench.c`, and + declare it in a C89 way rather than inside the `for` to avoid "error: + 'for' loop initial declarations are only allowed in C99 mode" ([#80]). + +## Version 2.0.1 ## + +2016-07-13: + +- Bug fix in `utf8proc_grapheme_break_stateful` ([#77]). + +- Tests now use versioned Unicode files, so they will no longer + break when a new version of Unicode is released ([#78]). + +## Version 2.0 ## + +2016-07-13: + +- Updated for Unicode 9.0 ([#70]). + +- New `utf8proc_grapheme_break_stateful` to handle the complicated + grapheme-breaking rules in Unicode 9. The old `utf8proc_grapheme_break` + is still provided, but may incorrectly identify grapheme breaks + in some Unicode-9 sequences. + +- Smaller Unicode tables ([#62], [#68]). This required changes + in the `utf8proc_property_t` structure, which breaks backward + compatibility if you access this `struct` directly. The + functions in the API remain backward-compatible, however. + +- Buffer overrun fix ([#66]). + +## Version 1.3.1 ## + +2015-11-02: + +- Do not export symbol for internal function `unsafe_encode_char()` ([#55]). + +- Install relative symbolic links for shared libraries ([#58]). + +- Enable and fix compiler warnings ([#55], [#58]). + +- Add missing files to `make clean` ([#58]). + +## Version 1.3 ## + +2015-07-06: + +- Updated for Unicode 8.0 ([#45]). + +- New `utf8proc_tolower` and `utf8proc_toupper` functions, portable + replacements for `towlower` and `towupper` in the C library ([#40]). + +- Don't treat Unicode "non-characters" as invalid, and improved + validity checking in general ([#35]). + +- Prefix all typedefs with `utf8proc_`, e.g. `utf8proc_int32_t`, + to avoid collisions with other libraries ([#32]). + +- Rename `DLLEXPORT` to `UTF8PROC_DLLEXPORT` to prevent collisions. + +- Fix build breakage in the benchmark routines. + +- More fine-grained Makefile variables (`PICFLAG` etcetera), so that + compilation flags can be selectively overridden, and in particular + so that `CFLAGS` can be changed without accidentally eliminating + necessary flags like `-fPIC` and `-std=c99` ([#43]). + +- Updated character-width tables based on Unifont 8.0.01 ([#51]) and + the Unicode 8 character categories ([#47]). + +## Version 1.2 ## + +2015-03-28: + +- Updated for Unicode 7.0 ([#6]). + +- New function `utf8proc_grapheme_break(c1,c2)` that returns whether + there is a grapheme break between `c1` and `c2` ([#20]). + +- New function `utf8proc_charwidth(c)` that returns the number of + column-positions that should be required for `c`; essentially a + portable replacment for `wcwidth(c)` ([#27]). + +- New function `utf8proc_category(c)` that returns the Unicode + category of `c` (as one of the constants `UTF8PROC_CATEGORY_xx`). + Also, a function `utf8proc_category_string(c)` that returns the Unicode + category of `c` as a two-character string. + +- `cmake` script `CMakeLists.txt`, in addition to `Makefile`, for + easier compilation on Windows ([#28]). + +- Various `Makefile` improvements: a `make check` target to perform + tests ([#13]), `make install`, a rule to automate updating the Unicode + tables, etcetera. + +- The shared library is now versioned (e.g. has a soname on GNU/Linux) ([#24]). + +- C++/MSVC compatibility ([#17]). + +- Most `#defined` constants are now `enums` ([#29]). + +- New preprocessor constants `UTF8PROC_VERSION_MAJOR`, + `UTF8PROC_VERSION_MINOR`, and `UTF8PROC_VERSION_PATCH` for compile-time + detection of the API version. + +- Doxygen-formatted documentation ([#29]). + +- The Ruby and PostgreSQL plugins have been removed due to lack of testing ([#22]). + +## Version 1.1.6 ## + +2013-11-27: + +- PostgreSQL 9.2 and 9.3 compatibility (lowercase `c` language name) + +## Version 1.1.5 ## + +2009-08-20: + +- Use `RSTRING_PTR()` and `RSTRING_LEN()` instead of `RSTRING()->ptr` and + `RSTRING()->len` for ruby1.9 compatibility (and `#define` them, if not + existent) + +2009-10-02: + +- Patches for compatibility with Microsoft Visual Studio + +2009-10-08: + +- Fixes to make utf8proc usable in C++ programs + +2009-10-16: + +## Version 1.1.4 ## + +2009-06-14: + +- replaced C++ style comments for compatibility reasons +- added typecasts to suppress compiler warnings +- removed redundant source files for ruby-gemfile generation + +2009-08-19: + +- Changed copyright notice for Public Software Group e. V. +- Minor changes in the `README` file + +## Version 1.1.3 ## + +2008-10-04: + +- Added a function `utf8proc_version` returning a string containing the version + number of the library. +- Included a target `libutf8proc.dylib` for MacOSX. + +2009-05-01: +- PostgreSQL 8.3 compatibility (use of `SET_VARSIZE` macro) + +## Version 1.1.2 ## + +2007-07-25: + +- Fixed a serious bug in the data file generator, which caused characters + being treated incorrectly, when stripping default ignorable characters or + calculating grapheme cluster boundaries. + +## Version 1.1.1 ## + +2007-06-25: + +- Added a new PostgreSQL function `unistrip`, which behaves like `unifold`, + but also removes all character marks (e.g. accents). + +2007-07-22: + +- Changed license from BSD to MIT style. +- Added a new function `utf8proc_codepoint_valid` to the C library. +- Changed compiler flags in `Makefile` from `-g -O0` to `-O2` +- The ruby script, which was used to build the `utf8proc_data.c` file, is now + included in the distribution. + +## Version 1.0.3 ## + +2007-03-16: + +- Fixed a bug in the ruby library, which caused an error, when splitting an + empty string at grapheme cluster boundaries (method `String#utf8chars`). + +## Version 1.0.2 ## + +2006-09-21: + +- included a check in `Integer#utf8`, which raises an exception, if the given + code-point is invalid because of being too high (this was missing yet) + +2006-12-26: + +- added support for PostgreSQL version 8.2 + +## Version 1.0.1 ## + +2006-09-20: + +- included a gem file for the ruby version of the library + +Release of version 1.0.1 + +## Version 1.0 ## + +2006-09-17: + +- added the `LUMP` option, which lumps certain characters together (see `lump.md`) (also used for the PostgreSQL `unifold` function) +- added the `STRIPMARK` option, which strips marking characters (or marks of composed characters) +- deprecated ruby method `String#char_ary` in favour of `String#utf8chars` + +## Version 0.3 ## + +2006-07-18: + +- changed normalization from NFC to NFKC for postgresql unifold function + +2006-08-04: + +- added support to mark the beginning of a grapheme cluster with 0xFF (option: `CHARBOUND`) +- added the ruby method `String#chars`, which is returning an array of UTF-8 encoded grapheme clusters +- added `NLF2LF` transformation in postgresql `unifold` function +- added the `DECOMPOSE` option, if you neither use `COMPOSE` or `DECOMPOSE`, no normalization will be performed (different from previous versions) +- using integer constants rather than C-strings for character properties +- fixed (hopefully) a problem with the ruby library on Mac OS X, which occurred when compiler optimization was switched on + +## Version 0.2 ## + +2006-06-05: + +- changed behaviour of PostgreSQL function to return NULL in case of invalid input, rather than raising an exceptional condition +- improved efficiency of PostgreSQL function (no transformation to C string is done) + +2006-06-20: + +- added -fpic compiler flag in Makefile +- fixed bug in the C code for the ruby library (usage of non-existent function) + +## Version 0.1 ## + +2006-06-02: initial release of version 0.1 + +[#6]: https://github.com/JuliaLang/utf8proc/issues/6 +[#13]: https://github.com/JuliaLang/utf8proc/issues/13 +[#17]: https://github.com/JuliaLang/utf8proc/issues/17 +[#20]: https://github.com/JuliaLang/utf8proc/issues/20 +[#22]: https://github.com/JuliaLang/utf8proc/issues/22 +[#24]: https://github.com/JuliaLang/utf8proc/issues/24 +[#27]: https://github.com/JuliaLang/utf8proc/issues/27 +[#28]: https://github.com/JuliaLang/utf8proc/issues/28 +[#29]: https://github.com/JuliaLang/utf8proc/issues/29 +[#32]: https://github.com/JuliaLang/utf8proc/issues/32 +[#35]: https://github.com/JuliaLang/utf8proc/issues/35 +[#40]: https://github.com/JuliaLang/utf8proc/issues/40 +[#43]: https://github.com/JuliaLang/utf8proc/issues/43 +[#45]: https://github.com/JuliaLang/utf8proc/issues/45 +[#47]: https://github.com/JuliaLang/utf8proc/issues/47 +[#51]: https://github.com/JuliaLang/utf8proc/issues/51 +[#55]: https://github.com/JuliaLang/utf8proc/issues/55 +[#58]: https://github.com/JuliaLang/utf8proc/issues/58 +[#62]: https://github.com/JuliaLang/utf8proc/issues/62 +[#66]: https://github.com/JuliaLang/utf8proc/issues/66 +[#68]: https://github.com/JuliaLang/utf8proc/issues/68 +[#70]: https://github.com/JuliaLang/utf8proc/issues/70 +[#77]: https://github.com/JuliaLang/utf8proc/issues/77 +[#78]: https://github.com/JuliaLang/utf8proc/issues/78 +[#79]: https://github.com/JuliaLang/utf8proc/issues/79 +[#80]: https://github.com/JuliaLang/utf8proc/issues/80 +[#84]: https://github.com/JuliaLang/utf8proc/pull/84 +[#88]: https://github.com/JuliaLang/utf8proc/pull/88 +[#89]: https://github.com/JuliaLang/utf8proc/pull/89 +[#90]: https://github.com/JuliaLang/utf8proc/issues/90 diff --git a/subversion/libsvn_subr/utf8proc/README b/subversion/libsvn_subr/utf8proc/README deleted file mode 100644 index e72ffff3bdb1..000000000000 --- a/subversion/libsvn_subr/utf8proc/README +++ /dev/null @@ -1,116 +0,0 @@ - -Please read the LICENSE file, which is shipping with this software. - - -*** QUICK START *** - -For compilation of the C library call "make c-library", for compilation of -the ruby library call "make ruby-library" and for compilation of the -PostgreSQL extension call "make pgsql-library". - -For ruby you can also create a gem-file by calling "make ruby-gem". - -"make all" can be used to build everything, but both ruby and PostgreSQL -installations are required in this case. - - -*** GENERAL INFORMATION *** - -The C library is found in this directory after successful compilation and -is named "libutf8proc.a" and "libutf8proc.so". The ruby library consists of -the files "utf8proc.rb" and "utf8proc_native.so", which are found in the -subdirectory "ruby/". If you chose to create a gem-file it is placed in the -"ruby/gem" directory. The PostgreSQL extension is named "utf8proc_pgsql.so" -and resides in the "pgsql/" directory. - -Both the ruby library and the PostgreSQL extension are built as stand-alone -libraries and are therefore not dependent the dynamic version of the -C library files, but this behaviour might change in future releases. - -The Unicode version being supported is 5.0.0. -Note: Version 4.1.0 of Unicode Standard Annex #29 was used, as - version 5.0.0 had not been available at the time of implementation. - -For Unicode normalizations, the following options have to be used: -Normalization Form C: STABLE, COMPOSE -Normalization Form D: STABLE, DECOMPOSE -Normalization Form KC: STABLE, COMPOSE, COMPAT -Normalization Form KD: STABLE, DECOMPOSE, COMPAT - - -*** C LIBRARY *** - -The documentation for the C library is found in the utf8proc.h header file. -"utf8proc_map" is most likely function you will be using for mapping UTF-8 -strings, unless you want to allocate memory yourself. - - -*** RUBY API *** - -The ruby library adds the methods "utf8map" and "utf8map!" to the String -class, and the method "utf8" to the Integer class. - -The String#utf8map method does the same as the "utf8proc_map" C function. -Options for the mapping procedure are passed as symbols, i.e: -"Hello".utf8map(:casefold) => "hello" - -The descriptions of all options are found in the C header file -"utf8proc.h". Please notice that the according symbols in ruby are all -lowercase. - -String#utf8map! is the destructive function in the meaning that the string -is replaced by the result. - -There are shortcuts for the 4 normalization forms specified by Unicode: -String#utf8nfd, String#utf8nfd!, -String#utf8nfc, String#utf8nfc!, -String#utf8nfkd, String#utf8nfkd!, -String#utf8nfkc, String#utf8nfkc! - -The method Integer#utf8 returns a UTF-8 string, which is containing the -unicode char given by the code point. -0x000A.utf8 => "\n" -0x2028.utf8 => "\342\200\250" - - -*** POSTGRESQL API *** - -For PostgreSQL there are two SQL functions supplied named "unifold" and -"unistrip". These functions function can be used to prepare index fields in -order to be folded in a way where string-comparisons make more sense, e.g. -where "bathtub" == "bathtub" -or "Hello World" == "hello world". - -CREATE TABLE people ( - id serial8 primary key, - name text, - CHECK (unifold(name) NOTNULL) -); -CREATE INDEX name_idx ON people (unifold(name)); -SELECT * FROM people WHERE unifold(name) = unifold('John Doe'); - -The function "unistrip" removes character marks like accents or diaeresis, -while "unifold" keeps then. - -NOTICE: The outputs of the function can change between releases, as - utf8proc does not follow a versioning stability policy. You have to - rebuild your database indicies, if you upgrade to a newer version - of utf8proc. - - -*** TODO *** - -- detect stable code points and process segments independently in order to - save memory -- do a quick check before normalizing strings to optimize speed -- support stream processing - - -*** CONTACT *** - -If you find any bugs or experience difficulties in compiling this software, -please contact us: - -Project page: http://www.public-software-group.org/utf8proc - - diff --git a/subversion/libsvn_subr/utf8proc/README.md b/subversion/libsvn_subr/utf8proc/README.md new file mode 100644 index 000000000000..cb9f69478dfc --- /dev/null +++ b/subversion/libsvn_subr/utf8proc/README.md @@ -0,0 +1,69 @@ +# utf8proc +[![Travis CI Status](https://travis-ci.org/JuliaLang/utf8proc.png)](https://travis-ci.org/JuliaLang/utf8proc) +[![AppVeyor Status](https://ci.appveyor.com/api/projects/status/aou20lfkyhj8xbwq/branch/master?svg=true)](https://ci.appveyor.com/project/tkelman/utf8proc/branch/master) + + +[utf8proc](http://julialang.org/utf8proc/) is a small, clean C +library that provides Unicode normalization, case-folding, and other +operations for data in the [UTF-8 +encoding](http://en.wikipedia.org/wiki/UTF-8). It was [initially +developed](http://www.public-software-group.org/utf8proc) by Jan +Behrens and the rest of the [Public Software +Group](http://www.public-software-group.org/), who deserve *nearly all +of the credit* for this package. With the blessing of the Public +Software Group, the [Julia developers](http://julialang.org/) have +taken over development of utf8proc, since the original developers have +moved to other projects. + +(utf8proc is used for basic Unicode +support in the [Julia language](http://julialang.org/), and the Julia +developers became involved because they wanted to add Unicode 7 support and other features.) + +(The original utf8proc package also includes Ruby and PostgreSQL plug-ins. +We removed those from utf8proc in order to focus exclusively on the C +library for the time being, but plan to add them back in or release them as separate packages.) + +The utf8proc package is licensed under the +free/open-source [MIT "expat" +license](http://opensource.org/licenses/MIT) (plus certain Unicode +data governed by the similarly permissive [Unicode data +license](http://www.unicode.org/copyright.html#Exhibit1)); please see +the included `LICENSE.md` file for more detailed information. + +## Quick Start + +For compilation of the C library run `make`. + +## General Information + +The C library is found in this directory after successful compilation +and is named `libutf8proc.a` (for the static library) and +`libutf8proc.so` (for the dynamic library). + +The Unicode version supported is 9.0.0. + +For Unicode normalizations, the following options are used: + +* Normalization Form C: `STABLE`, `COMPOSE` +* Normalization Form D: `STABLE`, `DECOMPOSE` +* Normalization Form KC: `STABLE`, `COMPOSE`, `COMPAT` +* Normalization Form KD: `STABLE`, `DECOMPOSE`, `COMPAT` + +## C Library + +The documentation for the C library is found in the `utf8proc.h` header file. +`utf8proc_map` is function you will most likely be using for mapping UTF-8 +strings, unless you want to allocate memory yourself. + +## To Do + +See the Github [issues list](https://github.com/JuliaLang/utf8proc/issues). + +## Contact + +Bug reports, feature requests, and other queries can be filed at +the [utf8proc issues page on Github](https://github.com/JuliaLang/utf8proc/issues). + +## See also + +An independent Lua translation of this library, [lua-mojibake](https://github.com/differentprogramming/lua-mojibake), is also available. diff --git a/subversion/libsvn_subr/utf8proc/lump.md b/subversion/libsvn_subr/utf8proc/lump.md new file mode 100644 index 000000000000..39186fb3b6cd --- /dev/null +++ b/subversion/libsvn_subr/utf8proc/lump.md @@ -0,0 +1,27 @@ +``` +U+0020 <-- all space characters (general category Zs) +U+0027 ' <-- left/right single quotation mark U+2018..2019, + modifier letter apostrophe U+02BC, + modifier letter vertical line U+02C8 +U+002D - <-- all dash characters (general category Pd), + minus U+2212 +U+002F / <-- fraction slash U+2044, + division slash U+2215 +U+003A : <-- ratio U+2236 +U+003C < <-- single left-pointing angle quotation mark U+2039, + left-pointing angle bracket U+2329, + left angle bracket U+3008 +U+003E > <-- single right-pointing angle quotation mark U+203A, + right-pointing angle bracket U+232A, + right angle bracket U+3009 +U+005C \ <-- set minus U+2216 +U+005E ^ <-- modifier letter up arrowhead U+02C4, + modifier letter circumflex accent U+02C6, + caret U+2038, + up arrowhead U+2303 +U+005F _ <-- all connector characters (general category Pc), + modifier letter low macron U+02CD +U+0060 ` <-- modifier letter grave accent U+02CB +U+007C | <-- divides U+2223 +U+007E ~ <-- tilde operator U+223C +``` diff --git a/subversion/libsvn_subr/utf8proc/utf8proc.c b/subversion/libsvn_subr/utf8proc/utf8proc.c index 2993c8fe228a..d2b78647b982 100644 --- a/subversion/libsvn_subr/utf8proc/utf8proc.c +++ b/subversion/libsvn_subr/utf8proc/utf8proc.c @@ -1,4 +1,6 @@ +/* -*- mode: c; c-basic-offset: 2; tab-width: 2; indent-tabs-mode: nil -*- */ /* + * Copyright (c) 2015 Steven G. Johnson, Jiahao Chen, Peter Colberg, Tony Kelman, Scott P. Jones, and other contributors. * Copyright (c) 2009 Public Software Group e. V., Berlin, Germany * * Permission is hereby granted, free of charge, to any person obtaining a @@ -39,12 +41,11 @@ */ -#include "utf8proc.h" +#include "utf8proc_internal.h" #include "utf8proc_data.c" -UTF8PROC_DATA -const int8_t utf8proc_utf8class[256] = { +UTF8PROC_DLLEXPORT const utf8proc_int8_t utf8proc_utf8class[256] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -82,134 +83,144 @@ const int8_t utf8proc_utf8class[256] = { #define UTF8PROC_HANGUL_S_START 0xAC00 #define UTF8PROC_HANGUL_S_END 0xD7A4 - -#define UTF8PROC_BOUNDCLASS_START 0 -#define UTF8PROC_BOUNDCLASS_OTHER 1 -#define UTF8PROC_BOUNDCLASS_CR 2 -#define UTF8PROC_BOUNDCLASS_LF 3 -#define UTF8PROC_BOUNDCLASS_CONTROL 4 -#define UTF8PROC_BOUNDCLASS_EXTEND 5 -#define UTF8PROC_BOUNDCLASS_L 6 -#define UTF8PROC_BOUNDCLASS_V 7 -#define UTF8PROC_BOUNDCLASS_T 8 -#define UTF8PROC_BOUNDCLASS_LV 9 -#define UTF8PROC_BOUNDCLASS_LVT 10 - - -UTF8PROC_API -const char *utf8proc_version(void) { - return "1.1.5"; +/* Should follow semantic-versioning rules (semver.org) based on API + compatibility. (Note that the shared-library version number will + be different, being based on ABI compatibility.): */ +#define STRINGIZEx(x) #x +#define STRINGIZE(x) STRINGIZEx(x) +UTF8PROC_DLLEXPORT const char *utf8proc_version(void) { + return STRINGIZE(UTF8PROC_VERSION_MAJOR) "." STRINGIZE(UTF8PROC_VERSION_MINOR) "." STRINGIZE(UTF8PROC_VERSION_PATCH) ""; } -/* - * This macro tells translators that string X should be translated, - * but does not look up the translation at run time. This is standard - * GNU gettext notation for annotating compile-time constant strings. - */ -#ifndef N_ -#define N_(x) x -#endif - -UTF8PROC_API -const char *utf8proc_errmsg(ssize_t errcode) { +UTF8PROC_DLLEXPORT const char *utf8proc_errmsg(utf8proc_ssize_t errcode) { switch (errcode) { case UTF8PROC_ERROR_NOMEM: - return N_("Memory for processing UTF-8 data could not be allocated."); + return "Memory for processing UTF-8 data could not be allocated."; case UTF8PROC_ERROR_OVERFLOW: - return N_("UTF-8 string is too long to be processed."); + return "UTF-8 string is too long to be processed."; case UTF8PROC_ERROR_INVALIDUTF8: - return N_("Invalid UTF-8 string"); + return "Invalid UTF-8 string"; case UTF8PROC_ERROR_NOTASSIGNED: - return N_("Unassigned Unicode code point found in UTF-8 string."); + return "Unassigned Unicode code point found in UTF-8 string."; case UTF8PROC_ERROR_INVALIDOPTS: - return N_("Invalid options for UTF-8 processing chosen."); + return "Invalid options for UTF-8 processing chosen."; default: - return N_("An unknown error occured while processing UTF-8 data."); + return "An unknown error occurred while processing UTF-8 data."; } } -UTF8PROC_API -ssize_t utf8proc_iterate( - const uint8_t *str, ssize_t strlen, int32_t *dst +#define utf_cont(ch) (((ch) & 0xc0) == 0x80) +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_iterate( + const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, utf8proc_int32_t *dst ) { - int length; - int i; - int32_t uc = -1; + utf8proc_uint32_t uc; + const utf8proc_uint8_t *end; + *dst = -1; if (!strlen) return 0; - length = utf8proc_utf8class[str[0]]; - if (!length) return UTF8PROC_ERROR_INVALIDUTF8; - if (strlen >= 0 && length > strlen) return UTF8PROC_ERROR_INVALIDUTF8; - for (i=1; i= 0xD800 && uc < 0xE000) || - (uc >= 0xFDD0 && uc < 0xFDF0)) uc = -1; - break; - case 4: - uc = ((str[0] & 0x07) << 18) + ((str[1] & 0x3F) << 12) - + ((str[2] & 0x3F) << 6) + (str[3] & 0x3F); - if (uc < 0x10000 || uc >= 0x110000) uc = -1; - break; + /* Must be between 0xc2 and 0xf4 inclusive to be valid */ + if ((uc - 0xc2) > (0xf4-0xc2)) return UTF8PROC_ERROR_INVALIDUTF8; + if (uc < 0xe0) { /* 2-byte sequence */ + /* Must have valid continuation character */ + if (str >= end || !utf_cont(*str)) return UTF8PROC_ERROR_INVALIDUTF8; + *dst = ((uc & 0x1f)<<6) | (*str & 0x3f); + return 2; } - if (uc < 0 || ((uc & 0xFFFF) >= 0xFFFE)) - return UTF8PROC_ERROR_INVALIDUTF8; - *dst = uc; - return length; + if (uc < 0xf0) { /* 3-byte sequence */ + if ((str + 1 >= end) || !utf_cont(*str) || !utf_cont(str[1])) + return UTF8PROC_ERROR_INVALIDUTF8; + /* Check for surrogate chars */ + if (uc == 0xed && *str > 0x9f) + return UTF8PROC_ERROR_INVALIDUTF8; + uc = ((uc & 0xf)<<12) | ((*str & 0x3f)<<6) | (str[1] & 0x3f); + if (uc < 0x800) + return UTF8PROC_ERROR_INVALIDUTF8; + *dst = uc; + return 3; + } + /* 4-byte sequence + Must have 3 valid continuation characters */ + if ((str + 2 >= end) || !utf_cont(*str) || !utf_cont(str[1]) || !utf_cont(str[2])) + return UTF8PROC_ERROR_INVALIDUTF8; + /* Make sure in correct range (0x10000 - 0x10ffff) */ + if (uc == 0xf0) { + if (*str < 0x90) return UTF8PROC_ERROR_INVALIDUTF8; + } else if (uc == 0xf4) { + if (*str > 0x8f) return UTF8PROC_ERROR_INVALIDUTF8; + } + *dst = ((uc & 7)<<18) | ((*str & 0x3f)<<12) | ((str[1] & 0x3f)<<6) | (str[2] & 0x3f); + return 4; } -UTF8PROC_API -bool utf8proc_codepoint_valid(int32_t uc) { - if (uc < 0 || uc >= 0x110000 || - ((uc & 0xFFFF) >= 0xFFFE) || (uc >= 0xD800 && uc < 0xE000) || - (uc >= 0xFDD0 && uc < 0xFDF0)) return false; - else return true; +UTF8PROC_DLLEXPORT utf8proc_bool utf8proc_codepoint_valid(utf8proc_int32_t uc) { + return (((utf8proc_uint32_t)uc)-0xd800 > 0x07ff) && ((utf8proc_uint32_t)uc < 0x110000); } -UTF8PROC_API -ssize_t utf8proc_encode_char(int32_t uc, uint8_t *dst) { +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_encode_char(utf8proc_int32_t uc, utf8proc_uint8_t *dst) { if (uc < 0x00) { return 0; } else if (uc < 0x80) { - dst[0] = (uint8_t)uc; + dst[0] = (utf8proc_uint8_t) uc; return 1; } else if (uc < 0x800) { - dst[0] = 0xC0 + (uint8_t)(uc >> 6); - dst[1] = 0x80 + (uc & 0x3F); + dst[0] = (utf8proc_uint8_t)(0xC0 + (uc >> 6)); + dst[1] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F)); return 2; - } else if (uc == 0xFFFF) { - dst[0] = 0xFF; - return 1; - } else if (uc == 0xFFFE) { - dst[0] = 0xFE; - return 1; + /* Note: we allow encoding 0xd800-0xdfff here, so as not to change + the API, however, these are actually invalid in UTF-8 */ } else if (uc < 0x10000) { - dst[0] = 0xE0 + (uint8_t)(uc >> 12); - dst[1] = 0x80 + ((uc >> 6) & 0x3F); - dst[2] = 0x80 + (uc & 0x3F); + dst[0] = (utf8proc_uint8_t)(0xE0 + (uc >> 12)); + dst[1] = (utf8proc_uint8_t)(0x80 + ((uc >> 6) & 0x3F)); + dst[2] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F)); return 3; } else if (uc < 0x110000) { - dst[0] = 0xF0 + (uint8_t)(uc >> 18); - dst[1] = 0x80 + ((uc >> 12) & 0x3F); - dst[2] = 0x80 + ((uc >> 6) & 0x3F); - dst[3] = 0x80 + (uc & 0x3F); + dst[0] = (utf8proc_uint8_t)(0xF0 + (uc >> 18)); + dst[1] = (utf8proc_uint8_t)(0x80 + ((uc >> 12) & 0x3F)); + dst[2] = (utf8proc_uint8_t)(0x80 + ((uc >> 6) & 0x3F)); + dst[3] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F)); return 4; } else return 0; } -UTF8PROC_API -const utf8proc_property_t *utf8proc_get_property(int32_t uc) { +/* internal "unsafe" version that does not check whether uc is in range */ +static utf8proc_ssize_t unsafe_encode_char(utf8proc_int32_t uc, utf8proc_uint8_t *dst) { + if (uc < 0x00) { + return 0; + } else if (uc < 0x80) { + dst[0] = (utf8proc_uint8_t)uc; + return 1; + } else if (uc < 0x800) { + dst[0] = (utf8proc_uint8_t)(0xC0 + (uc >> 6)); + dst[1] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F)); + return 2; + } else if (uc == 0xFFFF) { + dst[0] = (utf8proc_uint8_t)0xFF; + return 1; + } else if (uc == 0xFFFE) { + dst[0] = (utf8proc_uint8_t)0xFE; + return 1; + } else if (uc < 0x10000) { + dst[0] = (utf8proc_uint8_t)(0xE0 + (uc >> 12)); + dst[1] = (utf8proc_uint8_t)(0x80 + ((uc >> 6) & 0x3F)); + dst[2] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F)); + return 3; + } else if (uc < 0x110000) { + dst[0] = (utf8proc_uint8_t)(0xF0 + (uc >> 18)); + dst[1] = (utf8proc_uint8_t)(0x80 + ((uc >> 12) & 0x3F)); + dst[2] = (utf8proc_uint8_t)(0x80 + ((uc >> 6) & 0x3F)); + dst[3] = (utf8proc_uint8_t)(0x80 + (uc & 0x3F)); + return 4; + } else return 0; +} + +/* internal "unsafe" version that does not check whether uc is in range */ +static const utf8proc_property_t *unsafe_get_property(utf8proc_int32_t uc) { /* ASSERT: uc >= 0 && uc < 0x110000 */ return utf8proc_properties + ( utf8proc_stage2table[ @@ -218,23 +229,184 @@ const utf8proc_property_t *utf8proc_get_property(int32_t uc) { ); } +UTF8PROC_DLLEXPORT const utf8proc_property_t *utf8proc_get_property(utf8proc_int32_t uc) { + return uc < 0 || uc >= 0x110000 ? utf8proc_properties : unsafe_get_property(uc); +} + +/* return whether there is a grapheme break between boundclasses lbc and tbc + (according to the definition of extended grapheme clusters) + + Rule numbering refers to TR29 Version 29 (Unicode 9.0.0): + http://www.unicode.org/reports/tr29/tr29-29.html + + CAVEATS: + Please note that evaluation of GB10 (grapheme breaks between emoji zwj sequences) + and GB 12/13 (regional indicator code points) require knowledge of previous characters + and are thus not handled by this function. This may result in an incorrect break before + an E_Modifier class codepoint and an incorrectly missing break between two + REGIONAL_INDICATOR class code points if such support does not exist in the caller. + + See the special support in grapheme_break_extended, for required bookkeeping by the caller. +*/ +static utf8proc_bool grapheme_break_simple(int lbc, int tbc) { + return + (lbc == UTF8PROC_BOUNDCLASS_START) ? true : /* GB1 */ + (lbc == UTF8PROC_BOUNDCLASS_CR && /* GB3 */ + tbc == UTF8PROC_BOUNDCLASS_LF) ? false : /* --- */ + (lbc >= UTF8PROC_BOUNDCLASS_CR && lbc <= UTF8PROC_BOUNDCLASS_CONTROL) ? true : /* GB4 */ + (tbc >= UTF8PROC_BOUNDCLASS_CR && tbc <= UTF8PROC_BOUNDCLASS_CONTROL) ? true : /* GB5 */ + (lbc == UTF8PROC_BOUNDCLASS_L && /* GB6 */ + (tbc == UTF8PROC_BOUNDCLASS_L || /* --- */ + tbc == UTF8PROC_BOUNDCLASS_V || /* --- */ + tbc == UTF8PROC_BOUNDCLASS_LV || /* --- */ + tbc == UTF8PROC_BOUNDCLASS_LVT)) ? false : /* --- */ + ((lbc == UTF8PROC_BOUNDCLASS_LV || /* GB7 */ + lbc == UTF8PROC_BOUNDCLASS_V) && /* --- */ + (tbc == UTF8PROC_BOUNDCLASS_V || /* --- */ + tbc == UTF8PROC_BOUNDCLASS_T)) ? false : /* --- */ + ((lbc == UTF8PROC_BOUNDCLASS_LVT || /* GB8 */ + lbc == UTF8PROC_BOUNDCLASS_T) && /* --- */ + tbc == UTF8PROC_BOUNDCLASS_T) ? false : /* --- */ + (tbc == UTF8PROC_BOUNDCLASS_EXTEND || /* GB9 */ + tbc == UTF8PROC_BOUNDCLASS_ZWJ || /* --- */ + tbc == UTF8PROC_BOUNDCLASS_SPACINGMARK || /* GB9a */ + lbc == UTF8PROC_BOUNDCLASS_PREPEND) ? false : /* GB9b */ + ((lbc == UTF8PROC_BOUNDCLASS_E_BASE || /* GB10 (requires additional handling below) */ + lbc == UTF8PROC_BOUNDCLASS_E_BASE_GAZ) && /* ---- */ + tbc == UTF8PROC_BOUNDCLASS_E_MODIFIER) ? false : /* ---- */ + (lbc == UTF8PROC_BOUNDCLASS_ZWJ && /* GB11 */ + (tbc == UTF8PROC_BOUNDCLASS_GLUE_AFTER_ZWJ || /* ---- */ + tbc == UTF8PROC_BOUNDCLASS_E_BASE_GAZ)) ? false : /* ---- */ + (lbc == UTF8PROC_BOUNDCLASS_REGIONAL_INDICATOR && /* GB12/13 (requires additional handling below) */ + tbc == UTF8PROC_BOUNDCLASS_REGIONAL_INDICATOR) ? false : /* ---- */ + true; /* GB999 */ +} + +static utf8proc_bool grapheme_break_extended(int lbc, int tbc, utf8proc_int32_t *state) +{ + utf8proc_bool break_permitted; + int lbc_override = lbc; + if (state && *state != UTF8PROC_BOUNDCLASS_START) + lbc_override = *state; + break_permitted = grapheme_break_simple(lbc_override, tbc); + if (state) { + /* Special support for GB 12/13 made possible by GB999. After two RI + class codepoints we want to force a break. Do this by resetting the + second RI's bound class to UTF8PROC_BOUNDCLASS_OTHER, to force a break + after that character according to GB999 (unless of course such a break is + forbidden by a different rule such as GB9). */ + if (*state == tbc && tbc == UTF8PROC_BOUNDCLASS_REGIONAL_INDICATOR) + *state = UTF8PROC_BOUNDCLASS_OTHER; + /* Special support for GB10. Fold any EXTEND codepoints into the previous + boundclass if we're dealing with an emoji base boundclass. */ + else if ((*state == UTF8PROC_BOUNDCLASS_E_BASE || + *state == UTF8PROC_BOUNDCLASS_E_BASE_GAZ) && + tbc == UTF8PROC_BOUNDCLASS_EXTEND) + *state = UTF8PROC_BOUNDCLASS_E_BASE; + else + *state = tbc; + } + return break_permitted; +} + +UTF8PROC_DLLEXPORT utf8proc_bool utf8proc_grapheme_break_stateful( + utf8proc_int32_t c1, utf8proc_int32_t c2, utf8proc_int32_t *state) { + + return grapheme_break_extended(utf8proc_get_property(c1)->boundclass, + utf8proc_get_property(c2)->boundclass, + state); +} + + +UTF8PROC_DLLEXPORT utf8proc_bool utf8proc_grapheme_break( + utf8proc_int32_t c1, utf8proc_int32_t c2) { + return utf8proc_grapheme_break_stateful(c1, c2, NULL); +} + +static utf8proc_int32_t seqindex_decode_entry(const utf8proc_uint16_t **entry) +{ + utf8proc_int32_t entry_cp = **entry; + if ((entry_cp & 0xF800) == 0xD800) { + *entry = *entry + 1; + entry_cp = ((entry_cp & 0x03FF) << 10) | (**entry & 0x03FF); + entry_cp += 0x10000; + } + return entry_cp; +} + +static utf8proc_int32_t seqindex_decode_index(const utf8proc_uint32_t seqindex) +{ + const utf8proc_uint16_t *entry = &utf8proc_sequences[seqindex]; + return seqindex_decode_entry(&entry); +} + +static utf8proc_ssize_t seqindex_write_char_decomposed(utf8proc_uint16_t seqindex, utf8proc_int32_t *dst, utf8proc_ssize_t bufsize, utf8proc_option_t options, int *last_boundclass) { + utf8proc_ssize_t written = 0; + const utf8proc_uint16_t *entry = &utf8proc_sequences[seqindex & 0x1FFF]; + int len = seqindex >> 13; + if (len >= 7) { + len = *entry; + entry++; + } + for (; len >= 0; entry++, len--) { + utf8proc_int32_t entry_cp = seqindex_decode_entry(&entry); + + written += utf8proc_decompose_char(entry_cp, dst+written, + (bufsize > written) ? (bufsize - written) : 0, options, + last_boundclass); + if (written < 0) return UTF8PROC_ERROR_OVERFLOW; + } + return written; +} + +UTF8PROC_DLLEXPORT utf8proc_int32_t utf8proc_tolower(utf8proc_int32_t c) +{ + utf8proc_int32_t cl = utf8proc_get_property(c)->lowercase_seqindex; + return cl != UINT16_MAX ? seqindex_decode_index(cl) : c; +} + +UTF8PROC_DLLEXPORT utf8proc_int32_t utf8proc_toupper(utf8proc_int32_t c) +{ + utf8proc_int32_t cu = utf8proc_get_property(c)->uppercase_seqindex; + return cu != UINT16_MAX ? seqindex_decode_index(cu) : c; +} + +UTF8PROC_DLLEXPORT utf8proc_int32_t utf8proc_totitle(utf8proc_int32_t c) +{ + utf8proc_int32_t cu = utf8proc_get_property(c)->titlecase_seqindex; + return cu != UINT16_MAX ? seqindex_decode_index(cu) : c; +} + +/* return a character width analogous to wcwidth (except portable and + hopefully less buggy than most system wcwidth functions). */ +UTF8PROC_DLLEXPORT int utf8proc_charwidth(utf8proc_int32_t c) { + return utf8proc_get_property(c)->charwidth; +} + +UTF8PROC_DLLEXPORT utf8proc_category_t utf8proc_category(utf8proc_int32_t c) { + return utf8proc_get_property(c)->category; +} + +UTF8PROC_DLLEXPORT const char *utf8proc_category_string(utf8proc_int32_t c) { + static const char s[][3] = {"Cn","Lu","Ll","Lt","Lm","Lo","Mn","Mc","Me","Nd","Nl","No","Pc","Pd","Ps","Pe","Pi","Pf","Po","Sm","Sc","Sk","So","Zs","Zl","Zp","Cc","Cf","Cs","Co"}; + return s[utf8proc_category(c)]; +} + #define utf8proc_decompose_lump(replacement_uc) \ return utf8proc_decompose_char((replacement_uc), dst, bufsize, \ options & ~UTF8PROC_LUMP, last_boundclass) -UTF8PROC_API -ssize_t utf8proc_decompose_char(int32_t uc, int32_t *dst, ssize_t bufsize, - int options, int *last_boundclass) { - /* ASSERT: uc >= 0 && uc < 0x110000 */ +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_char(utf8proc_int32_t uc, utf8proc_int32_t *dst, utf8proc_ssize_t bufsize, utf8proc_option_t options, int *last_boundclass) { const utf8proc_property_t *property; utf8proc_propval_t category; - int32_t hangul_sindex; - property = utf8proc_get_property(uc); + utf8proc_int32_t hangul_sindex; + if (uc < 0 || uc >= 0x110000) return UTF8PROC_ERROR_NOTASSIGNED; + property = unsafe_get_property(uc); category = property->category; hangul_sindex = uc - UTF8PROC_HANGUL_SBASE; if (options & (UTF8PROC_COMPOSE|UTF8PROC_DECOMPOSE)) { if (hangul_sindex >= 0 && hangul_sindex < UTF8PROC_HANGUL_SCOUNT) { - int32_t hangul_tindex; + utf8proc_int32_t hangul_tindex; if (bufsize >= 1) { dst[0] = UTF8PROC_HANGUL_LBASE + hangul_sindex / UTF8PROC_HANGUL_NCOUNT; @@ -285,79 +457,20 @@ ssize_t utf8proc_decompose_char(int32_t uc, int32_t *dst, ssize_t bufsize, category == UTF8PROC_CATEGORY_ME) return 0; } if (options & UTF8PROC_CASEFOLD) { - if (property->casefold_mapping) { - const int32_t *casefold_entry; - ssize_t written = 0; - for (casefold_entry = property->casefold_mapping; - *casefold_entry >= 0; casefold_entry++) { - written += utf8proc_decompose_char(*casefold_entry, dst+written, - (bufsize > written) ? (bufsize - written) : 0, options, - last_boundclass); - if (written < 0) return UTF8PROC_ERROR_OVERFLOW; - } - return written; + if (property->casefold_seqindex != UINT16_MAX) { + return seqindex_write_char_decomposed(property->casefold_seqindex, dst, bufsize, options, last_boundclass); } } if (options & (UTF8PROC_COMPOSE|UTF8PROC_DECOMPOSE)) { - if (property->decomp_mapping && + if (property->decomp_seqindex != UINT16_MAX && (!property->decomp_type || (options & UTF8PROC_COMPAT))) { - const int32_t *decomp_entry; - ssize_t written = 0; - for (decomp_entry = property->decomp_mapping; - *decomp_entry >= 0; decomp_entry++) { - written += utf8proc_decompose_char(*decomp_entry, dst+written, - (bufsize > written) ? (bufsize - written) : 0, options, - last_boundclass); - if (written < 0) return UTF8PROC_ERROR_OVERFLOW; - } - return written; + return seqindex_write_char_decomposed(property->decomp_seqindex, dst, bufsize, options, last_boundclass); } } if (options & UTF8PROC_CHARBOUND) { - bool boundary; - int tbc, lbc; - tbc = - (uc == 0x000D) ? UTF8PROC_BOUNDCLASS_CR : - (uc == 0x000A) ? UTF8PROC_BOUNDCLASS_LF : - ((category == UTF8PROC_CATEGORY_ZL || - category == UTF8PROC_CATEGORY_ZP || - category == UTF8PROC_CATEGORY_CC || - category == UTF8PROC_CATEGORY_CF) && - !(uc == 0x200C || uc == 0x200D)) ? UTF8PROC_BOUNDCLASS_CONTROL : - property->extend ? UTF8PROC_BOUNDCLASS_EXTEND : - ((uc >= UTF8PROC_HANGUL_L_START && uc < UTF8PROC_HANGUL_L_END) || - uc == UTF8PROC_HANGUL_L_FILLER) ? UTF8PROC_BOUNDCLASS_L : - (uc >= UTF8PROC_HANGUL_V_START && uc < UTF8PROC_HANGUL_V_END) ? - UTF8PROC_BOUNDCLASS_V : - (uc >= UTF8PROC_HANGUL_T_START && uc < UTF8PROC_HANGUL_T_END) ? - UTF8PROC_BOUNDCLASS_T : - (uc >= UTF8PROC_HANGUL_S_START && uc < UTF8PROC_HANGUL_S_END) ? ( - ((uc-UTF8PROC_HANGUL_SBASE) % UTF8PROC_HANGUL_TCOUNT == 0) ? - UTF8PROC_BOUNDCLASS_LV : UTF8PROC_BOUNDCLASS_LVT - ) : - UTF8PROC_BOUNDCLASS_OTHER; - lbc = *last_boundclass; - boundary = - (tbc == UTF8PROC_BOUNDCLASS_EXTEND) ? false : - (lbc == UTF8PROC_BOUNDCLASS_START) ? true : - (lbc == UTF8PROC_BOUNDCLASS_CR && - tbc == UTF8PROC_BOUNDCLASS_LF) ? false : - (lbc == UTF8PROC_BOUNDCLASS_CONTROL) ? true : - (tbc == UTF8PROC_BOUNDCLASS_CONTROL) ? true : - (lbc == UTF8PROC_BOUNDCLASS_L && - (tbc == UTF8PROC_BOUNDCLASS_L || - tbc == UTF8PROC_BOUNDCLASS_V || - tbc == UTF8PROC_BOUNDCLASS_LV || - tbc == UTF8PROC_BOUNDCLASS_LVT)) ? false : - ((lbc == UTF8PROC_BOUNDCLASS_LV || - lbc == UTF8PROC_BOUNDCLASS_V) && - (tbc == UTF8PROC_BOUNDCLASS_V || - tbc == UTF8PROC_BOUNDCLASS_T)) ? false : - ((lbc == UTF8PROC_BOUNDCLASS_LVT || - lbc == UTF8PROC_BOUNDCLASS_T) && - tbc == UTF8PROC_BOUNDCLASS_T) ? false : - true; - *last_boundclass = tbc; + utf8proc_bool boundary; + int tbc = property->boundclass; + boundary = grapheme_break_extended(*last_boundclass, tbc, last_boundclass); if (boundary) { if (bufsize >= 1) dst[0] = 0xFFFF; if (bufsize >= 2) dst[1] = uc; @@ -368,27 +481,34 @@ ssize_t utf8proc_decompose_char(int32_t uc, int32_t *dst, ssize_t bufsize, return 1; } -UTF8PROC_API -ssize_t utf8proc_decompose( - const uint8_t *str, ssize_t strlen, - int32_t *buffer, ssize_t bufsize, int options +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose( + const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, + utf8proc_int32_t *buffer, utf8proc_ssize_t bufsize, utf8proc_option_t options +) { + return utf8proc_decompose_custom(str, strlen, buffer, bufsize, options, NULL, NULL); +} + +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_custom( + const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, + utf8proc_int32_t *buffer, utf8proc_ssize_t bufsize, utf8proc_option_t options, + utf8proc_custom_func custom_func, void *custom_data ) { /* strlen will be ignored, if UTF8PROC_NULLTERM is set in options */ - ssize_t wpos = 0; + utf8proc_ssize_t wpos = 0; if ((options & UTF8PROC_COMPOSE) && (options & UTF8PROC_DECOMPOSE)) return UTF8PROC_ERROR_INVALIDOPTS; if ((options & UTF8PROC_STRIPMARK) && !(options & UTF8PROC_COMPOSE) && !(options & UTF8PROC_DECOMPOSE)) return UTF8PROC_ERROR_INVALIDOPTS; { - int32_t uc; - ssize_t rpos = 0; - ssize_t decomp_result; + utf8proc_int32_t uc; + utf8proc_ssize_t rpos = 0; + utf8proc_ssize_t decomp_result; int boundclass = UTF8PROC_BOUNDCLASS_START; while (1) { if (options & UTF8PROC_NULLTERM) { rpos += utf8proc_iterate(str + rpos, -1, &uc); - /* checking of return value is not neccessary, + /* checking of return value is not necessary, as 'uc' is < 0 in case of error */ if (uc < 0) return UTF8PROC_ERROR_INVALIDUTF8; if (rpos < 0) return UTF8PROC_ERROR_OVERFLOW; @@ -398,6 +518,9 @@ ssize_t utf8proc_decompose( rpos += utf8proc_iterate(str + rpos, strlen - rpos, &uc); if (uc < 0) return UTF8PROC_ERROR_INVALIDUTF8; } + if (custom_func != NULL) { + uc = custom_func(uc, custom_data); /* user-specified custom mapping */ + } decomp_result = utf8proc_decompose_char( uc, buffer + wpos, (bufsize > wpos) ? (bufsize - wpos) : 0, options, &boundclass @@ -405,19 +528,20 @@ ssize_t utf8proc_decompose( if (decomp_result < 0) return decomp_result; wpos += decomp_result; /* prohibiting integer overflows due to too long strings: */ - if (wpos < 0 || wpos > SSIZE_MAX/sizeof(int32_t)/2) + if (wpos < 0 || + wpos > (utf8proc_ssize_t)(SSIZE_MAX/sizeof(utf8proc_int32_t)/2)) return UTF8PROC_ERROR_OVERFLOW; } } if ((options & (UTF8PROC_COMPOSE|UTF8PROC_DECOMPOSE)) && bufsize >= wpos) { - ssize_t pos = 0; + utf8proc_ssize_t pos = 0; while (pos < wpos-1) { - int32_t uc1, uc2; + utf8proc_int32_t uc1, uc2; const utf8proc_property_t *property1, *property2; uc1 = buffer[pos]; uc2 = buffer[pos+1]; - property1 = utf8proc_get_property(uc1); - property2 = utf8proc_get_property(uc2); + property1 = unsafe_get_property(uc1); + property2 = unsafe_get_property(uc2); if (property1->combining_class > property2->combining_class && property2->combining_class > 0) { buffer[pos] = uc2; @@ -431,14 +555,12 @@ ssize_t utf8proc_decompose( return wpos; } -UTF8PROC_API -ssize_t utf8proc_reencode(int32_t *buffer, ssize_t length, int options) { - /* UTF8PROC_NULLTERM option will be ignored, 'length' is never ignored - ASSERT: 'buffer' has one spare byte of free space at the end! */ +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_normalize_utf32(utf8proc_int32_t *buffer, utf8proc_ssize_t length, utf8proc_option_t options) { + /* UTF8PROC_NULLTERM option will be ignored, 'length' is never ignored */ if (options & (UTF8PROC_NLF2LS | UTF8PROC_NLF2PS | UTF8PROC_STRIPCC)) { - ssize_t rpos; - ssize_t wpos = 0; - int32_t uc; + utf8proc_ssize_t rpos; + utf8proc_ssize_t wpos = 0; + utf8proc_int32_t uc; for (rpos = 0; rpos < length; rpos++) { uc = buffer[rpos]; if (uc == 0x000D && rpos < length-1 && buffer[rpos+1] == 0x000A) rpos++; @@ -467,23 +589,23 @@ ssize_t utf8proc_reencode(int32_t *buffer, ssize_t length, int options) { length = wpos; } if (options & UTF8PROC_COMPOSE) { - int32_t *starter = NULL; - int32_t current_char; + utf8proc_int32_t *starter = NULL; + utf8proc_int32_t current_char; const utf8proc_property_t *starter_property = NULL, *current_property; utf8proc_propval_t max_combining_class = -1; - ssize_t rpos; - ssize_t wpos = 0; - int32_t composition; + utf8proc_ssize_t rpos; + utf8proc_ssize_t wpos = 0; + utf8proc_int32_t composition; for (rpos = 0; rpos < length; rpos++) { current_char = buffer[rpos]; - current_property = utf8proc_get_property(current_char); + current_property = unsafe_get_property(current_char); if (starter && current_property->combining_class > max_combining_class) { /* combination perhaps possible */ - int32_t hangul_lindex; - int32_t hangul_sindex; + utf8proc_int32_t hangul_lindex; + utf8proc_int32_t hangul_sindex; hangul_lindex = *starter - UTF8PROC_HANGUL_LBASE; if (hangul_lindex >= 0 && hangul_lindex < UTF8PROC_HANGUL_LCOUNT) { - int32_t hangul_vindex; + utf8proc_int32_t hangul_vindex; hangul_vindex = current_char - UTF8PROC_HANGUL_VBASE; if (hangul_vindex >= 0 && hangul_vindex < UTF8PROC_HANGUL_VCOUNT) { *starter = UTF8PROC_HANGUL_SBASE + @@ -496,7 +618,7 @@ ssize_t utf8proc_reencode(int32_t *buffer, ssize_t length, int options) { hangul_sindex = *starter - UTF8PROC_HANGUL_SBASE; if (hangul_sindex >= 0 && hangul_sindex < UTF8PROC_HANGUL_SCOUNT && (hangul_sindex % UTF8PROC_HANGUL_TCOUNT) == 0) { - int32_t hangul_tindex; + utf8proc_int32_t hangul_tindex; hangul_tindex = current_char - UTF8PROC_HANGUL_TBASE; if (hangul_tindex >= 0 && hangul_tindex < UTF8PROC_HANGUL_TCOUNT) { *starter += hangul_tindex; @@ -505,19 +627,26 @@ ssize_t utf8proc_reencode(int32_t *buffer, ssize_t length, int options) { } } if (!starter_property) { - starter_property = utf8proc_get_property(*starter); + starter_property = unsafe_get_property(*starter); } - if (starter_property->comb1st_index >= 0 && - current_property->comb2nd_index >= 0) { - composition = utf8proc_combinations[ - starter_property->comb1st_index + - current_property->comb2nd_index - ]; - if (composition >= 0 && (!(options & UTF8PROC_STABLE) || - !(utf8proc_get_property(composition)->comp_exclusion))) { - *starter = composition; - starter_property = NULL; - continue; + if (starter_property->comb_index < 0x8000 && + current_property->comb_index != UINT16_MAX && + current_property->comb_index >= 0x8000) { + int sidx = starter_property->comb_index; + int idx = (current_property->comb_index & 0x3FFF) - utf8proc_combinations[sidx]; + if (idx >= 0 && idx <= utf8proc_combinations[sidx + 1] ) { + idx += sidx + 2; + if (current_property->comb_index & 0x4000) { + composition = (utf8proc_combinations[idx] << 16) | utf8proc_combinations[idx+1]; + } else + composition = utf8proc_combinations[idx]; + + if (composition > 0 && (!(options & UTF8PROC_STABLE) || + !(unsafe_get_property(composition)->comp_exclusion))) { + *starter = composition; + starter_property = NULL; + continue; + } } } } @@ -535,30 +664,51 @@ ssize_t utf8proc_reencode(int32_t *buffer, ssize_t length, int options) { } length = wpos; } + return length; +} + +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_reencode(utf8proc_int32_t *buffer, utf8proc_ssize_t length, utf8proc_option_t options) { + /* UTF8PROC_NULLTERM option will be ignored, 'length' is never ignored + ASSERT: 'buffer' has one spare byte of free space at the end! */ + length = utf8proc_normalize_utf32(buffer, length, options); + if (length < 0) return length; { - ssize_t rpos, wpos = 0; - int32_t uc; - for (rpos = 0; rpos < length; rpos++) { - uc = buffer[rpos]; - wpos += utf8proc_encode_char(uc, ((uint8_t *)buffer) + wpos); + utf8proc_ssize_t rpos, wpos = 0; + utf8proc_int32_t uc; + if (options & UTF8PROC_CHARBOUND) { + for (rpos = 0; rpos < length; rpos++) { + uc = buffer[rpos]; + wpos += unsafe_encode_char(uc, ((utf8proc_uint8_t *)buffer) + wpos); + } + } else { + for (rpos = 0; rpos < length; rpos++) { + uc = buffer[rpos]; + wpos += utf8proc_encode_char(uc, ((utf8proc_uint8_t *)buffer) + wpos); + } } - ((uint8_t *)buffer)[wpos] = 0; + ((utf8proc_uint8_t *)buffer)[wpos] = 0; return wpos; } } -UTF8PROC_API -ssize_t utf8proc_map( - const uint8_t *str, ssize_t strlen, uint8_t **dstptr, int options +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_map( + const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, utf8proc_uint8_t **dstptr, utf8proc_option_t options ) { - int32_t *buffer; - ssize_t result; + return utf8proc_map_custom(str, strlen, dstptr, options, NULL, NULL); +} + +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_map_custom( + const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, utf8proc_uint8_t **dstptr, utf8proc_option_t options, + utf8proc_custom_func custom_func, void *custom_data +) { + utf8proc_int32_t *buffer; + utf8proc_ssize_t result; *dstptr = NULL; - result = utf8proc_decompose(str, strlen, NULL, 0, options); + result = utf8proc_decompose_custom(str, strlen, NULL, 0, options, custom_func, custom_data); if (result < 0) return result; - buffer = malloc(result * sizeof(int32_t) + 1); + buffer = (utf8proc_int32_t *) malloc(result * sizeof(utf8proc_int32_t) + 1); if (!buffer) return UTF8PROC_ERROR_NOMEM; - result = utf8proc_decompose(str, strlen, buffer, result, options); + result = utf8proc_decompose_custom(str, strlen, buffer, result, options, custom_func, custom_data); if (result < 0) { free(buffer); return result; @@ -569,43 +719,38 @@ ssize_t utf8proc_map( return result; } { - int32_t *newptr; - newptr = realloc(buffer, (size_t)result+1); + utf8proc_int32_t *newptr; + newptr = (utf8proc_int32_t *) realloc(buffer, (size_t)result+1); if (newptr) buffer = newptr; } - *dstptr = (uint8_t *)buffer; + *dstptr = (utf8proc_uint8_t *)buffer; return result; } -UTF8PROC_API -uint8_t *utf8proc_NFD(const uint8_t *str) { - uint8_t *retval; +UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFD(const utf8proc_uint8_t *str) { + utf8proc_uint8_t *retval; utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE | UTF8PROC_DECOMPOSE); return retval; } -UTF8PROC_API -uint8_t *utf8proc_NFC(const uint8_t *str) { - uint8_t *retval; +UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFC(const utf8proc_uint8_t *str) { + utf8proc_uint8_t *retval; utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE | UTF8PROC_COMPOSE); return retval; } -UTF8PROC_API -uint8_t *utf8proc_NFKD(const uint8_t *str) { - uint8_t *retval; +UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKD(const utf8proc_uint8_t *str) { + utf8proc_uint8_t *retval; utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE | UTF8PROC_DECOMPOSE | UTF8PROC_COMPAT); return retval; } -UTF8PROC_API -uint8_t *utf8proc_NFKC(const uint8_t *str) { - uint8_t *retval; +UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKC(const utf8proc_uint8_t *str) { + utf8proc_uint8_t *retval; utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE | UTF8PROC_COMPOSE | UTF8PROC_COMPAT); return retval; } - diff --git a/subversion/libsvn_subr/utf8proc/utf8proc.h b/subversion/libsvn_subr/utf8proc/utf8proc.h deleted file mode 100644 index 25ca139b65cd..000000000000 --- a/subversion/libsvn_subr/utf8proc/utf8proc.h +++ /dev/null @@ -1,447 +0,0 @@ -/* - * Copyright (c) 2009 Public Software Group e. V., Berlin, Germany - * - * 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. - */ - - -/* - * File name: utf8proc.h - * - * Description: - * Header files for libutf8proc, which is a mapping tool for UTF-8 strings - * with following features: - * - decomposing and composing of strings - * - replacing compatibility characters with their equivalents - * - stripping of "default ignorable characters" - * like SOFT-HYPHEN or ZERO-WIDTH-SPACE - * - folding of certain characters for string comparison - * (e.g. HYPHEN U+2010 and MINUS U+2212 to ASCII "-") - * (see "LUMP" option) - * - optional rejection of strings containing non-assigned code points - * - stripping of control characters - * - stripping of character marks (accents, etc.) - * - transformation of LF, CRLF, CR and NEL to line-feed (LF) - * or to the unicode chararacters for paragraph separation (PS) - * or line separation (LS). - * - unicode case folding (for case insensitive string comparisons) - * - rejection of illegal UTF-8 data - * (i.e. UTF-8 encoded UTF-16 surrogates) - * - support for korean hangul characters - * Unicode Version 5.0.0 is supported. - */ - - -#ifndef UTF8PROC_H -#define UTF8PROC_H - -/** @name API version - * - * The utf8proc API version MAJOR.MINOR.PATCH, following - * semantic-versioning rules (http://semver.org) based on API - * compatibility. - * - * This is also returned at runtime by @ref utf8proc_version; however, the - * runtime version may append a string like "-dev" to the version number - * for prerelease versions. - * - * @note The shared-library version number in the Makefile may be different, - * being based on ABI compatibility rather than API compatibility. - */ -/** @{ */ -/** The MAJOR version number (increased when backwards API compatibility is broken). */ -#define UTF8PROC_VERSION_MAJOR 1 -/** The MINOR version number (increased when new functionality is added in a backwards-compatible manner). */ -#define UTF8PROC_VERSION_MINOR 1 -/** The PATCH version (increased for fixes that do not change the API). */ -#define UTF8PROC_VERSION_PATCH 5 -/** @} */ - -/* - * Define UTF8PROC_INLINE and include utf8proc.c to embed a static - * version of utf8proc in your program or library without exporting - * any of its symbols. - */ -#ifdef UTF8PROC_INLINE -#define UTF8PROC_API static -#undef UTF8PROC_DATA_EXPORT -#define UTF8PROC_DATA static -#else -#define UTF8PROC_API -#define UTF8PROC_DATA_EXPORT -#define UTF8PROC_DATA -#endif - - -#include -#include -#ifdef _MSC_VER -# if _MSC_VER >= 1900 -# include -# include -# else - typedef signed char int8_t; - typedef unsigned char uint8_t; - typedef short int16_t; - typedef unsigned short uint16_t; - typedef int int32_t; - typedef unsigned char bool; - enum {false, true}; -# endif -# ifdef _WIN64 -# define ssize_t __int64 -# else -# define ssize_t int -# endif -#elif defined(HAVE_STDBOOL_H) && defined(HAVE_INTTYPES_H) -#include -#include -#else -#include -typedef uint8_t bool; -enum {false, true}; -#endif -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef SSIZE_MAX -#define SSIZE_MAX ((size_t)SIZE_MAX/2) -#endif - -#define UTF8PROC_NULLTERM (1<<0) -#define UTF8PROC_STABLE (1<<1) -#define UTF8PROC_COMPAT (1<<2) -#define UTF8PROC_COMPOSE (1<<3) -#define UTF8PROC_DECOMPOSE (1<<4) -#define UTF8PROC_IGNORE (1<<5) -#define UTF8PROC_REJECTNA (1<<6) -#define UTF8PROC_NLF2LS (1<<7) -#define UTF8PROC_NLF2PS (1<<8) -#define UTF8PROC_NLF2LF (UTF8PROC_NLF2LS | UTF8PROC_NLF2PS) -#define UTF8PROC_STRIPCC (1<<9) -#define UTF8PROC_CASEFOLD (1<<10) -#define UTF8PROC_CHARBOUND (1<<11) -#define UTF8PROC_LUMP (1<<12) -#define UTF8PROC_STRIPMARK (1<<13) -/* - * Flags being regarded by several functions in the library: - * NULLTERM: The given UTF-8 input is NULL terminated. - * STABLE: Unicode Versioning Stability has to be respected. - * COMPAT: Compatiblity decomposition - * (i.e. formatting information is lost) - * COMPOSE: Return a result with composed characters. - * DECOMPOSE: Return a result with decomposed characters. - * IGNORE: Strip "default ignorable characters" - * REJECTNA: Return an error, if the input contains unassigned - * code points. - * NLF2LS: Indicating that NLF-sequences (LF, CRLF, CR, NEL) are - * representing a line break, and should be converted to the - * unicode character for line separation (LS). - * NLF2PS: Indicating that NLF-sequences are representing a paragraph - * break, and should be converted to the unicode character for - * paragraph separation (PS). - * NLF2LF: Indicating that the meaning of NLF-sequences is unknown. - * STRIPCC: Strips and/or convers control characters. - * NLF-sequences are transformed into space, except if one of - * the NLF2LS/PS/LF options is given. - * HorizontalTab (HT) and FormFeed (FF) are treated as a - * NLF-sequence in this case. - * All other control characters are simply removed. - * CASEFOLD: Performs unicode case folding, to be able to do a - * case-insensitive string comparison. - * CHARBOUND: Inserts 0xFF bytes at the beginning of each sequence which - * is representing a single grapheme cluster (see UAX#29). - * LUMP: Lumps certain characters together - * (e.g. HYPHEN U+2010 and MINUS U+2212 to ASCII "-"). - * (See lump.txt for details.) - * If NLF2LF is set, this includes a transformation of - * paragraph and line separators to ASCII line-feed (LF). - * STRIPMARK: Strips all character markings - * (non-spacing, spacing and enclosing) (i.e. accents) - * NOTE: this option works only with COMPOSE or DECOMPOSE - */ - -#define UTF8PROC_ERROR_NOMEM -1 -#define UTF8PROC_ERROR_OVERFLOW -2 -#define UTF8PROC_ERROR_INVALIDUTF8 -3 -#define UTF8PROC_ERROR_NOTASSIGNED -4 -#define UTF8PROC_ERROR_INVALIDOPTS -5 -/* - * Error codes being returned by almost all functions: - * ERROR_NOMEM: Memory could not be allocated. - * ERROR_OVERFLOW: The given string is too long to be processed. - * ERROR_INVALIDUTF8: The given string is not a legal UTF-8 string. - * ERROR_NOTASSIGNED: The REJECTNA flag was set, - * and an unassigned code point was found. - * ERROR_INVALIDOPTS: Invalid options have been used. - */ - -typedef int16_t utf8proc_propval_t; -typedef struct utf8proc_property_struct { - utf8proc_propval_t category; - utf8proc_propval_t combining_class; - utf8proc_propval_t bidi_class; - utf8proc_propval_t decomp_type; - const int32_t *decomp_mapping; - unsigned bidi_mirrored:1; - int32_t uppercase_mapping; - int32_t lowercase_mapping; - int32_t titlecase_mapping; - int32_t comb1st_index; - int32_t comb2nd_index; - unsigned comp_exclusion:1; - unsigned ignorable:1; - unsigned control_boundary:1; - unsigned extend:1; - const int32_t *casefold_mapping; -} utf8proc_property_t; - -#define UTF8PROC_CATEGORY_LU 1 -#define UTF8PROC_CATEGORY_LL 2 -#define UTF8PROC_CATEGORY_LT 3 -#define UTF8PROC_CATEGORY_LM 4 -#define UTF8PROC_CATEGORY_LO 5 -#define UTF8PROC_CATEGORY_MN 6 -#define UTF8PROC_CATEGORY_MC 7 -#define UTF8PROC_CATEGORY_ME 8 -#define UTF8PROC_CATEGORY_ND 9 -#define UTF8PROC_CATEGORY_NL 10 -#define UTF8PROC_CATEGORY_NO 11 -#define UTF8PROC_CATEGORY_PC 12 -#define UTF8PROC_CATEGORY_PD 13 -#define UTF8PROC_CATEGORY_PS 14 -#define UTF8PROC_CATEGORY_PE 15 -#define UTF8PROC_CATEGORY_PI 16 -#define UTF8PROC_CATEGORY_PF 17 -#define UTF8PROC_CATEGORY_PO 18 -#define UTF8PROC_CATEGORY_SM 19 -#define UTF8PROC_CATEGORY_SC 20 -#define UTF8PROC_CATEGORY_SK 21 -#define UTF8PROC_CATEGORY_SO 22 -#define UTF8PROC_CATEGORY_ZS 23 -#define UTF8PROC_CATEGORY_ZL 24 -#define UTF8PROC_CATEGORY_ZP 25 -#define UTF8PROC_CATEGORY_CC 26 -#define UTF8PROC_CATEGORY_CF 27 -#define UTF8PROC_CATEGORY_CS 28 -#define UTF8PROC_CATEGORY_CO 29 -#define UTF8PROC_CATEGORY_CN 30 -#define UTF8PROC_BIDI_CLASS_L 1 -#define UTF8PROC_BIDI_CLASS_LRE 2 -#define UTF8PROC_BIDI_CLASS_LRO 3 -#define UTF8PROC_BIDI_CLASS_R 4 -#define UTF8PROC_BIDI_CLASS_AL 5 -#define UTF8PROC_BIDI_CLASS_RLE 6 -#define UTF8PROC_BIDI_CLASS_RLO 7 -#define UTF8PROC_BIDI_CLASS_PDF 8 -#define UTF8PROC_BIDI_CLASS_EN 9 -#define UTF8PROC_BIDI_CLASS_ES 10 -#define UTF8PROC_BIDI_CLASS_ET 11 -#define UTF8PROC_BIDI_CLASS_AN 12 -#define UTF8PROC_BIDI_CLASS_CS 13 -#define UTF8PROC_BIDI_CLASS_NSM 14 -#define UTF8PROC_BIDI_CLASS_BN 15 -#define UTF8PROC_BIDI_CLASS_B 16 -#define UTF8PROC_BIDI_CLASS_S 17 -#define UTF8PROC_BIDI_CLASS_WS 18 -#define UTF8PROC_BIDI_CLASS_ON 19 -#define UTF8PROC_DECOMP_TYPE_FONT 1 -#define UTF8PROC_DECOMP_TYPE_NOBREAK 2 -#define UTF8PROC_DECOMP_TYPE_INITIAL 3 -#define UTF8PROC_DECOMP_TYPE_MEDIAL 4 -#define UTF8PROC_DECOMP_TYPE_FINAL 5 -#define UTF8PROC_DECOMP_TYPE_ISOLATED 6 -#define UTF8PROC_DECOMP_TYPE_CIRCLE 7 -#define UTF8PROC_DECOMP_TYPE_SUPER 8 -#define UTF8PROC_DECOMP_TYPE_SUB 9 -#define UTF8PROC_DECOMP_TYPE_VERTICAL 10 -#define UTF8PROC_DECOMP_TYPE_WIDE 11 -#define UTF8PROC_DECOMP_TYPE_NARROW 12 -#define UTF8PROC_DECOMP_TYPE_SMALL 13 -#define UTF8PROC_DECOMP_TYPE_SQUARE 14 -#define UTF8PROC_DECOMP_TYPE_FRACTION 15 -#define UTF8PROC_DECOMP_TYPE_COMPAT 16 - -#ifdef UTF8PROC_DATA_EXPORT -extern const int8_t utf8proc_utf8class[256]; -#endif - -UTF8PROC_API -const char *utf8proc_version(void); - -UTF8PROC_API -const char *utf8proc_errmsg(ssize_t errcode); -/* - * Returns a static error string for the given error code. - */ - -UTF8PROC_API -ssize_t utf8proc_iterate(const uint8_t *str, ssize_t strlen, int32_t *dst); -/* - * Reads a single char from the UTF-8 sequence being pointed to by 'str'. - * The maximum number of bytes read is 'strlen', unless 'strlen' is - * negative. - * If a valid unicode char could be read, it is stored in the variable - * being pointed to by 'dst', otherwise that variable will be set to -1. - * In case of success the number of bytes read is returned, otherwise a - * negative error code is returned. - */ - -UTF8PROC_API -bool utf8proc_codepoint_valid(int32_t uc); -/* - * Returns 1, if the given unicode code-point is valid, otherwise 0. - */ - -UTF8PROC_API -ssize_t utf8proc_encode_char(int32_t uc, uint8_t *dst); -/* - * Encodes the unicode char with the code point 'uc' as an UTF-8 string in - * the byte array being pointed to by 'dst'. This array has to be at least - * 4 bytes long. - * In case of success the number of bytes written is returned, - * otherwise 0. - * This function does not check if 'uc' is a valid unicode code point. - */ - -UTF8PROC_API -const utf8proc_property_t *utf8proc_get_property(int32_t uc); -/* - * Returns a pointer to a (constant) struct containing information about - * the unicode char with the given code point 'uc'. - * If the character is not existent a pointer to a special struct is - * returned, where 'category' is a NULL pointer. - * WARNING: The parameter 'uc' has to be in the range of 0x0000 to - * 0x10FFFF, otherwise the program might crash! - */ - -UTF8PROC_API -ssize_t utf8proc_decompose_char( - int32_t uc, int32_t *dst, ssize_t bufsize, - int options, int *last_boundclass -); -/* - * Writes a decomposition of the unicode char 'uc' into the array being - * pointed to by 'dst'. - * Following flags in the 'options' field are regarded: - * REJECTNA: an unassigned unicode code point leads to an error - * IGNORE: "default ignorable" chars are stripped - * CASEFOLD: unicode casefolding is applied - * COMPAT: replace certain characters with their - * compatibility decomposition - * CHARBOUND: Inserts 0xFF bytes before each grapheme cluster - * LUMP: lumps certain different characters together - * STRIPMARK: removes all character marks - * The pointer 'last_boundclass' has to point to an integer variable which - * is storing the last character boundary class, if the CHARBOUND option - * is used. - * In case of success the number of chars written is returned, - * in case of an error, a negative error code is returned. - * If the number of written chars would be bigger than 'bufsize', - * the buffer (up to 'bufsize') has inpredictable data, and the needed - * buffer size is returned. - * WARNING: The parameter 'uc' has to be in the range of 0x0000 to - * 0x10FFFF, otherwise the program might crash! - */ - -UTF8PROC_API -ssize_t utf8proc_decompose( - const uint8_t *str, ssize_t strlen, - int32_t *buffer, ssize_t bufsize, int options -); -/* - * Does the same as 'utf8proc_decompose_char', but acts on a whole UTF-8 - * string, and orders the decomposed sequences correctly. - * If the NULLTERM flag in 'options' is set, processing will be stopped, - * when a NULL byte is encounted, otherwise 'strlen' bytes are processed. - * The result in form of unicode code points is written into the buffer - * being pointed to by 'buffer', having the length of 'bufsize' entries. - * In case of success the number of chars written is returned, - * in case of an error, a negative error code is returned. - * If the number of written chars would be bigger than 'bufsize', - * the buffer (up to 'bufsize') has inpredictable data, and the needed - * buffer size is returned. - */ - -UTF8PROC_API -ssize_t utf8proc_reencode(int32_t *buffer, ssize_t length, int options); -/* - * Reencodes the sequence of unicode characters given by the pointer - * 'buffer' and 'length' as UTF-8. - * The result is stored in the same memory area where the data is read. - * Following flags in the 'options' field are regarded: - * NLF2LS: converts LF, CRLF, CR and NEL into LS - * NLF2PS: converts LF, CRLF, CR and NEL into PS - * NLF2LF: converts LF, CRLF, CR and NEL into LF - * STRIPCC: strips or converts all non-affected control characters - * COMPOSE: tries to combine decomposed characters into composite - * characters - * STABLE: prohibits combining characters which would violate - * the unicode versioning stability - * In case of success the length of the resulting UTF-8 string is - * returned, otherwise a negative error code is returned. - * WARNING: The amount of free space being pointed to by 'buffer', has to - * exceed the amount of the input data by one byte, and the - * entries of the array pointed to by 'str' have to be in the - * range of 0x0000 to 0x10FFFF, otherwise the program might - * crash! - */ - -UTF8PROC_API -ssize_t utf8proc_map( - const uint8_t *str, ssize_t strlen, uint8_t **dstptr, int options -); -/* - * Maps the given UTF-8 string being pointed to by 'str' to a new UTF-8 - * string, which is allocated dynamically, and afterwards pointed to by - * the pointer being pointed to by 'dstptr'. - * If the NULLTERM flag in the 'options' field is set, the length is - * determined by a NULL terminator, otherwise the parameter 'strlen' is - * evaluated to determine the string length, but in any case the result - * will be NULL terminated (though it might contain NULL characters - * before). Other flags in the 'options' field are passed to the functions - * defined above, and regarded as described. - * In case of success the length of the new string is returned, - * otherwise a negative error code is returned. - * NOTICE: The memory of the new UTF-8 string will have been allocated with - * 'malloc', and has theirfore to be freed with 'free'. - */ - -UTF8PROC_API -uint8_t *utf8proc_NFD(const uint8_t *str); -UTF8PROC_API -uint8_t *utf8proc_NFC(const uint8_t *str); -UTF8PROC_API -uint8_t *utf8proc_NFKD(const uint8_t *str); -UTF8PROC_API -uint8_t *utf8proc_NFKC(const uint8_t *str); -/* - * Returns a pointer to newly allocated memory of a NFD, NFC, NFKD or NFKC - * normalized version of the null-terminated string 'str'. - */ - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/subversion/libsvn_subr/utf8proc/utf8proc_data.c b/subversion/libsvn_subr/utf8proc/utf8proc_data.c index 55ebb5327c7d..63ce17eda9f9 100644 --- a/subversion/libsvn_subr/utf8proc/utf8proc_data.c +++ b/subversion/libsvn_subr/utf8proc/utf8proc_data.c @@ -1,13388 +1,14391 @@ -/* - * This file contains derived data from a modified version of the - * Unicode data files. - * - * The original data files are available at - * http://www.unicode.org/Public/UNIDATA/ - * - * - * COPYRIGHT AND PERMISSION NOTICE - * - * Copyright (c) 1991-2007 Unicode, Inc. All rights reserved. Distributed - * under the Terms of Use in http://www.unicode.org/copyright.html. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of the Unicode data files and any associated documentation (the "Data - * Files") or Unicode software and any associated documentation (the - * "Software") to deal in the Data Files or Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, and/or sell copies of the Data Files or Software, and - * to permit persons to whom the Data Files or Software are furnished to do - * so, provided that (a) the above copyright notice(s) and this permission - * notice appear with all copies of the Data Files or Software, (b) both the - * above copyright notice(s) and this permission notice appear in associated - * documentation, and (c) there is clear notice in each modified Data File or - * in the Software as well as in the documentation associated with the Data - * File(s) or Software that the data or software has been modified. - * - * THE DATA FILES AND SOFTWARE ARE 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 OF - * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS - * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR - * CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF - * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THE DATA FILES OR SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder shall - * not be used in advertising or otherwise to promote the sale, use or other - * dealings in these Data Files or Software without prior written - * authorization of the copyright holder. - */ - +UTF8PROC_DATA +const utf8proc_uint16_t utf8proc_sequences[] = { + 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 32, 32, 776, 32, 772, + 50, 51, 32, 769, 956, 32, 807, 49, + 49, 8260, 52, 49, 8260, 50, 51, 8260, + 52, 65, 768, 224, 65, 769, 225, 65, + 770, 226, 65, 771, 227, 65, 776, 228, + 65, 778, 229, 230, 67, 807, 231, 69, + 768, 232, 69, 769, 233, 69, 770, 234, + 69, 776, 235, 73, 768, 236, 73, 769, + 237, 73, 770, 238, 73, 776, 239, 240, + 78, 771, 241, 79, 768, 242, 79, 769, + 243, 79, 770, 244, 79, 771, 245, 79, + 776, 246, 248, 85, 768, 249, 85, 769, + 250, 85, 770, 251, 85, 776, 252, 89, + 769, 253, 254, 115, 115, 97, 768, 97, + 769, 97, 770, 97, 771, 97, 776, 97, + 778, 99, 807, 101, 768, 101, 769, 101, + 770, 101, 776, 105, 768, 105, 769, 105, + 770, 105, 776, 110, 771, 111, 768, 111, + 769, 111, 770, 111, 771, 111, 776, 117, + 768, 117, 769, 117, 770, 117, 776, 121, + 769, 121, 776, 65, 772, 257, 97, 772, + 65, 774, 259, 97, 774, 65, 808, 261, + 97, 808, 67, 769, 263, 99, 769, 67, + 770, 265, 99, 770, 67, 775, 267, 99, + 775, 67, 780, 269, 99, 780, 68, 780, + 271, 100, 780, 273, 69, 772, 275, 101, + 772, 69, 774, 277, 101, 774, 69, 775, + 279, 101, 775, 69, 808, 281, 101, 808, + 69, 780, 283, 101, 780, 71, 770, 285, + 103, 770, 71, 774, 287, 103, 774, 71, + 775, 289, 103, 775, 71, 807, 291, 103, + 807, 72, 770, 293, 104, 770, 295, 73, + 771, 297, 105, 771, 73, 772, 299, 105, + 772, 73, 774, 301, 105, 774, 73, 808, + 303, 105, 808, 73, 775, 105, 775, 73, + 74, 307, 105, 106, 74, 770, 309, 106, + 770, 75, 807, 311, 107, 807, 76, 769, + 314, 108, 769, 76, 807, 316, 108, 807, + 76, 780, 318, 108, 780, 76, 183, 320, + 108, 183, 322, 78, 769, 324, 110, 769, + 78, 807, 326, 110, 807, 78, 780, 328, + 110, 780, 700, 110, 331, 79, 772, 333, + 111, 772, 79, 774, 335, 111, 774, 79, + 779, 337, 111, 779, 339, 82, 769, 341, + 114, 769, 82, 807, 343, 114, 807, 82, + 780, 345, 114, 780, 83, 769, 347, 115, + 769, 83, 770, 349, 115, 770, 83, 807, + 351, 115, 807, 83, 780, 353, 115, 780, + 84, 807, 355, 116, 807, 84, 780, 357, + 116, 780, 359, 85, 771, 361, 117, 771, + 85, 772, 363, 117, 772, 85, 774, 365, + 117, 774, 85, 778, 367, 117, 778, 85, + 779, 369, 117, 779, 85, 808, 371, 117, + 808, 87, 770, 373, 119, 770, 89, 770, + 375, 121, 770, 89, 776, 255, 90, 769, + 378, 122, 769, 90, 775, 380, 122, 775, + 90, 780, 382, 122, 780, 595, 387, 389, + 596, 392, 598, 599, 396, 477, 601, 603, + 402, 608, 611, 617, 616, 409, 623, 626, + 629, 79, 795, 417, 111, 795, 419, 421, + 640, 424, 643, 429, 648, 85, 795, 432, + 117, 795, 650, 651, 436, 438, 658, 441, + 445, 68, 381, 454, 68, 382, 100, 382, + 76, 74, 457, 76, 106, 108, 106, 78, + 74, 460, 78, 106, 110, 106, 65, 780, + 462, 97, 780, 73, 780, 464, 105, 780, + 79, 780, 466, 111, 780, 85, 780, 468, + 117, 780, 220, 772, 470, 252, 772, 220, + 769, 472, 252, 769, 220, 780, 474, 252, + 780, 220, 768, 476, 252, 768, 196, 772, + 479, 228, 772, 550, 772, 481, 551, 772, + 198, 772, 483, 230, 772, 485, 71, 780, + 487, 103, 780, 75, 780, 489, 107, 780, + 79, 808, 491, 111, 808, 490, 772, 493, + 491, 772, 439, 780, 495, 658, 780, 106, + 780, 68, 90, 499, 68, 122, 100, 122, + 71, 769, 501, 103, 769, 405, 447, 78, + 768, 505, 110, 768, 197, 769, 507, 229, + 769, 198, 769, 509, 230, 769, 216, 769, + 511, 248, 769, 65, 783, 513, 97, 783, + 65, 785, 515, 97, 785, 69, 783, 517, + 101, 783, 69, 785, 519, 101, 785, 73, + 783, 521, 105, 783, 73, 785, 523, 105, + 785, 79, 783, 525, 111, 783, 79, 785, + 527, 111, 785, 82, 783, 529, 114, 783, + 82, 785, 531, 114, 785, 85, 783, 533, + 117, 783, 85, 785, 535, 117, 785, 83, + 806, 537, 115, 806, 84, 806, 539, 116, + 806, 541, 72, 780, 543, 104, 780, 414, + 547, 549, 65, 775, 551, 97, 775, 69, + 807, 553, 101, 807, 214, 772, 555, 246, + 772, 213, 772, 557, 245, 772, 79, 775, + 559, 111, 775, 558, 772, 561, 559, 772, + 89, 772, 563, 121, 772, 11365, 572, 410, + 11366, 578, 384, 649, 652, 583, 585, 587, + 589, 591, 614, 633, 635, 641, 32, 774, + 32, 775, 32, 778, 32, 808, 32, 771, + 32, 779, 661, 768, 769, 787, 776, 769, + 953, 881, 883, 697, 887, 32, 837, 59, + 1011, 168, 769, 913, 769, 940, 183, 917, + 769, 941, 919, 769, 942, 921, 769, 943, + 927, 769, 972, 933, 769, 973, 937, 769, + 974, 970, 769, 953, 776, 769, 945, 946, + 947, 948, 949, 950, 951, 952, 954, 955, + 957, 958, 959, 960, 961, 963, 964, 965, + 966, 967, 968, 969, 921, 776, 970, 933, + 776, 971, 945, 769, 949, 769, 951, 769, + 953, 769, 971, 769, 965, 776, 769, 953, + 776, 965, 776, 959, 769, 965, 769, 969, + 769, 983, 933, 978, 769, 978, 776, 985, + 987, 989, 991, 993, 995, 997, 999, 1001, + 1003, 1005, 1007, 962, 920, 1016, 931, 1010, + 1019, 891, 892, 893, 1045, 768, 1104, 1045, + 776, 1105, 1106, 1043, 769, 1107, 1108, 1109, + 1110, 1030, 776, 1111, 1112, 1113, 1114, 1115, + 1050, 769, 1116, 1048, 768, 1117, 1059, 774, + 1118, 1119, 1072, 1073, 1074, 1075, 1076, 1077, + 1078, 1079, 1080, 1048, 774, 1081, 1082, 1083, + 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, + 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, + 1100, 1101, 1102, 1103, 1080, 774, 1077, 768, + 1077, 776, 1075, 769, 1110, 776, 1082, 769, + 1080, 768, 1091, 774, 1121, 1123, 1125, 1127, + 1129, 1131, 1133, 1135, 1137, 1139, 1141, 1140, + 783, 1143, 1141, 783, 1145, 1147, 1149, 1151, + 1153, 1163, 1165, 1167, 1169, 1171, 1173, 1175, + 1177, 1179, 1181, 1183, 1185, 1187, 1189, 1191, + 1193, 1195, 1197, 1199, 1201, 1203, 1205, 1207, + 1209, 1211, 1213, 1215, 1231, 1046, 774, 1218, + 1078, 774, 1220, 1222, 1224, 1226, 1228, 1230, + 1040, 774, 1233, 1072, 774, 1040, 776, 1235, + 1072, 776, 1237, 1045, 774, 1239, 1077, 774, + 1241, 1240, 776, 1243, 1241, 776, 1046, 776, + 1245, 1078, 776, 1047, 776, 1247, 1079, 776, + 1249, 1048, 772, 1251, 1080, 772, 1048, 776, + 1253, 1080, 776, 1054, 776, 1255, 1086, 776, + 1257, 1256, 776, 1259, 1257, 776, 1069, 776, + 1261, 1101, 776, 1059, 772, 1263, 1091, 772, + 1059, 776, 1265, 1091, 776, 1059, 779, 1267, + 1091, 779, 1063, 776, 1269, 1095, 776, 1271, + 1067, 776, 1273, 1099, 776, 1275, 1277, 1279, + 1281, 1283, 1285, 1287, 1289, 1291, 1293, 1295, + 1297, 1299, 1301, 1303, 1305, 1307, 1309, 1311, + 1313, 1315, 1317, 1319, 1321, 1323, 1325, 1327, + 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, + 1385, 1386, 1387, 1388, 1389, 1390, 1391, 1392, + 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, + 1401, 1402, 1403, 1404, 1405, 1406, 1407, 1408, + 1409, 1410, 1411, 1412, 1413, 1414, 1381, 1410, + 1575, 1619, 1575, 1620, 1608, 1620, 1575, 1621, + 1610, 1620, 1575, 1652, 1608, 1652, 1735, 1652, + 1610, 1652, 1749, 1620, 1729, 1620, 1746, 1620, + 2344, 2364, 2352, 2364, 2355, 2364, 2325, 2364, + 2326, 2364, 2327, 2364, 2332, 2364, 2337, 2364, + 2338, 2364, 2347, 2364, 2351, 2364, 2503, 2494, + 2503, 2519, 2465, 2492, 2466, 2492, 2479, 2492, + 2610, 2620, 2616, 2620, 2582, 2620, 2583, 2620, + 2588, 2620, 2603, 2620, 2887, 2902, 2887, 2878, + 2887, 2903, 2849, 2876, 2850, 2876, 2962, 3031, + 3014, 3006, 3015, 3006, 3014, 3031, 3142, 3158, + 3263, 3285, 3270, 3285, 3270, 3286, 3270, 3266, + 3274, 3285, 3398, 3390, 3399, 3390, 3398, 3415, + 3545, 3530, 3545, 3535, 3548, 3530, 3545, 3551, + 3661, 3634, 3789, 3762, 3755, 3737, 3755, 3745, + 3851, 3906, 4023, 3916, 4023, 3921, 4023, 3926, + 4023, 3931, 4023, 3904, 4021, 3953, 3954, 3953, + 3956, 4018, 3968, 4018, 3969, 4019, 3968, 4019, + 3969, 3953, 3968, 3986, 4023, 3996, 4023, 4001, + 4023, 4006, 4023, 4011, 4023, 3984, 4021, 4133, + 4142, 11520, 11521, 11522, 11523, 11524, 11525, 11526, + 11527, 11528, 11529, 11530, 11531, 11532, 11533, 11534, + 11535, 11536, 11537, 11538, 11539, 11540, 11541, 11542, + 11543, 11544, 11545, 11546, 11547, 11548, 11549, 11550, + 11551, 11552, 11553, 11554, 11555, 11556, 11557, 11559, + 11565, 4316, 5104, 5105, 5106, 5107, 5108, 5109, + 6917, 6965, 6919, 6965, 6921, 6965, 6923, 6965, + 6925, 6965, 6929, 6965, 6970, 6965, 6972, 6965, + 6974, 6965, 6975, 6965, 6978, 6965, 42571, 65, + 198, 66, 68, 69, 398, 71, 72, 73, + 74, 75, 76, 77, 78, 79, 546, 80, + 82, 84, 85, 87, 592, 593, 7426, 604, + 7446, 7447, 7453, 7461, 594, 597, 607, 609, + 613, 618, 7547, 669, 621, 7557, 671, 625, + 624, 627, 628, 632, 642, 427, 7452, 656, + 657, 65, 805, 7681, 97, 805, 66, 775, + 7683, 98, 775, 66, 803, 7685, 98, 803, + 66, 817, 7687, 98, 817, 199, 769, 7689, + 231, 769, 68, 775, 7691, 100, 775, 68, + 803, 7693, 100, 803, 68, 817, 7695, 100, + 817, 68, 807, 7697, 100, 807, 68, 813, + 7699, 100, 813, 274, 768, 7701, 275, 768, + 274, 769, 7703, 275, 769, 69, 813, 7705, + 101, 813, 69, 816, 7707, 101, 816, 552, + 774, 7709, 553, 774, 70, 775, 7711, 102, + 775, 71, 772, 7713, 103, 772, 72, 775, + 7715, 104, 775, 72, 803, 7717, 104, 803, + 72, 776, 7719, 104, 776, 72, 807, 7721, + 104, 807, 72, 814, 7723, 104, 814, 73, + 816, 7725, 105, 816, 207, 769, 7727, 239, + 769, 75, 769, 7729, 107, 769, 75, 803, + 7731, 107, 803, 75, 817, 7733, 107, 817, + 76, 803, 7735, 108, 803, 7734, 772, 7737, + 7735, 772, 76, 817, 7739, 108, 817, 76, + 813, 7741, 108, 813, 77, 769, 7743, 109, + 769, 77, 775, 7745, 109, 775, 77, 803, + 7747, 109, 803, 78, 775, 7749, 110, 775, + 78, 803, 7751, 110, 803, 78, 817, 7753, + 110, 817, 78, 813, 7755, 110, 813, 213, + 769, 7757, 245, 769, 213, 776, 7759, 245, + 776, 332, 768, 7761, 333, 768, 332, 769, + 7763, 333, 769, 80, 769, 7765, 112, 769, + 80, 775, 7767, 112, 775, 82, 775, 7769, + 114, 775, 82, 803, 7771, 114, 803, 7770, + 772, 7773, 7771, 772, 82, 817, 7775, 114, + 817, 83, 775, 7777, 115, 775, 83, 803, + 7779, 115, 803, 346, 775, 7781, 347, 775, + 352, 775, 7783, 353, 775, 7778, 775, 7785, + 7779, 775, 84, 775, 7787, 116, 775, 84, + 803, 7789, 116, 803, 84, 817, 7791, 116, + 817, 84, 813, 7793, 116, 813, 85, 804, + 7795, 117, 804, 85, 816, 7797, 117, 816, + 85, 813, 7799, 117, 813, 360, 769, 7801, + 361, 769, 362, 776, 7803, 363, 776, 86, + 771, 7805, 118, 771, 86, 803, 7807, 118, + 803, 87, 768, 7809, 119, 768, 87, 769, + 7811, 119, 769, 87, 776, 7813, 119, 776, + 87, 775, 7815, 119, 775, 87, 803, 7817, + 119, 803, 88, 775, 7819, 120, 775, 88, + 776, 7821, 120, 776, 89, 775, 7823, 121, + 775, 90, 770, 7825, 122, 770, 90, 803, + 7827, 122, 803, 90, 817, 7829, 122, 817, + 104, 817, 116, 776, 119, 778, 121, 778, + 97, 702, 383, 775, 223, 65, 803, 7841, + 97, 803, 65, 777, 7843, 97, 777, 194, + 769, 7845, 226, 769, 194, 768, 7847, 226, + 768, 194, 777, 7849, 226, 777, 194, 771, + 7851, 226, 771, 7840, 770, 7853, 7841, 770, + 258, 769, 7855, 259, 769, 258, 768, 7857, + 259, 768, 258, 777, 7859, 259, 777, 258, + 771, 7861, 259, 771, 7840, 774, 7863, 7841, + 774, 69, 803, 7865, 101, 803, 69, 777, + 7867, 101, 777, 69, 771, 7869, 101, 771, + 202, 769, 7871, 234, 769, 202, 768, 7873, + 234, 768, 202, 777, 7875, 234, 777, 202, + 771, 7877, 234, 771, 7864, 770, 7879, 7865, + 770, 73, 777, 7881, 105, 777, 73, 803, + 7883, 105, 803, 79, 803, 7885, 111, 803, + 79, 777, 7887, 111, 777, 212, 769, 7889, + 244, 769, 212, 768, 7891, 244, 768, 212, + 777, 7893, 244, 777, 212, 771, 7895, 244, + 771, 7884, 770, 7897, 7885, 770, 416, 769, + 7899, 417, 769, 416, 768, 7901, 417, 768, + 416, 777, 7903, 417, 777, 416, 771, 7905, + 417, 771, 416, 803, 7907, 417, 803, 85, + 803, 7909, 117, 803, 85, 777, 7911, 117, + 777, 431, 769, 7913, 432, 769, 431, 768, + 7915, 432, 768, 431, 777, 7917, 432, 777, + 431, 771, 7919, 432, 771, 431, 803, 7921, + 432, 803, 89, 768, 7923, 121, 768, 89, + 803, 7925, 121, 803, 89, 777, 7927, 121, + 777, 89, 771, 7929, 121, 771, 7931, 7933, + 7935, 945, 787, 945, 788, 7936, 768, 7937, + 768, 7936, 769, 7937, 769, 7936, 834, 7937, + 834, 913, 787, 7936, 913, 788, 7937, 7944, + 768, 7938, 7945, 768, 7939, 7944, 769, 7940, + 7945, 769, 7941, 7944, 834, 7942, 7945, 834, + 7943, 949, 787, 949, 788, 7952, 768, 7953, + 768, 7952, 769, 7953, 769, 917, 787, 7952, + 917, 788, 7953, 7960, 768, 7954, 7961, 768, + 7955, 7960, 769, 7956, 7961, 769, 7957, 951, + 787, 951, 788, 7968, 768, 7969, 768, 7968, + 769, 7969, 769, 7968, 834, 7969, 834, 919, + 787, 7968, 919, 788, 7969, 7976, 768, 7970, + 7977, 768, 7971, 7976, 769, 7972, 7977, 769, + 7973, 7976, 834, 7974, 7977, 834, 7975, 953, + 787, 953, 788, 7984, 768, 7985, 768, 7984, + 769, 7985, 769, 7984, 834, 7985, 834, 921, + 787, 7984, 921, 788, 7985, 7992, 768, 7986, + 7993, 768, 7987, 7992, 769, 7988, 7993, 769, + 7989, 7992, 834, 7990, 7993, 834, 7991, 959, + 787, 959, 788, 8000, 768, 8001, 768, 8000, + 769, 8001, 769, 927, 787, 8000, 927, 788, + 8001, 8008, 768, 8002, 8009, 768, 8003, 8008, + 769, 8004, 8009, 769, 8005, 965, 787, 965, + 788, 8016, 768, 965, 787, 768, 8017, 768, + 8016, 769, 965, 787, 769, 8017, 769, 8016, + 834, 965, 787, 834, 8017, 834, 933, 788, + 8017, 8025, 768, 8019, 8025, 769, 8021, 8025, + 834, 8023, 969, 787, 969, 788, 8032, 768, + 8033, 768, 8032, 769, 8033, 769, 8032, 834, + 8033, 834, 937, 787, 8032, 937, 788, 8033, + 8040, 768, 8034, 8041, 768, 8035, 8040, 769, + 8036, 8041, 769, 8037, 8040, 834, 8038, 8041, + 834, 8039, 945, 768, 949, 768, 951, 768, + 953, 768, 959, 768, 965, 768, 969, 768, + 7936, 837, 7936, 953, 7937, 837, 7937, 953, + 7938, 837, 7938, 953, 7939, 837, 7939, 953, + 7940, 837, 7940, 953, 7941, 837, 7941, 953, + 7942, 837, 7942, 953, 7943, 837, 7943, 953, + 7944, 837, 8064, 7945, 837, 8065, 7946, 837, + 8066, 7947, 837, 8067, 7948, 837, 8068, 7949, + 837, 8069, 7950, 837, 8070, 7951, 837, 8071, + 7968, 837, 7968, 953, 7969, 837, 7969, 953, + 7970, 837, 7970, 953, 7971, 837, 7971, 953, + 7972, 837, 7972, 953, 7973, 837, 7973, 953, + 7974, 837, 7974, 953, 7975, 837, 7975, 953, + 7976, 837, 8080, 7977, 837, 8081, 7978, 837, + 8082, 7979, 837, 8083, 7980, 837, 8084, 7981, + 837, 8085, 7982, 837, 8086, 7983, 837, 8087, + 8032, 837, 8032, 953, 8033, 837, 8033, 953, + 8034, 837, 8034, 953, 8035, 837, 8035, 953, + 8036, 837, 8036, 953, 8037, 837, 8037, 953, + 8038, 837, 8038, 953, 8039, 837, 8039, 953, + 8040, 837, 8096, 8041, 837, 8097, 8042, 837, + 8098, 8043, 837, 8099, 8044, 837, 8100, 8045, + 837, 8101, 8046, 837, 8102, 8047, 837, 8103, + 945, 774, 945, 772, 8048, 837, 8048, 953, + 945, 837, 945, 953, 940, 837, 940, 953, + 945, 834, 8118, 837, 945, 834, 953, 913, + 774, 8112, 913, 772, 8113, 913, 768, 8048, + 902, 8049, 913, 837, 8115, 32, 787, 32, + 834, 168, 834, 8052, 837, 8052, 953, 951, + 837, 951, 953, 942, 837, 942, 953, 951, + 834, 8134, 837, 951, 834, 953, 917, 768, + 8050, 904, 8051, 919, 768, 8052, 905, 8053, + 919, 837, 8131, 8127, 768, 8127, 769, 8127, + 834, 953, 774, 953, 772, 970, 768, 953, + 776, 768, 912, 953, 834, 970, 834, 953, + 776, 834, 921, 774, 8144, 921, 772, 8145, + 921, 768, 8054, 906, 8055, 8190, 768, 8190, + 769, 8190, 834, 965, 774, 965, 772, 971, + 768, 965, 776, 768, 944, 961, 787, 961, + 788, 965, 834, 971, 834, 965, 776, 834, + 933, 774, 8160, 933, 772, 8161, 933, 768, + 8058, 910, 8059, 929, 788, 8165, 168, 768, + 901, 96, 8060, 837, 8060, 953, 969, 837, + 969, 953, 974, 837, 974, 953, 969, 834, + 8182, 837, 969, 834, 953, 927, 768, 8056, + 908, 8057, 937, 768, 8060, 911, 8061, 937, + 837, 8179, 180, 32, 788, 8194, 8195, 8208, + 32, 819, 46, 46, 46, 46, 46, 46, + 8242, 8242, 8242, 8242, 8242, 8245, 8245, 8245, + 8245, 8245, 33, 33, 32, 773, 63, 63, + 63, 33, 33, 63, 8242, 8242, 8242, 8242, + 48, 52, 53, 54, 55, 56, 57, 43, + 8722, 61, 40, 41, 82, 115, 97, 47, + 99, 97, 47, 115, 67, 176, 67, 99, + 47, 111, 99, 47, 117, 400, 176, 70, + 78, 111, 81, 83, 77, 84, 69, 76, + 84, 77, 90, 937, 197, 70, 8526, 1488, + 1489, 1490, 1491, 70, 65, 88, 915, 928, + 8721, 49, 8260, 55, 49, 8260, 57, 49, + 8260, 49, 48, 49, 8260, 51, 50, 8260, + 51, 49, 8260, 53, 50, 8260, 53, 51, + 8260, 53, 52, 8260, 53, 49, 8260, 54, + 53, 8260, 54, 49, 8260, 56, 51, 8260, + 56, 53, 8260, 56, 55, 8260, 56, 49, + 8260, 8560, 73, 73, 8561, 73, 73, 73, + 8562, 73, 86, 8563, 86, 8564, 86, 73, + 8565, 86, 73, 73, 8566, 86, 73, 73, + 73, 8567, 73, 88, 8568, 88, 8569, 88, + 73, 8570, 88, 73, 73, 8571, 8572, 8573, + 8574, 8575, 105, 105, 105, 105, 105, 105, + 118, 118, 105, 118, 105, 105, 118, 105, + 105, 105, 105, 120, 120, 105, 120, 105, + 105, 8580, 48, 8260, 51, 8592, 824, 8594, + 824, 8596, 824, 8656, 824, 8660, 824, 8658, + 824, 8707, 824, 8712, 824, 8715, 824, 8739, + 824, 8741, 824, 8747, 8747, 8747, 8747, 8747, + 8750, 8750, 8750, 8750, 8750, 8764, 824, 8771, + 824, 8773, 824, 8776, 824, 61, 824, 8801, + 824, 8781, 824, 60, 824, 62, 824, 8804, + 824, 8805, 824, 8818, 824, 8819, 824, 8822, + 824, 8823, 824, 8826, 824, 8827, 824, 8834, + 824, 8835, 824, 8838, 824, 8839, 824, 8866, + 824, 8872, 824, 8873, 824, 8875, 824, 8828, + 824, 8829, 824, 8849, 824, 8850, 824, 8882, + 824, 8883, 824, 8884, 824, 8885, 824, 12296, + 12297, 49, 48, 49, 49, 49, 50, 49, + 51, 49, 52, 49, 53, 49, 54, 49, + 55, 49, 56, 49, 57, 50, 48, 40, + 49, 41, 40, 50, 41, 40, 51, 41, + 40, 52, 41, 40, 53, 41, 40, 54, + 41, 40, 55, 41, 40, 56, 41, 40, + 57, 41, 40, 49, 48, 41, 40, 49, + 49, 41, 40, 49, 50, 41, 40, 49, + 51, 41, 40, 49, 52, 41, 40, 49, + 53, 41, 40, 49, 54, 41, 40, 49, + 55, 41, 40, 49, 56, 41, 40, 49, + 57, 41, 40, 50, 48, 41, 49, 46, + 50, 46, 51, 46, 52, 46, 53, 46, + 54, 46, 55, 46, 56, 46, 57, 46, + 49, 48, 46, 49, 49, 46, 49, 50, + 46, 49, 51, 46, 49, 52, 46, 49, + 53, 46, 49, 54, 46, 49, 55, 46, + 49, 56, 46, 49, 57, 46, 50, 48, + 46, 40, 97, 41, 40, 98, 41, 40, + 99, 41, 40, 100, 41, 40, 101, 41, + 40, 102, 41, 40, 103, 41, 40, 104, + 41, 40, 105, 41, 40, 106, 41, 40, + 107, 41, 40, 108, 41, 40, 109, 41, + 40, 110, 41, 40, 111, 41, 40, 112, + 41, 40, 113, 41, 40, 114, 41, 40, + 115, 41, 40, 116, 41, 40, 117, 41, + 40, 118, 41, 40, 119, 41, 40, 120, + 41, 40, 121, 41, 40, 122, 41, 9424, + 9425, 9426, 9427, 9428, 9429, 9430, 9431, 9432, + 9433, 9434, 9435, 9436, 9437, 9438, 9439, 9440, + 9441, 83, 9442, 9443, 9444, 9445, 9446, 9447, + 89, 9448, 9449, 8747, 8747, 8747, 8747, 58, + 58, 61, 61, 61, 61, 61, 61, 10973, + 824, 11312, 11313, 11314, 11315, 11316, 11317, 11318, + 11319, 11320, 11321, 11322, 11323, 11324, 11325, 11326, + 11327, 11328, 11329, 11330, 11331, 11332, 11333, 11334, + 11335, 11336, 11337, 11338, 11339, 11340, 11341, 11342, + 11343, 11344, 11345, 11346, 11347, 11348, 11349, 11350, + 11351, 11352, 11353, 11354, 11355, 11356, 11357, 11358, + 11361, 619, 7549, 637, 11368, 11370, 11372, 11379, + 11382, 575, 576, 11393, 11395, 11397, 11399, 11401, + 11403, 11405, 11407, 11409, 11411, 11413, 11415, 11417, + 11419, 11421, 11423, 11425, 11427, 11429, 11431, 11433, + 11435, 11437, 11439, 11441, 11443, 11445, 11447, 11449, + 11451, 11453, 11455, 11457, 11459, 11461, 11463, 11465, + 11467, 11469, 11471, 11473, 11475, 11477, 11479, 11481, + 11483, 11485, 11487, 11489, 11491, 11500, 11502, 11507, + 11617, 27597, 40863, 19968, 20008, 20022, 20031, 20057, + 20101, 20108, 20128, 20154, 20799, 20837, 20843, 20866, + 20886, 20907, 20960, 20981, 20992, 21147, 21241, 21269, + 21274, 21304, 21313, 21340, 21353, 21378, 21430, 21448, + 21475, 22231, 22303, 22763, 22786, 22794, 22805, 22823, + 22899, 23376, 23424, 23544, 23567, 23586, 23608, 23662, + 23665, 24027, 24037, 24049, 24062, 24178, 24186, 24191, + 24308, 24318, 24331, 24339, 24400, 24417, 24435, 24515, + 25096, 25142, 25163, 25903, 25908, 25991, 26007, 26020, + 26041, 26080, 26085, 26352, 26376, 26408, 27424, 27490, + 27513, 27571, 27595, 27604, 27611, 27663, 27668, 27700, + 28779, 29226, 29238, 29243, 29247, 29255, 29273, 29275, + 29356, 29572, 29577, 29916, 29926, 29976, 29983, 29992, + 30000, 30091, 30098, 30326, 30333, 30382, 30399, 30446, + 30683, 30690, 30707, 31034, 31160, 31166, 31348, 31435, + 31481, 31859, 31992, 32566, 32593, 32650, 32701, 32769, + 32780, 32786, 32819, 32895, 32905, 33251, 33258, 33267, + 33276, 33292, 33307, 33311, 33390, 33394, 33400, 34381, + 34411, 34880, 34892, 34915, 35198, 35211, 35282, 35328, + 35895, 35910, 35925, 35960, 35997, 36196, 36208, 36275, + 36523, 36554, 36763, 36784, 36789, 37009, 37193, 37318, + 37324, 37329, 38263, 38272, 38428, 38582, 38585, 38632, + 38737, 38750, 38754, 38761, 38859, 38893, 38899, 38913, + 39080, 39131, 39135, 39318, 39321, 39340, 39592, 39640, + 39647, 39717, 39727, 39730, 39740, 39770, 40165, 40565, + 40575, 40613, 40635, 40643, 40653, 40657, 40697, 40701, + 40718, 40723, 40736, 40763, 40778, 40786, 40845, 40860, + 40864, 12306, 21316, 21317, 12363, 12441, 12365, 12441, + 12367, 12441, 12369, 12441, 12371, 12441, 12373, 12441, + 12375, 12441, 12377, 12441, 12379, 12441, 12381, 12441, + 12383, 12441, 12385, 12441, 12388, 12441, 12390, 12441, + 12392, 12441, 12399, 12441, 12399, 12442, 12402, 12441, + 12402, 12442, 12405, 12441, 12405, 12442, 12408, 12441, + 12408, 12442, 12411, 12441, 12411, 12442, 12358, 12441, + 32, 12441, 32, 12442, 12445, 12441, 12424, 12426, + 12459, 12441, 12461, 12441, 12463, 12441, 12465, 12441, + 12467, 12441, 12469, 12441, 12471, 12441, 12473, 12441, + 12475, 12441, 12477, 12441, 12479, 12441, 12481, 12441, + 12484, 12441, 12486, 12441, 12488, 12441, 12495, 12441, + 12495, 12442, 12498, 12441, 12498, 12442, 12501, 12441, + 12501, 12442, 12504, 12441, 12504, 12442, 12507, 12441, + 12507, 12442, 12454, 12441, 12527, 12441, 12528, 12441, + 12529, 12441, 12530, 12441, 12541, 12441, 12467, 12488, + 4352, 4353, 4522, 4354, 4524, 4525, 4355, 4356, + 4357, 4528, 4529, 4530, 4531, 4532, 4533, 4378, + 4358, 4359, 4360, 4385, 4361, 4362, 4363, 4364, + 4365, 4366, 4367, 4368, 4369, 4370, 4449, 4450, + 4451, 4452, 4453, 4454, 4455, 4456, 4457, 4458, + 4459, 4460, 4461, 4462, 4463, 4464, 4465, 4466, + 4467, 4468, 4469, 4448, 4372, 4373, 4551, 4552, + 4556, 4558, 4563, 4567, 4569, 4380, 4573, 4575, + 4381, 4382, 4384, 4386, 4387, 4391, 4393, 4395, + 4396, 4397, 4398, 4399, 4402, 4406, 4416, 4423, + 4428, 4593, 4594, 4439, 4440, 4441, 4484, 4485, + 4488, 4497, 4498, 4500, 4510, 4513, 19977, 22235, + 19978, 20013, 19979, 30002, 19993, 19969, 22825, 22320, + 40, 4352, 41, 40, 4354, 41, 40, 4355, + 41, 40, 4357, 41, 40, 4358, 41, 40, + 4359, 41, 40, 4361, 41, 40, 4363, 41, + 40, 4364, 41, 40, 4366, 41, 40, 4367, + 41, 40, 4368, 41, 40, 4369, 41, 40, + 4370, 41, 40, 4352, 4449, 41, 40, 4354, + 4449, 41, 40, 4355, 4449, 41, 40, 4357, + 4449, 41, 40, 4358, 4449, 41, 40, 4359, + 4449, 41, 40, 4361, 4449, 41, 40, 4363, + 4449, 41, 40, 4364, 4449, 41, 40, 4366, + 4449, 41, 40, 4367, 4449, 41, 40, 4368, + 4449, 41, 40, 4369, 4449, 41, 40, 4370, + 4449, 41, 40, 4364, 4462, 41, 40, 4363, + 4457, 4364, 4453, 4523, 41, 40, 4363, 4457, + 4370, 4462, 41, 40, 19968, 41, 40, 20108, + 41, 40, 19977, 41, 40, 22235, 41, 40, + 20116, 41, 40, 20845, 41, 40, 19971, 41, + 40, 20843, 41, 40, 20061, 41, 40, 21313, + 41, 40, 26376, 41, 40, 28779, 41, 40, + 27700, 41, 40, 26408, 41, 40, 37329, 41, + 40, 22303, 41, 40, 26085, 41, 40, 26666, + 41, 40, 26377, 41, 40, 31038, 41, 40, + 21517, 41, 40, 29305, 41, 40, 36001, 41, + 40, 31069, 41, 40, 21172, 41, 40, 20195, + 41, 40, 21628, 41, 40, 23398, 41, 40, + 30435, 41, 40, 20225, 41, 40, 36039, 41, + 40, 21332, 41, 40, 31085, 41, 40, 20241, + 41, 40, 33258, 41, 40, 33267, 41, 21839, + 24188, 31631, 80, 84, 69, 50, 49, 50, + 50, 50, 51, 50, 52, 50, 53, 50, + 54, 50, 55, 50, 56, 50, 57, 51, + 48, 51, 49, 51, 50, 51, 51, 51, + 52, 51, 53, 4352, 4449, 4354, 4449, 4355, + 4449, 4357, 4449, 4358, 4449, 4359, 4449, 4361, + 4449, 4363, 4449, 4364, 4449, 4366, 4449, 4367, + 4449, 4368, 4449, 4369, 4449, 4370, 4449, 4366, + 4449, 4535, 4352, 4457, 4364, 4462, 4363, 4468, + 4363, 4462, 20116, 20845, 19971, 20061, 26666, 26377, + 31038, 21517, 29305, 36001, 31069, 21172, 31192, 30007, + 36969, 20778, 21360, 27880, 38917, 20241, 20889, 27491, + 24038, 21491, 21307, 23447, 23398, 30435, 20225, 36039, + 21332, 22812, 51, 54, 51, 55, 51, 56, + 51, 57, 52, 48, 52, 49, 52, 50, + 52, 51, 52, 52, 52, 53, 52, 54, + 52, 55, 52, 56, 52, 57, 53, 48, + 49, 26376, 50, 26376, 51, 26376, 52, 26376, + 53, 26376, 54, 26376, 55, 26376, 56, 26376, + 57, 26376, 49, 48, 26376, 49, 49, 26376, + 49, 50, 26376, 72, 103, 101, 114, 103, + 101, 86, 76, 84, 68, 12450, 12452, 12454, + 12456, 12458, 12459, 12461, 12463, 12465, 12467, 12469, + 12471, 12473, 12475, 12477, 12479, 12481, 12484, 12486, + 12488, 12490, 12491, 12492, 12493, 12494, 12495, 12498, + 12501, 12504, 12507, 12510, 12511, 12512, 12513, 12514, + 12516, 12518, 12520, 12521, 12522, 12523, 12524, 12525, + 12527, 12528, 12529, 12530, 12450, 12497, 12540, 12488, + 12450, 12523, 12501, 12449, 12450, 12531, 12506, 12450, + 12450, 12540, 12523, 12452, 12491, 12531, 12464, 12452, + 12531, 12481, 12454, 12457, 12531, 12456, 12473, 12463, + 12540, 12489, 12456, 12540, 12459, 12540, 12458, 12531, + 12473, 12458, 12540, 12512, 12459, 12452, 12522, 12459, + 12521, 12483, 12488, 12459, 12525, 12522, 12540, 12460, + 12525, 12531, 12460, 12531, 12510, 12462, 12460, 12462, + 12491, 12540, 12461, 12517, 12522, 12540, 12462, 12523, + 12480, 12540, 12461, 12525, 12461, 12525, 12464, 12521, + 12512, 12461, 12525, 12513, 12540, 12488, 12523, 12461, + 12525, 12527, 12483, 12488, 12464, 12521, 12512, 12464, + 12521, 12512, 12488, 12531, 12463, 12523, 12476, 12452, + 12525, 12463, 12525, 12540, 12493, 12465, 12540, 12473, + 12467, 12523, 12490, 12467, 12540, 12509, 12469, 12452, + 12463, 12523, 12469, 12531, 12481, 12540, 12512, 12471, + 12522, 12531, 12464, 12475, 12531, 12481, 12475, 12531, + 12488, 12480, 12540, 12473, 12487, 12471, 12489, 12523, + 12488, 12531, 12490, 12494, 12494, 12483, 12488, 12495, + 12452, 12484, 12497, 12540, 12475, 12531, 12488, 12497, + 12540, 12484, 12496, 12540, 12524, 12523, 12500, 12450, + 12473, 12488, 12523, 12500, 12463, 12523, 12500, 12467, + 12499, 12523, 12501, 12449, 12521, 12483, 12489, 12501, + 12451, 12540, 12488, 12502, 12483, 12471, 12455, 12523, + 12501, 12521, 12531, 12504, 12463, 12479, 12540, 12523, + 12506, 12477, 12506, 12491, 12498, 12504, 12523, 12484, + 12506, 12531, 12473, 12506, 12540, 12472, 12505, 12540, + 12479, 12509, 12452, 12531, 12488, 12508, 12523, 12488, + 12507, 12531, 12509, 12531, 12489, 12507, 12540, 12523, + 12507, 12540, 12531, 12510, 12452, 12463, 12525, 12510, + 12452, 12523, 12510, 12483, 12495, 12510, 12523, 12463, + 12510, 12531, 12471, 12519, 12531, 12511, 12463, 12525, + 12531, 12511, 12522, 12511, 12522, 12496, 12540, 12523, + 12513, 12460, 12513, 12460, 12488, 12531, 12513, 12540, + 12488, 12523, 12516, 12540, 12489, 12516, 12540, 12523, + 12518, 12450, 12531, 12522, 12483, 12488, 12523, 12522, + 12521, 12523, 12500, 12540, 12523, 12540, 12502, 12523, + 12524, 12512, 12524, 12531, 12488, 12466, 12531, 12527, + 12483, 12488, 48, 28857, 49, 28857, 50, 28857, + 51, 28857, 52, 28857, 53, 28857, 54, 28857, + 55, 28857, 56, 28857, 57, 28857, 49, 48, + 28857, 49, 49, 28857, 49, 50, 28857, 49, + 51, 28857, 49, 52, 28857, 49, 53, 28857, + 49, 54, 28857, 49, 55, 28857, 49, 56, + 28857, 49, 57, 28857, 50, 48, 28857, 50, + 49, 28857, 50, 50, 28857, 50, 51, 28857, + 50, 52, 28857, 104, 80, 97, 100, 97, + 65, 85, 98, 97, 114, 111, 86, 112, + 99, 100, 109, 100, 109, 178, 100, 109, + 179, 73, 85, 24179, 25104, 26157, 21644, 22823, + 27491, 26126, 27835, 26666, 24335, 20250, 31038, 112, + 65, 110, 65, 956, 65, 109, 65, 107, + 65, 75, 66, 77, 66, 71, 66, 99, + 97, 108, 107, 99, 97, 108, 112, 70, + 110, 70, 956, 70, 956, 103, 109, 103, + 107, 103, 72, 122, 107, 72, 122, 77, + 72, 122, 71, 72, 122, 84, 72, 122, + 956, 8467, 109, 8467, 100, 8467, 107, 8467, + 102, 109, 110, 109, 956, 109, 109, 109, + 99, 109, 107, 109, 109, 109, 178, 99, + 109, 178, 109, 178, 107, 109, 178, 109, + 109, 179, 99, 109, 179, 109, 179, 107, + 109, 179, 109, 8725, 115, 109, 8725, 115, + 178, 80, 97, 107, 80, 97, 77, 80, + 97, 71, 80, 97, 114, 97, 100, 114, + 97, 100, 8725, 115, 114, 97, 100, 8725, + 115, 178, 112, 115, 110, 115, 956, 115, + 109, 115, 112, 86, 110, 86, 956, 86, + 109, 86, 107, 86, 77, 86, 112, 87, + 110, 87, 956, 87, 109, 87, 107, 87, + 77, 87, 107, 937, 77, 937, 97, 46, + 109, 46, 66, 113, 99, 99, 99, 100, + 67, 8725, 107, 103, 67, 111, 46, 100, + 66, 71, 121, 104, 97, 72, 80, 105, + 110, 75, 75, 75, 77, 107, 116, 108, + 109, 108, 110, 108, 111, 103, 108, 120, + 109, 98, 109, 105, 108, 109, 111, 108, + 80, 72, 112, 46, 109, 46, 80, 80, + 77, 80, 82, 115, 114, 83, 118, 87, + 98, 86, 8725, 109, 65, 8725, 109, 49, + 26085, 50, 26085, 51, 26085, 52, 26085, 53, + 26085, 54, 26085, 55, 26085, 56, 26085, 57, + 26085, 49, 48, 26085, 49, 49, 26085, 49, + 50, 26085, 49, 51, 26085, 49, 52, 26085, + 49, 53, 26085, 49, 54, 26085, 49, 55, + 26085, 49, 56, 26085, 49, 57, 26085, 50, + 48, 26085, 50, 49, 26085, 50, 50, 26085, + 50, 51, 26085, 50, 52, 26085, 50, 53, + 26085, 50, 54, 26085, 50, 55, 26085, 50, + 56, 26085, 50, 57, 26085, 51, 48, 26085, + 51, 49, 26085, 103, 97, 108, 42561, 42563, + 42565, 42567, 42569, 42573, 42575, 42577, 42579, 42581, + 42583, 42585, 42587, 42589, 42591, 42593, 42595, 42597, + 42599, 42601, 42603, 42605, 42625, 42627, 42629, 42631, + 42633, 42635, 42637, 42639, 42641, 42643, 42645, 42647, + 42649, 42651, 42787, 42789, 42791, 42793, 42795, 42797, + 42799, 42803, 42805, 42807, 42809, 42811, 42813, 42815, + 42817, 42819, 42821, 42823, 42825, 42827, 42829, 42831, + 42833, 42835, 42837, 42839, 42841, 42843, 42845, 42847, + 42849, 42851, 42853, 42855, 42857, 42859, 42861, 42863, + 42874, 42876, 7545, 42879, 42881, 42883, 42885, 42887, + 42892, 42897, 42899, 42903, 42905, 42907, 42909, 42911, + 42913, 42915, 42917, 42919, 42921, 620, 670, 647, + 43859, 42933, 42935, 294, 43831, 43858, 5024, 5025, + 5026, 5027, 5028, 5029, 5030, 5031, 5032, 5033, + 5034, 5035, 5036, 5037, 5038, 5039, 5040, 5041, + 5042, 5043, 5044, 5045, 5046, 5047, 5048, 5049, + 5050, 5051, 5052, 5053, 5054, 5055, 5056, 5057, + 5058, 5059, 5060, 5061, 5062, 5063, 5064, 5065, + 5066, 5067, 5068, 5069, 5070, 5071, 5072, 5073, + 5074, 5075, 5076, 5077, 5078, 5079, 5080, 5081, + 5082, 5083, 5084, 5085, 5086, 5087, 5088, 5089, + 5090, 5091, 5092, 5093, 5094, 5095, 5096, 5097, + 5098, 5099, 5100, 5101, 5102, 5103, 35912, 26356, + 36040, 28369, 20018, 21477, 22865, 21895, 22856, 25078, + 30313, 32645, 34367, 34746, 35064, 37007, 27138, 27931, + 28889, 29662, 33853, 37226, 39409, 20098, 21365, 27396, + 29211, 34349, 40478, 23888, 28651, 34253, 35172, 25289, + 33240, 34847, 24266, 26391, 28010, 29436, 37070, 20358, + 20919, 21214, 25796, 27347, 29200, 30439, 34310, 34396, + 36335, 38706, 39791, 40442, 30860, 31103, 32160, 33737, + 37636, 35542, 22751, 24324, 31840, 32894, 29282, 30922, + 36034, 38647, 22744, 23650, 27155, 28122, 28431, 32047, + 32311, 38475, 21202, 32907, 20956, 20940, 31260, 32190, + 33777, 38517, 35712, 25295, 35582, 20025, 23527, 24594, + 29575, 30064, 21271, 30971, 20415, 24489, 19981, 27852, + 25976, 32034, 21443, 22622, 30465, 33865, 35498, 27578, + 27784, 25342, 33509, 25504, 30053, 20142, 20841, 20937, + 26753, 31975, 33391, 35538, 37327, 21237, 21570, 24300, + 26053, 28670, 31018, 38317, 39530, 40599, 40654, 26310, + 27511, 36706, 24180, 24976, 25088, 25754, 28451, 29001, + 29833, 31178, 32244, 32879, 36646, 34030, 36899, 37706, + 21015, 21155, 21693, 28872, 35010, 24265, 24565, 25467, + 27566, 31806, 29557, 20196, 22265, 23994, 24604, 29618, + 29801, 32666, 32838, 37428, 38646, 38728, 38936, 20363, + 31150, 37300, 38584, 24801, 20102, 20698, 23534, 23615, + 26009, 29134, 30274, 34044, 36988, 26248, 38446, 21129, + 26491, 26611, 27969, 28316, 29705, 30041, 30827, 32016, + 39006, 25134, 38520, 20523, 23833, 28138, 36650, 24459, + 24900, 26647, 38534, 21033, 21519, 23653, 26131, 26446, + 26792, 27877, 29702, 30178, 32633, 35023, 35041, 38626, + 21311, 28346, 21533, 29136, 29848, 34298, 38563, 40023, + 40607, 26519, 28107, 33256, 31520, 31890, 29376, 28825, + 35672, 20160, 33590, 21050, 20999, 24230, 25299, 31958, + 23429, 27934, 26292, 36667, 38477, 24275, 20800, 21952, + 22618, 26228, 20958, 29482, 30410, 31036, 31070, 31077, + 31119, 38742, 31934, 34322, 35576, 36920, 37117, 39151, + 39164, 39208, 40372, 37086, 38583, 20398, 20711, 20813, + 21193, 21220, 21329, 21917, 22022, 22120, 22592, 22696, + 23652, 24724, 24936, 24974, 25074, 25935, 26082, 26257, + 26757, 28023, 28186, 28450, 29038, 29227, 29730, 30865, + 31049, 31048, 31056, 31062, 31117, 31118, 31296, 31361, + 31680, 32265, 32321, 32626, 32773, 33261, 33401, 33879, + 35088, 35222, 35585, 35641, 36051, 36104, 36790, 38627, + 38911, 38971, 24693, 55376, 57070, 33304, 20006, 20917, + 20840, 20352, 20805, 20864, 21191, 21242, 21845, 21913, + 21986, 22707, 22852, 22868, 23138, 23336, 24274, 24281, + 24425, 24493, 24792, 24910, 24840, 24928, 25140, 25540, + 25628, 25682, 25942, 26395, 26454, 28379, 28363, 28702, + 30631, 29237, 29359, 29809, 29958, 30011, 30237, 30239, + 30427, 30452, 30538, 30528, 30924, 31409, 31867, 32091, + 32574, 33618, 33775, 34681, 35137, 35206, 35519, 35531, + 35565, 35722, 36664, 36978, 37273, 37494, 38524, 38875, + 38923, 39698, 55370, 56394, 55370, 56388, 55372, 57301, + 15261, 16408, 16441, 55380, 56905, 55383, 56528, 55391, + 57043, 40771, 40846, 102, 102, 102, 105, 102, + 108, 102, 102, 105, 102, 102, 108, 383, + 116, 115, 116, 1396, 1398, 1396, 1381, 1396, + 1387, 1406, 1398, 1396, 1389, 1497, 1460, 1522, + 1463, 1506, 1492, 1499, 1500, 1501, 1512, 1514, + 1513, 1473, 1513, 1474, 64329, 1473, 64329, 1474, + 1488, 1463, 1488, 1464, 1488, 1468, 1489, 1468, + 1490, 1468, 1491, 1468, 1492, 1468, 1493, 1468, + 1494, 1468, 1496, 1468, 1497, 1468, 1498, 1468, + 1499, 1468, 1500, 1468, 1502, 1468, 1504, 1468, + 1505, 1468, 1507, 1468, 1508, 1468, 1510, 1468, + 1511, 1468, 1512, 1468, 1513, 1468, 1514, 1468, + 1493, 1465, 1489, 1471, 1499, 1471, 1508, 1471, + 1488, 1500, 1649, 1659, 1662, 1664, 1658, 1663, + 1657, 1700, 1702, 1668, 1667, 1670, 1671, 1677, + 1676, 1678, 1672, 1688, 1681, 1705, 1711, 1715, + 1713, 1722, 1723, 1728, 1729, 1726, 1746, 1747, + 1709, 1735, 1734, 1736, 1655, 1739, 1733, 1737, + 1744, 1609, 1574, 1575, 1574, 1749, 1574, 1608, + 1574, 1735, 1574, 1734, 1574, 1736, 1574, 1744, + 1574, 1609, 1740, 1574, 1580, 1574, 1581, 1574, + 1605, 1574, 1610, 1576, 1580, 1576, 1581, 1576, + 1582, 1576, 1605, 1576, 1609, 1576, 1610, 1578, + 1580, 1578, 1581, 1578, 1582, 1578, 1605, 1578, + 1609, 1578, 1610, 1579, 1580, 1579, 1605, 1579, + 1609, 1579, 1610, 1580, 1581, 1580, 1605, 1581, + 1580, 1581, 1605, 1582, 1580, 1582, 1581, 1582, + 1605, 1587, 1580, 1587, 1581, 1587, 1582, 1587, + 1605, 1589, 1581, 1589, 1605, 1590, 1580, 1590, + 1581, 1590, 1582, 1590, 1605, 1591, 1581, 1591, + 1605, 1592, 1605, 1593, 1580, 1593, 1605, 1594, + 1580, 1594, 1605, 1601, 1580, 1601, 1581, 1601, + 1582, 1601, 1605, 1601, 1609, 1601, 1610, 1602, + 1581, 1602, 1605, 1602, 1609, 1602, 1610, 1603, + 1575, 1603, 1580, 1603, 1581, 1603, 1582, 1603, + 1604, 1603, 1605, 1603, 1609, 1603, 1610, 1604, + 1580, 1604, 1581, 1604, 1582, 1604, 1605, 1604, + 1609, 1604, 1610, 1605, 1580, 1605, 1581, 1605, + 1582, 1605, 1605, 1605, 1609, 1605, 1610, 1606, + 1580, 1606, 1581, 1606, 1582, 1606, 1605, 1606, + 1609, 1606, 1610, 1607, 1580, 1607, 1605, 1607, + 1609, 1607, 1610, 1610, 1580, 1610, 1581, 1610, + 1582, 1610, 1605, 1610, 1609, 1610, 1610, 1584, + 1648, 1585, 1648, 1609, 1648, 32, 1612, 1617, + 32, 1613, 1617, 32, 1614, 1617, 32, 1615, + 1617, 32, 1616, 1617, 32, 1617, 1648, 1574, + 1585, 1574, 1586, 1574, 1606, 1576, 1585, 1576, + 1586, 1576, 1606, 1578, 1585, 1578, 1586, 1578, + 1606, 1579, 1585, 1579, 1586, 1579, 1606, 1605, + 1575, 1606, 1585, 1606, 1586, 1606, 1606, 1610, + 1585, 1610, 1586, 1610, 1606, 1574, 1582, 1574, + 1607, 1576, 1607, 1578, 1607, 1589, 1582, 1604, + 1607, 1606, 1607, 1607, 1648, 1610, 1607, 1579, + 1607, 1587, 1607, 1588, 1605, 1588, 1607, 1600, + 1614, 1617, 1600, 1615, 1617, 1600, 1616, 1617, + 1591, 1609, 1591, 1610, 1593, 1609, 1593, 1610, + 1594, 1609, 1594, 1610, 1587, 1609, 1587, 1610, + 1588, 1609, 1588, 1610, 1581, 1609, 1581, 1610, + 1580, 1609, 1580, 1610, 1582, 1609, 1582, 1610, + 1589, 1609, 1589, 1610, 1590, 1609, 1590, 1610, + 1588, 1580, 1588, 1581, 1588, 1582, 1588, 1585, + 1587, 1585, 1589, 1585, 1590, 1585, 1575, 1611, + 1578, 1580, 1605, 1578, 1581, 1580, 1578, 1581, + 1605, 1578, 1582, 1605, 1578, 1605, 1580, 1578, + 1605, 1581, 1578, 1605, 1582, 1580, 1605, 1581, + 1581, 1605, 1610, 1581, 1605, 1609, 1587, 1581, + 1580, 1587, 1580, 1581, 1587, 1580, 1609, 1587, + 1605, 1581, 1587, 1605, 1580, 1587, 1605, 1605, + 1589, 1581, 1581, 1589, 1605, 1605, 1588, 1581, + 1605, 1588, 1580, 1610, 1588, 1605, 1582, 1588, + 1605, 1605, 1590, 1581, 1609, 1590, 1582, 1605, + 1591, 1605, 1581, 1591, 1605, 1605, 1591, 1605, + 1610, 1593, 1580, 1605, 1593, 1605, 1605, 1593, + 1605, 1609, 1594, 1605, 1605, 1594, 1605, 1610, + 1594, 1605, 1609, 1601, 1582, 1605, 1602, 1605, + 1581, 1602, 1605, 1605, 1604, 1581, 1605, 1604, + 1581, 1610, 1604, 1581, 1609, 1604, 1580, 1580, + 1604, 1582, 1605, 1604, 1605, 1581, 1605, 1581, + 1580, 1605, 1581, 1605, 1605, 1581, 1610, 1605, + 1580, 1581, 1605, 1580, 1605, 1605, 1582, 1580, + 1605, 1582, 1605, 1605, 1580, 1582, 1607, 1605, + 1580, 1607, 1605, 1605, 1606, 1581, 1605, 1606, + 1581, 1609, 1606, 1580, 1605, 1606, 1580, 1609, + 1606, 1605, 1610, 1606, 1605, 1609, 1610, 1605, + 1605, 1576, 1582, 1610, 1578, 1580, 1610, 1578, + 1580, 1609, 1578, 1582, 1610, 1578, 1582, 1609, + 1578, 1605, 1610, 1578, 1605, 1609, 1580, 1605, + 1610, 1580, 1581, 1609, 1580, 1605, 1609, 1587, + 1582, 1609, 1589, 1581, 1610, 1588, 1581, 1610, + 1590, 1581, 1610, 1604, 1580, 1610, 1604, 1605, + 1610, 1610, 1581, 1610, 1610, 1580, 1610, 1610, + 1605, 1610, 1605, 1605, 1610, 1602, 1605, 1610, + 1606, 1581, 1610, 1593, 1605, 1610, 1603, 1605, + 1610, 1606, 1580, 1581, 1605, 1582, 1610, 1604, + 1580, 1605, 1603, 1605, 1605, 1580, 1581, 1610, + 1581, 1580, 1610, 1605, 1580, 1610, 1601, 1605, + 1610, 1576, 1581, 1610, 1587, 1582, 1610, 1606, + 1580, 1610, 1589, 1604, 1746, 1602, 1604, 1746, + 1575, 1604, 1604, 1607, 1575, 1603, 1576, 1585, + 1605, 1581, 1605, 1583, 1589, 1604, 1593, 1605, + 1585, 1587, 1608, 1604, 1593, 1604, 1610, 1607, + 1608, 1587, 1604, 1605, 1589, 1604, 1609, 17, + 1589, 1604, 1609, 32, 1575, 1604, 1604, 1607, + 32, 1593, 1604, 1610, 1607, 32, 1608, 1587, + 1604, 1605, 7, 1580, 1604, 32, 1580, 1604, + 1575, 1604, 1607, 1585, 1740, 1575, 1604, 44, + 12289, 12290, 58, 33, 63, 12310, 12311, 8230, + 8229, 8212, 8211, 95, 123, 125, 12308, 12309, + 12304, 12305, 12298, 12299, 12300, 12301, 12302, 12303, + 91, 93, 8254, 35, 38, 42, 45, 60, + 62, 92, 36, 37, 64, 32, 1611, 1600, + 1611, 32, 1612, 32, 1613, 32, 1614, 1600, + 1614, 32, 1615, 1600, 1615, 32, 1616, 1600, + 1616, 32, 1617, 1600, 1617, 32, 1618, 1600, + 1618, 1569, 1570, 1571, 1572, 1573, 1574, 1575, + 1576, 1577, 1578, 1579, 1580, 1581, 1582, 1583, + 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, + 1592, 1593, 1594, 1601, 1602, 1603, 1604, 1605, + 1606, 1607, 1608, 1610, 1604, 1570, 1604, 1571, + 1604, 1573, 1604, 1575, 34, 39, 47, 65345, + 65346, 65347, 65348, 65349, 65350, 65351, 65352, 65353, + 65354, 65355, 65356, 65357, 65358, 65359, 65360, 65361, + 65362, 65363, 65364, 65365, 65366, 65367, 65368, 65369, + 65370, 94, 124, 126, 10629, 10630, 12539, 12449, + 12451, 12453, 12455, 12457, 12515, 12517, 12519, 12483, + 12540, 12531, 12441, 12442, 12644, 12593, 12594, 12595, + 12596, 12597, 12598, 12599, 12600, 12601, 12602, 12603, + 12604, 12605, 12606, 12607, 12608, 12609, 12610, 12611, + 12612, 12613, 12614, 12615, 12616, 12617, 12618, 12619, + 12620, 12621, 12622, 12623, 12624, 12625, 12626, 12627, + 12628, 12629, 12630, 12631, 12632, 12633, 12634, 12635, + 12636, 12637, 12638, 12639, 12640, 12641, 12642, 12643, + 162, 163, 172, 175, 166, 165, 8361, 9474, + 8592, 8593, 8594, 8595, 9632, 9675, 55297, 56360, + 55297, 56361, 55297, 56362, 55297, 56363, 55297, 56364, + 55297, 56365, 55297, 56366, 55297, 56367, 55297, 56368, + 55297, 56369, 55297, 56370, 55297, 56371, 55297, 56372, + 55297, 56373, 55297, 56374, 55297, 56375, 55297, 56376, + 55297, 56377, 55297, 56378, 55297, 56379, 55297, 56380, + 55297, 56381, 55297, 56382, 55297, 56383, 55297, 56384, + 55297, 56385, 55297, 56386, 55297, 56387, 55297, 56388, + 55297, 56389, 55297, 56390, 55297, 56391, 55297, 56392, + 55297, 56393, 55297, 56394, 55297, 56395, 55297, 56396, + 55297, 56397, 55297, 56398, 55297, 56399, 55297, 56536, + 55297, 56537, 55297, 56538, 55297, 56539, 55297, 56540, + 55297, 56541, 55297, 56542, 55297, 56543, 55297, 56544, + 55297, 56545, 55297, 56546, 55297, 56547, 55297, 56548, + 55297, 56549, 55297, 56550, 55297, 56551, 55297, 56552, + 55297, 56553, 55297, 56554, 55297, 56555, 55297, 56556, + 55297, 56557, 55297, 56558, 55297, 56559, 55297, 56560, + 55297, 56561, 55297, 56562, 55297, 56563, 55297, 56564, + 55297, 56565, 55297, 56566, 55297, 56567, 55297, 56568, + 55297, 56569, 55297, 56570, 55297, 56571, 55299, 56512, + 55299, 56513, 55299, 56514, 55299, 56515, 55299, 56516, + 55299, 56517, 55299, 56518, 55299, 56519, 55299, 56520, + 55299, 56521, 55299, 56522, 55299, 56523, 55299, 56524, + 55299, 56525, 55299, 56526, 55299, 56527, 55299, 56528, + 55299, 56529, 55299, 56530, 55299, 56531, 55299, 56532, + 55299, 56533, 55299, 56534, 55299, 56535, 55299, 56536, + 55299, 56537, 55299, 56538, 55299, 56539, 55299, 56540, + 55299, 56541, 55299, 56542, 55299, 56543, 55299, 56544, + 55299, 56545, 55299, 56546, 55299, 56547, 55299, 56548, + 55299, 56549, 55299, 56550, 55299, 56551, 55299, 56552, + 55299, 56553, 55299, 56554, 55299, 56555, 55299, 56556, + 55299, 56557, 55299, 56558, 55299, 56559, 55299, 56560, + 55299, 56561, 55299, 56562, 55300, 56473, 55300, 56506, + 55300, 56475, 55300, 56506, 55300, 56485, 55300, 56506, + 55300, 56625, 55300, 56615, 55300, 56626, 55300, 56615, + 55300, 57159, 55300, 57150, 55300, 57159, 55300, 57175, + 55301, 56505, 55301, 56506, 55301, 56505, 55301, 56496, + 55301, 56505, 55301, 56509, 55301, 56760, 55301, 56751, + 55301, 56761, 55301, 56751, 55302, 56512, 55302, 56513, + 55302, 56514, 55302, 56515, 55302, 56516, 55302, 56517, + 55302, 56518, 55302, 56519, 55302, 56520, 55302, 56521, + 55302, 56522, 55302, 56523, 55302, 56524, 55302, 56525, + 55302, 56526, 55302, 56527, 55302, 56528, 55302, 56529, + 55302, 56530, 55302, 56531, 55302, 56532, 55302, 56533, + 55302, 56534, 55302, 56535, 55302, 56536, 55302, 56537, + 55302, 56538, 55302, 56539, 55302, 56540, 55302, 56541, + 55302, 56542, 55302, 56543, 55348, 56663, 55348, 56677, + 55348, 56664, 55348, 56677, 55348, 56671, 55348, 56686, + 55348, 56671, 55348, 56687, 55348, 56671, 55348, 56688, + 55348, 56671, 55348, 56689, 55348, 56671, 55348, 56690, + 55348, 56761, 55348, 56677, 55348, 56762, 55348, 56677, + 55348, 56763, 55348, 56686, 55348, 56764, 55348, 56686, + 55348, 56763, 55348, 56687, 55348, 56764, 55348, 56687, + 305, 567, 913, 914, 916, 917, 918, 919, + 921, 922, 923, 924, 925, 926, 927, 929, + 1012, 932, 934, 935, 936, 8711, 8706, 1013, + 977, 1008, 981, 1009, 982, 988, 55354, 56610, + 55354, 56611, 55354, 56612, 55354, 56613, 55354, 56614, + 55354, 56615, 55354, 56616, 55354, 56617, 55354, 56618, + 55354, 56619, 55354, 56620, 55354, 56621, 55354, 56622, + 55354, 56623, 55354, 56624, 55354, 56625, 55354, 56626, + 55354, 56627, 55354, 56628, 55354, 56629, 55354, 56630, + 55354, 56631, 55354, 56632, 55354, 56633, 55354, 56634, + 55354, 56635, 55354, 56636, 55354, 56637, 55354, 56638, + 55354, 56639, 55354, 56640, 55354, 56641, 55354, 56642, + 55354, 56643, 1646, 1697, 1647, 48, 46, 48, + 44, 49, 44, 50, 44, 51, 44, 52, + 44, 53, 44, 54, 44, 55, 44, 56, + 44, 57, 44, 40, 65, 41, 40, 66, + 41, 40, 67, 41, 40, 68, 41, 40, + 69, 41, 40, 70, 41, 40, 71, 41, + 40, 72, 41, 40, 73, 41, 40, 74, + 41, 40, 75, 41, 40, 76, 41, 40, + 77, 41, 40, 78, 41, 40, 79, 41, + 40, 80, 41, 40, 81, 41, 40, 82, + 41, 40, 83, 41, 40, 84, 41, 40, + 85, 41, 40, 86, 41, 40, 87, 41, + 40, 88, 41, 40, 89, 41, 40, 90, + 41, 12308, 83, 12309, 67, 68, 87, 90, + 72, 86, 83, 68, 83, 83, 80, 80, + 86, 87, 67, 77, 67, 77, 68, 68, + 74, 12411, 12363, 12467, 12467, 23383, 21452, 12487, + 22810, 35299, 20132, 26144, 28961, 21069, 24460, 20877, + 26032, 21021, 32066, 36009, 22768, 21561, 28436, 25237, + 25429, 36938, 25351, 25171, 31105, 31354, 21512, 28288, + 30003, 21106, 21942, 37197, 12308, 26412, 12309, 12308, + 19977, 12309, 12308, 20108, 12309, 12308, 23433, 12309, + 12308, 28857, 12309, 12308, 25171, 12309, 12308, 30423, + 12309, 12308, 21213, 12309, 12308, 25943, 12309, 24471, + 21487, 20029, 20024, 20033, 55360, 56610, 20320, 20411, + 20482, 20602, 20633, 20687, 13470, 55361, 56890, 20820, + 20836, 20855, 55361, 56604, 13497, 20839, 55361, 56651, + 20887, 20900, 20172, 20908, 55396, 56799, 20995, 13535, + 21051, 21062, 21111, 13589, 21253, 21254, 21321, 21338, + 21363, 21373, 21375, 55362, 56876, 28784, 21450, 21471, + 55362, 57187, 21483, 21489, 21510, 21662, 21560, 21576, + 21608, 21666, 21750, 21776, 21843, 21859, 21892, 21931, + 21939, 21954, 22294, 22295, 22097, 22132, 22766, 22478, + 22516, 22541, 22411, 22578, 22577, 22700, 55365, 56548, + 22770, 22775, 22790, 22818, 22882, 55365, 57000, 55365, + 57066, 23020, 23067, 23079, 23000, 23142, 14062, 14076, + 23304, 23358, 55366, 56776, 23491, 23512, 23539, 55366, + 57112, 23551, 23558, 24403, 14209, 23648, 23744, 23693, + 55367, 56804, 23875, 55367, 56806, 23918, 23915, 23932, + 24033, 24034, 14383, 24061, 24104, 24125, 24169, 14434, + 55368, 56707, 14460, 24240, 24243, 24246, 55400, 57234, + 55368, 57137, 33281, 24354, 14535, 55372, 57016, 55384, + 56794, 24418, 24427, 14563, 24474, 24525, 24535, 24569, + 24705, 14650, 14620, 55369, 57044, 24775, 24904, 24908, + 24954, 25010, 24996, 25007, 25054, 25104, 25115, 25181, + 25265, 25300, 25424, 55370, 57100, 25405, 25340, 25448, + 25475, 25572, 55370, 57329, 25634, 25541, 25513, 14894, + 25705, 25726, 25757, 25719, 14956, 25964, 55372, 56330, + 26083, 26360, 26185, 15129, 15112, 15076, 20882, 20885, + 26368, 26268, 32941, 17369, 26401, 26462, 26451, 55372, + 57283, 15177, 26618, 26501, 26706, 55373, 56429, 26766, + 26655, 26900, 26946, 27043, 27114, 27304, 55373, 56995, + 27355, 15384, 27425, 55374, 56487, 27476, 15438, 27506, + 27551, 27579, 55374, 56973, 55367, 56587, 55374, 57082, + 27726, 55375, 56508, 27839, 27853, 27751, 27926, 27966, + 28009, 28024, 28037, 55375, 56606, 27956, 28207, 28270, + 15667, 28359, 55375, 57041, 28153, 28526, 55375, 57182, + 55375, 57230, 28614, 28729, 28699, 15766, 28746, 28797, + 28791, 28845, 55361, 56613, 28997, 55376, 56931, 29084, + 55376, 57259, 29224, 29264, 55377, 56840, 29312, 29333, + 55377, 57141, 55378, 56340, 29562, 29579, 16044, 29605, + 16056, 29767, 29788, 29829, 29898, 16155, 29988, 55379, + 56374, 30014, 55379, 56466, 55368, 56735, 30224, 55379, + 57249, 55379, 57272, 55380, 56388, 16380, 16392, 55380, + 56563, 55380, 56562, 55380, 56601, 55380, 56627, 30494, + 30495, 30603, 16454, 16534, 55381, 56349, 30798, 16611, + 55381, 56870, 55381, 56986, 55381, 57029, 31211, 16687, + 31306, 31311, 55382, 56700, 55382, 56999, 31470, 16898, + 55382, 57259, 31686, 31689, 16935, 55383, 56448, 31954, + 17056, 31976, 31971, 32000, 55383, 57222, 32099, 17153, + 32199, 32258, 32325, 17204, 55384, 56872, 55384, 56903, + 17241, 55384, 57049, 32634, 55384, 57150, 32661, 32762, + 55385, 56538, 55385, 56611, 32864, 55385, 56744, 32880, + 55372, 57183, 17365, 32946, 33027, 17419, 33086, 23221, + 55385, 57255, 55385, 57269, 55372, 57235, 55372, 57244, + 33284, 36766, 17515, 33425, 33419, 33437, 21171, 33457, + 33459, 33469, 33510, 55386, 57148, 33565, 33635, 33709, + 33571, 33725, 33767, 33619, 33738, 33740, 33756, 55387, + 56374, 55387, 56683, 55387, 56533, 17707, 34033, 34035, + 34070, 55388, 57290, 34148, 55387, 57132, 17757, 17761, + 55387, 57265, 55388, 56530, 17771, 34384, 34407, 34409, + 34473, 34440, 34574, 34530, 34600, 34667, 34694, 17879, + 34785, 34817, 17913, 34912, 55389, 56935, 35031, 35038, + 17973, 35066, 13499, 55390, 56494, 55390, 56678, 18110, + 18119, 35488, 55391, 56488, 36011, 36033, 36123, 36215, + 55391, 57135, 55362, 56324, 36299, 36284, 36336, 55362, + 56542, 36564, 55393, 56786, 55393, 56813, 37012, 37105, + 37137, 55393, 57134, 37147, 37432, 37591, 37592, 37500, + 37881, 37909, 55394, 57338, 38283, 18837, 38327, 55395, + 56695, 18918, 38595, 23986, 38691, 55396, 56645, 55396, + 56858, 19054, 19062, 38880, 55397, 56330, 19122, 55397, + 56470, 38953, 55397, 56758, 39138, 19251, 39209, 39335, + 39362, 39422, 19406, 55398, 57136, 40000, 40189, 19662, + 19693, 40295, 55400, 56526, 19704, 55400, 56581, 55400, + 56846, 55400, 56977, 19798, 40702, 40709, 40719, 40726, + 55401, 56832, 192, 193, 194, 195, 196, 199, + 200, 201, 202, 203, 204, 205, 206, 207, + 208, 209, 210, 211, 212, 213, 214, 216, + 217, 218, 219, 220, 221, 222, 376, 256, + 258, 260, 262, 264, 266, 268, 270, 272, + 274, 276, 278, 280, 282, 284, 286, 288, + 290, 292, 296, 298, 300, 302, 306, 308, + 310, 313, 315, 317, 319, 321, 323, 325, + 327, 330, 332, 334, 336, 338, 340, 342, + 344, 346, 348, 350, 352, 354, 356, 358, + 360, 362, 364, 366, 368, 370, 372, 374, + 377, 379, 381, 579, 386, 388, 391, 395, + 401, 502, 408, 573, 544, 416, 418, 420, + 423, 428, 431, 435, 437, 440, 444, 503, + 453, 452, 456, 455, 459, 458, 461, 463, + 465, 467, 469, 471, 473, 475, 478, 480, + 482, 484, 486, 488, 490, 492, 494, 498, + 497, 500, 504, 506, 508, 510, 512, 514, + 516, 518, 520, 522, 524, 526, 528, 530, + 532, 534, 536, 538, 540, 542, 548, 550, + 552, 554, 556, 558, 560, 562, 571, 11390, + 11391, 577, 582, 584, 586, 588, 590, 11375, + 11373, 11376, 385, 390, 393, 394, 399, 42923, + 403, 42924, 404, 42893, 42922, 407, 406, 42926, + 11362, 42925, 412, 11374, 413, 415, 11364, 422, + 425, 42929, 430, 580, 433, 434, 581, 439, + 42930, 42928, 880, 882, 886, 1021, 1022, 1023, + 938, 939, 975, 984, 986, 990, 992, 994, + 996, 998, 1000, 1002, 1004, 1006, 1017, 895, + 1015, 1018, 1040, 1041, 1042, 1043, 1044, 1045, + 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, + 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, + 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, + 1070, 1071, 1024, 1025, 1026, 1027, 1028, 1029, + 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, + 1038, 1039, 1120, 1122, 1124, 1126, 1128, 1130, + 1132, 1134, 1136, 1138, 1140, 1142, 1144, 1146, + 1148, 1150, 1152, 1162, 1164, 1166, 1168, 1170, + 1172, 1174, 1176, 1178, 1180, 1182, 1184, 1186, + 1188, 1190, 1192, 1194, 1196, 1198, 1200, 1202, + 1204, 1206, 1208, 1210, 1212, 1214, 1217, 1219, + 1221, 1223, 1225, 1227, 1229, 1216, 1232, 1234, + 1236, 1238, 1240, 1242, 1244, 1246, 1248, 1250, + 1252, 1254, 1256, 1258, 1260, 1262, 1264, 1266, + 1268, 1270, 1272, 1274, 1276, 1278, 1280, 1282, + 1284, 1286, 1288, 1290, 1292, 1294, 1296, 1298, + 1300, 1302, 1304, 1306, 1308, 1310, 1312, 1314, + 1316, 1318, 1320, 1322, 1324, 1326, 1329, 1330, + 1331, 1332, 1333, 1334, 1335, 1336, 1337, 1338, + 1339, 1340, 1341, 1342, 1343, 1344, 1345, 1346, + 1347, 1348, 1349, 1350, 1351, 1352, 1353, 1354, + 1355, 1356, 1357, 1358, 1359, 1360, 1361, 1362, + 1363, 1364, 1365, 1366, 43888, 43889, 43890, 43891, + 43892, 43893, 43894, 43895, 43896, 43897, 43898, 43899, + 43900, 43901, 43902, 43903, 43904, 43905, 43906, 43907, + 43908, 43909, 43910, 43911, 43912, 43913, 43914, 43915, + 43916, 43917, 43918, 43919, 43920, 43921, 43922, 43923, + 43924, 43925, 43926, 43927, 43928, 43929, 43930, 43931, + 43932, 43933, 43934, 43935, 43936, 43937, 43938, 43939, + 43940, 43941, 43942, 43943, 43944, 43945, 43946, 43947, + 43948, 43949, 43950, 43951, 43952, 43953, 43954, 43955, + 43956, 43957, 43958, 43959, 43960, 43961, 43962, 43963, + 43964, 43965, 43966, 43967, 5112, 5113, 5114, 5115, + 5116, 5117, 42570, 42877, 11363, 7680, 7682, 7684, + 7686, 7688, 7690, 7692, 7694, 7696, 7698, 7700, + 7702, 7704, 7706, 7708, 7710, 7712, 7714, 7716, + 7718, 7720, 7722, 7724, 7726, 7728, 7730, 7732, + 7734, 7736, 7738, 7740, 7742, 7744, 7746, 7748, + 7750, 7752, 7754, 7756, 7758, 7760, 7762, 7764, + 7766, 7768, 7770, 7772, 7774, 7776, 7778, 7780, + 7782, 7784, 7786, 7788, 7790, 7792, 7794, 7796, + 7798, 7800, 7802, 7804, 7806, 7808, 7810, 7812, + 7814, 7816, 7818, 7820, 7822, 7824, 7826, 7828, + 7840, 7842, 7844, 7846, 7848, 7850, 7852, 7854, + 7856, 7858, 7860, 7862, 7864, 7866, 7868, 7870, + 7872, 7874, 7876, 7878, 7880, 7882, 7884, 7886, + 7888, 7890, 7892, 7894, 7896, 7898, 7900, 7902, + 7904, 7906, 7908, 7910, 7912, 7914, 7916, 7918, + 7920, 7922, 7924, 7926, 7928, 7930, 7932, 7934, + 7944, 7945, 7946, 7947, 7948, 7949, 7950, 7951, + 7960, 7961, 7962, 7963, 7964, 7965, 7976, 7977, + 7978, 7979, 7980, 7981, 7982, 7983, 7992, 7993, + 7994, 7995, 7996, 7997, 7998, 7999, 8008, 8009, + 8010, 8011, 8012, 8013, 8025, 8027, 8029, 8031, + 8040, 8041, 8042, 8043, 8044, 8045, 8046, 8047, + 8122, 8123, 8136, 8137, 8138, 8139, 8154, 8155, + 8184, 8185, 8170, 8171, 8186, 8187, 8072, 8073, + 8074, 8075, 8076, 8077, 8078, 8079, 8088, 8089, + 8090, 8091, 8092, 8093, 8094, 8095, 8104, 8105, + 8106, 8107, 8108, 8109, 8110, 8111, 8120, 8121, + 8124, 8140, 8152, 8153, 8168, 8169, 8172, 8188, + 8498, 8544, 8545, 8546, 8547, 8548, 8549, 8550, + 8551, 8552, 8553, 8554, 8555, 8556, 8557, 8558, + 8559, 8579, 9398, 9399, 9400, 9401, 9402, 9403, + 9404, 9405, 9406, 9407, 9408, 9409, 9410, 9411, + 9412, 9413, 9414, 9415, 9416, 9417, 9418, 9419, + 9420, 9421, 9422, 9423, 11264, 11265, 11266, 11267, + 11268, 11269, 11270, 11271, 11272, 11273, 11274, 11275, + 11276, 11277, 11278, 11279, 11280, 11281, 11282, 11283, + 11284, 11285, 11286, 11287, 11288, 11289, 11290, 11291, + 11292, 11293, 11294, 11295, 11296, 11297, 11298, 11299, + 11300, 11301, 11302, 11303, 11304, 11305, 11306, 11307, + 11308, 11309, 11310, 11360, 570, 574, 11367, 11369, + 11371, 11378, 11381, 11392, 11394, 11396, 11398, 11400, + 11402, 11404, 11406, 11408, 11410, 11412, 11414, 11416, + 11418, 11420, 11422, 11424, 11426, 11428, 11430, 11432, + 11434, 11436, 11438, 11440, 11442, 11444, 11446, 11448, + 11450, 11452, 11454, 11456, 11458, 11460, 11462, 11464, + 11466, 11468, 11470, 11472, 11474, 11476, 11478, 11480, + 11482, 11484, 11486, 11488, 11490, 11499, 11501, 11506, + 4256, 4257, 4258, 4259, 4260, 4261, 4262, 4263, + 4264, 4265, 4266, 4267, 4268, 4269, 4270, 4271, + 4272, 4273, 4274, 4275, 4276, 4277, 4278, 4279, + 4280, 4281, 4282, 4283, 4284, 4285, 4286, 4287, + 4288, 4289, 4290, 4291, 4292, 4293, 4295, 4301, + 42560, 42562, 42564, 42566, 42568, 42572, 42574, 42576, + 42578, 42580, 42582, 42584, 42586, 42588, 42590, 42592, + 42594, 42596, 42598, 42600, 42602, 42604, 42624, 42626, + 42628, 42630, 42632, 42634, 42636, 42638, 42640, 42642, + 42644, 42646, 42648, 42650, 42786, 42788, 42790, 42792, + 42794, 42796, 42798, 42802, 42804, 42806, 42808, 42810, + 42812, 42814, 42816, 42818, 42820, 42822, 42824, 42826, + 42828, 42830, 42832, 42834, 42836, 42838, 42840, 42842, + 42844, 42846, 42848, 42850, 42852, 42854, 42856, 42858, + 42860, 42862, 42873, 42875, 42878, 42880, 42882, 42884, + 42886, 42891, 42896, 42898, 42902, 42904, 42906, 42908, + 42910, 42912, 42914, 42916, 42918, 42920, 42932, 42934, + 42931, 65313, 65314, 65315, 65316, 65317, 65318, 65319, + 65320, 65321, 65322, 65323, 65324, 65325, 65326, 65327, + 65328, 65329, 65330, 65331, 65332, 65333, 65334, 65335, + 65336, 65337, 65338, 55297, 56320, 55297, 56321, 55297, + 56322, 55297, 56323, 55297, 56324, 55297, 56325, 55297, + 56326, 55297, 56327, 55297, 56328, 55297, 56329, 55297, + 56330, 55297, 56331, 55297, 56332, 55297, 56333, 55297, + 56334, 55297, 56335, 55297, 56336, 55297, 56337, 55297, + 56338, 55297, 56339, 55297, 56340, 55297, 56341, 55297, + 56342, 55297, 56343, 55297, 56344, 55297, 56345, 55297, + 56346, 55297, 56347, 55297, 56348, 55297, 56349, 55297, + 56350, 55297, 56351, 55297, 56352, 55297, 56353, 55297, + 56354, 55297, 56355, 55297, 56356, 55297, 56357, 55297, + 56358, 55297, 56359, 55297, 56496, 55297, 56497, 55297, + 56498, 55297, 56499, 55297, 56500, 55297, 56501, 55297, + 56502, 55297, 56503, 55297, 56504, 55297, 56505, 55297, + 56506, 55297, 56507, 55297, 56508, 55297, 56509, 55297, + 56510, 55297, 56511, 55297, 56512, 55297, 56513, 55297, + 56514, 55297, 56515, 55297, 56516, 55297, 56517, 55297, + 56518, 55297, 56519, 55297, 56520, 55297, 56521, 55297, + 56522, 55297, 56523, 55297, 56524, 55297, 56525, 55297, + 56526, 55297, 56527, 55297, 56528, 55297, 56529, 55297, + 56530, 55297, 56531, 55299, 56448, 55299, 56449, 55299, + 56450, 55299, 56451, 55299, 56452, 55299, 56453, 55299, + 56454, 55299, 56455, 55299, 56456, 55299, 56457, 55299, + 56458, 55299, 56459, 55299, 56460, 55299, 56461, 55299, + 56462, 55299, 56463, 55299, 56464, 55299, 56465, 55299, + 56466, 55299, 56467, 55299, 56468, 55299, 56469, 55299, + 56470, 55299, 56471, 55299, 56472, 55299, 56473, 55299, + 56474, 55299, 56475, 55299, 56476, 55299, 56477, 55299, + 56478, 55299, 56479, 55299, 56480, 55299, 56481, 55299, + 56482, 55299, 56483, 55299, 56484, 55299, 56485, 55299, + 56486, 55299, 56487, 55299, 56488, 55299, 56489, 55299, + 56490, 55299, 56491, 55299, 56492, 55299, 56493, 55299, + 56494, 55299, 56495, 55299, 56496, 55299, 56497, 55299, + 56498, 55302, 56480, 55302, 56481, 55302, 56482, 55302, + 56483, 55302, 56484, 55302, 56485, 55302, 56486, 55302, + 56487, 55302, 56488, 55302, 56489, 55302, 56490, 55302, + 56491, 55302, 56492, 55302, 56493, 55302, 56494, 55302, + 56495, 55302, 56496, 55302, 56497, 55302, 56498, 55302, + 56499, 55302, 56500, 55302, 56501, 55302, 56502, 55302, + 56503, 55302, 56504, 55302, 56505, 55302, 56506, 55302, + 56507, 55302, 56508, 55302, 56509, 55302, 56510, 55302, + 56511, 55354, 56576, 55354, 56577, 55354, 56578, 55354, + 56579, 55354, 56580, 55354, 56581, 55354, 56582, 55354, + 56583, 55354, 56584, 55354, 56585, 55354, 56586, 55354, + 56587, 55354, 56588, 55354, 56589, 55354, 56590, 55354, + 56591, 55354, 56592, 55354, 56593, 55354, 56594, 55354, + 56595, 55354, 56596, 55354, 56597, 55354, 56598, 55354, + 56599, 55354, 56600, 55354, 56601, 55354, 56602, 55354, + 56603, 55354, 56604, 55354, 56605, 55354, 56606, 55354, + 56607, 55354, 56608, 55354, 56609, }; UTF8PROC_DATA -const int32_t utf8proc_sequences[] = { - 97, -1, 98, -1, 99, -1, 100, - -1, 101, -1, 102, -1, 103, -1, 104, - -1, 105, -1, 106, -1, 107, -1, 108, - -1, 109, -1, 110, -1, 111, -1, 112, - -1, 113, -1, 114, -1, 115, -1, 116, - -1, 117, -1, 118, -1, 119, -1, 120, - -1, 121, -1, 122, -1, 32, -1, 32, - 776, -1, 32, 772, -1, 50, -1, 51, - -1, 32, 769, -1, 956, -1, 32, 807, - -1, 49, -1, 49, 8260, 52, -1, 49, - 8260, 50, -1, 51, 8260, 52, -1, 65, - 768, -1, 224, -1, 65, 769, -1, 225, - -1, 65, 770, -1, 226, -1, 65, 771, - -1, 227, -1, 65, 776, -1, 228, -1, - 65, 778, -1, 229, -1, 230, -1, 67, - 807, -1, 231, -1, 69, 768, -1, 232, - -1, 69, 769, -1, 233, -1, 69, 770, - -1, 234, -1, 69, 776, -1, 235, -1, - 73, 768, -1, 236, -1, 73, 769, -1, - 237, -1, 73, 770, -1, 238, -1, 73, - 776, -1, 239, -1, 240, -1, 78, 771, - -1, 241, -1, 79, 768, -1, 242, -1, - 79, 769, -1, 243, -1, 79, 770, -1, - 244, -1, 79, 771, -1, 245, -1, 79, - 776, -1, 246, -1, 248, -1, 85, 768, - -1, 249, -1, 85, 769, -1, 250, -1, - 85, 770, -1, 251, -1, 85, 776, -1, - 252, -1, 89, 769, -1, 253, -1, 254, - -1, 115, 115, -1, 97, 768, -1, 97, - 769, -1, 97, 770, -1, 97, 771, -1, - 97, 776, -1, 97, 778, -1, 99, 807, - -1, 101, 768, -1, 101, 769, -1, 101, - 770, -1, 101, 776, -1, 105, 768, -1, - 105, 769, -1, 105, 770, -1, 105, 776, - -1, 110, 771, -1, 111, 768, -1, 111, - 769, -1, 111, 770, -1, 111, 771, -1, - 111, 776, -1, 117, 768, -1, 117, 769, - -1, 117, 770, -1, 117, 776, -1, 121, - 769, -1, 121, 776, -1, 65, 772, -1, - 257, -1, 97, 772, -1, 65, 774, -1, - 259, -1, 97, 774, -1, 65, 808, -1, - 261, -1, 97, 808, -1, 67, 769, -1, - 263, -1, 99, 769, -1, 67, 770, -1, - 265, -1, 99, 770, -1, 67, 775, -1, - 267, -1, 99, 775, -1, 67, 780, -1, - 269, -1, 99, 780, -1, 68, 780, -1, - 271, -1, 100, 780, -1, 273, -1, 69, - 772, -1, 275, -1, 101, 772, -1, 69, - 774, -1, 277, -1, 101, 774, -1, 69, - 775, -1, 279, -1, 101, 775, -1, 69, - 808, -1, 281, -1, 101, 808, -1, 69, - 780, -1, 283, -1, 101, 780, -1, 71, - 770, -1, 285, -1, 103, 770, -1, 71, - 774, -1, 287, -1, 103, 774, -1, 71, - 775, -1, 289, -1, 103, 775, -1, 71, - 807, -1, 291, -1, 103, 807, -1, 72, - 770, -1, 293, -1, 104, 770, -1, 295, - -1, 73, 771, -1, 297, -1, 105, 771, - -1, 73, 772, -1, 299, -1, 105, 772, - -1, 73, 774, -1, 301, -1, 105, 774, - -1, 73, 808, -1, 303, -1, 105, 808, - -1, 73, 775, -1, 105, 775, -1, 73, - 74, -1, 307, -1, 105, 106, -1, 74, - 770, -1, 309, -1, 106, 770, -1, 75, - 807, -1, 311, -1, 107, 807, -1, 76, - 769, -1, 314, -1, 108, 769, -1, 76, - 807, -1, 316, -1, 108, 807, -1, 76, - 780, -1, 318, -1, 108, 780, -1, 76, - 183, -1, 320, -1, 108, 183, -1, 322, - -1, 78, 769, -1, 324, -1, 110, 769, - -1, 78, 807, -1, 326, -1, 110, 807, - -1, 78, 780, -1, 328, -1, 110, 780, - -1, 700, 110, -1, 331, -1, 79, 772, - -1, 333, -1, 111, 772, -1, 79, 774, - -1, 335, -1, 111, 774, -1, 79, 779, - -1, 337, -1, 111, 779, -1, 339, -1, - 82, 769, -1, 341, -1, 114, 769, -1, - 82, 807, -1, 343, -1, 114, 807, -1, - 82, 780, -1, 345, -1, 114, 780, -1, - 83, 769, -1, 347, -1, 115, 769, -1, - 83, 770, -1, 349, -1, 115, 770, -1, - 83, 807, -1, 351, -1, 115, 807, -1, - 83, 780, -1, 353, -1, 115, 780, -1, - 84, 807, -1, 355, -1, 116, 807, -1, - 84, 780, -1, 357, -1, 116, 780, -1, - 359, -1, 85, 771, -1, 361, -1, 117, - 771, -1, 85, 772, -1, 363, -1, 117, - 772, -1, 85, 774, -1, 365, -1, 117, - 774, -1, 85, 778, -1, 367, -1, 117, - 778, -1, 85, 779, -1, 369, -1, 117, - 779, -1, 85, 808, -1, 371, -1, 117, - 808, -1, 87, 770, -1, 373, -1, 119, - 770, -1, 89, 770, -1, 375, -1, 121, - 770, -1, 89, 776, -1, 255, -1, 90, - 769, -1, 378, -1, 122, 769, -1, 90, - 775, -1, 380, -1, 122, 775, -1, 90, - 780, -1, 382, -1, 122, 780, -1, 595, - -1, 387, -1, 389, -1, 596, -1, 392, - -1, 598, -1, 599, -1, 396, -1, 477, - -1, 601, -1, 603, -1, 402, -1, 608, - -1, 611, -1, 617, -1, 616, -1, 409, - -1, 623, -1, 626, -1, 629, -1, 79, - 795, -1, 417, -1, 111, 795, -1, 419, - -1, 421, -1, 640, -1, 424, -1, 643, - -1, 429, -1, 648, -1, 85, 795, -1, - 432, -1, 117, 795, -1, 650, -1, 651, - -1, 436, -1, 438, -1, 658, -1, 441, - -1, 445, -1, 68, 381, -1, 454, -1, - 68, 382, -1, 100, 382, -1, 76, 74, - -1, 457, -1, 76, 106, -1, 108, 106, - -1, 78, 74, -1, 460, -1, 78, 106, - -1, 110, 106, -1, 65, 780, -1, 462, - -1, 97, 780, -1, 73, 780, -1, 464, - -1, 105, 780, -1, 79, 780, -1, 466, - -1, 111, 780, -1, 85, 780, -1, 468, - -1, 117, 780, -1, 220, 772, -1, 470, - -1, 252, 772, -1, 220, 769, -1, 472, - -1, 252, 769, -1, 220, 780, -1, 474, - -1, 252, 780, -1, 220, 768, -1, 476, - -1, 252, 768, -1, 196, 772, -1, 479, - -1, 228, 772, -1, 550, 772, -1, 481, - -1, 551, 772, -1, 198, 772, -1, 483, - -1, 230, 772, -1, 485, -1, 71, 780, - -1, 487, -1, 103, 780, -1, 75, 780, - -1, 489, -1, 107, 780, -1, 79, 808, - -1, 491, -1, 111, 808, -1, 490, 772, - -1, 493, -1, 491, 772, -1, 439, 780, - -1, 495, -1, 658, 780, -1, 106, 780, - -1, 68, 90, -1, 499, -1, 68, 122, - -1, 100, 122, -1, 71, 769, -1, 501, - -1, 103, 769, -1, 405, -1, 447, -1, - 78, 768, -1, 505, -1, 110, 768, -1, - 197, 769, -1, 507, -1, 229, 769, -1, - 198, 769, -1, 509, -1, 230, 769, -1, - 216, 769, -1, 511, -1, 248, 769, -1, - 65, 783, -1, 513, -1, 97, 783, -1, - 65, 785, -1, 515, -1, 97, 785, -1, - 69, 783, -1, 517, -1, 101, 783, -1, - 69, 785, -1, 519, -1, 101, 785, -1, - 73, 783, -1, 521, -1, 105, 783, -1, - 73, 785, -1, 523, -1, 105, 785, -1, - 79, 783, -1, 525, -1, 111, 783, -1, - 79, 785, -1, 527, -1, 111, 785, -1, - 82, 783, -1, 529, -1, 114, 783, -1, - 82, 785, -1, 531, -1, 114, 785, -1, - 85, 783, -1, 533, -1, 117, 783, -1, - 85, 785, -1, 535, -1, 117, 785, -1, - 83, 806, -1, 537, -1, 115, 806, -1, - 84, 806, -1, 539, -1, 116, 806, -1, - 541, -1, 72, 780, -1, 543, -1, 104, - 780, -1, 414, -1, 547, -1, 549, -1, - 65, 775, -1, 551, -1, 97, 775, -1, - 69, 807, -1, 553, -1, 101, 807, -1, - 214, 772, -1, 555, -1, 246, 772, -1, - 213, 772, -1, 557, -1, 245, 772, -1, - 79, 775, -1, 559, -1, 111, 775, -1, - 558, 772, -1, 561, -1, 559, 772, -1, - 89, 772, -1, 563, -1, 121, 772, -1, - 11365, -1, 572, -1, 410, -1, 11366, -1, - 578, -1, 384, -1, 649, -1, 652, -1, - 583, -1, 585, -1, 587, -1, 589, -1, - 591, -1, 614, -1, 633, -1, 635, -1, - 641, -1, 32, 774, -1, 32, 775, -1, - 32, 778, -1, 32, 808, -1, 32, 771, - -1, 32, 779, -1, 661, -1, 768, -1, - 769, -1, 787, -1, 776, 769, -1, 953, - -1, 697, -1, 32, 837, -1, 59, -1, - 168, 769, -1, 913, 769, -1, 940, -1, - 183, -1, 917, 769, -1, 941, -1, 919, - 769, -1, 942, -1, 921, 769, -1, 943, - -1, 927, 769, -1, 972, -1, 933, 769, - -1, 973, -1, 937, 769, -1, 974, -1, - 970, 769, -1, 953, 776, 769, -1, 945, - -1, 946, -1, 947, -1, 948, -1, 949, - -1, 950, -1, 951, -1, 952, -1, 954, - -1, 955, -1, 957, -1, 958, -1, 959, - -1, 960, -1, 961, -1, 963, -1, 964, - -1, 965, -1, 966, -1, 967, -1, 968, - -1, 969, -1, 921, 776, -1, 970, -1, - 933, 776, -1, 971, -1, 945, 769, -1, - 949, 769, -1, 951, 769, -1, 953, 769, - -1, 971, 769, -1, 965, 776, 769, -1, - 953, 776, -1, 965, 776, -1, 959, 769, - -1, 965, 769, -1, 969, 769, -1, 933, - -1, 978, 769, -1, 978, 776, -1, 985, - -1, 987, -1, 989, -1, 991, -1, 993, - -1, 995, -1, 997, -1, 999, -1, 1001, - -1, 1003, -1, 1005, -1, 1007, -1, 962, - -1, 920, -1, 1016, -1, 931, -1, 1010, - -1, 1019, -1, 891, -1, 892, -1, 893, - -1, 1045, 768, -1, 1104, -1, 1045, 776, - -1, 1105, -1, 1106, -1, 1043, 769, -1, - 1107, -1, 1108, -1, 1109, -1, 1110, -1, - 1030, 776, -1, 1111, -1, 1112, -1, 1113, - -1, 1114, -1, 1115, -1, 1050, 769, -1, - 1116, -1, 1048, 768, -1, 1117, -1, 1059, - 774, -1, 1118, -1, 1119, -1, 1072, -1, - 1073, -1, 1074, -1, 1075, -1, 1076, -1, - 1077, -1, 1078, -1, 1079, -1, 1080, -1, - 1048, 774, -1, 1081, -1, 1082, -1, 1083, - -1, 1084, -1, 1085, -1, 1086, -1, 1087, - -1, 1088, -1, 1089, -1, 1090, -1, 1091, - -1, 1092, -1, 1093, -1, 1094, -1, 1095, - -1, 1096, -1, 1097, -1, 1098, -1, 1099, - -1, 1100, -1, 1101, -1, 1102, -1, 1103, - -1, 1080, 774, -1, 1077, 768, -1, 1077, - 776, -1, 1075, 769, -1, 1110, 776, -1, - 1082, 769, -1, 1080, 768, -1, 1091, 774, - -1, 1121, -1, 1123, -1, 1125, -1, 1127, - -1, 1129, -1, 1131, -1, 1133, -1, 1135, - -1, 1137, -1, 1139, -1, 1141, -1, 1140, - 783, -1, 1143, -1, 1141, 783, -1, 1145, - -1, 1147, -1, 1149, -1, 1151, -1, 1153, - -1, 1163, -1, 1165, -1, 1167, -1, 1169, - -1, 1171, -1, 1173, -1, 1175, -1, 1177, - -1, 1179, -1, 1181, -1, 1183, -1, 1185, - -1, 1187, -1, 1189, -1, 1191, -1, 1193, - -1, 1195, -1, 1197, -1, 1199, -1, 1201, - -1, 1203, -1, 1205, -1, 1207, -1, 1209, - -1, 1211, -1, 1213, -1, 1215, -1, 1231, - -1, 1046, 774, -1, 1218, -1, 1078, 774, - -1, 1220, -1, 1222, -1, 1224, -1, 1226, - -1, 1228, -1, 1230, -1, 1040, 774, -1, - 1233, -1, 1072, 774, -1, 1040, 776, -1, - 1235, -1, 1072, 776, -1, 1237, -1, 1045, - 774, -1, 1239, -1, 1077, 774, -1, 1241, - -1, 1240, 776, -1, 1243, -1, 1241, 776, - -1, 1046, 776, -1, 1245, -1, 1078, 776, - -1, 1047, 776, -1, 1247, -1, 1079, 776, - -1, 1249, -1, 1048, 772, -1, 1251, -1, - 1080, 772, -1, 1048, 776, -1, 1253, -1, - 1080, 776, -1, 1054, 776, -1, 1255, -1, - 1086, 776, -1, 1257, -1, 1256, 776, -1, - 1259, -1, 1257, 776, -1, 1069, 776, -1, - 1261, -1, 1101, 776, -1, 1059, 772, -1, - 1263, -1, 1091, 772, -1, 1059, 776, -1, - 1265, -1, 1091, 776, -1, 1059, 779, -1, - 1267, -1, 1091, 779, -1, 1063, 776, -1, - 1269, -1, 1095, 776, -1, 1271, -1, 1067, - 776, -1, 1273, -1, 1099, 776, -1, 1275, - -1, 1277, -1, 1279, -1, 1281, -1, 1283, - -1, 1285, -1, 1287, -1, 1289, -1, 1291, - -1, 1293, -1, 1295, -1, 1297, -1, 1299, - -1, 1377, -1, 1378, -1, 1379, -1, 1380, - -1, 1381, -1, 1382, -1, 1383, -1, 1384, - -1, 1385, -1, 1386, -1, 1387, -1, 1388, - -1, 1389, -1, 1390, -1, 1391, -1, 1392, - -1, 1393, -1, 1394, -1, 1395, -1, 1396, - -1, 1397, -1, 1398, -1, 1399, -1, 1400, - -1, 1401, -1, 1402, -1, 1403, -1, 1404, - -1, 1405, -1, 1406, -1, 1407, -1, 1408, - -1, 1409, -1, 1410, -1, 1411, -1, 1412, - -1, 1413, -1, 1414, -1, 1381, 1410, -1, - 1575, 1619, -1, 1575, 1620, -1, 1608, 1620, - -1, 1575, 1621, -1, 1610, 1620, -1, 1575, - 1652, -1, 1608, 1652, -1, 1735, 1652, -1, - 1610, 1652, -1, 1749, 1620, -1, 1729, 1620, - -1, 1746, 1620, -1, 2344, 2364, -1, 2352, - 2364, -1, 2355, 2364, -1, 2325, 2364, -1, - 2326, 2364, -1, 2327, 2364, -1, 2332, 2364, - -1, 2337, 2364, -1, 2338, 2364, -1, 2347, - 2364, -1, 2351, 2364, -1, 2503, 2494, -1, - 2503, 2519, -1, 2465, 2492, -1, 2466, 2492, - -1, 2479, 2492, -1, 2610, 2620, -1, 2616, - 2620, -1, 2582, 2620, -1, 2583, 2620, -1, - 2588, 2620, -1, 2603, 2620, -1, 2887, 2902, - -1, 2887, 2878, -1, 2887, 2903, -1, 2849, - 2876, -1, 2850, 2876, -1, 2962, 3031, -1, - 3014, 3006, -1, 3015, 3006, -1, 3014, 3031, - -1, 3142, 3158, -1, 3263, 3285, -1, 3270, - 3285, -1, 3270, 3286, -1, 3270, 3266, -1, - 3274, 3285, -1, 3398, 3390, -1, 3399, 3390, - -1, 3398, 3415, -1, 3545, 3530, -1, 3545, - 3535, -1, 3548, 3530, -1, 3545, 3551, -1, - 3661, 3634, -1, 3789, 3762, -1, 3755, 3737, - -1, 3755, 3745, -1, 3851, -1, 3906, 4023, - -1, 3916, 4023, -1, 3921, 4023, -1, 3926, - 4023, -1, 3931, 4023, -1, 3904, 4021, -1, - 3953, 3954, -1, 3953, 3956, -1, 4018, 3968, - -1, 4018, 3969, -1, 4019, 3968, -1, 4019, - 3969, -1, 3953, 3968, -1, 3986, 4023, -1, - 3996, 4023, -1, 4001, 4023, -1, 4006, 4023, - -1, 4011, 4023, -1, 3984, 4021, -1, 4133, - 4142, -1, 11520, -1, 11521, -1, 11522, -1, - 11523, -1, 11524, -1, 11525, -1, 11526, -1, - 11527, -1, 11528, -1, 11529, -1, 11530, -1, - 11531, -1, 11532, -1, 11533, -1, 11534, -1, - 11535, -1, 11536, -1, 11537, -1, 11538, -1, - 11539, -1, 11540, -1, 11541, -1, 11542, -1, - 11543, -1, 11544, -1, 11545, -1, 11546, -1, - 11547, -1, 11548, -1, 11549, -1, 11550, -1, - 11551, -1, 11552, -1, 11553, -1, 11554, -1, - 11555, -1, 11556, -1, 11557, -1, 4316, -1, - 6917, 6965, -1, 6919, 6965, -1, 6921, 6965, - -1, 6923, 6965, -1, 6925, 6965, -1, 6929, - 6965, -1, 6970, 6965, -1, 6972, 6965, -1, - 6974, 6965, -1, 6975, 6965, -1, 6978, 6965, - -1, 65, -1, 198, -1, 66, -1, 68, - -1, 69, -1, 398, -1, 71, -1, 72, - -1, 73, -1, 74, -1, 75, -1, 76, - -1, 77, -1, 78, -1, 79, -1, 546, - -1, 80, -1, 82, -1, 84, -1, 85, - -1, 87, -1, 592, -1, 593, -1, 7426, - -1, 604, -1, 7446, -1, 7447, -1, 7453, - -1, 7461, -1, 594, -1, 597, -1, 607, - -1, 609, -1, 613, -1, 618, -1, 7547, - -1, 669, -1, 621, -1, 7557, -1, 671, - -1, 625, -1, 624, -1, 627, -1, 628, - -1, 632, -1, 642, -1, 427, -1, 7452, - -1, 656, -1, 657, -1, 65, 805, -1, - 7681, -1, 97, 805, -1, 66, 775, -1, - 7683, -1, 98, 775, -1, 66, 803, -1, - 7685, -1, 98, 803, -1, 66, 817, -1, - 7687, -1, 98, 817, -1, 199, 769, -1, - 7689, -1, 231, 769, -1, 68, 775, -1, - 7691, -1, 100, 775, -1, 68, 803, -1, - 7693, -1, 100, 803, -1, 68, 817, -1, - 7695, -1, 100, 817, -1, 68, 807, -1, - 7697, -1, 100, 807, -1, 68, 813, -1, - 7699, -1, 100, 813, -1, 274, 768, -1, - 7701, -1, 275, 768, -1, 274, 769, -1, - 7703, -1, 275, 769, -1, 69, 813, -1, - 7705, -1, 101, 813, -1, 69, 816, -1, - 7707, -1, 101, 816, -1, 552, 774, -1, - 7709, -1, 553, 774, -1, 70, 775, -1, - 7711, -1, 102, 775, -1, 71, 772, -1, - 7713, -1, 103, 772, -1, 72, 775, -1, - 7715, -1, 104, 775, -1, 72, 803, -1, - 7717, -1, 104, 803, -1, 72, 776, -1, - 7719, -1, 104, 776, -1, 72, 807, -1, - 7721, -1, 104, 807, -1, 72, 814, -1, - 7723, -1, 104, 814, -1, 73, 816, -1, - 7725, -1, 105, 816, -1, 207, 769, -1, - 7727, -1, 239, 769, -1, 75, 769, -1, - 7729, -1, 107, 769, -1, 75, 803, -1, - 7731, -1, 107, 803, -1, 75, 817, -1, - 7733, -1, 107, 817, -1, 76, 803, -1, - 7735, -1, 108, 803, -1, 7734, 772, -1, - 7737, -1, 7735, 772, -1, 76, 817, -1, - 7739, -1, 108, 817, -1, 76, 813, -1, - 7741, -1, 108, 813, -1, 77, 769, -1, - 7743, -1, 109, 769, -1, 77, 775, -1, - 7745, -1, 109, 775, -1, 77, 803, -1, - 7747, -1, 109, 803, -1, 78, 775, -1, - 7749, -1, 110, 775, -1, 78, 803, -1, - 7751, -1, 110, 803, -1, 78, 817, -1, - 7753, -1, 110, 817, -1, 78, 813, -1, - 7755, -1, 110, 813, -1, 213, 769, -1, - 7757, -1, 245, 769, -1, 213, 776, -1, - 7759, -1, 245, 776, -1, 332, 768, -1, - 7761, -1, 333, 768, -1, 332, 769, -1, - 7763, -1, 333, 769, -1, 80, 769, -1, - 7765, -1, 112, 769, -1, 80, 775, -1, - 7767, -1, 112, 775, -1, 82, 775, -1, - 7769, -1, 114, 775, -1, 82, 803, -1, - 7771, -1, 114, 803, -1, 7770, 772, -1, - 7773, -1, 7771, 772, -1, 82, 817, -1, - 7775, -1, 114, 817, -1, 83, 775, -1, - 7777, -1, 115, 775, -1, 83, 803, -1, - 7779, -1, 115, 803, -1, 346, 775, -1, - 7781, -1, 347, 775, -1, 352, 775, -1, - 7783, -1, 353, 775, -1, 7778, 775, -1, - 7785, -1, 7779, 775, -1, 84, 775, -1, - 7787, -1, 116, 775, -1, 84, 803, -1, - 7789, -1, 116, 803, -1, 84, 817, -1, - 7791, -1, 116, 817, -1, 84, 813, -1, - 7793, -1, 116, 813, -1, 85, 804, -1, - 7795, -1, 117, 804, -1, 85, 816, -1, - 7797, -1, 117, 816, -1, 85, 813, -1, - 7799, -1, 117, 813, -1, 360, 769, -1, - 7801, -1, 361, 769, -1, 362, 776, -1, - 7803, -1, 363, 776, -1, 86, 771, -1, - 7805, -1, 118, 771, -1, 86, 803, -1, - 7807, -1, 118, 803, -1, 87, 768, -1, - 7809, -1, 119, 768, -1, 87, 769, -1, - 7811, -1, 119, 769, -1, 87, 776, -1, - 7813, -1, 119, 776, -1, 87, 775, -1, - 7815, -1, 119, 775, -1, 87, 803, -1, - 7817, -1, 119, 803, -1, 88, 775, -1, - 7819, -1, 120, 775, -1, 88, 776, -1, - 7821, -1, 120, 776, -1, 89, 775, -1, - 7823, -1, 121, 775, -1, 90, 770, -1, - 7825, -1, 122, 770, -1, 90, 803, -1, - 7827, -1, 122, 803, -1, 90, 817, -1, - 7829, -1, 122, 817, -1, 104, 817, -1, - 116, 776, -1, 119, 778, -1, 121, 778, - -1, 97, 702, -1, 383, 775, -1, 65, - 803, -1, 7841, -1, 97, 803, -1, 65, - 777, -1, 7843, -1, 97, 777, -1, 194, - 769, -1, 7845, -1, 226, 769, -1, 194, - 768, -1, 7847, -1, 226, 768, -1, 194, - 777, -1, 7849, -1, 226, 777, -1, 194, - 771, -1, 7851, -1, 226, 771, -1, 7840, - 770, -1, 7853, -1, 7841, 770, -1, 258, - 769, -1, 7855, -1, 259, 769, -1, 258, - 768, -1, 7857, -1, 259, 768, -1, 258, - 777, -1, 7859, -1, 259, 777, -1, 258, - 771, -1, 7861, -1, 259, 771, -1, 7840, - 774, -1, 7863, -1, 7841, 774, -1, 69, - 803, -1, 7865, -1, 101, 803, -1, 69, - 777, -1, 7867, -1, 101, 777, -1, 69, - 771, -1, 7869, -1, 101, 771, -1, 202, - 769, -1, 7871, -1, 234, 769, -1, 202, - 768, -1, 7873, -1, 234, 768, -1, 202, - 777, -1, 7875, -1, 234, 777, -1, 202, - 771, -1, 7877, -1, 234, 771, -1, 7864, - 770, -1, 7879, -1, 7865, 770, -1, 73, - 777, -1, 7881, -1, 105, 777, -1, 73, - 803, -1, 7883, -1, 105, 803, -1, 79, - 803, -1, 7885, -1, 111, 803, -1, 79, - 777, -1, 7887, -1, 111, 777, -1, 212, - 769, -1, 7889, -1, 244, 769, -1, 212, - 768, -1, 7891, -1, 244, 768, -1, 212, - 777, -1, 7893, -1, 244, 777, -1, 212, - 771, -1, 7895, -1, 244, 771, -1, 7884, - 770, -1, 7897, -1, 7885, 770, -1, 416, - 769, -1, 7899, -1, 417, 769, -1, 416, - 768, -1, 7901, -1, 417, 768, -1, 416, - 777, -1, 7903, -1, 417, 777, -1, 416, - 771, -1, 7905, -1, 417, 771, -1, 416, - 803, -1, 7907, -1, 417, 803, -1, 85, - 803, -1, 7909, -1, 117, 803, -1, 85, - 777, -1, 7911, -1, 117, 777, -1, 431, - 769, -1, 7913, -1, 432, 769, -1, 431, - 768, -1, 7915, -1, 432, 768, -1, 431, - 777, -1, 7917, -1, 432, 777, -1, 431, - 771, -1, 7919, -1, 432, 771, -1, 431, - 803, -1, 7921, -1, 432, 803, -1, 89, - 768, -1, 7923, -1, 121, 768, -1, 89, - 803, -1, 7925, -1, 121, 803, -1, 89, - 777, -1, 7927, -1, 121, 777, -1, 89, - 771, -1, 7929, -1, 121, 771, -1, 945, - 787, -1, 945, 788, -1, 7936, 768, -1, - 7937, 768, -1, 7936, 769, -1, 7937, 769, - -1, 7936, 834, -1, 7937, 834, -1, 913, - 787, -1, 7936, -1, 913, 788, -1, 7937, - -1, 7944, 768, -1, 7938, -1, 7945, 768, - -1, 7939, -1, 7944, 769, -1, 7940, -1, - 7945, 769, -1, 7941, -1, 7944, 834, -1, - 7942, -1, 7945, 834, -1, 7943, -1, 949, - 787, -1, 949, 788, -1, 7952, 768, -1, - 7953, 768, -1, 7952, 769, -1, 7953, 769, - -1, 917, 787, -1, 7952, -1, 917, 788, - -1, 7953, -1, 7960, 768, -1, 7954, -1, - 7961, 768, -1, 7955, -1, 7960, 769, -1, - 7956, -1, 7961, 769, -1, 7957, -1, 951, - 787, -1, 951, 788, -1, 7968, 768, -1, - 7969, 768, -1, 7968, 769, -1, 7969, 769, - -1, 7968, 834, -1, 7969, 834, -1, 919, - 787, -1, 7968, -1, 919, 788, -1, 7969, - -1, 7976, 768, -1, 7970, -1, 7977, 768, - -1, 7971, -1, 7976, 769, -1, 7972, -1, - 7977, 769, -1, 7973, -1, 7976, 834, -1, - 7974, -1, 7977, 834, -1, 7975, -1, 953, - 787, -1, 953, 788, -1, 7984, 768, -1, - 7985, 768, -1, 7984, 769, -1, 7985, 769, - -1, 7984, 834, -1, 7985, 834, -1, 921, - 787, -1, 7984, -1, 921, 788, -1, 7985, - -1, 7992, 768, -1, 7986, -1, 7993, 768, - -1, 7987, -1, 7992, 769, -1, 7988, -1, - 7993, 769, -1, 7989, -1, 7992, 834, -1, - 7990, -1, 7993, 834, -1, 7991, -1, 959, - 787, -1, 959, 788, -1, 8000, 768, -1, - 8001, 768, -1, 8000, 769, -1, 8001, 769, - -1, 927, 787, -1, 8000, -1, 927, 788, - -1, 8001, -1, 8008, 768, -1, 8002, -1, - 8009, 768, -1, 8003, -1, 8008, 769, -1, - 8004, -1, 8009, 769, -1, 8005, -1, 965, - 787, -1, 965, 788, -1, 8016, 768, -1, - 965, 787, 768, -1, 8017, 768, -1, 8016, - 769, -1, 965, 787, 769, -1, 8017, 769, - -1, 8016, 834, -1, 965, 787, 834, -1, - 8017, 834, -1, 933, 788, -1, 8017, -1, - 8025, 768, -1, 8019, -1, 8025, 769, -1, - 8021, -1, 8025, 834, -1, 8023, -1, 969, - 787, -1, 969, 788, -1, 8032, 768, -1, - 8033, 768, -1, 8032, 769, -1, 8033, 769, - -1, 8032, 834, -1, 8033, 834, -1, 937, - 787, -1, 8032, -1, 937, 788, -1, 8033, - -1, 8040, 768, -1, 8034, -1, 8041, 768, - -1, 8035, -1, 8040, 769, -1, 8036, -1, - 8041, 769, -1, 8037, -1, 8040, 834, -1, - 8038, -1, 8041, 834, -1, 8039, -1, 945, - 768, -1, 949, 768, -1, 951, 768, -1, - 953, 768, -1, 959, 768, -1, 965, 768, - -1, 969, 768, -1, 7936, 837, -1, 7936, - 953, -1, 7937, 837, -1, 7937, 953, -1, - 7938, 837, -1, 7938, 953, -1, 7939, 837, - -1, 7939, 953, -1, 7940, 837, -1, 7940, - 953, -1, 7941, 837, -1, 7941, 953, -1, - 7942, 837, -1, 7942, 953, -1, 7943, 837, - -1, 7943, 953, -1, 7944, 837, -1, 8064, - -1, 7945, 837, -1, 8065, -1, 7946, 837, - -1, 8066, -1, 7947, 837, -1, 8067, -1, - 7948, 837, -1, 8068, -1, 7949, 837, -1, - 8069, -1, 7950, 837, -1, 8070, -1, 7951, - 837, -1, 8071, -1, 7968, 837, -1, 7968, - 953, -1, 7969, 837, -1, 7969, 953, -1, - 7970, 837, -1, 7970, 953, -1, 7971, 837, - -1, 7971, 953, -1, 7972, 837, -1, 7972, - 953, -1, 7973, 837, -1, 7973, 953, -1, - 7974, 837, -1, 7974, 953, -1, 7975, 837, - -1, 7975, 953, -1, 7976, 837, -1, 8080, - -1, 7977, 837, -1, 8081, -1, 7978, 837, - -1, 8082, -1, 7979, 837, -1, 8083, -1, - 7980, 837, -1, 8084, -1, 7981, 837, -1, - 8085, -1, 7982, 837, -1, 8086, -1, 7983, - 837, -1, 8087, -1, 8032, 837, -1, 8032, - 953, -1, 8033, 837, -1, 8033, 953, -1, - 8034, 837, -1, 8034, 953, -1, 8035, 837, - -1, 8035, 953, -1, 8036, 837, -1, 8036, - 953, -1, 8037, 837, -1, 8037, 953, -1, - 8038, 837, -1, 8038, 953, -1, 8039, 837, - -1, 8039, 953, -1, 8040, 837, -1, 8096, - -1, 8041, 837, -1, 8097, -1, 8042, 837, - -1, 8098, -1, 8043, 837, -1, 8099, -1, - 8044, 837, -1, 8100, -1, 8045, 837, -1, - 8101, -1, 8046, 837, -1, 8102, -1, 8047, - 837, -1, 8103, -1, 945, 774, -1, 945, - 772, -1, 8048, 837, -1, 8048, 953, -1, - 945, 837, -1, 945, 953, -1, 940, 837, - -1, 940, 953, -1, 945, 834, -1, 8118, - 837, -1, 945, 834, 953, -1, 913, 774, - -1, 8112, -1, 913, 772, -1, 8113, -1, - 913, 768, -1, 8048, -1, 902, -1, 8049, - -1, 913, 837, -1, 8115, -1, 32, 787, - -1, 32, 834, -1, 168, 834, -1, 8052, - 837, -1, 8052, 953, -1, 951, 837, -1, - 951, 953, -1, 942, 837, -1, 942, 953, - -1, 951, 834, -1, 8134, 837, -1, 951, - 834, 953, -1, 917, 768, -1, 8050, -1, - 904, -1, 8051, -1, 919, 768, -1, 8052, - -1, 905, -1, 8053, -1, 919, 837, -1, - 8131, -1, 8127, 768, -1, 8127, 769, -1, - 8127, 834, -1, 953, 774, -1, 953, 772, - -1, 970, 768, -1, 953, 776, 768, -1, - 912, -1, 953, 834, -1, 970, 834, -1, - 953, 776, 834, -1, 921, 774, -1, 8144, - -1, 921, 772, -1, 8145, -1, 921, 768, - -1, 8054, -1, 906, -1, 8055, -1, 8190, - 768, -1, 8190, 769, -1, 8190, 834, -1, - 965, 774, -1, 965, 772, -1, 971, 768, - -1, 965, 776, 768, -1, 944, -1, 961, - 787, -1, 961, 788, -1, 965, 834, -1, - 971, 834, -1, 965, 776, 834, -1, 933, - 774, -1, 8160, -1, 933, 772, -1, 8161, - -1, 933, 768, -1, 8058, -1, 910, -1, - 8059, -1, 929, 788, -1, 8165, -1, 168, - 768, -1, 901, -1, 96, -1, 8060, 837, - -1, 8060, 953, -1, 969, 837, -1, 969, - 953, -1, 974, 837, -1, 974, 953, -1, - 969, 834, -1, 8182, 837, -1, 969, 834, - 953, -1, 927, 768, -1, 8056, -1, 908, - -1, 8057, -1, 937, 768, -1, 8060, -1, - 911, -1, 8061, -1, 937, 837, -1, 8179, - -1, 180, -1, 32, 788, -1, 8194, -1, - 8195, -1, 8208, -1, 32, 819, -1, 46, - -1, 46, 46, -1, 46, 46, 46, -1, - 8242, 8242, -1, 8242, 8242, 8242, -1, 8245, - 8245, -1, 8245, 8245, 8245, -1, 33, 33, - -1, 32, 773, -1, 63, 63, -1, 63, - 33, -1, 33, 63, -1, 8242, 8242, 8242, - 8242, -1, 48, -1, 52, -1, 53, -1, - 54, -1, 55, -1, 56, -1, 57, -1, - 43, -1, 8722, -1, 61, -1, 40, -1, - 41, -1, 82, 115, -1, 97, 47, 99, - -1, 97, 47, 115, -1, 67, -1, 176, - 67, -1, 99, 47, 111, -1, 99, 47, - 117, -1, 400, -1, 176, 70, -1, 78, - 111, -1, 81, -1, 83, 77, -1, 84, - 69, 76, -1, 84, 77, -1, 90, -1, - 937, -1, 197, -1, 70, -1, 8526, -1, - 1488, -1, 1489, -1, 1490, -1, 1491, -1, - 70, 65, 88, -1, 915, -1, 928, -1, - 8721, -1, 49, 8260, 51, -1, 50, 8260, - 51, -1, 49, 8260, 53, -1, 50, 8260, - 53, -1, 51, 8260, 53, -1, 52, 8260, - 53, -1, 49, 8260, 54, -1, 53, 8260, - 54, -1, 49, 8260, 56, -1, 51, 8260, - 56, -1, 53, 8260, 56, -1, 55, 8260, - 56, -1, 49, 8260, -1, 8560, -1, 73, - 73, -1, 8561, -1, 73, 73, 73, -1, - 8562, -1, 73, 86, -1, 8563, -1, 86, - -1, 8564, -1, 86, 73, -1, 8565, -1, - 86, 73, 73, -1, 8566, -1, 86, 73, - 73, 73, -1, 8567, -1, 73, 88, -1, - 8568, -1, 88, -1, 8569, -1, 88, 73, - -1, 8570, -1, 88, 73, 73, -1, 8571, - -1, 8572, -1, 8573, -1, 8574, -1, 8575, - -1, 105, 105, -1, 105, 105, 105, -1, - 105, 118, -1, 118, 105, -1, 118, 105, - 105, -1, 118, 105, 105, 105, -1, 105, - 120, -1, 120, 105, -1, 120, 105, 105, - -1, 8580, -1, 8592, 824, -1, 8594, 824, - -1, 8596, 824, -1, 8656, 824, -1, 8660, - 824, -1, 8658, 824, -1, 8707, 824, -1, - 8712, 824, -1, 8715, 824, -1, 8739, 824, - -1, 8741, 824, -1, 8747, 8747, -1, 8747, - 8747, 8747, -1, 8750, 8750, -1, 8750, 8750, - 8750, -1, 8764, 824, -1, 8771, 824, -1, - 8773, 824, -1, 8776, 824, -1, 61, 824, - -1, 8801, 824, -1, 8781, 824, -1, 60, - 824, -1, 62, 824, -1, 8804, 824, -1, - 8805, 824, -1, 8818, 824, -1, 8819, 824, - -1, 8822, 824, -1, 8823, 824, -1, 8826, - 824, -1, 8827, 824, -1, 8834, 824, -1, - 8835, 824, -1, 8838, 824, -1, 8839, 824, - -1, 8866, 824, -1, 8872, 824, -1, 8873, - 824, -1, 8875, 824, -1, 8828, 824, -1, - 8829, 824, -1, 8849, 824, -1, 8850, 824, - -1, 8882, 824, -1, 8883, 824, -1, 8884, - 824, -1, 8885, 824, -1, 12296, -1, 12297, - -1, 49, 48, -1, 49, 49, -1, 49, - 50, -1, 49, 51, -1, 49, 52, -1, - 49, 53, -1, 49, 54, -1, 49, 55, - -1, 49, 56, -1, 49, 57, -1, 50, - 48, -1, 40, 49, 41, -1, 40, 50, - 41, -1, 40, 51, 41, -1, 40, 52, - 41, -1, 40, 53, 41, -1, 40, 54, - 41, -1, 40, 55, 41, -1, 40, 56, - 41, -1, 40, 57, 41, -1, 40, 49, - 48, 41, -1, 40, 49, 49, 41, -1, - 40, 49, 50, 41, -1, 40, 49, 51, - 41, -1, 40, 49, 52, 41, -1, 40, - 49, 53, 41, -1, 40, 49, 54, 41, - -1, 40, 49, 55, 41, -1, 40, 49, - 56, 41, -1, 40, 49, 57, 41, -1, - 40, 50, 48, 41, -1, 49, 46, -1, - 50, 46, -1, 51, 46, -1, 52, 46, - -1, 53, 46, -1, 54, 46, -1, 55, - 46, -1, 56, 46, -1, 57, 46, -1, - 49, 48, 46, -1, 49, 49, 46, -1, - 49, 50, 46, -1, 49, 51, 46, -1, - 49, 52, 46, -1, 49, 53, 46, -1, - 49, 54, 46, -1, 49, 55, 46, -1, - 49, 56, 46, -1, 49, 57, 46, -1, - 50, 48, 46, -1, 40, 97, 41, -1, - 40, 98, 41, -1, 40, 99, 41, -1, - 40, 100, 41, -1, 40, 101, 41, -1, - 40, 102, 41, -1, 40, 103, 41, -1, - 40, 104, 41, -1, 40, 105, 41, -1, - 40, 106, 41, -1, 40, 107, 41, -1, - 40, 108, 41, -1, 40, 109, 41, -1, - 40, 110, 41, -1, 40, 111, 41, -1, - 40, 112, 41, -1, 40, 113, 41, -1, - 40, 114, 41, -1, 40, 115, 41, -1, - 40, 116, 41, -1, 40, 117, 41, -1, - 40, 118, 41, -1, 40, 119, 41, -1, - 40, 120, 41, -1, 40, 121, 41, -1, - 40, 122, 41, -1, 9424, -1, 9425, -1, - 9426, -1, 9427, -1, 9428, -1, 9429, -1, - 9430, -1, 9431, -1, 9432, -1, 9433, -1, - 9434, -1, 9435, -1, 9436, -1, 9437, -1, - 9438, -1, 9439, -1, 9440, -1, 9441, -1, - 83, -1, 9442, -1, 9443, -1, 9444, -1, - 9445, -1, 9446, -1, 9447, -1, 89, -1, - 9448, -1, 9449, -1, 8747, 8747, 8747, 8747, - -1, 58, 58, 61, -1, 61, 61, -1, - 61, 61, 61, -1, 10973, 824, -1, 11312, - -1, 11313, -1, 11314, -1, 11315, -1, 11316, - -1, 11317, -1, 11318, -1, 11319, -1, 11320, - -1, 11321, -1, 11322, -1, 11323, -1, 11324, - -1, 11325, -1, 11326, -1, 11327, -1, 11328, - -1, 11329, -1, 11330, -1, 11331, -1, 11332, - -1, 11333, -1, 11334, -1, 11335, -1, 11336, - -1, 11337, -1, 11338, -1, 11339, -1, 11340, - -1, 11341, -1, 11342, -1, 11343, -1, 11344, - -1, 11345, -1, 11346, -1, 11347, -1, 11348, - -1, 11349, -1, 11350, -1, 11351, -1, 11352, - -1, 11353, -1, 11354, -1, 11355, -1, 11356, - -1, 11357, -1, 11358, -1, 11361, -1, 619, - -1, 7549, -1, 637, -1, 11368, -1, 11370, - -1, 11372, -1, 11382, -1, 11393, -1, 11395, - -1, 11397, -1, 11399, -1, 11401, -1, 11403, - -1, 11405, -1, 11407, -1, 11409, -1, 11411, - -1, 11413, -1, 11415, -1, 11417, -1, 11419, - -1, 11421, -1, 11423, -1, 11425, -1, 11427, - -1, 11429, -1, 11431, -1, 11433, -1, 11435, - -1, 11437, -1, 11439, -1, 11441, -1, 11443, - -1, 11445, -1, 11447, -1, 11449, -1, 11451, - -1, 11453, -1, 11455, -1, 11457, -1, 11459, - -1, 11461, -1, 11463, -1, 11465, -1, 11467, - -1, 11469, -1, 11471, -1, 11473, -1, 11475, - -1, 11477, -1, 11479, -1, 11481, -1, 11483, - -1, 11485, -1, 11487, -1, 11489, -1, 11491, - -1, 11617, -1, 27597, -1, 40863, -1, 19968, - -1, 20008, -1, 20022, -1, 20031, -1, 20057, - -1, 20101, -1, 20108, -1, 20128, -1, 20154, - -1, 20799, -1, 20837, -1, 20843, -1, 20866, - -1, 20886, -1, 20907, -1, 20960, -1, 20981, - -1, 20992, -1, 21147, -1, 21241, -1, 21269, - -1, 21274, -1, 21304, -1, 21313, -1, 21340, - -1, 21353, -1, 21378, -1, 21430, -1, 21448, - -1, 21475, -1, 22231, -1, 22303, -1, 22763, - -1, 22786, -1, 22794, -1, 22805, -1, 22823, - -1, 22899, -1, 23376, -1, 23424, -1, 23544, - -1, 23567, -1, 23586, -1, 23608, -1, 23662, - -1, 23665, -1, 24027, -1, 24037, -1, 24049, - -1, 24062, -1, 24178, -1, 24186, -1, 24191, - -1, 24308, -1, 24318, -1, 24331, -1, 24339, - -1, 24400, -1, 24417, -1, 24435, -1, 24515, - -1, 25096, -1, 25142, -1, 25163, -1, 25903, - -1, 25908, -1, 25991, -1, 26007, -1, 26020, - -1, 26041, -1, 26080, -1, 26085, -1, 26352, - -1, 26376, -1, 26408, -1, 27424, -1, 27490, - -1, 27513, -1, 27571, -1, 27595, -1, 27604, - -1, 27611, -1, 27663, -1, 27668, -1, 27700, - -1, 28779, -1, 29226, -1, 29238, -1, 29243, - -1, 29247, -1, 29255, -1, 29273, -1, 29275, - -1, 29356, -1, 29572, -1, 29577, -1, 29916, - -1, 29926, -1, 29976, -1, 29983, -1, 29992, - -1, 30000, -1, 30091, -1, 30098, -1, 30326, - -1, 30333, -1, 30382, -1, 30399, -1, 30446, - -1, 30683, -1, 30690, -1, 30707, -1, 31034, - -1, 31160, -1, 31166, -1, 31348, -1, 31435, - -1, 31481, -1, 31859, -1, 31992, -1, 32566, - -1, 32593, -1, 32650, -1, 32701, -1, 32769, - -1, 32780, -1, 32786, -1, 32819, -1, 32895, - -1, 32905, -1, 33251, -1, 33258, -1, 33267, - -1, 33276, -1, 33292, -1, 33307, -1, 33311, - -1, 33390, -1, 33394, -1, 33400, -1, 34381, - -1, 34411, -1, 34880, -1, 34892, -1, 34915, - -1, 35198, -1, 35211, -1, 35282, -1, 35328, - -1, 35895, -1, 35910, -1, 35925, -1, 35960, - -1, 35997, -1, 36196, -1, 36208, -1, 36275, - -1, 36523, -1, 36554, -1, 36763, -1, 36784, - -1, 36789, -1, 37009, -1, 37193, -1, 37318, - -1, 37324, -1, 37329, -1, 38263, -1, 38272, - -1, 38428, -1, 38582, -1, 38585, -1, 38632, - -1, 38737, -1, 38750, -1, 38754, -1, 38761, - -1, 38859, -1, 38893, -1, 38899, -1, 38913, - -1, 39080, -1, 39131, -1, 39135, -1, 39318, - -1, 39321, -1, 39340, -1, 39592, -1, 39640, - -1, 39647, -1, 39717, -1, 39727, -1, 39730, - -1, 39740, -1, 39770, -1, 40165, -1, 40565, - -1, 40575, -1, 40613, -1, 40635, -1, 40643, - -1, 40653, -1, 40657, -1, 40697, -1, 40701, - -1, 40718, -1, 40723, -1, 40736, -1, 40763, - -1, 40778, -1, 40786, -1, 40845, -1, 40860, - -1, 40864, -1, 12306, -1, 21316, -1, 21317, - -1, 12363, 12441, -1, 12365, 12441, -1, 12367, - 12441, -1, 12369, 12441, -1, 12371, 12441, -1, - 12373, 12441, -1, 12375, 12441, -1, 12377, 12441, - -1, 12379, 12441, -1, 12381, 12441, -1, 12383, - 12441, -1, 12385, 12441, -1, 12388, 12441, -1, - 12390, 12441, -1, 12392, 12441, -1, 12399, 12441, - -1, 12399, 12442, -1, 12402, 12441, -1, 12402, - 12442, -1, 12405, 12441, -1, 12405, 12442, -1, - 12408, 12441, -1, 12408, 12442, -1, 12411, 12441, - -1, 12411, 12442, -1, 12358, 12441, -1, 32, - 12441, -1, 32, 12442, -1, 12445, 12441, -1, - 12424, 12426, -1, 12459, 12441, -1, 12461, 12441, - -1, 12463, 12441, -1, 12465, 12441, -1, 12467, - 12441, -1, 12469, 12441, -1, 12471, 12441, -1, - 12473, 12441, -1, 12475, 12441, -1, 12477, 12441, - -1, 12479, 12441, -1, 12481, 12441, -1, 12484, - 12441, -1, 12486, 12441, -1, 12488, 12441, -1, - 12495, 12441, -1, 12495, 12442, -1, 12498, 12441, - -1, 12498, 12442, -1, 12501, 12441, -1, 12501, - 12442, -1, 12504, 12441, -1, 12504, 12442, -1, - 12507, 12441, -1, 12507, 12442, -1, 12454, 12441, - -1, 12527, 12441, -1, 12528, 12441, -1, 12529, - 12441, -1, 12530, 12441, -1, 12541, 12441, -1, - 12467, 12488, -1, 4352, -1, 4353, -1, 4522, - -1, 4354, -1, 4524, -1, 4525, -1, 4355, - -1, 4356, -1, 4357, -1, 4528, -1, 4529, - -1, 4530, -1, 4531, -1, 4532, -1, 4533, - -1, 4378, -1, 4358, -1, 4359, -1, 4360, - -1, 4385, -1, 4361, -1, 4362, -1, 4363, - -1, 4364, -1, 4365, -1, 4366, -1, 4367, - -1, 4368, -1, 4369, -1, 4370, -1, 4449, - -1, 4450, -1, 4451, -1, 4452, -1, 4453, - -1, 4454, -1, 4455, -1, 4456, -1, 4457, - -1, 4458, -1, 4459, -1, 4460, -1, 4461, - -1, 4462, -1, 4463, -1, 4464, -1, 4465, - -1, 4466, -1, 4467, -1, 4468, -1, 4469, - -1, 4448, -1, 4372, -1, 4373, -1, 4551, - -1, 4552, -1, 4556, -1, 4558, -1, 4563, - -1, 4567, -1, 4569, -1, 4380, -1, 4573, - -1, 4575, -1, 4381, -1, 4382, -1, 4384, - -1, 4386, -1, 4387, -1, 4391, -1, 4393, - -1, 4395, -1, 4396, -1, 4397, -1, 4398, - -1, 4399, -1, 4402, -1, 4406, -1, 4416, - -1, 4423, -1, 4428, -1, 4593, -1, 4594, - -1, 4439, -1, 4440, -1, 4441, -1, 4484, - -1, 4485, -1, 4488, -1, 4497, -1, 4498, - -1, 4500, -1, 4510, -1, 4513, -1, 19977, - -1, 22235, -1, 19978, -1, 20013, -1, 19979, - -1, 30002, -1, 19993, -1, 19969, -1, 22825, - -1, 22320, -1, 40, 4352, 41, -1, 40, - 4354, 41, -1, 40, 4355, 41, -1, 40, - 4357, 41, -1, 40, 4358, 41, -1, 40, - 4359, 41, -1, 40, 4361, 41, -1, 40, - 4363, 41, -1, 40, 4364, 41, -1, 40, - 4366, 41, -1, 40, 4367, 41, -1, 40, - 4368, 41, -1, 40, 4369, 41, -1, 40, - 4370, 41, -1, 40, 4352, 4449, 41, -1, - 40, 4354, 4449, 41, -1, 40, 4355, 4449, - 41, -1, 40, 4357, 4449, 41, -1, 40, - 4358, 4449, 41, -1, 40, 4359, 4449, 41, - -1, 40, 4361, 4449, 41, -1, 40, 4363, - 4449, 41, -1, 40, 4364, 4449, 41, -1, - 40, 4366, 4449, 41, -1, 40, 4367, 4449, - 41, -1, 40, 4368, 4449, 41, -1, 40, - 4369, 4449, 41, -1, 40, 4370, 4449, 41, - -1, 40, 4364, 4462, 41, -1, 40, 4363, - 4457, 4364, 4453, 4523, 41, -1, 40, 4363, - 4457, 4370, 4462, 41, -1, 40, 19968, 41, - -1, 40, 20108, 41, -1, 40, 19977, 41, - -1, 40, 22235, 41, -1, 40, 20116, 41, - -1, 40, 20845, 41, -1, 40, 19971, 41, - -1, 40, 20843, 41, -1, 40, 20061, 41, - -1, 40, 21313, 41, -1, 40, 26376, 41, - -1, 40, 28779, 41, -1, 40, 27700, 41, - -1, 40, 26408, 41, -1, 40, 37329, 41, - -1, 40, 22303, 41, -1, 40, 26085, 41, - -1, 40, 26666, 41, -1, 40, 26377, 41, - -1, 40, 31038, 41, -1, 40, 21517, 41, - -1, 40, 29305, 41, -1, 40, 36001, 41, - -1, 40, 31069, 41, -1, 40, 21172, 41, - -1, 40, 20195, 41, -1, 40, 21628, 41, - -1, 40, 23398, 41, -1, 40, 30435, 41, - -1, 40, 20225, 41, -1, 40, 36039, 41, - -1, 40, 21332, 41, -1, 40, 31085, 41, - -1, 40, 20241, 41, -1, 40, 33258, 41, - -1, 40, 33267, 41, -1, 80, 84, 69, - -1, 50, 49, -1, 50, 50, -1, 50, - 51, -1, 50, 52, -1, 50, 53, -1, - 50, 54, -1, 50, 55, -1, 50, 56, - -1, 50, 57, -1, 51, 48, -1, 51, - 49, -1, 51, 50, -1, 51, 51, -1, - 51, 52, -1, 51, 53, -1, 4352, 4449, - -1, 4354, 4449, -1, 4355, 4449, -1, 4357, - 4449, -1, 4358, 4449, -1, 4359, 4449, -1, - 4361, 4449, -1, 4363, 4449, -1, 4364, 4449, - -1, 4366, 4449, -1, 4367, 4449, -1, 4368, - 4449, -1, 4369, 4449, -1, 4370, 4449, -1, - 4366, 4449, 4535, 4352, 4457, -1, 4364, 4462, - 4363, 4468, -1, 4363, 4462, -1, 20116, -1, - 20845, -1, 19971, -1, 20061, -1, 26666, -1, - 26377, -1, 31038, -1, 21517, -1, 29305, -1, - 36001, -1, 31069, -1, 21172, -1, 31192, -1, - 30007, -1, 36969, -1, 20778, -1, 21360, -1, - 27880, -1, 38917, -1, 20241, -1, 20889, -1, - 27491, -1, 24038, -1, 21491, -1, 21307, -1, - 23447, -1, 23398, -1, 30435, -1, 20225, -1, - 36039, -1, 21332, -1, 22812, -1, 51, 54, - -1, 51, 55, -1, 51, 56, -1, 51, - 57, -1, 52, 48, -1, 52, 49, -1, - 52, 50, -1, 52, 51, -1, 52, 52, - -1, 52, 53, -1, 52, 54, -1, 52, - 55, -1, 52, 56, -1, 52, 57, -1, - 53, 48, -1, 49, 26376, -1, 50, 26376, - -1, 51, 26376, -1, 52, 26376, -1, 53, - 26376, -1, 54, 26376, -1, 55, 26376, -1, - 56, 26376, -1, 57, 26376, -1, 49, 48, - 26376, -1, 49, 49, 26376, -1, 49, 50, - 26376, -1, 72, 103, -1, 101, 114, 103, - -1, 101, 86, -1, 76, 84, 68, -1, - 12450, -1, 12452, -1, 12454, -1, 12456, -1, - 12458, -1, 12459, -1, 12461, -1, 12463, -1, - 12465, -1, 12467, -1, 12469, -1, 12471, -1, - 12473, -1, 12475, -1, 12477, -1, 12479, -1, - 12481, -1, 12484, -1, 12486, -1, 12488, -1, - 12490, -1, 12491, -1, 12492, -1, 12493, -1, - 12494, -1, 12495, -1, 12498, -1, 12501, -1, - 12504, -1, 12507, -1, 12510, -1, 12511, -1, - 12512, -1, 12513, -1, 12514, -1, 12516, -1, - 12518, -1, 12520, -1, 12521, -1, 12522, -1, - 12523, -1, 12524, -1, 12525, -1, 12527, -1, - 12528, -1, 12529, -1, 12530, -1, 12450, 12497, - 12540, 12488, -1, 12450, 12523, 12501, 12449, -1, - 12450, 12531, 12506, 12450, -1, 12450, 12540, 12523, - -1, 12452, 12491, 12531, 12464, -1, 12452, 12531, - 12481, -1, 12454, 12457, 12531, -1, 12456, 12473, - 12463, 12540, 12489, -1, 12456, 12540, 12459, 12540, - -1, 12458, 12531, 12473, -1, 12458, 12540, 12512, - -1, 12459, 12452, 12522, -1, 12459, 12521, 12483, - 12488, -1, 12459, 12525, 12522, 12540, -1, 12460, - 12525, 12531, -1, 12460, 12531, 12510, -1, 12462, - 12460, -1, 12462, 12491, 12540, -1, 12461, 12517, - 12522, 12540, -1, 12462, 12523, 12480, 12540, -1, - 12461, 12525, -1, 12461, 12525, 12464, 12521, 12512, - -1, 12461, 12525, 12513, 12540, 12488, 12523, -1, - 12461, 12525, 12527, 12483, 12488, -1, 12464, 12521, - 12512, -1, 12464, 12521, 12512, 12488, 12531, -1, - 12463, 12523, 12476, 12452, 12525, -1, 12463, 12525, - 12540, 12493, -1, 12465, 12540, 12473, -1, 12467, - 12523, 12490, -1, 12467, 12540, 12509, -1, 12469, - 12452, 12463, 12523, -1, 12469, 12531, 12481, 12540, - 12512, -1, 12471, 12522, 12531, 12464, -1, 12475, - 12531, 12481, -1, 12475, 12531, 12488, -1, 12480, - 12540, 12473, -1, 12487, 12471, -1, 12489, 12523, - -1, 12488, 12531, -1, 12490, 12494, -1, 12494, - 12483, 12488, -1, 12495, 12452, 12484, -1, 12497, - 12540, 12475, 12531, 12488, -1, 12497, 12540, 12484, - -1, 12496, 12540, 12524, 12523, -1, 12500, 12450, - 12473, 12488, 12523, -1, 12500, 12463, 12523, -1, - 12500, 12467, -1, 12499, 12523, -1, 12501, 12449, - 12521, 12483, 12489, -1, 12501, 12451, 12540, 12488, - -1, 12502, 12483, 12471, 12455, 12523, -1, 12501, - 12521, 12531, -1, 12504, 12463, 12479, 12540, 12523, - -1, 12506, 12477, -1, 12506, 12491, 12498, -1, - 12504, 12523, 12484, -1, 12506, 12531, 12473, -1, - 12506, 12540, 12472, -1, 12505, 12540, 12479, -1, - 12509, 12452, 12531, 12488, -1, 12508, 12523, 12488, - -1, 12507, 12531, -1, 12509, 12531, 12489, -1, - 12507, 12540, 12523, -1, 12507, 12540, 12531, -1, - 12510, 12452, 12463, 12525, -1, 12510, 12452, 12523, - -1, 12510, 12483, 12495, -1, 12510, 12523, 12463, - -1, 12510, 12531, 12471, 12519, 12531, -1, 12511, - 12463, 12525, 12531, -1, 12511, 12522, -1, 12511, - 12522, 12496, 12540, 12523, -1, 12513, 12460, -1, - 12513, 12460, 12488, 12531, -1, 12513, 12540, 12488, - 12523, -1, 12516, 12540, 12489, -1, 12516, 12540, - 12523, -1, 12518, 12450, 12531, -1, 12522, 12483, - 12488, 12523, -1, 12522, 12521, -1, 12523, 12500, - 12540, -1, 12523, 12540, 12502, 12523, -1, 12524, - 12512, -1, 12524, 12531, 12488, 12466, 12531, -1, - 12527, 12483, 12488, -1, 48, 28857, -1, 49, - 28857, -1, 50, 28857, -1, 51, 28857, -1, - 52, 28857, -1, 53, 28857, -1, 54, 28857, - -1, 55, 28857, -1, 56, 28857, -1, 57, - 28857, -1, 49, 48, 28857, -1, 49, 49, - 28857, -1, 49, 50, 28857, -1, 49, 51, - 28857, -1, 49, 52, 28857, -1, 49, 53, - 28857, -1, 49, 54, 28857, -1, 49, 55, - 28857, -1, 49, 56, 28857, -1, 49, 57, - 28857, -1, 50, 48, 28857, -1, 50, 49, - 28857, -1, 50, 50, 28857, -1, 50, 51, - 28857, -1, 50, 52, 28857, -1, 104, 80, - 97, -1, 100, 97, -1, 65, 85, -1, - 98, 97, 114, -1, 111, 86, -1, 112, - 99, -1, 100, 109, -1, 100, 109, 178, - -1, 100, 109, 179, -1, 73, 85, -1, - 24179, 25104, -1, 26157, 21644, -1, 22823, 27491, - -1, 26126, 27835, -1, 26666, 24335, 20250, 31038, - -1, 112, 65, -1, 110, 65, -1, 956, - 65, -1, 109, 65, -1, 107, 65, -1, - 75, 66, -1, 77, 66, -1, 71, 66, - -1, 99, 97, 108, -1, 107, 99, 97, - 108, -1, 112, 70, -1, 110, 70, -1, - 956, 70, -1, 956, 103, -1, 109, 103, - -1, 107, 103, -1, 72, 122, -1, 107, - 72, 122, -1, 77, 72, 122, -1, 71, - 72, 122, -1, 84, 72, 122, -1, 956, - 8467, -1, 109, 8467, -1, 100, 8467, -1, - 107, 8467, -1, 102, 109, -1, 110, 109, - -1, 956, 109, -1, 109, 109, -1, 99, - 109, -1, 107, 109, -1, 109, 109, 178, - -1, 99, 109, 178, -1, 109, 178, -1, - 107, 109, 178, -1, 109, 109, 179, -1, - 99, 109, 179, -1, 109, 179, -1, 107, - 109, 179, -1, 109, 8725, 115, -1, 109, - 8725, 115, 178, -1, 80, 97, -1, 107, - 80, 97, -1, 77, 80, 97, -1, 71, - 80, 97, -1, 114, 97, 100, -1, 114, - 97, 100, 8725, 115, -1, 114, 97, 100, - 8725, 115, 178, -1, 112, 115, -1, 110, - 115, -1, 956, 115, -1, 109, 115, -1, - 112, 86, -1, 110, 86, -1, 956, 86, - -1, 109, 86, -1, 107, 86, -1, 77, - 86, -1, 112, 87, -1, 110, 87, -1, - 956, 87, -1, 109, 87, -1, 107, 87, - -1, 77, 87, -1, 107, 937, -1, 77, - 937, -1, 97, 46, 109, 46, -1, 66, - 113, -1, 99, 99, -1, 99, 100, -1, - 67, 8725, 107, 103, -1, 67, 111, 46, - -1, 100, 66, -1, 71, 121, -1, 104, - 97, -1, 72, 80, -1, 105, 110, -1, - 75, 75, -1, 75, 77, -1, 107, 116, - -1, 108, 109, -1, 108, 110, -1, 108, - 111, 103, -1, 108, 120, -1, 109, 98, - -1, 109, 105, 108, -1, 109, 111, 108, - -1, 80, 72, -1, 112, 46, 109, 46, - -1, 80, 80, 77, -1, 80, 82, -1, - 115, 114, -1, 83, 118, -1, 87, 98, - -1, 86, 8725, 109, -1, 65, 8725, 109, - -1, 49, 26085, -1, 50, 26085, -1, 51, - 26085, -1, 52, 26085, -1, 53, 26085, -1, - 54, 26085, -1, 55, 26085, -1, 56, 26085, - -1, 57, 26085, -1, 49, 48, 26085, -1, - 49, 49, 26085, -1, 49, 50, 26085, -1, - 49, 51, 26085, -1, 49, 52, 26085, -1, - 49, 53, 26085, -1, 49, 54, 26085, -1, - 49, 55, 26085, -1, 49, 56, 26085, -1, - 49, 57, 26085, -1, 50, 48, 26085, -1, - 50, 49, 26085, -1, 50, 50, 26085, -1, - 50, 51, 26085, -1, 50, 52, 26085, -1, - 50, 53, 26085, -1, 50, 54, 26085, -1, - 50, 55, 26085, -1, 50, 56, 26085, -1, - 50, 57, 26085, -1, 51, 48, 26085, -1, - 51, 49, 26085, -1, 103, 97, 108, -1, - 35912, -1, 26356, -1, 36040, -1, 28369, -1, - 20018, -1, 21477, -1, 22865, -1, 21895, -1, - 22856, -1, 25078, -1, 30313, -1, 32645, -1, - 34367, -1, 34746, -1, 35064, -1, 37007, -1, - 27138, -1, 27931, -1, 28889, -1, 29662, -1, - 33853, -1, 37226, -1, 39409, -1, 20098, -1, - 21365, -1, 27396, -1, 29211, -1, 34349, -1, - 40478, -1, 23888, -1, 28651, -1, 34253, -1, - 35172, -1, 25289, -1, 33240, -1, 34847, -1, - 24266, -1, 26391, -1, 28010, -1, 29436, -1, - 37070, -1, 20358, -1, 20919, -1, 21214, -1, - 25796, -1, 27347, -1, 29200, -1, 30439, -1, - 34310, -1, 34396, -1, 36335, -1, 38706, -1, - 39791, -1, 40442, -1, 30860, -1, 31103, -1, - 32160, -1, 33737, -1, 37636, -1, 35542, -1, - 22751, -1, 24324, -1, 31840, -1, 32894, -1, - 29282, -1, 30922, -1, 36034, -1, 38647, -1, - 22744, -1, 23650, -1, 27155, -1, 28122, -1, - 28431, -1, 32047, -1, 32311, -1, 38475, -1, - 21202, -1, 32907, -1, 20956, -1, 20940, -1, - 31260, -1, 32190, -1, 33777, -1, 38517, -1, - 35712, -1, 25295, -1, 35582, -1, 20025, -1, - 23527, -1, 24594, -1, 29575, -1, 30064, -1, - 21271, -1, 30971, -1, 20415, -1, 24489, -1, - 19981, -1, 27852, -1, 25976, -1, 32034, -1, - 21443, -1, 22622, -1, 30465, -1, 33865, -1, - 35498, -1, 27578, -1, 27784, -1, 25342, -1, - 33509, -1, 25504, -1, 30053, -1, 20142, -1, - 20841, -1, 20937, -1, 26753, -1, 31975, -1, - 33391, -1, 35538, -1, 37327, -1, 21237, -1, - 21570, -1, 24300, -1, 26053, -1, 28670, -1, - 31018, -1, 38317, -1, 39530, -1, 40599, -1, - 40654, -1, 26310, -1, 27511, -1, 36706, -1, - 24180, -1, 24976, -1, 25088, -1, 25754, -1, - 28451, -1, 29001, -1, 29833, -1, 31178, -1, - 32244, -1, 32879, -1, 36646, -1, 34030, -1, - 36899, -1, 37706, -1, 21015, -1, 21155, -1, - 21693, -1, 28872, -1, 35010, -1, 24265, -1, - 24565, -1, 25467, -1, 27566, -1, 31806, -1, - 29557, -1, 20196, -1, 22265, -1, 23994, -1, - 24604, -1, 29618, -1, 29801, -1, 32666, -1, - 32838, -1, 37428, -1, 38646, -1, 38728, -1, - 38936, -1, 20363, -1, 31150, -1, 37300, -1, - 38584, -1, 24801, -1, 20102, -1, 20698, -1, - 23534, -1, 23615, -1, 26009, -1, 29134, -1, - 30274, -1, 34044, -1, 36988, -1, 26248, -1, - 38446, -1, 21129, -1, 26491, -1, 26611, -1, - 27969, -1, 28316, -1, 29705, -1, 30041, -1, - 30827, -1, 32016, -1, 39006, -1, 25134, -1, - 38520, -1, 20523, -1, 23833, -1, 28138, -1, - 36650, -1, 24459, -1, 24900, -1, 26647, -1, - 38534, -1, 21033, -1, 21519, -1, 23653, -1, - 26131, -1, 26446, -1, 26792, -1, 27877, -1, - 29702, -1, 30178, -1, 32633, -1, 35023, -1, - 35041, -1, 38626, -1, 21311, -1, 28346, -1, - 21533, -1, 29136, -1, 29848, -1, 34298, -1, - 38563, -1, 40023, -1, 40607, -1, 26519, -1, - 28107, -1, 33256, -1, 31520, -1, 31890, -1, - 29376, -1, 28825, -1, 35672, -1, 20160, -1, - 33590, -1, 21050, -1, 20999, -1, 24230, -1, - 25299, -1, 31958, -1, 23429, -1, 27934, -1, - 26292, -1, 36667, -1, 38477, -1, 24275, -1, - 20800, -1, 21952, -1, 22618, -1, 26228, -1, - 20958, -1, 29482, -1, 30410, -1, 31036, -1, - 31070, -1, 31077, -1, 31119, -1, 38742, -1, - 31934, -1, 34322, -1, 35576, -1, 36920, -1, - 37117, -1, 39151, -1, 39164, -1, 39208, -1, - 40372, -1, 20398, -1, 20711, -1, 20813, -1, - 21193, -1, 21220, -1, 21329, -1, 21917, -1, - 22022, -1, 22120, -1, 22592, -1, 22696, -1, - 23652, -1, 24724, -1, 24936, -1, 24974, -1, - 25074, -1, 25935, -1, 26082, -1, 26257, -1, - 26757, -1, 28023, -1, 28186, -1, 28450, -1, - 29038, -1, 29227, -1, 29730, -1, 30865, -1, - 31049, -1, 31048, -1, 31056, -1, 31062, -1, - 31117, -1, 31118, -1, 31296, -1, 31361, -1, - 31680, -1, 32265, -1, 32321, -1, 32626, -1, - 32773, -1, 33261, -1, 33401, -1, 33879, -1, - 35088, -1, 35222, -1, 35585, -1, 35641, -1, - 36051, -1, 36104, -1, 36790, -1, 38627, -1, - 38911, -1, 38971, -1, 20006, -1, 20917, -1, - 20840, -1, 20352, -1, 20805, -1, 20864, -1, - 21191, -1, 21242, -1, 21845, -1, 21913, -1, - 21986, -1, 22707, -1, 22852, -1, 22868, -1, - 23138, -1, 23336, -1, 24274, -1, 24281, -1, - 24425, -1, 24493, -1, 24792, -1, 24910, -1, - 24840, -1, 24928, -1, 25140, -1, 25540, -1, - 25628, -1, 25682, -1, 25942, -1, 26395, -1, - 26454, -1, 28379, -1, 28363, -1, 28702, -1, - 30631, -1, 29237, -1, 29359, -1, 29809, -1, - 29958, -1, 30011, -1, 30237, -1, 30239, -1, - 30427, -1, 30452, -1, 30538, -1, 30528, -1, - 30924, -1, 31409, -1, 31867, -1, 32091, -1, - 32574, -1, 33618, -1, 33775, -1, 34681, -1, - 35137, -1, 35206, -1, 35519, -1, 35531, -1, - 35565, -1, 35722, -1, 36664, -1, 36978, -1, - 37273, -1, 37494, -1, 38524, -1, 38875, -1, - 38923, -1, 39698, -1, 141386, -1, 141380, -1, - 144341, -1, 15261, -1, 16408, -1, 16441, -1, - 152137, -1, 154832, -1, 163539, -1, 40771, -1, - 40846, -1, 102, 102, -1, 102, 105, -1, - 102, 108, -1, 102, 102, 105, -1, 102, - 102, 108, -1, 383, 116, -1, 115, 116, - -1, 1396, 1398, -1, 1396, 1381, -1, 1396, - 1387, -1, 1406, 1398, -1, 1396, 1389, -1, - 1497, 1460, -1, 1522, 1463, -1, 1506, -1, - 1492, -1, 1499, -1, 1500, -1, 1501, -1, - 1512, -1, 1514, -1, 1513, 1473, -1, 1513, - 1474, -1, 64329, 1473, -1, 64329, 1474, -1, - 1488, 1463, -1, 1488, 1464, -1, 1488, 1468, - -1, 1489, 1468, -1, 1490, 1468, -1, 1491, - 1468, -1, 1492, 1468, -1, 1493, 1468, -1, - 1494, 1468, -1, 1496, 1468, -1, 1497, 1468, - -1, 1498, 1468, -1, 1499, 1468, -1, 1500, - 1468, -1, 1502, 1468, -1, 1504, 1468, -1, - 1505, 1468, -1, 1507, 1468, -1, 1508, 1468, - -1, 1510, 1468, -1, 1511, 1468, -1, 1512, - 1468, -1, 1513, 1468, -1, 1514, 1468, -1, - 1493, 1465, -1, 1489, 1471, -1, 1499, 1471, - -1, 1508, 1471, -1, 1488, 1500, -1, 1649, - -1, 1659, -1, 1662, -1, 1664, -1, 1658, - -1, 1663, -1, 1657, -1, 1700, -1, 1702, - -1, 1668, -1, 1667, -1, 1670, -1, 1671, - -1, 1677, -1, 1676, -1, 1678, -1, 1672, - -1, 1688, -1, 1681, -1, 1705, -1, 1711, - -1, 1715, -1, 1713, -1, 1722, -1, 1723, - -1, 1728, -1, 1729, -1, 1726, -1, 1746, - -1, 1747, -1, 1709, -1, 1735, -1, 1734, - -1, 1736, -1, 1655, -1, 1739, -1, 1733, - -1, 1737, -1, 1744, -1, 1609, -1, 1574, - 1575, -1, 1574, 1749, -1, 1574, 1608, -1, - 1574, 1735, -1, 1574, 1734, -1, 1574, 1736, - -1, 1574, 1744, -1, 1574, 1609, -1, 1740, - -1, 1574, 1580, -1, 1574, 1581, -1, 1574, - 1605, -1, 1574, 1610, -1, 1576, 1580, -1, - 1576, 1581, -1, 1576, 1582, -1, 1576, 1605, - -1, 1576, 1609, -1, 1576, 1610, -1, 1578, - 1580, -1, 1578, 1581, -1, 1578, 1582, -1, - 1578, 1605, -1, 1578, 1609, -1, 1578, 1610, - -1, 1579, 1580, -1, 1579, 1605, -1, 1579, - 1609, -1, 1579, 1610, -1, 1580, 1581, -1, - 1580, 1605, -1, 1581, 1580, -1, 1581, 1605, - -1, 1582, 1580, -1, 1582, 1581, -1, 1582, - 1605, -1, 1587, 1580, -1, 1587, 1581, -1, - 1587, 1582, -1, 1587, 1605, -1, 1589, 1581, - -1, 1589, 1605, -1, 1590, 1580, -1, 1590, - 1581, -1, 1590, 1582, -1, 1590, 1605, -1, - 1591, 1581, -1, 1591, 1605, -1, 1592, 1605, - -1, 1593, 1580, -1, 1593, 1605, -1, 1594, - 1580, -1, 1594, 1605, -1, 1601, 1580, -1, - 1601, 1581, -1, 1601, 1582, -1, 1601, 1605, - -1, 1601, 1609, -1, 1601, 1610, -1, 1602, - 1581, -1, 1602, 1605, -1, 1602, 1609, -1, - 1602, 1610, -1, 1603, 1575, -1, 1603, 1580, - -1, 1603, 1581, -1, 1603, 1582, -1, 1603, - 1604, -1, 1603, 1605, -1, 1603, 1609, -1, - 1603, 1610, -1, 1604, 1580, -1, 1604, 1581, - -1, 1604, 1582, -1, 1604, 1605, -1, 1604, - 1609, -1, 1604, 1610, -1, 1605, 1580, -1, - 1605, 1581, -1, 1605, 1582, -1, 1605, 1605, - -1, 1605, 1609, -1, 1605, 1610, -1, 1606, - 1580, -1, 1606, 1581, -1, 1606, 1582, -1, - 1606, 1605, -1, 1606, 1609, -1, 1606, 1610, - -1, 1607, 1580, -1, 1607, 1605, -1, 1607, - 1609, -1, 1607, 1610, -1, 1610, 1580, -1, - 1610, 1581, -1, 1610, 1582, -1, 1610, 1605, - -1, 1610, 1609, -1, 1610, 1610, -1, 1584, - 1648, -1, 1585, 1648, -1, 1609, 1648, -1, - 32, 1612, 1617, -1, 32, 1613, 1617, -1, - 32, 1614, 1617, -1, 32, 1615, 1617, -1, - 32, 1616, 1617, -1, 32, 1617, 1648, -1, - 1574, 1585, -1, 1574, 1586, -1, 1574, 1606, - -1, 1576, 1585, -1, 1576, 1586, -1, 1576, - 1606, -1, 1578, 1585, -1, 1578, 1586, -1, - 1578, 1606, -1, 1579, 1585, -1, 1579, 1586, - -1, 1579, 1606, -1, 1605, 1575, -1, 1606, - 1585, -1, 1606, 1586, -1, 1606, 1606, -1, - 1610, 1585, -1, 1610, 1586, -1, 1610, 1606, - -1, 1574, 1582, -1, 1574, 1607, -1, 1576, - 1607, -1, 1578, 1607, -1, 1589, 1582, -1, - 1604, 1607, -1, 1606, 1607, -1, 1607, 1648, - -1, 1610, 1607, -1, 1579, 1607, -1, 1587, - 1607, -1, 1588, 1605, -1, 1588, 1607, -1, - 1600, 1614, 1617, -1, 1600, 1615, 1617, -1, - 1600, 1616, 1617, -1, 1591, 1609, -1, 1591, - 1610, -1, 1593, 1609, -1, 1593, 1610, -1, - 1594, 1609, -1, 1594, 1610, -1, 1587, 1609, - -1, 1587, 1610, -1, 1588, 1609, -1, 1588, - 1610, -1, 1581, 1609, -1, 1581, 1610, -1, - 1580, 1609, -1, 1580, 1610, -1, 1582, 1609, - -1, 1582, 1610, -1, 1589, 1609, -1, 1589, - 1610, -1, 1590, 1609, -1, 1590, 1610, -1, - 1588, 1580, -1, 1588, 1581, -1, 1588, 1582, - -1, 1588, 1585, -1, 1587, 1585, -1, 1589, - 1585, -1, 1590, 1585, -1, 1575, 1611, -1, - 1578, 1580, 1605, -1, 1578, 1581, 1580, -1, - 1578, 1581, 1605, -1, 1578, 1582, 1605, -1, - 1578, 1605, 1580, -1, 1578, 1605, 1581, -1, - 1578, 1605, 1582, -1, 1580, 1605, 1581, -1, - 1581, 1605, 1610, -1, 1581, 1605, 1609, -1, - 1587, 1581, 1580, -1, 1587, 1580, 1581, -1, - 1587, 1580, 1609, -1, 1587, 1605, 1581, -1, - 1587, 1605, 1580, -1, 1587, 1605, 1605, -1, - 1589, 1581, 1581, -1, 1589, 1605, 1605, -1, - 1588, 1581, 1605, -1, 1588, 1580, 1610, -1, - 1588, 1605, 1582, -1, 1588, 1605, 1605, -1, - 1590, 1581, 1609, -1, 1590, 1582, 1605, -1, - 1591, 1605, 1581, -1, 1591, 1605, 1605, -1, - 1591, 1605, 1610, -1, 1593, 1580, 1605, -1, - 1593, 1605, 1605, -1, 1593, 1605, 1609, -1, - 1594, 1605, 1605, -1, 1594, 1605, 1610, -1, - 1594, 1605, 1609, -1, 1601, 1582, 1605, -1, - 1602, 1605, 1581, -1, 1602, 1605, 1605, -1, - 1604, 1581, 1605, -1, 1604, 1581, 1610, -1, - 1604, 1581, 1609, -1, 1604, 1580, 1580, -1, - 1604, 1582, 1605, -1, 1604, 1605, 1581, -1, - 1605, 1581, 1580, -1, 1605, 1581, 1605, -1, - 1605, 1581, 1610, -1, 1605, 1580, 1581, -1, - 1605, 1580, 1605, -1, 1605, 1582, 1580, -1, - 1605, 1582, 1605, -1, 1605, 1580, 1582, -1, - 1607, 1605, 1580, -1, 1607, 1605, 1605, -1, - 1606, 1581, 1605, -1, 1606, 1581, 1609, -1, - 1606, 1580, 1605, -1, 1606, 1580, 1609, -1, - 1606, 1605, 1610, -1, 1606, 1605, 1609, -1, - 1610, 1605, 1605, -1, 1576, 1582, 1610, -1, - 1578, 1580, 1610, -1, 1578, 1580, 1609, -1, - 1578, 1582, 1610, -1, 1578, 1582, 1609, -1, - 1578, 1605, 1610, -1, 1578, 1605, 1609, -1, - 1580, 1605, 1610, -1, 1580, 1581, 1609, -1, - 1580, 1605, 1609, -1, 1587, 1582, 1609, -1, - 1589, 1581, 1610, -1, 1588, 1581, 1610, -1, - 1590, 1581, 1610, -1, 1604, 1580, 1610, -1, - 1604, 1605, 1610, -1, 1610, 1581, 1610, -1, - 1610, 1580, 1610, -1, 1610, 1605, 1610, -1, - 1605, 1605, 1610, -1, 1602, 1605, 1610, -1, - 1606, 1581, 1610, -1, 1593, 1605, 1610, -1, - 1603, 1605, 1610, -1, 1606, 1580, 1581, -1, - 1605, 1582, 1610, -1, 1604, 1580, 1605, -1, - 1603, 1605, 1605, -1, 1580, 1581, 1610, -1, - 1581, 1580, 1610, -1, 1605, 1580, 1610, -1, - 1601, 1605, 1610, -1, 1576, 1581, 1610, -1, - 1587, 1582, 1610, -1, 1606, 1580, 1610, -1, - 1589, 1604, 1746, -1, 1602, 1604, 1746, -1, - 1575, 1604, 1604, 1607, -1, 1575, 1603, 1576, - 1585, -1, 1605, 1581, 1605, 1583, -1, 1589, - 1604, 1593, 1605, -1, 1585, 1587, 1608, 1604, - -1, 1593, 1604, 1610, 1607, -1, 1608, 1587, - 1604, 1605, -1, 1589, 1604, 1609, -1, 1589, - 1604, 1609, 32, 1575, 1604, 1604, 1607, 32, - 1593, 1604, 1610, 1607, 32, 1608, 1587, 1604, - 1605, -1, 1580, 1604, 32, 1580, 1604, 1575, - 1604, 1607, -1, 1585, 1740, 1575, 1604, -1, - 44, -1, 12289, -1, 12290, -1, 58, -1, - 33, -1, 63, -1, 12310, -1, 12311, -1, - 8230, -1, 8229, -1, 8212, -1, 8211, -1, - 95, -1, 123, -1, 125, -1, 12308, -1, - 12309, -1, 12304, -1, 12305, -1, 12298, -1, - 12299, -1, 12300, -1, 12301, -1, 12302, -1, - 12303, -1, 91, -1, 93, -1, 8254, -1, - 35, -1, 38, -1, 42, -1, 45, -1, - 60, -1, 62, -1, 92, -1, 36, -1, - 37, -1, 64, -1, 32, 1611, -1, 1600, - 1611, -1, 32, 1612, -1, 32, 1613, -1, - 32, 1614, -1, 1600, 1614, -1, 32, 1615, - -1, 1600, 1615, -1, 32, 1616, -1, 1600, - 1616, -1, 32, 1617, -1, 1600, 1617, -1, - 32, 1618, -1, 1600, 1618, -1, 1569, -1, - 1570, -1, 1571, -1, 1572, -1, 1573, -1, - 1574, -1, 1575, -1, 1576, -1, 1577, -1, - 1578, -1, 1579, -1, 1580, -1, 1581, -1, - 1582, -1, 1583, -1, 1584, -1, 1585, -1, - 1586, -1, 1587, -1, 1588, -1, 1589, -1, - 1590, -1, 1591, -1, 1592, -1, 1593, -1, - 1594, -1, 1601, -1, 1602, -1, 1603, -1, - 1604, -1, 1605, -1, 1606, -1, 1607, -1, - 1608, -1, 1610, -1, 1604, 1570, -1, 1604, - 1571, -1, 1604, 1573, -1, 1604, 1575, -1, - 34, -1, 39, -1, 47, -1, 65345, -1, - 65346, -1, 65347, -1, 65348, -1, 65349, -1, - 65350, -1, 65351, -1, 65352, -1, 65353, -1, - 65354, -1, 65355, -1, 65356, -1, 65357, -1, - 65358, -1, 65359, -1, 65360, -1, 65361, -1, - 65362, -1, 65363, -1, 65364, -1, 65365, -1, - 65366, -1, 65367, -1, 65368, -1, 65369, -1, - 65370, -1, 94, -1, 124, -1, 126, -1, - 10629, -1, 10630, -1, 12539, -1, 12449, -1, - 12451, -1, 12453, -1, 12455, -1, 12457, -1, - 12515, -1, 12517, -1, 12519, -1, 12483, -1, - 12540, -1, 12531, -1, 12441, -1, 12442, -1, - 12644, -1, 12593, -1, 12594, -1, 12595, -1, - 12596, -1, 12597, -1, 12598, -1, 12599, -1, - 12600, -1, 12601, -1, 12602, -1, 12603, -1, - 12604, -1, 12605, -1, 12606, -1, 12607, -1, - 12608, -1, 12609, -1, 12610, -1, 12611, -1, - 12612, -1, 12613, -1, 12614, -1, 12615, -1, - 12616, -1, 12617, -1, 12618, -1, 12619, -1, - 12620, -1, 12621, -1, 12622, -1, 12623, -1, - 12624, -1, 12625, -1, 12626, -1, 12627, -1, - 12628, -1, 12629, -1, 12630, -1, 12631, -1, - 12632, -1, 12633, -1, 12634, -1, 12635, -1, - 12636, -1, 12637, -1, 12638, -1, 12639, -1, - 12640, -1, 12641, -1, 12642, -1, 12643, -1, - 162, -1, 163, -1, 172, -1, 175, -1, - 166, -1, 165, -1, 8361, -1, 9474, -1, - 8592, -1, 8593, -1, 8594, -1, 8595, -1, - 9632, -1, 9675, -1, 66600, -1, 66601, -1, - 66602, -1, 66603, -1, 66604, -1, 66605, -1, - 66606, -1, 66607, -1, 66608, -1, 66609, -1, - 66610, -1, 66611, -1, 66612, -1, 66613, -1, - 66614, -1, 66615, -1, 66616, -1, 66617, -1, - 66618, -1, 66619, -1, 66620, -1, 66621, -1, - 66622, -1, 66623, -1, 66624, -1, 66625, -1, - 66626, -1, 66627, -1, 66628, -1, 66629, -1, - 66630, -1, 66631, -1, 66632, -1, 66633, -1, - 66634, -1, 66635, -1, 66636, -1, 66637, -1, - 66638, -1, 66639, -1, 119127, 119141, -1, 119128, - 119141, -1, 119135, 119150, -1, 119135, 119151, -1, - 119135, 119152, -1, 119135, 119153, -1, 119135, 119154, - -1, 119225, 119141, -1, 119226, 119141, -1, 119227, - 119150, -1, 119228, 119150, -1, 119227, 119151, -1, - 119228, 119151, -1, 305, -1, 567, -1, 913, - -1, 914, -1, 916, -1, 917, -1, 918, - -1, 919, -1, 921, -1, 922, -1, 923, - -1, 924, -1, 925, -1, 926, -1, 927, - -1, 929, -1, 1012, -1, 932, -1, 934, - -1, 935, -1, 936, -1, 8711, -1, 8706, - -1, 1013, -1, 977, -1, 1008, -1, 981, - -1, 1009, -1, 982, -1, 988, -1, 20029, - -1, 20024, -1, 20033, -1, 131362, -1, 20320, - -1, 20411, -1, 20482, -1, 20602, -1, 20633, - -1, 20687, -1, 13470, -1, 132666, -1, 20820, - -1, 20836, -1, 20855, -1, 132380, -1, 13497, - -1, 20839, -1, 20877, -1, 132427, -1, 20887, - -1, 20900, -1, 20172, -1, 20908, -1, 168415, - -1, 20995, -1, 13535, -1, 21051, -1, 21062, - -1, 21106, -1, 21111, -1, 13589, -1, 21253, - -1, 21254, -1, 21321, -1, 21338, -1, 21363, - -1, 21373, -1, 21375, -1, 133676, -1, 28784, - -1, 21450, -1, 21471, -1, 133987, -1, 21483, - -1, 21489, -1, 21510, -1, 21662, -1, 21560, - -1, 21576, -1, 21608, -1, 21666, -1, 21750, - -1, 21776, -1, 21843, -1, 21859, -1, 21892, - -1, 21931, -1, 21939, -1, 21954, -1, 22294, - -1, 22295, -1, 22097, -1, 22132, -1, 22766, - -1, 22478, -1, 22516, -1, 22541, -1, 22411, - -1, 22578, -1, 22577, -1, 22700, -1, 136420, - -1, 22770, -1, 22775, -1, 22790, -1, 22810, - -1, 22818, -1, 22882, -1, 136872, -1, 136938, - -1, 23020, -1, 23067, -1, 23079, -1, 23000, - -1, 23142, -1, 14062, -1, 14076, -1, 23304, - -1, 23358, -1, 137672, -1, 23491, -1, 23512, - -1, 23539, -1, 138008, -1, 23551, -1, 23558, - -1, 24403, -1, 14209, -1, 23648, -1, 23744, - -1, 23693, -1, 138724, -1, 23875, -1, 138726, - -1, 23918, -1, 23915, -1, 23932, -1, 24033, - -1, 24034, -1, 14383, -1, 24061, -1, 24104, - -1, 24125, -1, 24169, -1, 14434, -1, 139651, - -1, 14460, -1, 24240, -1, 24243, -1, 24246, - -1, 172946, -1, 140081, -1, 33281, -1, 24354, - -1, 14535, -1, 144056, -1, 156122, -1, 24418, - -1, 24427, -1, 14563, -1, 24474, -1, 24525, - -1, 24535, -1, 24569, -1, 24705, -1, 14650, - -1, 14620, -1, 141012, -1, 24775, -1, 24904, - -1, 24908, -1, 24954, -1, 25010, -1, 24996, - -1, 25007, -1, 25054, -1, 25104, -1, 25115, - -1, 25181, -1, 25265, -1, 25300, -1, 25424, - -1, 142092, -1, 25405, -1, 25340, -1, 25448, - -1, 25475, -1, 25572, -1, 142321, -1, 25634, - -1, 25541, -1, 25513, -1, 14894, -1, 25705, - -1, 25726, -1, 25757, -1, 25719, -1, 14956, - -1, 25964, -1, 143370, -1, 26083, -1, 26360, - -1, 26185, -1, 15129, -1, 15112, -1, 15076, - -1, 20882, -1, 20885, -1, 26368, -1, 26268, - -1, 32941, -1, 17369, -1, 26401, -1, 26462, - -1, 26451, -1, 144323, -1, 15177, -1, 26618, - -1, 26501, -1, 26706, -1, 144493, -1, 26766, - -1, 26655, -1, 26900, -1, 26946, -1, 27043, - -1, 27114, -1, 27304, -1, 145059, -1, 27355, - -1, 15384, -1, 27425, -1, 145575, -1, 27476, - -1, 15438, -1, 27506, -1, 27551, -1, 27579, - -1, 146061, -1, 138507, -1, 146170, -1, 27726, - -1, 146620, -1, 27839, -1, 27853, -1, 27751, - -1, 27926, -1, 27966, -1, 28009, -1, 28024, - -1, 28037, -1, 146718, -1, 27956, -1, 28207, - -1, 28270, -1, 15667, -1, 28359, -1, 147153, - -1, 28153, -1, 28526, -1, 147294, -1, 147342, - -1, 28614, -1, 28729, -1, 28699, -1, 15766, - -1, 28746, -1, 28797, -1, 28791, -1, 28845, - -1, 132389, -1, 28997, -1, 148067, -1, 29084, - -1, 148395, -1, 29224, -1, 29264, -1, 149000, - -1, 29312, -1, 29333, -1, 149301, -1, 149524, - -1, 29562, -1, 29579, -1, 16044, -1, 29605, - -1, 16056, -1, 29767, -1, 29788, -1, 29829, - -1, 29898, -1, 16155, -1, 29988, -1, 150582, - -1, 30014, -1, 150674, -1, 139679, -1, 30224, - -1, 151457, -1, 151480, -1, 151620, -1, 16380, - -1, 16392, -1, 151795, -1, 151794, -1, 151833, - -1, 151859, -1, 30494, -1, 30495, -1, 30603, - -1, 16454, -1, 16534, -1, 152605, -1, 30798, - -1, 16611, -1, 153126, -1, 153242, -1, 153285, - -1, 31211, -1, 16687, -1, 31306, -1, 31311, - -1, 153980, -1, 154279, -1, 31470, -1, 16898, - -1, 154539, -1, 31686, -1, 31689, -1, 16935, - -1, 154752, -1, 31954, -1, 17056, -1, 31976, - -1, 31971, -1, 32000, -1, 155526, -1, 32099, - -1, 17153, -1, 32199, -1, 32258, -1, 32325, - -1, 17204, -1, 156200, -1, 156231, -1, 17241, - -1, 156377, -1, 32634, -1, 156478, -1, 32661, - -1, 32762, -1, 156890, -1, 156963, -1, 32864, - -1, 157096, -1, 32880, -1, 144223, -1, 17365, - -1, 32946, -1, 33027, -1, 17419, -1, 33086, - -1, 23221, -1, 157607, -1, 157621, -1, 144275, - -1, 144284, -1, 33284, -1, 36766, -1, 17515, - -1, 33425, -1, 33419, -1, 33437, -1, 21171, - -1, 33457, -1, 33459, -1, 33469, -1, 33510, - -1, 158524, -1, 33565, -1, 33635, -1, 33709, - -1, 33571, -1, 33725, -1, 33767, -1, 33619, - -1, 33738, -1, 33740, -1, 33756, -1, 158774, - -1, 159083, -1, 158933, -1, 17707, -1, 34033, - -1, 34035, -1, 34070, -1, 160714, -1, 34148, - -1, 159532, -1, 17757, -1, 17761, -1, 159665, - -1, 159954, -1, 17771, -1, 34384, -1, 34407, - -1, 34409, -1, 34473, -1, 34440, -1, 34574, - -1, 34530, -1, 34600, -1, 34667, -1, 34694, - -1, 17879, -1, 34785, -1, 34817, -1, 17913, - -1, 34912, -1, 161383, -1, 35031, -1, 35038, - -1, 17973, -1, 35066, -1, 13499, -1, 161966, - -1, 162150, -1, 18110, -1, 18119, -1, 35488, - -1, 162984, -1, 36011, -1, 36033, -1, 36123, - -1, 36215, -1, 163631, -1, 133124, -1, 36299, - -1, 36284, -1, 36336, -1, 133342, -1, 36564, - -1, 165330, -1, 165357, -1, 37012, -1, 37105, - -1, 37137, -1, 165678, -1, 37147, -1, 37432, - -1, 37591, -1, 37592, -1, 37500, -1, 37881, - -1, 37909, -1, 166906, -1, 38283, -1, 18837, - -1, 38327, -1, 167287, -1, 18918, -1, 38595, - -1, 23986, -1, 38691, -1, 168261, -1, 168474, - -1, 19054, -1, 19062, -1, 38880, -1, 168970, - -1, 19122, -1, 169110, -1, 38953, -1, 169398, - -1, 39138, -1, 19251, -1, 39209, -1, 39335, - -1, 39362, -1, 39422, -1, 19406, -1, 170800, - -1, 40000, -1, 40189, -1, 19662, -1, 19693, - -1, 40295, -1, 172238, -1, 19704, -1, 172293, - -1, 172558, -1, 172689, -1, 19798, -1, 40702, - -1, 40709, -1, 40719, -1, 40726, -1, 173568, - -1, }; +const utf8proc_uint16_t utf8proc_stage1table[] = { + 0, 256, 512, 768, 1024, 1280, 1536, + 1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584, + 3840, 4096, 4352, 4608, 4864, 5120, 5376, 5632, + 5888, 6144, 6400, 6656, 6912, 7168, 7424, 7680, + 7936, 8192, 8448, 8704, 8960, 9216, 9472, 9728, + 9984, 10240, 10496, 10752, 11008, 11264, 11520, 11776, + 12032, 12288, 12544, 12800, 13056, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13568, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13824, 14080, 13312, 13312, 13312, 14336, 13312, 14592, + 14848, 15104, 15360, 15616, 15872, 16128, 16384, 16640, + 16896, 17152, 17408, 17664, 16128, 16384, 16640, 16896, + 17152, 17408, 17664, 16128, 16384, 16640, 16896, 17152, + 17408, 17664, 16128, 16384, 16640, 16896, 17152, 17408, + 17664, 16128, 16384, 16640, 16896, 17152, 17408, 17664, + 16128, 16384, 16640, 16896, 17152, 17408, 17664, 16128, + 17920, 18176, 18176, 18176, 18176, 18176, 18176, 18176, + 18176, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18688, 18944, 19200, 19456, 19712, 19968, + 20224, 20480, 20736, 20992, 21248, 21504, 21760, 22016, + 22272, 22528, 22784, 23040, 23296, 23552, 23808, 24064, + 23808, 24320, 24576, 24832, 25088, 25344, 25600, 25856, + 26112, 26368, 23808, 26624, 23808, 26880, 23808, 23808, + 23808, 27136, 27136, 27136, 27392, 27648, 27904, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 27136, 27136, 27136, 27136, 28160, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 27136, 27136, 28416, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 27136, 27136, 28672, 28928, 23808, 23808, 23808, + 29184, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 29440, 13312, 13312, 29696, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 29952, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 30208, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 30464, 30720, 30976, 31232, 31488, 31744, 32000, + 32256, 10240, 10240, 32512, 23808, 23808, 23808, 23808, + 23808, 32768, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 33024, 33280, 23808, 23808, 23808, 23808, 33536, + 23808, 33792, 34048, 34304, 34560, 34816, 35072, 35328, + 35584, 35840, 36096, 23808, 23808, 23808, 23808, 23808, + 23808, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 36352, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 36608, 36864, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 13312, + 13312, 13312, 13312, 13312, 13312, 13312, 13312, 37120, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 37376, 37632, 37888, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 38144, 38400, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 23808, 23808, 23808, 23808, 23808, 23808, 23808, + 23808, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 38656, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 18432, 18432, 18432, 18432, 18432, 18432, 18432, 18432, + 38656, }; UTF8PROC_DATA -const uint16_t utf8proc_stage1table[] = { - 0, 256, 512, 768, 1024, 1280, 1536, - 1792, 2048, 2304, 2560, 2816, 3072, 3328, 3584, - 3840, 4096, 4352, 4608, 4864, 5120, 5376, 5632, - 5888, 6144, 6400, 6656, 6912, 2048, 7168, 7424, - 7680, 7936, 8192, 8448, 8704, 8960, 9216, 9472, - 9728, 9984, 10240, 10496, 10752, 11008, 11264, 11520, - 11776, 12032, 12288, 12544, 12800, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 13056, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 13312, 13568, 5376, 5376, 5376, 13824, 2048, 2048, - 14080, 14336, 2048, 2048, 2048, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 14592, 14848, 14848, 14848, 14848, 14848, 14848, 14848, - 14848, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15360, 15616, 15872, 16128, 16384, 16640, - 16896, 17152, 17408, 2048, 17664, 17920, 2048, 2048, - 2048, 18176, 18432, 18688, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 5376, 5376, 5376, 18944, 19200, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 19456, 19712, 19968, 20224, 20480, 20736, 20992, - 21248, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 5376, - 5376, 5376, 5376, 5376, 5376, 5376, 5376, 21504, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 21760, 22016, 22272, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 22528, 22784, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, - 2048, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 23040, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 15104, 15104, 15104, 15104, 15104, 15104, 15104, 15104, - 23040, }; - -UTF8PROC_DATA -const uint16_t utf8proc_stage2table[] = { - 1, 1, 1, 1, 1, 1, 1, - 1, 1, 2, 3, 2, 4, 3, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 5, 5, 5, - 6, 7, 8, 8, 9, 10, 9, 8, - 8, 11, 12, 8, 13, 14, 15, 14, - 14, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 14, 8, 17, 18, 19, - 8, 8, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 41, - 42, 43, 44, 45, 11, 8, 12, 46, - 47, 46, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 67, 68, 69, - 70, 71, 72, 73, 11, 74, 12, 74, - 1, 1, 1, 1, 1, 1, 3, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, - 1, 75, 8, 10, 10, 10, 10, 76, - 76, 77, 76, 78, 79, 74, 80, 76, - 81, 82, 83, 84, 85, 86, 87, 76, - 8, 88, 89, 90, 91, 92, 93, 94, - 8, 95, 96, 97, 98, 99, 100, 101, - 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, 116, 117, - 74, 118, 119, 120, 121, 122, 123, 124, - 125, 126, 127, 128, 129, 130, 131, 132, - 133, 134, 135, 136, 137, 138, 139, 140, - 141, 142, 143, 144, 145, 146, 147, 148, - 74, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, 160, 161, 162, 163, - 164, 165, 166, 167, 168, 169, 170, 171, - 172, 173, 174, 175, 176, 177, 178, 179, - 180, 181, 182, 183, 184, 185, 186, 187, - 188, 189, 190, 191, 192, 193, 194, 195, - 196, 197, 198, 199, 200, 201, 202, 203, - 204, 205, 206, 207, 208, 209, 210, 211, - 212, 213, 214, 215, 216, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 226, 227, - 228, 229, 230, 231, 232, 233, 234, 235, - 236, 237, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 255, 256, 257, 258, 259, - 260, 261, 262, 263, 264, 265, 266, 267, - 268, 269, 270, 271, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 290, 291, - 292, 293, 294, 295, 296, 297, 213, 298, - 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 213, 311, 312, 313, - 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 324, 213, 213, 325, 326, 327, - 328, 329, 330, 331, 332, 333, 334, 335, - 336, 337, 338, 213, 339, 340, 341, 213, - 342, 339, 339, 339, 339, 343, 344, 345, - 346, 347, 348, 349, 350, 351, 352, 353, - 354, 355, 356, 357, 358, 359, 360, 361, - 362, 363, 364, 365, 366, 367, 368, 369, - 370, 371, 372, 373, 374, 375, 376, 377, - 378, 379, 380, 381, 382, 383, 384, 385, - 386, 387, 388, 389, 390, 391, 392, 393, - 394, 395, 396, 397, 398, 399, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, - 410, 411, 412, 413, 414, 415, 416, 417, - 418, 419, 420, 421, 422, 423, 424, 425, - 426, 427, 428, 429, 430, 431, 432, 433, - 434, 435, 213, 436, 437, 438, 439, 440, - 441, 442, 443, 444, 445, 446, 447, 448, - 449, 450, 451, 452, 453, 213, 213, 213, - 213, 213, 213, 454, 455, 456, 457, 458, - 213, 213, 459, 460, 461, 462, 463, 464, - 465, 466, 467, 468, 469, 470, 471, 472, - 473, 213, 213, 213, 474, 475, 213, 476, - 477, 213, 478, 213, 479, 213, 213, 213, - 213, 480, 213, 213, 481, 213, 213, 213, - 213, 482, 483, 213, 484, 213, 213, 213, - 485, 213, 213, 486, 213, 213, 487, 213, - 213, 213, 213, 213, 213, 213, 488, 213, - 213, 489, 213, 213, 490, 213, 213, 213, - 213, 491, 492, 493, 494, 495, 213, 213, - 213, 213, 213, 496, 213, 339, 213, 213, - 213, 213, 213, 213, 213, 213, 213, 213, - 213, 213, 213, 213, 213, 213, 213, 213, - 213, 213, 213, 213, 213, 213, 213, 213, - 213, 497, 498, 499, 500, 501, 502, 503, - 504, 505, 506, 506, 507, 507, 507, 507, - 507, 507, 507, 46, 46, 46, 46, 506, - 506, 506, 506, 506, 506, 506, 506, 506, - 506, 507, 507, 46, 46, 46, 46, 46, - 46, 508, 509, 510, 511, 512, 513, 46, - 46, 514, 515, 516, 517, 518, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 507, - 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 46, - 46, 519, 520, 521, 522, 523, 524, 525, - 526, 527, 528, 529, 530, 531, 524, 524, - 532, 524, 533, 524, 534, 535, 536, 537, - 537, 537, 537, 536, 538, 537, 537, 537, - 537, 537, 539, 539, 540, 541, 542, 543, - 544, 545, 537, 537, 537, 537, 546, 547, - 537, 548, 549, 537, 537, 550, 550, 550, - 550, 551, 537, 537, 537, 537, 524, 524, - 524, 552, 553, 554, 555, 556, 557, 524, - 537, 537, 537, 524, 524, 524, 537, 537, - 558, 524, 524, 524, 537, 537, 537, 537, - 524, 536, 537, 537, 524, 559, 560, 560, - 559, 560, 560, 559, 524, 524, 524, 524, - 524, 524, 524, 524, 524, 524, 524, 524, - 524, 0, 0, 0, 0, 561, 46, 0, - 0, 0, 0, 562, 563, 564, 565, 566, - 0, 0, 0, 0, 0, 86, 567, 568, - 569, 570, 571, 572, 0, 573, 0, 574, - 575, 576, 577, 578, 579, 580, 581, 582, - 583, 584, 585, 586, 587, 588, 589, 590, - 591, 592, 593, 0, 594, 595, 596, 597, - 598, 599, 600, 601, 602, 603, 604, 605, - 606, 607, 608, 609, 610, 611, 612, 613, - 614, 615, 616, 617, 618, 619, 620, 621, - 622, 623, 624, 625, 626, 627, 628, 629, - 630, 631, 632, 633, 634, 635, 636, 637, - 0, 638, 639, 640, 641, 642, 643, 644, - 213, 645, 646, 647, 648, 649, 650, 651, - 652, 653, 654, 655, 656, 657, 658, 659, - 660, 661, 662, 663, 664, 665, 666, 667, - 668, 669, 670, 671, 213, 672, 673, 74, - 674, 675, 676, 677, 678, 213, 679, 680, - 681, 682, 683, 684, 685, 686, 687, 688, - 689, 690, 691, 692, 693, 694, 695, 696, - 697, 698, 699, 700, 701, 702, 703, 704, - 705, 706, 707, 708, 709, 710, 711, 712, - 713, 714, 715, 716, 717, 718, 719, 720, - 721, 722, 723, 724, 725, 726, 727, 728, - 729, 730, 731, 732, 733, 734, 735, 736, - 737, 738, 739, 740, 741, 742, 743, 744, - 745, 746, 747, 748, 749, 750, 751, 752, - 753, 754, 755, 756, 757, 758, 759, 760, - 761, 762, 763, 764, 765, 766, 767, 768, - 769, 770, 771, 772, 773, 774, 775, 776, - 777, 778, 779, 780, 781, 782, 783, 784, - 785, 786, 787, 788, 789, 790, 791, 792, - 793, 794, 795, 796, 797, 798, 799, 800, - 801, 802, 803, 804, 805, 806, 807, 808, - 809, 810, 811, 812, 524, 524, 524, 524, - 0, 813, 813, 814, 815, 816, 817, 818, - 819, 820, 821, 822, 823, 824, 825, 826, - 827, 828, 829, 830, 831, 832, 833, 834, - 835, 836, 837, 838, 839, 840, 841, 842, - 843, 844, 845, 846, 847, 848, 849, 850, - 851, 852, 853, 854, 855, 856, 857, 858, - 859, 860, 861, 862, 863, 864, 865, 866, - 867, 868, 869, 870, 871, 872, 873, 874, - 875, 876, 877, 878, 879, 880, 881, 882, - 883, 884, 885, 886, 887, 888, 889, 890, - 891, 892, 893, 894, 895, 896, 897, 898, - 899, 900, 901, 902, 903, 904, 905, 906, - 907, 908, 909, 910, 911, 912, 913, 914, - 915, 916, 917, 918, 919, 920, 921, 922, - 923, 924, 925, 926, 927, 928, 929, 930, - 931, 932, 933, 934, 935, 936, 937, 938, - 939, 940, 941, 942, 943, 944, 945, 946, - 947, 948, 949, 950, 951, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 952, 953, 954, 955, 956, 957, - 958, 959, 960, 961, 962, 963, 964, 965, - 966, 967, 968, 969, 970, 971, 972, 973, - 974, 975, 976, 977, 978, 979, 980, 981, - 982, 983, 984, 985, 986, 987, 988, 989, - 0, 0, 507, 990, 990, 990, 990, 990, - 990, 0, 991, 992, 993, 994, 995, 996, - 997, 998, 999, 1000, 1001, 1002, 1003, 1004, - 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, - 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, - 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, - 1029, 0, 990, 1030, 0, 0, 0, 0, - 0, 0, 537, 524, 524, 524, 524, 537, - 524, 524, 524, 1031, 537, 524, 524, 524, - 524, 524, 524, 537, 537, 537, 537, 537, - 537, 524, 524, 537, 524, 524, 1031, 1032, - 524, 1033, 1034, 1035, 1036, 1037, 1038, 1039, - 1040, 1041, 1042, 1042, 1043, 1044, 1045, 1046, - 1047, 1046, 1048, 1049, 1046, 524, 537, 1046, - 1041, 0, 0, 0, 0, 0, 0, 0, - 0, 1050, 1050, 1050, 1050, 1050, 1050, 1050, - 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, - 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, - 1050, 1050, 1050, 1050, 0, 0, 0, 0, - 0, 1050, 1050, 1050, 1046, 1046, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1051, 1051, 1051, 1051, 0, 0, 0, - 0, 0, 0, 0, 1052, 14, 1053, 76, - 76, 524, 524, 524, 524, 524, 524, 0, - 0, 0, 0, 0, 1053, 0, 0, 1053, - 1053, 0, 1054, 1055, 1056, 1057, 1058, 1059, - 1060, 1054, 1054, 1054, 1054, 1054, 1054, 1054, - 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, - 1054, 1054, 1054, 1054, 0, 0, 0, 0, - 0, 1061, 1054, 1054, 1054, 1054, 1054, 1054, - 1054, 1062, 1054, 1063, 1064, 1065, 1066, 1067, - 1068, 1069, 1070, 1071, 1072, 1073, 1074, 537, - 524, 524, 524, 524, 524, 537, 524, 524, - 0, 1075, 1075, 1075, 1075, 1075, 1075, 1075, - 1075, 1075, 1075, 9, 1076, 1076, 1053, 1054, - 1054, 1077, 1054, 1054, 1054, 1054, 1078, 1079, - 1080, 1081, 1054, 1054, 1054, 1054, 1054, 1054, - 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, - 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, - 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, - 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, - 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, - 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, - 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, - 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, - 1054, 1082, 1083, 1084, 1054, 1054, 1054, 1054, - 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, - 1054, 1054, 1054, 1085, 1086, 1053, 1087, 524, - 524, 524, 524, 524, 524, 524, 1051, 813, - 524, 524, 524, 524, 537, 524, 1061, 1061, - 524, 524, 76, 537, 524, 524, 537, 1054, - 1054, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 1054, 1054, 1054, 1088, 1088, - 1054, 1053, 1053, 1053, 1053, 1053, 1053, 1053, - 1053, 1053, 1053, 1053, 1053, 1053, 1053, 0, - 80, 1054, 1089, 1054, 1054, 1054, 1054, 1054, - 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, - 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, - 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, - 1054, 524, 537, 524, 524, 537, 524, 524, - 537, 537, 537, 524, 537, 537, 524, 537, - 524, 524, 524, 537, 524, 537, 524, 537, - 524, 537, 524, 524, 0, 0, 1054, 1054, - 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, - 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, - 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, - 1054, 1054, 1054, 1054, 1054, 1054, 1054, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1054, 1054, 1054, 1054, 1054, 1054, 1054, - 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, - 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, - 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1054, - 1054, 1054, 1054, 1054, 1054, 1054, 1054, 1090, - 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, - 1090, 1090, 1054, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1091, 1091, 1091, 1091, 1091, 1091, 1091, - 1091, 1091, 1091, 1050, 1050, 1050, 1050, 1050, - 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, - 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, - 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, - 1050, 1050, 1050, 1050, 524, 524, 524, 524, - 524, 524, 524, 537, 524, 1092, 1092, 76, - 8, 8, 8, 1092, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1090, 1090, 1093, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 1094, 1095, 339, 339, 339, 339, 339, - 339, 1096, 1097, 339, 1098, 1099, 339, 339, - 339, 339, 339, 0, 0, 1100, 339, 1093, - 1093, 1093, 1090, 1090, 1090, 1090, 1090, 1090, - 1090, 1090, 1093, 1093, 1093, 1093, 1101, 0, - 0, 339, 524, 537, 524, 524, 0, 0, - 0, 1102, 1103, 1104, 1105, 1106, 1107, 1108, - 1109, 339, 339, 1090, 1090, 990, 990, 1110, - 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, - 1110, 990, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 339, 339, 339, 339, - 339, 0, 1090, 1093, 1093, 0, 339, 339, - 339, 339, 339, 339, 339, 339, 0, 0, - 339, 339, 0, 0, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 0, 339, 339, 339, 339, 339, - 339, 339, 0, 339, 0, 0, 0, 339, - 339, 339, 339, 0, 0, 1111, 339, 1112, - 1093, 1093, 1090, 1090, 1090, 1090, 0, 0, - 1113, 1093, 0, 0, 1114, 1115, 1101, 339, - 0, 0, 0, 0, 0, 0, 0, 0, - 1116, 0, 0, 0, 0, 1117, 1118, 0, - 1119, 339, 339, 1090, 1090, 0, 0, 1110, - 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, - 1110, 339, 339, 10, 10, 1120, 1120, 1120, - 1120, 1120, 1120, 812, 0, 0, 0, 0, - 0, 0, 1090, 1090, 1093, 0, 339, 339, - 339, 339, 339, 339, 0, 0, 0, 0, - 339, 339, 0, 0, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 0, 339, 339, 339, 339, 339, - 339, 339, 0, 339, 1121, 0, 339, 1122, - 0, 339, 339, 0, 0, 1111, 0, 1093, - 1093, 1093, 1090, 1090, 0, 0, 0, 0, - 1090, 1090, 0, 0, 1090, 1090, 1101, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1123, 1124, 1125, 339, 0, 1126, - 0, 0, 0, 0, 0, 0, 0, 1110, - 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, - 1110, 1090, 1090, 339, 339, 339, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1090, 1090, 1093, 0, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 0, - 339, 339, 339, 0, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 0, 339, 339, 339, 339, 339, - 339, 339, 0, 339, 339, 0, 339, 339, - 339, 339, 339, 0, 0, 1111, 339, 1093, - 1093, 1093, 1090, 1090, 1090, 1090, 1090, 0, - 1090, 1090, 1093, 0, 1093, 1093, 1101, 0, - 0, 339, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 339, 339, 1090, 1090, 0, 0, 1110, - 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, - 1110, 0, 10, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1090, 1093, 1093, 0, 339, 339, - 339, 339, 339, 339, 339, 339, 0, 0, - 339, 339, 0, 0, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 0, 339, 339, 339, 339, 339, - 339, 339, 0, 339, 339, 0, 339, 339, - 339, 339, 339, 0, 0, 1111, 339, 1127, - 1090, 1093, 1090, 1090, 1090, 0, 0, 0, - 1128, 1129, 0, 0, 1130, 1131, 1101, 0, - 0, 0, 0, 0, 0, 0, 0, 1132, - 1133, 0, 0, 0, 0, 1134, 1135, 0, - 339, 339, 339, 0, 0, 0, 0, 1110, - 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, - 1110, 812, 339, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1090, 339, 0, 339, 339, - 339, 339, 339, 339, 0, 0, 0, 339, - 339, 339, 0, 1136, 339, 1137, 339, 0, - 0, 0, 339, 339, 0, 339, 0, 339, - 339, 0, 0, 0, 339, 339, 0, 0, - 0, 339, 339, 339, 0, 0, 0, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 0, 0, 0, 0, 1138, - 1093, 1090, 1093, 1093, 0, 0, 0, 1139, - 1140, 1093, 0, 1141, 1142, 1143, 1101, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1144, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1110, - 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, - 1110, 1120, 1120, 1120, 76, 76, 76, 76, - 76, 76, 10, 76, 0, 0, 0, 0, - 0, 0, 1093, 1093, 1093, 0, 339, 339, - 339, 339, 339, 339, 339, 339, 0, 339, - 339, 339, 0, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 0, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 0, 339, 339, - 339, 339, 339, 0, 0, 0, 0, 1090, - 1090, 1090, 1093, 1093, 1093, 1093, 0, 1145, - 1090, 1146, 0, 1090, 1090, 1090, 1101, 0, - 0, 0, 0, 0, 0, 0, 1147, 1148, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 339, 339, 0, 0, 0, 0, 1110, - 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, - 1110, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1093, 1093, 0, 339, 339, - 339, 339, 339, 339, 339, 339, 0, 339, - 339, 339, 0, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 0, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 0, 339, 339, - 339, 339, 339, 0, 0, 1111, 339, 1093, - 1149, 1150, 1093, 1151, 1093, 1093, 0, 1152, - 1153, 1154, 0, 1155, 1156, 1090, 1101, 0, - 0, 0, 0, 0, 0, 0, 1157, 1158, - 0, 0, 0, 0, 0, 0, 0, 339, - 0, 339, 339, 1090, 1090, 0, 0, 1110, - 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, - 1110, 0, 76, 76, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1093, 1093, 0, 339, 339, - 339, 339, 339, 339, 339, 339, 0, 339, - 339, 339, 0, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 0, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 0, 0, 0, 0, 1159, - 1093, 1093, 1090, 1090, 1090, 0, 0, 1160, - 1161, 1093, 0, 1162, 1163, 1164, 1101, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1165, 0, 0, 0, 0, 0, 0, 0, - 0, 339, 339, 0, 0, 0, 0, 1110, - 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, - 1110, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1093, 1093, 0, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 0, 0, 0, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 0, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 0, 339, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 0, 0, 0, 1166, 0, 0, 0, 0, - 1167, 1093, 1093, 1090, 1090, 1090, 0, 1090, - 0, 1093, 1168, 1169, 1093, 1170, 1171, 1172, - 1173, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1093, 1093, 990, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 1090, 339, 1174, 1090, 1090, 1090, - 1090, 1175, 1175, 1101, 0, 0, 0, 0, - 10, 339, 339, 339, 339, 339, 339, 507, - 1090, 1176, 1176, 1176, 1176, 1090, 1090, 1090, - 990, 1110, 1110, 1110, 1110, 1110, 1110, 1110, - 1110, 1110, 1110, 990, 990, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 339, 339, 0, 339, 0, 0, - 339, 339, 0, 339, 0, 0, 339, 0, - 0, 0, 0, 0, 0, 339, 339, 339, - 339, 0, 339, 339, 339, 339, 339, 339, - 339, 0, 339, 339, 339, 0, 339, 0, - 339, 0, 0, 339, 339, 0, 339, 339, - 339, 339, 1090, 339, 1177, 1090, 1090, 1090, - 1090, 1178, 1178, 0, 1090, 1090, 339, 0, - 0, 339, 339, 339, 339, 339, 0, 507, - 0, 1179, 1179, 1179, 1179, 1090, 1090, 0, - 0, 1110, 1110, 1110, 1110, 1110, 1110, 1110, - 1110, 1110, 1110, 0, 0, 1180, 1181, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 339, 812, 812, 812, 990, 990, 990, - 990, 990, 990, 990, 990, 1182, 990, 990, - 990, 990, 990, 990, 812, 812, 812, 812, - 812, 537, 537, 812, 812, 812, 812, 812, - 812, 1110, 1110, 1110, 1110, 1110, 1110, 1110, - 1110, 1110, 1110, 1120, 1120, 1120, 1120, 1120, - 1120, 1120, 1120, 1120, 1120, 812, 537, 812, - 537, 812, 1183, 11, 12, 11, 12, 1093, - 1093, 339, 339, 339, 1184, 339, 339, 339, - 339, 0, 339, 339, 339, 339, 1185, 339, - 339, 339, 339, 1186, 339, 339, 339, 339, - 1187, 339, 339, 339, 339, 1188, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 1189, 339, 0, 0, 0, 0, - 0, 0, 1190, 1191, 1192, 1193, 1194, 1195, - 1196, 1197, 1198, 1191, 1191, 1191, 1191, 1090, - 1093, 1191, 1199, 524, 524, 1101, 990, 524, - 524, 339, 339, 339, 339, 0, 0, 0, - 0, 1090, 1090, 1090, 1200, 1090, 1090, 1090, - 1090, 0, 1090, 1090, 1090, 1090, 1201, 1090, - 1090, 1090, 1090, 1202, 1090, 1090, 1090, 1090, - 1203, 1090, 1090, 1090, 1090, 1204, 1090, 1090, - 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1090, - 1090, 1090, 1205, 1090, 1090, 1090, 0, 812, - 812, 812, 812, 812, 812, 812, 812, 537, - 812, 812, 812, 812, 812, 812, 0, 0, - 812, 990, 990, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 0, 339, 339, 1206, 1207, - 339, 0, 339, 339, 0, 1093, 1090, 1208, - 1090, 1090, 1093, 1090, 0, 0, 0, 1090, - 1111, 1093, 1101, 0, 0, 0, 0, 0, - 0, 1110, 1110, 1110, 1110, 1110, 1110, 1110, - 1110, 1110, 1110, 990, 990, 990, 990, 990, - 990, 339, 339, 339, 339, 339, 339, 1093, - 1093, 1090, 1090, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1209, 1210, 1211, 1212, 1213, 1214, 1215, - 1216, 1217, 1218, 1219, 1220, 1221, 1222, 1223, - 1224, 1225, 1226, 1227, 1228, 1229, 1230, 1231, - 1232, 1233, 1234, 1235, 1236, 1237, 1238, 1239, - 1240, 1241, 1242, 1243, 1244, 1245, 1246, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 990, 1247, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 0, 0, 0, 0, 0, - 1248, 1248, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 0, 0, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 0, 0, 0, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 0, 339, 339, 339, 339, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 0, 339, 0, 339, 339, 339, 339, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 0, 339, 339, 339, 339, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 0, 339, 339, 339, 339, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 0, 339, 0, 339, 339, 339, 339, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 0, 339, 339, 339, 339, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 0, 0, 0, 0, - 524, 812, 990, 990, 990, 990, 990, 990, - 990, 990, 1120, 1120, 1120, 1120, 1120, 1120, - 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, - 1120, 1120, 1120, 1120, 1120, 1120, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 0, 0, 0, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 990, 990, - 339, 339, 339, 339, 339, 339, 339, 339, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 7, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 11, 12, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 990, 990, 990, 1249, - 1249, 1249, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 0, 339, - 339, 339, 339, 1090, 1090, 1101, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 1090, 1090, 1101, 990, 990, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 1090, 1090, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 0, 339, - 339, 339, 0, 1090, 1090, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 1250, 1250, 1093, - 1090, 1090, 1090, 1090, 1090, 1090, 1090, 1093, - 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1090, - 1093, 1093, 1090, 1090, 1090, 1090, 1090, 1090, - 1090, 1090, 1090, 1101, 1090, 990, 990, 990, - 507, 990, 990, 990, 10, 339, 524, 0, - 0, 1110, 1110, 1110, 1110, 1110, 1110, 1110, - 1110, 1110, 1110, 0, 0, 0, 0, 0, - 0, 1251, 1251, 1251, 1251, 1251, 1251, 1251, - 1251, 1251, 1251, 0, 0, 0, 0, 0, - 0, 8, 8, 8, 8, 8, 8, 1030, - 8, 8, 8, 8, 558, 558, 558, 7, - 0, 1110, 1110, 1110, 1110, 1110, 1110, 1110, - 1110, 1110, 1110, 0, 0, 0, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 507, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 0, 0, 0, 0, 0, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 1032, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 0, 0, - 0, 1090, 1090, 1090, 1093, 1093, 1093, 1093, - 1090, 1090, 1252, 1252, 1252, 0, 0, 0, - 0, 1093, 1093, 1090, 1093, 1093, 1093, 1093, - 1093, 1093, 1031, 524, 537, 0, 0, 0, - 0, 76, 0, 0, 0, 8, 8, 1110, - 1110, 1110, 1110, 1110, 1110, 1110, 1110, 1110, - 1110, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 0, - 0, 339, 339, 339, 339, 339, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 0, 0, 0, 0, 0, - 0, 1093, 1093, 1093, 1093, 1093, 1093, 1093, - 1093, 1093, 1093, 1093, 1093, 1093, 1093, 1093, - 1093, 1093, 339, 339, 339, 339, 339, 339, - 339, 1093, 1093, 0, 0, 0, 0, 0, - 0, 1110, 1110, 1110, 1110, 1110, 1110, 1110, - 1110, 1110, 1110, 0, 0, 0, 0, 8, - 8, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 524, 537, 1093, 1093, 1093, 0, 0, 990, - 990, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1090, 1090, 1090, 1090, 1093, 1253, 1254, - 1255, 1256, 1257, 1258, 1259, 1260, 1261, 1262, - 339, 339, 1263, 1264, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 1111, 1265, 1090, - 1090, 1090, 1090, 1266, 1267, 1268, 1269, 1270, - 1271, 1272, 1273, 1274, 1275, 1276, 339, 339, - 339, 339, 339, 339, 339, 0, 0, 0, - 0, 1110, 1110, 1110, 1110, 1110, 1110, 1110, - 1110, 1110, 1110, 990, 990, 990, 990, 990, - 990, 990, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 524, 537, 524, 524, - 524, 524, 524, 524, 524, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 213, 213, 213, 213, 213, 213, 213, - 213, 213, 213, 213, 213, 213, 213, 213, - 213, 213, 213, 213, 213, 213, 213, 213, - 213, 213, 213, 213, 213, 213, 213, 213, - 213, 213, 213, 213, 213, 213, 213, 213, - 213, 213, 213, 213, 213, 1277, 1278, 1279, - 507, 1280, 1281, 1282, 1283, 1284, 1285, 1286, - 1287, 1288, 1289, 1290, 507, 1291, 1292, 1293, - 1294, 1295, 1296, 1297, 1298, 1299, 1300, 1301, - 1302, 1303, 1304, 1305, 1306, 1307, 1308, 507, - 1309, 1310, 1311, 1312, 1313, 1314, 1315, 1316, - 1317, 1318, 1319, 1320, 1321, 1322, 1323, 1324, - 1325, 1326, 1327, 1328, 1329, 1330, 1331, 1332, - 1333, 1334, 1335, 1336, 213, 213, 213, 213, - 213, 213, 213, 213, 213, 213, 213, 213, - 213, 1337, 213, 213, 213, 213, 1338, 213, - 213, 213, 213, 213, 213, 213, 213, 213, - 213, 213, 213, 213, 213, 213, 213, 213, - 213, 213, 213, 213, 213, 213, 213, 213, - 213, 213, 213, 213, 1339, 1340, 1341, 1342, - 1307, 1343, 1344, 1345, 1346, 1347, 1348, 1349, - 1350, 1351, 1352, 1353, 1354, 1355, 1356, 1357, - 1358, 1359, 1360, 1361, 1362, 1363, 1364, 1365, - 1366, 1367, 1368, 1369, 1370, 1371, 1372, 1373, - 1374, 524, 524, 537, 524, 524, 524, 524, - 524, 524, 524, 537, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 524, - 537, 1375, 1376, 1377, 1378, 1379, 1380, 1381, - 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, - 1390, 1391, 1392, 1393, 1394, 1395, 1396, 1397, - 1398, 1399, 1400, 1401, 1402, 1403, 1404, 1405, - 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, - 1414, 1415, 1416, 1417, 1418, 1419, 1420, 1421, - 1422, 1423, 1424, 1425, 1426, 1427, 1428, 1429, - 1430, 1431, 1432, 1433, 1434, 1435, 1436, 1437, - 1438, 1439, 1440, 1441, 1442, 1443, 1444, 1445, - 1446, 1447, 1448, 1449, 1450, 1451, 1452, 1453, - 1454, 1455, 1456, 1457, 1458, 1459, 1460, 1461, - 1462, 1463, 1464, 1465, 1466, 1467, 1468, 1469, - 1470, 1471, 1472, 1473, 1474, 1475, 1476, 1477, - 1478, 1479, 1480, 1481, 1482, 1483, 1484, 1485, - 1486, 1487, 1488, 1489, 1490, 1491, 1492, 1493, - 1494, 1495, 1496, 1497, 1498, 1499, 1500, 1501, - 1502, 1503, 1504, 1505, 1506, 1507, 1508, 1509, - 1510, 1511, 1512, 1513, 1514, 1515, 1516, 1517, - 1518, 1519, 1520, 1521, 1522, 1523, 1524, 1525, - 1526, 1527, 1528, 1529, 1530, 0, 0, 0, - 0, 1531, 1532, 1533, 1534, 1535, 1536, 1537, - 1538, 1539, 1540, 1541, 1542, 1543, 1544, 1545, - 1546, 1547, 1548, 1549, 1550, 1551, 1552, 1553, - 1554, 1555, 1556, 1557, 1558, 1559, 1560, 1561, - 1562, 1563, 1564, 1565, 1566, 1567, 1568, 1569, - 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, - 1578, 1579, 1580, 1581, 1582, 1583, 1584, 1585, - 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593, - 1594, 1595, 1596, 1597, 1598, 1599, 1600, 1601, - 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609, - 1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, - 1618, 1619, 1620, 0, 0, 0, 0, 0, - 0, 1621, 1622, 1623, 1624, 1625, 1626, 1627, - 1628, 1629, 1630, 1631, 1632, 1633, 1634, 1635, - 1636, 1637, 1638, 1639, 1640, 1641, 1642, 0, - 0, 1643, 1644, 1645, 1646, 1647, 1648, 0, - 0, 1649, 1650, 1651, 1652, 1653, 1654, 1655, - 1656, 1657, 1658, 1659, 1660, 1661, 1662, 1663, - 1664, 1665, 1666, 1667, 1668, 1669, 1670, 1671, - 1672, 1673, 1674, 1675, 1676, 1677, 1678, 1679, - 1680, 1681, 1682, 1683, 1684, 1685, 1686, 0, - 0, 1687, 1688, 1689, 1690, 1691, 1692, 0, - 0, 1693, 1694, 1695, 1696, 1697, 1698, 1699, - 1700, 0, 1701, 0, 1702, 0, 1703, 0, - 1704, 1705, 1706, 1707, 1708, 1709, 1710, 1711, - 1712, 1713, 1714, 1715, 1716, 1717, 1718, 1719, - 1720, 1721, 1722, 1723, 1724, 1725, 1726, 1727, - 1728, 1729, 1730, 1731, 1732, 1733, 1734, 0, - 0, 1735, 1736, 1737, 1738, 1739, 1740, 1741, - 1742, 1743, 1744, 1745, 1746, 1747, 1748, 1749, - 1750, 1751, 1752, 1753, 1754, 1755, 1756, 1757, - 1758, 1759, 1760, 1761, 1762, 1763, 1764, 1765, - 1766, 1767, 1768, 1769, 1770, 1771, 1772, 1773, - 1774, 1775, 1776, 1777, 1778, 1779, 1780, 1781, - 1782, 1783, 1784, 1785, 1786, 1787, 0, 1788, - 1789, 1790, 1791, 1792, 1793, 1794, 1795, 1796, - 1797, 1798, 1799, 1800, 1801, 1802, 0, 1803, - 1804, 1805, 1806, 1807, 1808, 1809, 1810, 1811, - 1812, 1813, 1814, 1815, 1816, 0, 0, 1817, - 1818, 1819, 1820, 1821, 1822, 0, 1823, 1824, - 1825, 1826, 1827, 1828, 1829, 1830, 1831, 1832, - 1833, 1834, 1835, 1836, 1837, 1838, 1839, 1840, - 1841, 0, 0, 1842, 1843, 1844, 0, 1845, - 1846, 1847, 1848, 1849, 1850, 1851, 1852, 1853, - 0, 1854, 1855, 1856, 1856, 1856, 1856, 1856, - 1857, 1856, 1856, 1856, 80, 1858, 1858, 1250, - 1859, 1030, 1860, 1030, 1030, 1030, 1030, 8, - 1861, 79, 91, 11, 79, 79, 91, 11, - 79, 8, 8, 8, 8, 1862, 1863, 1864, - 8, 1865, 1866, 1867, 1868, 1869, 1870, 1871, - 75, 9, 9, 9, 1872, 1873, 8, 1874, - 1875, 8, 79, 91, 8, 1876, 8, 1877, - 47, 47, 8, 8, 8, 1878, 11, 12, - 1879, 1880, 1881, 8, 8, 8, 8, 8, - 8, 8, 8, 74, 8, 47, 8, 8, - 1882, 8, 8, 8, 8, 8, 8, 8, - 1856, 80, 80, 80, 80, 0, 0, 0, - 0, 0, 0, 80, 80, 80, 80, 80, - 80, 1883, 1884, 0, 0, 1885, 1886, 1887, - 1888, 1889, 1890, 1891, 1892, 1893, 1894, 1895, - 1896, 1897, 1898, 1899, 1900, 1901, 1902, 1903, - 1904, 1905, 1906, 1907, 1908, 1909, 1910, 1911, - 0, 1912, 1913, 1914, 1915, 1916, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 10, 10, 10, 10, 10, 10, 10, - 10, 1917, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 524, 524, 550, 550, 524, 524, 524, - 524, 550, 550, 550, 524, 524, 813, 813, - 813, 813, 524, 813, 813, 813, 550, 550, - 524, 537, 524, 550, 550, 537, 537, 537, - 537, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1918, 1919, 1920, 1921, 76, 1922, 1923, - 1924, 76, 1925, 1926, 1927, 1927, 1927, 1928, - 1929, 1930, 1930, 1931, 1932, 76, 1933, 1934, - 76, 76, 1935, 1936, 1937, 1937, 1937, 76, - 76, 1938, 1939, 1940, 76, 1941, 76, 1942, - 76, 1941, 76, 1943, 1944, 1945, 1920, 82, - 1946, 1947, 1948, 1949, 1950, 1951, 1952, 1953, - 1954, 1955, 1956, 76, 1957, 1958, 1959, 1960, - 1961, 1962, 74, 74, 74, 74, 1963, 1964, - 1946, 1956, 1965, 76, 74, 76, 76, 1966, - 0, 0, 0, 0, 1967, 1968, 1969, 1970, - 1971, 1972, 1973, 1974, 1975, 1976, 1977, 1978, - 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986, - 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, - 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, - 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, - 2011, 1249, 1249, 1249, 2012, 2013, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2014, 74, 2015, 74, 2016, 76, 76, - 76, 76, 76, 2017, 2018, 76, 76, 76, - 76, 74, 76, 76, 74, 76, 76, 74, - 76, 76, 76, 76, 76, 76, 76, 2019, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 2020, 2021, - 2022, 2023, 76, 2024, 76, 2025, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 2026, 2026, 2027, 2028, 74, 74, - 74, 2029, 2030, 2026, 2031, 2032, 2026, 74, - 74, 74, 2026, 13, 83, 74, 2026, 2026, - 74, 74, 74, 2026, 2026, 2026, 2026, 74, - 2026, 2026, 2026, 2026, 2033, 2034, 2035, 2036, - 74, 74, 74, 74, 2026, 2037, 2038, 2026, - 2039, 2040, 2026, 2026, 2026, 74, 74, 74, - 74, 74, 2026, 74, 2026, 2041, 2026, 2026, - 2026, 2026, 2042, 2026, 2043, 2044, 2045, 2026, - 2046, 2047, 2048, 2026, 2026, 2026, 2049, 74, - 74, 74, 74, 2026, 2026, 2026, 2026, 74, - 74, 74, 74, 74, 74, 74, 74, 74, - 2026, 2050, 2051, 2052, 74, 2053, 2054, 2026, - 2026, 2026, 2026, 2026, 2026, 74, 2055, 2056, - 2057, 2058, 2059, 2060, 2061, 2062, 2063, 2064, - 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2026, - 2026, 2072, 2073, 2074, 2075, 2076, 2077, 2078, - 2079, 2080, 2081, 2026, 2026, 2026, 74, 74, - 2026, 2026, 2082, 2083, 74, 74, 74, 74, - 74, 2026, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 2084, 2026, 74, 74, 2026, - 2026, 2085, 2086, 2026, 2087, 2088, 2089, 2090, - 2091, 2026, 2026, 2092, 2093, 2094, 2095, 2026, - 2026, 2026, 74, 74, 74, 74, 74, 2026, - 2026, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 2026, 2026, 2026, 2026, 2026, 74, - 74, 2026, 2026, 74, 74, 74, 74, 2026, - 2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, - 2026, 2096, 2097, 2098, 2099, 2026, 2026, 2026, - 2026, 2026, 2026, 2100, 2101, 2102, 2103, 74, - 74, 2026, 2026, 2026, 2026, 2026, 2026, 2026, - 2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, - 2026, 76, 76, 76, 76, 76, 76, 76, - 76, 2026, 2026, 2026, 2026, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 2026, 2026, 76, 76, 76, 76, 76, - 76, 76, 2104, 2105, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 76, 74, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 812, 76, - 76, 76, 76, 76, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 74, 74, 74, - 74, 74, 74, 76, 76, 76, 76, 76, - 76, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2106, 2107, 2108, 2109, 2110, 2111, 2112, - 2113, 2114, 2115, 2116, 2117, 2118, 2119, 2120, - 2121, 2122, 2123, 2124, 2125, 2126, 2127, 2128, - 2129, 2130, 2131, 2132, 2133, 2134, 2135, 2136, - 2137, 2138, 2139, 2140, 2141, 2142, 2143, 2144, - 2145, 2146, 2147, 2148, 2149, 2150, 2151, 2152, - 2153, 2154, 2155, 2156, 2157, 2158, 2159, 2160, - 2161, 2162, 2163, 2164, 2165, 2166, 2167, 2168, - 2169, 2170, 2171, 2172, 2173, 2174, 2175, 2176, - 2177, 2178, 2179, 2180, 2181, 2182, 2183, 2184, - 2185, 2186, 2187, 2188, 2189, 2190, 2191, 2192, - 2193, 2194, 2195, 2196, 2197, 2198, 2199, 2200, - 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, - 2209, 2210, 2211, 2212, 2213, 2214, 2215, 2216, - 2217, 2218, 2219, 2220, 2221, 2222, 2223, 2224, - 2225, 2226, 2227, 2228, 2229, 2230, 2231, 2232, - 2233, 2234, 2235, 2236, 2237, 2238, 2239, 2240, - 2241, 2242, 2243, 2244, 1251, 1251, 1251, 1251, - 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, - 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, - 1251, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 74, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 74, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 74, 74, 74, 74, 74, 74, 74, - 74, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 74, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 0, 0, - 0, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 812, 76, 76, - 76, 76, 76, 76, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 76, 76, 76, 76, 0, 76, - 76, 76, 76, 0, 0, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 0, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 0, 76, 0, - 76, 76, 76, 76, 0, 0, 0, 76, - 0, 76, 76, 76, 76, 76, 76, 76, - 0, 0, 76, 76, 76, 76, 76, 76, - 76, 11, 12, 11, 12, 11, 12, 11, - 12, 11, 12, 11, 12, 11, 12, 1251, - 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, - 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, - 1251, 1251, 1251, 1251, 1251, 1251, 1251, 1251, - 1251, 1251, 1251, 1251, 1251, 76, 0, 0, - 0, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 0, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 0, 2026, 74, 74, 2026, 2026, 11, 12, - 74, 74, 74, 74, 0, 0, 0, 0, - 0, 74, 74, 74, 2026, 2026, 2026, 2026, - 74, 74, 74, 74, 74, 2026, 2026, 2026, - 74, 74, 74, 2026, 2026, 2026, 2026, 11, - 12, 11, 12, 11, 12, 0, 0, 0, - 0, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, - 74, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 11, 12, 11, 12, - 11, 12, 11, 12, 11, 12, 11, 12, - 11, 12, 11, 12, 11, 12, 11, 12, - 11, 12, 74, 74, 2026, 2026, 2026, 2026, - 2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, - 2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, - 2026, 74, 74, 74, 74, 74, 74, 74, - 74, 2026, 74, 74, 74, 74, 74, 74, - 74, 2026, 2026, 2026, 2026, 2026, 2026, 74, - 74, 74, 2026, 74, 74, 74, 74, 2026, - 2026, 2026, 2026, 2026, 74, 2026, 2026, 74, - 74, 11, 12, 11, 12, 2026, 74, 74, - 74, 74, 2026, 74, 2026, 2026, 2026, 74, - 74, 2026, 2026, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 2026, 2026, 2026, - 2026, 2026, 2026, 74, 74, 11, 12, 74, - 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 2026, 2026, 2245, 2026, 2026, - 2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, - 2026, 2026, 2026, 2026, 2026, 2026, 74, 2026, - 2026, 2026, 2026, 74, 74, 2026, 74, 2026, - 74, 74, 2026, 74, 2026, 2026, 2026, 2026, - 74, 74, 74, 74, 74, 2026, 2026, 74, - 74, 74, 74, 74, 74, 2026, 2026, 2026, - 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, - 2026, 2026, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 2026, 2026, 74, - 74, 74, 74, 2026, 2026, 2026, 2026, 74, - 2026, 2026, 74, 74, 2026, 2246, 2247, 2248, - 74, 74, 2026, 2026, 2026, 2026, 2026, 2026, - 2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, - 2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, - 2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, - 2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, - 2026, 2026, 2026, 2026, 2026, 74, 74, 2026, - 2026, 2026, 2026, 2026, 2026, 2026, 2026, 74, - 2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, - 2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, - 2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, - 2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, - 2026, 2026, 2026, 2026, 2026, 2026, 2026, 2026, - 74, 74, 74, 74, 74, 2249, 2250, 2026, - 74, 74, 74, 2026, 2026, 2026, 2026, 2026, - 74, 74, 74, 74, 74, 2026, 2026, 2026, - 74, 74, 74, 74, 2026, 74, 74, 74, - 2026, 2026, 2026, 2026, 2026, 74, 2026, 74, - 74, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 0, 0, 0, 0, - 0, 76, 76, 76, 76, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2251, 2252, 2253, 2254, 2255, 2256, 2257, - 2258, 2259, 2260, 2261, 2262, 2263, 2264, 2265, - 2266, 2267, 2268, 2269, 2270, 2271, 2272, 2273, - 2274, 2275, 2276, 2277, 2278, 2279, 2280, 2281, - 2282, 2283, 2284, 2285, 2286, 2287, 2288, 2289, - 2290, 2291, 2292, 2293, 2294, 2295, 2296, 2297, - 0, 2298, 2299, 2300, 2301, 2302, 2303, 2304, - 2305, 2306, 2307, 2308, 2309, 2310, 2311, 2312, - 2313, 2314, 2315, 2316, 2317, 2318, 2319, 2320, - 2321, 2322, 2323, 2324, 2325, 2326, 2327, 2328, - 2329, 2330, 2331, 2332, 2333, 2334, 2335, 2336, - 2337, 2338, 2339, 2340, 2341, 2342, 2343, 2344, - 0, 2345, 2346, 2347, 2348, 2349, 2350, 2351, - 2352, 2353, 2354, 2355, 2356, 2357, 0, 0, - 0, 0, 0, 0, 0, 213, 2358, 2359, - 213, 0, 0, 0, 0, 0, 0, 0, - 0, 2360, 2361, 2362, 2363, 2364, 2365, 2366, - 2367, 2368, 2369, 2370, 2371, 2372, 2373, 2374, - 2375, 2376, 2377, 2378, 2379, 2380, 2381, 2382, - 2383, 2384, 2385, 2386, 2387, 2388, 2389, 2390, - 2391, 2392, 2393, 2394, 2395, 2396, 2397, 2398, - 2399, 2400, 2401, 2402, 2403, 2404, 2405, 2406, - 2407, 2408, 2409, 2410, 2411, 2412, 2413, 2414, - 2415, 2416, 2417, 2418, 2419, 2420, 2421, 2422, - 2423, 2424, 2425, 2426, 2427, 2428, 2429, 2430, - 2431, 2432, 2433, 2434, 2435, 2436, 2437, 2438, - 2439, 2440, 2441, 2442, 2443, 2444, 2445, 2446, - 2447, 2448, 2449, 2450, 2451, 2452, 2453, 2454, - 2455, 2456, 2457, 2458, 2459, 213, 76, 76, - 76, 76, 76, 76, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 8, 8, 8, 8, 1251, 8, - 8, 2460, 2461, 2462, 2463, 2464, 2465, 2466, - 2467, 2468, 2469, 2470, 2471, 2472, 2473, 2474, - 2475, 2476, 2477, 2478, 2479, 2480, 2481, 2482, - 2483, 2484, 2485, 2486, 2487, 2488, 2489, 2490, - 2491, 2492, 2493, 2494, 2495, 2496, 2497, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 2498, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 0, 339, 339, 339, 339, 339, 339, 339, - 0, 339, 339, 339, 339, 339, 339, 339, - 0, 339, 339, 339, 339, 339, 339, 339, - 0, 339, 339, 339, 339, 339, 339, 339, - 0, 339, 339, 339, 339, 339, 339, 339, - 0, 339, 339, 339, 339, 339, 339, 339, - 0, 339, 339, 339, 339, 339, 339, 339, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 8, 8, 79, 91, 79, 91, 8, - 8, 8, 79, 91, 8, 79, 91, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 1030, 0, 0, 0, 0, 79, 91, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 0, 76, 76, 76, 76, - 2499, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 2500, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2501, 2502, 2503, 2504, 2505, 2506, 2507, - 2508, 2509, 2510, 2511, 2512, 2513, 2514, 2515, - 2516, 2517, 2518, 2519, 2520, 2521, 2522, 2523, - 2524, 2525, 2526, 2527, 2528, 2529, 2530, 2531, - 2532, 2533, 2534, 2535, 2536, 2537, 2538, 2539, - 2540, 2541, 2542, 2543, 2544, 2545, 2546, 2547, - 2548, 2549, 2550, 2551, 2552, 2553, 2554, 2555, - 2556, 2557, 2558, 2559, 2560, 2561, 2562, 2563, - 2564, 2565, 2566, 2567, 2568, 2569, 2570, 2571, - 2572, 2573, 2574, 2575, 2576, 2577, 2578, 2579, - 2580, 2581, 2582, 2583, 2584, 2585, 2586, 2587, - 2588, 2589, 2590, 2591, 2592, 2593, 2594, 2595, - 2596, 2597, 2598, 2599, 2600, 2601, 2602, 2603, - 2604, 2605, 2606, 2607, 2608, 2609, 2610, 2611, - 2612, 2613, 2614, 2615, 2616, 2617, 2618, 2619, - 2620, 2621, 2622, 2623, 2624, 2625, 2626, 2627, - 2628, 2629, 2630, 2631, 2632, 2633, 2634, 2635, - 2636, 2637, 2638, 2639, 2640, 2641, 2642, 2643, - 2644, 2645, 2646, 2647, 2648, 2649, 2650, 2651, - 2652, 2653, 2654, 2655, 2656, 2657, 2658, 2659, - 2660, 2661, 2662, 2663, 2664, 2665, 2666, 2667, - 2668, 2669, 2670, 2671, 2672, 2673, 2674, 2675, - 2676, 2677, 2678, 2679, 2680, 2681, 2682, 2683, - 2684, 2685, 2686, 2687, 2688, 2689, 2690, 2691, - 2692, 2693, 2694, 2695, 2696, 2697, 2698, 2699, - 2700, 2701, 2702, 2703, 2704, 2705, 2706, 2707, - 2708, 2709, 2710, 2711, 2712, 2713, 2714, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 0, 0, 0, - 0, 2715, 8, 8, 8, 76, 507, 339, - 1249, 11, 12, 11, 12, 11, 12, 11, - 12, 11, 12, 76, 76, 11, 12, 11, - 12, 11, 12, 11, 12, 1030, 11, 12, - 12, 76, 1249, 1249, 1249, 1249, 1249, 1249, - 1249, 1249, 1249, 2716, 1032, 536, 1031, 2717, - 2717, 1030, 507, 507, 507, 507, 507, 2718, - 76, 2719, 2720, 2721, 507, 339, 8, 76, - 76, 0, 339, 339, 339, 339, 339, 2722, - 339, 339, 339, 339, 2723, 2724, 2725, 2726, - 2727, 2728, 2729, 2730, 2731, 2732, 2733, 2734, - 2735, 2736, 2737, 2738, 2739, 2740, 2741, 2742, - 2743, 2744, 2745, 2746, 339, 2747, 2748, 2749, - 2750, 2751, 2752, 339, 339, 339, 339, 339, - 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2760, - 2761, 2762, 2763, 2764, 2765, 2766, 2767, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 2768, 339, 339, - 0, 0, 2769, 2770, 2771, 2772, 2773, 2774, - 2775, 1030, 339, 339, 339, 339, 339, 2776, - 339, 339, 339, 339, 2777, 2778, 2779, 2780, - 2781, 2782, 2783, 2784, 2785, 2786, 2787, 2788, - 2789, 2790, 2791, 2792, 2793, 2794, 2795, 2796, - 2797, 2798, 2799, 2800, 339, 2801, 2802, 2803, - 2804, 2805, 2806, 339, 339, 339, 339, 339, - 2807, 2808, 2809, 2810, 2811, 2812, 2813, 2814, - 2815, 2816, 2817, 2818, 2819, 2820, 2821, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 2822, 2823, 2824, 2825, 339, 2826, 339, 339, - 2827, 2828, 2829, 2830, 8, 507, 2831, 2832, - 2833, 0, 0, 0, 0, 0, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 0, 0, - 0, 0, 2834, 2835, 2836, 2837, 2838, 2839, - 2840, 2841, 2842, 2843, 2844, 2845, 2846, 2847, - 2848, 2849, 2850, 2851, 2852, 2853, 2854, 2855, - 2856, 2857, 2858, 2859, 2860, 2861, 2862, 2863, - 2864, 2865, 2866, 2867, 2868, 2869, 2870, 2871, - 2872, 2873, 2874, 2875, 2876, 2877, 2878, 2879, - 2880, 2881, 2882, 2883, 2884, 2885, 2886, 2887, - 2888, 2889, 2890, 2891, 2892, 2893, 2894, 2895, - 2896, 2897, 2898, 2899, 2900, 2901, 2902, 2903, - 2904, 2905, 2906, 2907, 2908, 2909, 2910, 2911, - 2912, 2913, 2914, 2915, 2916, 2917, 2918, 2919, - 2920, 2921, 2922, 2923, 2924, 2925, 2926, 2927, - 0, 812, 812, 2928, 2929, 2930, 2931, 2932, - 2933, 2934, 2935, 2936, 2937, 2938, 2939, 2940, - 2941, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 0, 0, 0, 0, 0, 0, 0, - 0, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 2942, 2943, 2944, 2945, 2946, 2947, 2948, - 2949, 2950, 2951, 2952, 2953, 2954, 2955, 2956, - 2957, 2958, 2959, 2960, 2961, 2962, 2963, 2964, - 2965, 2966, 2967, 2968, 2969, 2970, 2971, 2972, - 0, 2973, 2974, 2975, 2976, 2977, 2978, 2979, - 2980, 2981, 2982, 2983, 2984, 2985, 2986, 2987, - 2988, 2989, 2990, 2991, 2992, 2993, 2994, 2995, - 2996, 2997, 2998, 2999, 3000, 3001, 3002, 3003, - 3004, 3005, 3006, 3007, 3008, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 3009, 3010, 3011, 3012, 3013, 3014, 3015, - 3016, 3017, 3018, 3019, 3020, 3021, 3022, 3023, - 3024, 3025, 3026, 3027, 3028, 3029, 3030, 3031, - 3032, 3033, 3034, 3035, 3036, 3037, 3038, 3039, - 3040, 3041, 3042, 3043, 3044, 3045, 3046, 3047, - 3048, 3049, 3050, 3051, 3052, 3053, 3054, 3055, - 812, 3056, 3057, 3058, 3059, 3060, 3061, 3062, - 3063, 3064, 3065, 3066, 3067, 3068, 3069, 3070, - 3071, 3072, 3073, 3074, 3075, 3076, 3077, 3078, - 3079, 3080, 3081, 3082, 3083, 3084, 3085, 3086, - 3087, 3088, 3089, 3090, 3091, 3092, 3093, 3094, - 3095, 3096, 3097, 3098, 3099, 3100, 3101, 3102, - 3103, 3104, 3105, 3106, 3107, 3108, 3109, 3110, - 3111, 3112, 3113, 3114, 3115, 3116, 3117, 3118, - 3119, 3120, 3121, 3122, 3123, 3124, 3125, 3126, - 3127, 3128, 3129, 3130, 3131, 3132, 3133, 3134, - 3135, 3136, 3137, 3138, 3139, 3140, 3141, 3142, - 3143, 3144, 3145, 3146, 3147, 3148, 3149, 3150, - 3151, 3152, 3153, 3154, 3155, 3156, 3157, 3158, - 3159, 3160, 3161, 3162, 3163, 3164, 3165, 3166, - 3167, 3168, 3169, 3170, 3171, 3172, 3173, 3174, - 3175, 3176, 3177, 3178, 3179, 3180, 3181, 3182, - 0, 3183, 3184, 3185, 3186, 3187, 3188, 3189, - 3190, 3191, 3192, 3193, 3194, 3195, 3196, 3197, - 3198, 3199, 3200, 3201, 3202, 3203, 3204, 3205, - 3206, 3207, 3208, 3209, 3210, 3211, 3212, 3213, - 3214, 3215, 3216, 3217, 3218, 3219, 3220, 3221, - 3222, 3223, 3224, 3225, 3226, 3227, 3228, 3229, - 3230, 3231, 3232, 3233, 3234, 3235, 3236, 3237, - 3238, 3239, 3240, 3241, 3242, 3243, 3244, 3245, - 3246, 3247, 3248, 3249, 3250, 3251, 3252, 3253, - 3254, 3255, 3256, 3257, 3258, 3259, 3260, 3261, - 3262, 3263, 3264, 3265, 3266, 3267, 3268, 3269, - 3270, 3271, 3272, 3273, 3274, 3275, 3276, 3277, - 3278, 3279, 3280, 3281, 3282, 3283, 3284, 3285, - 3286, 3287, 3288, 3289, 3290, 3291, 3292, 3293, - 3294, 3295, 3296, 3297, 3298, 3299, 3300, 3301, - 3302, 3303, 3304, 3305, 3306, 3307, 3308, 3309, - 3310, 3311, 3312, 3313, 3314, 3315, 3316, 3317, - 3318, 3319, 3320, 3321, 3322, 3323, 3324, 3325, - 3326, 3327, 3328, 3329, 3330, 3331, 3332, 3333, - 3334, 3335, 3336, 3337, 3338, 3339, 3340, 3341, - 3342, 3343, 3344, 3345, 3346, 3347, 3348, 3349, - 3350, 3351, 3352, 3353, 3354, 3355, 3356, 3357, - 3358, 3359, 3360, 3361, 3362, 3363, 3364, 3365, - 3366, 3367, 3368, 3369, 3370, 3371, 3372, 3373, - 3374, 3375, 3376, 3377, 3378, 3379, 3380, 3381, - 3382, 3383, 3384, 3385, 3386, 3387, 3388, 3389, - 3390, 3391, 3392, 3393, 3394, 3395, 3396, 3397, - 3398, 3399, 3400, 3401, 3402, 3403, 3404, 3405, - 3406, 3407, 3408, 3409, 3410, 3411, 3412, 3413, - 3414, 3415, 3416, 3417, 3418, 3419, 3420, 3421, - 3422, 3423, 3424, 3425, 3426, 3427, 3428, 3429, - 3430, 3431, 3432, 3433, 3434, 3435, 3436, 3437, - 3438, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 507, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 0, 0, - 0, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 46, - 46, 46, 46, 46, 46, 46, 46, 46, - 506, 506, 506, 506, 0, 0, 0, 0, - 0, 46, 46, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 339, 339, 1252, 339, 339, 339, 1101, - 339, 339, 339, 339, 1090, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 1093, 1093, 1090, 1090, - 1093, 76, 76, 76, 76, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 8, 8, 8, - 8, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3439, 3439, 3439, 3439, 3439, 3439, 3439, - 3439, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3441, 3442, 3443, 3444, 3445, 3446, 3447, - 3448, 3448, 3449, 3450, 3451, 3452, 3453, 3454, - 3455, 3456, 3457, 3458, 3459, 3460, 3461, 3462, - 3463, 3464, 3465, 3466, 3467, 3468, 3469, 3470, - 3471, 3472, 3473, 3474, 3475, 3476, 3477, 3478, - 3479, 3480, 3481, 3482, 3483, 3484, 3485, 3486, - 3487, 3488, 3489, 3490, 3491, 3492, 3493, 3494, - 3495, 3496, 3497, 3498, 3499, 3500, 3501, 3502, - 3503, 3504, 3505, 3506, 3507, 3508, 3509, 3510, - 3511, 3512, 3513, 3514, 3515, 3516, 3517, 3518, - 3519, 3520, 3521, 3522, 3523, 3524, 3525, 3526, - 3527, 3528, 3529, 3530, 3531, 3460, 3532, 3533, - 3534, 3535, 3536, 3537, 3538, 3539, 3540, 3541, - 3542, 3543, 3544, 3545, 3546, 3547, 3548, 3549, - 3550, 3551, 3552, 3553, 3554, 3555, 3556, 3557, - 3558, 3559, 3560, 3561, 3562, 3563, 3564, 3565, - 3566, 3567, 3568, 3569, 3570, 3571, 3572, 3573, - 3574, 3575, 3576, 3577, 3578, 3579, 3580, 3581, - 3582, 3583, 3584, 3585, 3586, 3587, 3588, 3589, - 3590, 3591, 3592, 3593, 3594, 3595, 3596, 3597, - 3598, 3599, 3550, 3600, 3601, 3602, 3603, 3604, - 3605, 3606, 3607, 3534, 3608, 3609, 3610, 3611, - 3612, 3613, 3614, 3615, 3616, 3617, 3618, 3619, - 3620, 3621, 3622, 3623, 3624, 3625, 3626, 3627, - 3460, 3628, 3629, 3630, 3631, 3632, 3633, 3634, - 3635, 3636, 3637, 3638, 3639, 3640, 3641, 3642, - 3643, 3644, 3645, 3646, 3647, 3648, 3649, 3650, - 3651, 3652, 3653, 3654, 3536, 3655, 3656, 3657, - 3658, 3659, 3660, 3661, 3662, 3663, 3664, 3665, - 3666, 3667, 3668, 3669, 3670, 3671, 3672, 3673, - 3674, 3675, 3676, 3677, 3678, 3679, 3680, 3681, - 3682, 3683, 3684, 3685, 3686, 3687, 3688, 3689, - 3690, 3691, 3692, 3693, 3694, 3695, 3696, 3697, - 3698, 3699, 3700, 3701, 3702, 3703, 3704, 339, - 339, 3705, 339, 3706, 339, 339, 3707, 3708, - 3709, 3710, 3711, 3712, 3713, 3714, 3715, 3716, - 339, 3717, 339, 3718, 339, 339, 3719, 3720, - 339, 339, 339, 3721, 3722, 3723, 3724, 0, - 0, 3725, 3726, 3727, 3728, 3729, 3730, 3731, - 3732, 3733, 3734, 3735, 3736, 3737, 3738, 3739, - 3740, 3741, 3742, 3743, 3744, 3745, 3746, 3747, - 3748, 3749, 3750, 3751, 3752, 3753, 3754, 3755, - 3756, 3757, 3758, 3759, 3760, 3761, 3762, 3763, - 3589, 3764, 3765, 3766, 3767, 3768, 3769, 3769, - 3770, 3771, 3772, 3773, 3774, 3775, 3776, 3777, - 3719, 3778, 3779, 3780, 0, 0, 0, 0, - 0, 3781, 3782, 3783, 3784, 3785, 3786, 3787, - 3788, 3731, 3789, 3790, 3791, 3705, 3792, 3793, - 3794, 3795, 3796, 3797, 3798, 3799, 3800, 3801, - 3802, 3803, 3740, 3804, 3741, 3805, 3806, 3807, - 3808, 3809, 3706, 3481, 3810, 3811, 3812, 3551, - 3638, 3813, 3814, 3748, 3815, 3749, 3816, 3817, - 3818, 3708, 3819, 3820, 3821, 3822, 3823, 3709, - 3824, 3825, 3826, 3827, 3828, 3829, 3763, 3830, - 3831, 3589, 3832, 3767, 3833, 3834, 3835, 3836, - 3837, 3772, 3838, 3718, 3839, 3773, 3532, 3840, - 3774, 3841, 3776, 3842, 3843, 3844, 3845, 3846, - 3778, 3714, 3847, 3779, 3848, 3780, 3849, 3448, - 3850, 3851, 3852, 3853, 3854, 3855, 3856, 3857, - 3858, 3859, 3860, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 3861, 3862, 3863, 3864, 3865, 3866, 3867, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3868, 3869, 3870, 3871, - 3872, 0, 0, 0, 0, 0, 3873, 3874, - 3875, 3876, 3877, 3878, 3879, 3880, 3881, 3882, - 3883, 3884, 3885, 3886, 3887, 3888, 3889, 3890, - 3891, 3892, 3893, 3894, 3895, 3896, 3897, 3898, - 0, 3899, 3900, 3901, 3902, 3903, 0, 3904, - 0, 3905, 3906, 0, 3907, 3908, 0, 3909, - 3910, 3911, 3912, 3913, 3914, 3915, 3916, 3917, - 3918, 3919, 3920, 3921, 3922, 3923, 3924, 3925, - 3926, 3927, 3928, 3929, 3930, 3931, 3932, 3933, - 3934, 3935, 3936, 3937, 3938, 3939, 3940, 3941, - 3942, 3943, 3944, 3945, 3946, 3947, 3948, 3949, - 3950, 3951, 3952, 3953, 3954, 3955, 3956, 3957, - 3958, 3959, 3960, 3961, 3962, 3963, 3964, 3965, - 3966, 3967, 3968, 3969, 3970, 3971, 3972, 3973, - 3974, 3975, 3976, 3977, 3978, 3979, 3980, 3981, - 3982, 3983, 3984, 3985, 3986, 3987, 3988, 3989, - 3990, 3991, 3992, 3993, 3994, 3995, 3996, 3997, - 3998, 3999, 4000, 4001, 4002, 4003, 4004, 4005, - 4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013, - 4014, 4015, 4016, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 4017, 4018, 4019, 4020, - 4021, 4022, 4023, 4024, 4025, 4026, 4027, 4028, - 4029, 4030, 4031, 4032, 4033, 4034, 4035, 4036, - 4037, 4038, 4039, 4040, 4041, 4042, 4043, 4044, - 4045, 4046, 4047, 4048, 4049, 4050, 4051, 4052, - 4053, 4054, 4055, 4056, 4057, 4058, 4059, 4060, - 4061, 4062, 4063, 4064, 4055, 4065, 4066, 4067, - 4068, 4069, 4070, 4071, 4072, 4073, 4074, 4075, - 4076, 4077, 4078, 4079, 4080, 4081, 4082, 4083, - 4084, 4085, 4086, 4087, 4088, 4089, 4090, 4091, - 4092, 4093, 4094, 4095, 4096, 4097, 4098, 4099, - 4100, 4101, 4102, 4103, 4104, 4105, 4106, 4107, - 4108, 4109, 4110, 4111, 4112, 4113, 4114, 4115, - 4116, 4117, 4118, 4119, 4120, 4121, 4122, 4123, - 4124, 4125, 4126, 4127, 4128, 4129, 4130, 4131, - 4132, 4133, 4134, 4135, 4136, 4137, 4138, 4139, - 4140, 4141, 4142, 4143, 4144, 4145, 4146, 4147, - 4148, 4149, 4150, 4151, 4152, 4153, 4154, 4155, - 4156, 4157, 4158, 4159, 4160, 4161, 4162, 4163, - 4164, 4056, 4165, 4166, 4167, 4168, 4169, 4170, - 4171, 4172, 4173, 4174, 4175, 4176, 4177, 4178, - 4179, 4180, 4181, 4182, 4183, 4184, 4185, 4186, - 4187, 4188, 4189, 4190, 4191, 4192, 4193, 4194, - 4195, 4196, 4197, 4198, 4199, 4200, 4201, 4202, - 4203, 4204, 4205, 4206, 4207, 4208, 4209, 4210, - 4211, 4212, 4213, 4214, 4215, 4216, 4217, 4218, - 4219, 4220, 4221, 4222, 4223, 4224, 4225, 4226, - 4227, 4228, 4229, 4230, 4231, 4232, 4233, 4234, - 4235, 4236, 4237, 4238, 4239, 4240, 4241, 4242, - 4243, 4244, 4245, 4246, 4247, 4248, 4249, 4250, - 4251, 4252, 4253, 4254, 4255, 4256, 4257, 4258, - 4259, 4260, 4261, 4262, 4263, 4264, 4265, 4266, - 4267, 4268, 4269, 4270, 4271, 4272, 4273, 4274, - 4275, 4276, 4277, 4278, 4279, 4280, 4281, 4282, - 4283, 4284, 4285, 4286, 4287, 4288, 4289, 4290, - 4291, 4292, 4293, 4294, 4295, 4296, 4297, 4298, - 4299, 4300, 4301, 4302, 4303, 4304, 4305, 4306, - 4307, 4308, 4309, 4310, 4311, 4312, 4313, 4314, - 4315, 4316, 4317, 4318, 4319, 4320, 4321, 4322, - 4323, 4324, 4325, 4326, 4327, 4328, 4329, 4330, - 4331, 4332, 4333, 4334, 4335, 4336, 4337, 4338, - 4339, 4340, 4341, 4342, 4343, 4344, 4345, 4346, - 4347, 4348, 4349, 4350, 4351, 4352, 4353, 4354, - 4355, 4356, 4357, 4358, 4359, 4360, 4361, 4362, - 4363, 4364, 4365, 4366, 4367, 4368, 4369, 4370, - 4371, 4372, 4373, 4374, 4375, 4376, 4377, 4378, - 4379, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 4380, 4381, 4382, 4383, 4384, 4385, 4386, - 4387, 4388, 4389, 4390, 4391, 4392, 4393, 4394, - 4395, 4396, 4397, 4398, 4399, 4400, 4401, 4402, - 4403, 4404, 4405, 4406, 4407, 4408, 4409, 4410, - 4411, 4412, 4413, 4414, 4415, 4416, 4417, 4418, - 4419, 4420, 4421, 4422, 4423, 4424, 4425, 4426, - 4427, 4428, 4429, 4430, 4431, 4432, 4433, 4434, - 4435, 4436, 4437, 4438, 4439, 4440, 4441, 4442, - 4443, 0, 0, 4444, 4445, 4446, 4447, 4448, - 4449, 4450, 4451, 4452, 4453, 4454, 4455, 4456, - 4457, 4458, 4459, 4460, 4461, 4462, 4463, 4464, - 4465, 4466, 4467, 4468, 4469, 4470, 4471, 4472, - 4473, 4474, 4475, 4476, 4477, 4478, 4479, 4480, - 4481, 4482, 4483, 4484, 4485, 4486, 4487, 4488, - 4489, 4490, 4491, 4492, 4493, 4494, 4495, 4496, - 4497, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 4498, 4499, 4500, 4501, 4502, 4503, 4504, - 4505, 4506, 4507, 4508, 4509, 4510, 76, 0, - 0, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 4511, 4512, 4513, 4514, 4515, 4516, 4517, - 4518, 4519, 4520, 0, 0, 0, 0, 0, - 0, 524, 524, 524, 524, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 4521, 4522, 4523, 4524, 4524, 4525, 4526, - 4527, 4528, 4529, 4530, 4531, 4532, 4533, 4534, - 4535, 4536, 4537, 4538, 4539, 4540, 8, 8, - 4541, 4542, 4543, 4543, 4543, 4543, 4544, 4544, - 4544, 4545, 4546, 4547, 0, 4548, 4549, 4550, - 4551, 4552, 4553, 4554, 4555, 4556, 4557, 4558, - 4559, 4560, 4561, 4562, 4563, 4564, 4565, 4566, - 0, 4567, 4568, 4569, 4570, 0, 0, 0, - 0, 4571, 4572, 4573, 1054, 4574, 0, 4575, - 4576, 4577, 4578, 4579, 4580, 4581, 4582, 4583, - 4584, 4585, 4586, 4587, 4588, 4589, 4590, 4591, - 4592, 4593, 4594, 4595, 4596, 4597, 4598, 4599, - 4600, 4601, 4602, 4603, 4604, 4605, 4606, 4607, - 4608, 4609, 4610, 4611, 4612, 4613, 4614, 4615, - 4616, 4617, 4618, 4619, 4620, 4621, 4622, 4623, - 4624, 4625, 4626, 4627, 4628, 4629, 4630, 4631, - 4632, 4633, 4634, 4635, 4636, 4637, 4638, 4639, - 4640, 4641, 4642, 4643, 4644, 4645, 4646, 4647, - 4648, 4649, 4650, 4651, 4652, 4653, 4654, 4655, - 4656, 4657, 4658, 4659, 4660, 4661, 4662, 4663, - 4664, 4665, 4666, 4667, 4668, 4669, 4670, 4671, - 4672, 4673, 4674, 4675, 4676, 4677, 4678, 4679, - 4680, 4681, 4682, 4683, 4684, 4685, 4686, 4687, - 4688, 4689, 4690, 4691, 4692, 4693, 4694, 4695, - 4696, 4697, 4698, 4699, 4700, 4701, 4702, 4703, - 4704, 4705, 4706, 4707, 4708, 4709, 0, 0, - 80, 0, 4710, 4711, 4712, 4713, 4714, 4715, - 4716, 4717, 4718, 4719, 4720, 4721, 4722, 4723, - 4724, 4725, 4726, 4727, 4728, 4729, 4730, 4731, - 4732, 4733, 4734, 4735, 4736, 4737, 4738, 4739, - 4740, 4741, 4742, 4743, 4744, 4745, 4746, 4747, - 4748, 4749, 4750, 4751, 4752, 4753, 4754, 4755, - 4756, 4757, 4758, 4759, 4760, 4761, 4762, 4763, - 4764, 4765, 4766, 4767, 4768, 4769, 4770, 4771, - 4772, 4773, 4774, 4775, 4776, 4777, 4778, 4779, - 4780, 4781, 4782, 4783, 4784, 4785, 4786, 4787, - 4788, 4789, 4790, 4791, 4792, 4793, 4794, 4795, - 4796, 4797, 4798, 4799, 4800, 4801, 4802, 4803, - 4804, 4805, 4806, 4807, 4808, 4809, 4810, 4811, - 4812, 4813, 4814, 4815, 4816, 4817, 4818, 4819, - 4820, 4821, 4822, 4823, 4824, 4825, 4826, 4827, - 4828, 4829, 4830, 4831, 4832, 4833, 4834, 4835, - 4836, 4837, 4838, 4839, 4840, 4841, 4842, 4843, - 4844, 4845, 4846, 4847, 4848, 4849, 4850, 4851, - 4852, 4853, 4854, 4855, 4856, 4857, 4858, 4859, - 4860, 4861, 4862, 4863, 4864, 4865, 4866, 4867, - 4868, 4869, 4870, 4871, 4872, 4873, 4874, 4875, - 4876, 4877, 4878, 4879, 4880, 4881, 4882, 4883, - 4884, 4885, 4886, 4887, 4888, 4889, 4890, 4891, - 4892, 4893, 4894, 4895, 4896, 4897, 4898, 4899, - 0, 0, 0, 4900, 4901, 4902, 4903, 4904, - 4905, 0, 0, 4906, 4907, 4908, 4909, 4910, - 4911, 0, 0, 4912, 4913, 4914, 4915, 4916, - 4917, 0, 0, 4918, 4919, 4920, 0, 0, - 0, 4921, 4922, 4923, 4924, 4925, 4926, 4927, - 0, 4928, 4929, 4930, 4931, 4932, 4933, 4934, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 4935, 4935, 4935, 76, 76, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 0, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 0, 339, 339, 0, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 0, 0, 0, 0, - 0, 990, 8, 812, 0, 0, 0, 0, - 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, - 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, - 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, - 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, - 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, - 1120, 1120, 1120, 1120, 1120, 0, 0, 0, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 4936, 4936, 4936, 4936, 4936, 4936, 4936, - 4936, 4936, 4936, 4936, 4936, 4936, 4936, 4936, - 4936, 4936, 4936, 4936, 4936, 4936, 4936, 4936, - 4936, 4936, 4936, 4936, 4936, 4936, 4936, 4936, - 4936, 4936, 4936, 4936, 4936, 4936, 4936, 4936, - 4936, 4936, 4936, 4936, 4936, 4936, 4936, 4936, - 4936, 4936, 4936, 4936, 4936, 4936, 1251, 1251, - 1251, 1251, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 1251, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 0, 1120, 1120, 1120, 1120, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 1249, 339, 339, 339, 339, 339, - 339, 339, 339, 1249, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 0, - 990, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 0, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 990, 1249, 1249, 1249, 1249, 1249, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 4937, 4938, 4939, 4940, 4941, 4942, 4943, - 4944, 4945, 4946, 4947, 4948, 4949, 4950, 4951, - 4952, 4953, 4954, 4955, 4956, 4957, 4958, 4959, - 4960, 4961, 4962, 4963, 4964, 4965, 4966, 4967, - 4968, 4969, 4970, 4971, 4972, 4973, 4974, 4975, - 4976, 4977, 4978, 4979, 4980, 4981, 4982, 4983, - 4984, 4985, 4986, 4987, 4988, 4989, 4990, 4991, - 4992, 4993, 4994, 4995, 4996, 4997, 4998, 4999, - 5000, 5001, 5002, 5003, 5004, 5005, 5006, 5007, - 5008, 5009, 5010, 5011, 5012, 5013, 5014, 5015, - 5016, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 0, - 0, 1110, 1110, 1110, 1110, 1110, 1110, 1110, - 1110, 1110, 1110, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1050, 1050, 1050, 1050, 1050, 1050, 0, - 0, 1050, 0, 1050, 1050, 1050, 1050, 1050, - 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, - 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, - 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, - 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, - 1050, 1050, 1050, 1050, 1050, 1050, 1050, 0, - 1050, 1050, 0, 0, 0, 1050, 0, 0, - 1050, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1050, 1050, 1050, 1050, 1050, 1050, 1050, - 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, - 1050, 1050, 1050, 1050, 1050, 1050, 1050, 5017, - 5017, 5017, 5017, 0, 0, 0, 0, 0, - 8, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1050, 1090, 1090, 1090, 0, 1090, 1090, - 0, 0, 0, 0, 0, 1090, 537, 1090, - 524, 1050, 1050, 1050, 1050, 0, 1050, 1050, - 1050, 0, 1050, 1050, 1050, 1050, 1050, 1050, - 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, - 1050, 1050, 1050, 1050, 1050, 1050, 1050, 1050, - 1050, 1050, 1050, 1050, 1050, 0, 0, 0, - 0, 524, 550, 537, 0, 0, 0, 0, - 1101, 5017, 5017, 5017, 5017, 5017, 5017, 5017, - 5017, 0, 0, 0, 0, 0, 0, 0, - 0, 1046, 1046, 1046, 1046, 1046, 1046, 1046, - 1046, 1046, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1249, 1249, 1249, 1249, 1249, 1249, 1249, - 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, - 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, - 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, - 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, - 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, - 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, - 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, - 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, - 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, - 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, - 1249, 1249, 1249, 1249, 1249, 1249, 1249, 1249, - 1249, 1249, 1249, 1249, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 990, 990, 990, 990, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 0, 0, 0, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 5018, 5019, 812, 812, 812, 812, 812, 5020, - 5021, 5022, 5023, 5024, 5025, 5026, 5027, 5028, - 550, 550, 550, 812, 812, 812, 5029, 5030, - 5031, 5032, 5033, 5034, 80, 80, 80, 80, - 80, 80, 80, 80, 537, 537, 537, 537, - 537, 537, 537, 537, 812, 812, 524, 524, - 524, 524, 524, 537, 537, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 524, 524, 524, 524, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 5035, 5036, 5037, 5038, 5039, 5040, - 5041, 5042, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 812, - 812, 812, 812, 812, 812, 812, 812, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 524, 524, 524, 76, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 76, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1120, 1120, 1120, 1120, 1120, 1120, 1120, - 1120, 1120, 1120, 1120, 1120, 1120, 1120, 1120, - 1120, 1120, 1120, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 5043, 1945, 1920, 1963, 1947, 1948, 5044, - 1927, 1930, 5045, 5046, 1931, 1950, 1933, 5047, - 1935, 1936, 1937, 5048, 5049, 5050, 5051, 5052, - 5053, 5054, 1941, 5055, 5056, 5057, 1964, 1946, - 5058, 1926, 1928, 1956, 1965, 5059, 1932, 5060, - 5061, 1951, 5062, 5063, 5064, 5065, 5066, 5067, - 5068, 5069, 5070, 5071, 5072, 5043, 1945, 1920, - 1963, 1947, 1948, 5044, 1927, 1930, 5045, 5046, - 1931, 1950, 1933, 5047, 1935, 1936, 1937, 5048, - 5049, 5050, 5051, 5052, 5053, 5054, 1941, 5055, - 5056, 5057, 1964, 1946, 5058, 1926, 0, 1956, - 1965, 5059, 1932, 5060, 5061, 1951, 5062, 5063, - 5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, - 5072, 5043, 1945, 1920, 1963, 1947, 1948, 5044, - 1927, 1930, 5045, 5046, 1931, 1950, 1933, 5047, - 1935, 1936, 1937, 5048, 5049, 5050, 5051, 5052, - 5053, 5054, 1941, 5055, 5056, 5057, 1964, 1946, - 5058, 1926, 1928, 1956, 1965, 5059, 1932, 5060, - 5061, 1951, 5062, 5063, 5064, 5065, 5066, 5067, - 5068, 5069, 5070, 5071, 5072, 5043, 0, 1920, - 1963, 0, 0, 5044, 0, 0, 5045, 5046, - 0, 0, 1933, 5047, 1935, 1936, 0, 5048, - 5049, 5050, 5051, 5052, 5053, 5054, 1941, 5055, - 5056, 5057, 1964, 0, 5058, 0, 1928, 1956, - 1965, 5059, 1932, 5060, 5061, 0, 5062, 5063, - 5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, - 5072, 5043, 1945, 1920, 1963, 1947, 1948, 5044, - 1927, 1930, 5045, 5046, 1931, 1950, 1933, 5047, - 1935, 1936, 1937, 5048, 5049, 5050, 5051, 5052, - 5053, 5054, 1941, 5055, 5056, 5057, 1964, 1946, - 5058, 1926, 1928, 1956, 1965, 5059, 1932, 5060, - 5061, 1951, 5062, 5063, 5064, 5065, 5066, 5067, - 5068, 5069, 5070, 5071, 5072, 5043, 1945, 0, - 1963, 1947, 1948, 5044, 0, 0, 5045, 5046, - 1931, 1950, 1933, 5047, 1935, 1936, 0, 5048, - 5049, 5050, 5051, 5052, 5053, 5054, 0, 5055, - 5056, 5057, 1964, 1946, 5058, 1926, 1928, 1956, - 1965, 5059, 1932, 5060, 5061, 1951, 5062, 5063, - 5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, - 5072, 5043, 1945, 0, 1963, 1947, 1948, 5044, - 0, 1930, 5045, 5046, 1931, 1950, 0, 5047, - 0, 0, 0, 5048, 5049, 5050, 5051, 5052, - 5053, 5054, 0, 5055, 5056, 5057, 1964, 1946, - 5058, 1926, 1928, 1956, 1965, 5059, 1932, 5060, - 5061, 1951, 5062, 5063, 5064, 5065, 5066, 5067, - 5068, 5069, 5070, 5071, 5072, 5043, 1945, 1920, - 1963, 1947, 1948, 5044, 1927, 1930, 5045, 5046, - 1931, 1950, 1933, 5047, 1935, 1936, 1937, 5048, - 5049, 5050, 5051, 5052, 5053, 5054, 1941, 5055, - 5056, 5057, 1964, 1946, 5058, 1926, 1928, 1956, - 1965, 5059, 1932, 5060, 5061, 1951, 5062, 5063, - 5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, - 5072, 5043, 1945, 1920, 1963, 1947, 1948, 5044, - 1927, 1930, 5045, 5046, 1931, 1950, 1933, 5047, - 1935, 1936, 1937, 5048, 5049, 5050, 5051, 5052, - 5053, 5054, 1941, 5055, 5056, 5057, 1964, 1946, - 5058, 1926, 1928, 1956, 1965, 5059, 1932, 5060, - 5061, 1951, 5062, 5063, 5064, 5065, 5066, 5067, - 5068, 5069, 5070, 5071, 5072, 5043, 1945, 1920, - 1963, 1947, 1948, 5044, 1927, 1930, 5045, 5046, - 1931, 1950, 1933, 5047, 1935, 1936, 1937, 5048, - 5049, 5050, 5051, 5052, 5053, 5054, 1941, 5055, - 5056, 5057, 1964, 1946, 5058, 1926, 1928, 1956, - 1965, 5059, 1932, 5060, 5061, 1951, 5062, 5063, - 5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, - 5072, 5043, 1945, 1920, 1963, 1947, 1948, 5044, - 1927, 1930, 5045, 5046, 1931, 1950, 1933, 5047, - 1935, 1936, 1937, 5048, 5049, 5050, 5051, 5052, - 5053, 5054, 1941, 5055, 5056, 5057, 1964, 1946, - 5058, 1926, 1928, 1956, 1965, 5059, 1932, 5060, - 5061, 1951, 5062, 5063, 5064, 5065, 5066, 5067, - 5068, 5069, 5070, 5071, 5072, 5043, 1945, 1920, - 1963, 1947, 1948, 5044, 1927, 1930, 5045, 5046, - 1931, 1950, 1933, 5047, 1935, 1936, 1937, 5048, - 5049, 5050, 5051, 5052, 5053, 5054, 1941, 5055, - 5056, 5057, 1964, 1946, 5058, 1926, 1928, 1956, - 1965, 5059, 1932, 5060, 5061, 1951, 5062, 5063, - 5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, - 5072, 5043, 1945, 1920, 1963, 1947, 1948, 5044, - 1927, 1930, 5045, 5046, 1931, 1950, 1933, 5047, - 1935, 1936, 1937, 5048, 5049, 5050, 5051, 5052, - 5053, 5054, 1941, 5055, 5056, 5057, 1964, 1946, - 5058, 1926, 1928, 1956, 1965, 5059, 1932, 5060, - 5061, 1951, 5062, 5063, 5064, 5065, 5066, 5067, - 5068, 5069, 5070, 5071, 5072, 5073, 5074, 0, - 0, 5075, 5076, 1960, 5077, 5078, 5079, 5080, - 5081, 5082, 5083, 5084, 5085, 5086, 5087, 5088, - 1961, 5089, 5090, 5091, 5092, 5093, 5094, 5095, - 5096, 5097, 5098, 5099, 5100, 1959, 5101, 5102, - 5103, 5104, 5105, 5106, 5107, 5108, 5109, 5110, - 5111, 5112, 1958, 5113, 5114, 5115, 5116, 5117, - 5118, 5119, 5120, 5121, 5122, 5123, 5124, 5125, - 5126, 5127, 5128, 5075, 5076, 1960, 5077, 5078, - 5079, 5080, 5081, 5082, 5083, 5084, 5085, 5086, - 5087, 5088, 1961, 5089, 5090, 5091, 5092, 5093, - 5094, 5095, 5096, 5097, 5098, 5099, 5100, 1959, - 5101, 5102, 5103, 5104, 5105, 5106, 5107, 5108, - 5109, 5110, 5111, 5112, 1958, 5113, 5114, 5115, - 5116, 5117, 5118, 5119, 5120, 5121, 5122, 5123, - 5124, 5125, 5126, 5127, 5128, 5075, 5076, 1960, - 5077, 5078, 5079, 5080, 5081, 5082, 5083, 5084, - 5085, 5086, 5087, 5088, 1961, 5089, 5090, 5091, - 5092, 5093, 5094, 5095, 5096, 5097, 5098, 5099, - 5100, 1959, 5101, 5102, 5103, 5104, 5105, 5106, - 5107, 5108, 5109, 5110, 5111, 5112, 1958, 5113, - 5114, 5115, 5116, 5117, 5118, 5119, 5120, 5121, - 5122, 5123, 5124, 5125, 5126, 5127, 5128, 5075, - 5076, 1960, 5077, 5078, 5079, 5080, 5081, 5082, - 5083, 5084, 5085, 5086, 5087, 5088, 1961, 5089, - 5090, 5091, 5092, 5093, 5094, 5095, 5096, 5097, - 5098, 5099, 5100, 1959, 5101, 5102, 5103, 5104, - 5105, 5106, 5107, 5108, 5109, 5110, 5111, 5112, - 1958, 5113, 5114, 5115, 5116, 5117, 5118, 5119, - 5120, 5121, 5122, 5123, 5124, 5125, 5126, 5127, - 5128, 5075, 5076, 1960, 5077, 5078, 5079, 5080, - 5081, 5082, 5083, 5084, 5085, 5086, 5087, 5088, - 1961, 5089, 5090, 5091, 5092, 5093, 5094, 5095, - 5096, 5097, 5098, 5099, 5100, 1959, 5101, 5102, - 5103, 5104, 5105, 5106, 5107, 5108, 5109, 5110, - 5111, 5112, 1958, 5113, 5114, 5115, 5116, 5117, - 5118, 5119, 5120, 5121, 5122, 5123, 5124, 5125, - 5126, 5127, 5128, 5129, 5130, 0, 0, 5131, - 5132, 5133, 5134, 5135, 5136, 5137, 5138, 5139, - 5140, 5131, 5132, 5133, 5134, 5135, 5136, 5137, - 5138, 5139, 5140, 5131, 5132, 5133, 5134, 5135, - 5136, 5137, 5138, 5139, 5140, 5131, 5132, 5133, - 5134, 5135, 5136, 5137, 5138, 5139, 5140, 5131, - 5132, 5133, 5134, 5135, 5136, 5137, 5138, 5139, - 5140, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 339, 339, 339, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 5141, 5142, 5143, 5144, 5145, 3725, 5146, - 5147, 5148, 5149, 3726, 5150, 5151, 5152, 3727, - 5153, 5154, 5155, 5156, 5157, 5158, 5159, 5160, - 5161, 5162, 5163, 5164, 3782, 5165, 5166, 5167, - 5168, 5169, 5170, 5171, 5172, 5173, 3787, 3728, - 3729, 3788, 5174, 5175, 3538, 5176, 3730, 5177, - 5178, 5179, 5180, 5180, 5180, 5181, 5182, 5183, - 5184, 5185, 5186, 5187, 5188, 5189, 5190, 5191, - 5192, 5193, 5194, 5195, 5196, 5197, 5198, 5198, - 3790, 5199, 5200, 5201, 5202, 3732, 5203, 5204, - 5205, 3691, 5206, 5207, 5208, 5209, 5210, 5211, - 5212, 5213, 5214, 5215, 5216, 5217, 5218, 5219, - 5220, 5221, 5222, 5223, 5224, 5225, 5226, 5227, - 5228, 5229, 5230, 5231, 5231, 5232, 5233, 5234, - 3534, 5235, 5236, 5237, 5238, 5239, 5240, 5241, - 5242, 3737, 5243, 5244, 5245, 5246, 5247, 5248, - 5249, 5250, 5251, 5252, 5253, 5254, 5255, 5256, - 5257, 5258, 5259, 5260, 5261, 5262, 5263, 3480, - 5264, 5265, 5266, 5266, 5267, 5268, 5268, 5269, - 5270, 5271, 5272, 5273, 5274, 5275, 5276, 5277, - 5278, 5279, 5280, 5281, 3738, 5282, 5283, 5284, - 5285, 3802, 5285, 5286, 3740, 5287, 5288, 5289, - 5290, 3741, 3453, 5291, 5292, 5293, 5294, 5295, - 5296, 5297, 5298, 5299, 5300, 5301, 5302, 5303, - 5304, 5305, 5306, 5307, 5308, 5309, 5310, 5311, - 5312, 3742, 5313, 5314, 5315, 5316, 5317, 5318, - 3744, 5319, 5320, 5321, 5322, 5323, 5324, 5325, - 5326, 3481, 3810, 5327, 5328, 5329, 5330, 5331, - 5332, 5333, 5334, 3745, 5335, 5336, 5337, 5338, - 3853, 5339, 5340, 5341, 5342, 5343, 5344, 5345, - 5346, 5347, 5348, 5349, 5350, 5351, 3551, 5352, - 5353, 5354, 5355, 5356, 5357, 5358, 5359, 5360, - 5361, 5362, 3746, 3638, 5363, 5364, 5365, 5366, - 5367, 5368, 5369, 5370, 3814, 5371, 5372, 5373, - 5374, 5375, 5376, 5377, 5378, 3815, 5379, 5380, - 5381, 5382, 5383, 5384, 5385, 5386, 5387, 5388, - 5389, 5390, 3817, 5391, 5392, 5393, 5394, 5395, - 5396, 5397, 5398, 5399, 5400, 5401, 5401, 5402, - 5403, 3819, 5404, 5405, 5406, 5407, 5408, 5409, - 5410, 3537, 5411, 5412, 5413, 5414, 5415, 5416, - 5417, 3825, 5418, 5419, 5420, 5421, 5422, 5423, - 5423, 3826, 3855, 5424, 5425, 5426, 5427, 5428, - 3499, 3828, 5429, 5430, 3757, 5431, 5432, 3713, - 5433, 5434, 3761, 5435, 5436, 5437, 5438, 5438, - 5439, 5440, 5441, 5442, 5443, 5444, 5445, 5446, - 5447, 5448, 5449, 5450, 5451, 5452, 5453, 5454, - 5455, 5456, 5457, 5458, 5459, 5460, 5461, 5462, - 5463, 5464, 5465, 3767, 5466, 5467, 5468, 5469, - 5470, 5471, 5472, 5473, 5474, 5475, 5476, 5477, - 5478, 5479, 5480, 5481, 5267, 5482, 5483, 5484, - 5485, 5486, 5487, 5488, 5489, 5490, 5491, 5492, - 5493, 3555, 5494, 5495, 5496, 5497, 5498, 5499, - 3770, 5500, 5501, 5502, 5503, 5504, 5505, 5506, - 5507, 5508, 5509, 5510, 5511, 5512, 5513, 5514, - 5515, 5516, 5517, 5518, 5519, 3494, 5520, 5521, - 5522, 5523, 5524, 5525, 3835, 5526, 5527, 5528, - 5529, 5530, 5531, 5532, 5533, 5534, 5535, 5536, - 5537, 5538, 5539, 5540, 5541, 5542, 5543, 5544, - 5545, 3840, 3841, 5546, 5547, 5548, 5549, 5550, - 5551, 5552, 5553, 5554, 5555, 5556, 5557, 5558, - 3842, 5559, 5560, 5561, 5562, 5563, 5564, 5565, - 5566, 5567, 5568, 5569, 5570, 5571, 5572, 5573, - 5574, 5575, 5576, 5577, 5578, 5579, 5580, 5581, - 5582, 5583, 5584, 5585, 5586, 5587, 5588, 3848, - 3848, 5589, 5590, 5591, 5592, 5593, 5594, 5595, - 5596, 5597, 5598, 3849, 5599, 5600, 5601, 5602, - 5603, 5604, 5605, 5606, 5607, 5608, 5609, 5610, - 5611, 5612, 5613, 5614, 5615, 5616, 5617, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 80, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, - 80, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 558, 558, 558, 558, 558, 558, 558, - 558, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 3440, - 3440, 3440, 3440, 3440, 3440, 3440, 3440, 0, +const utf8proc_uint16_t utf8proc_stage2table[] = { + 1, 2, 2, 2, 2, 2, 2, + 2, 2, 3, 4, 3, 5, 6, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 7, 7, 7, + 3, 8, 9, 9, 10, 11, 10, 9, + 9, 12, 13, 9, 14, 15, 16, 15, + 15, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 15, 9, 18, 19, 20, + 9, 9, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 12, 9, 13, 47, + 48, 47, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 12, 75, 13, 75, + 2, 2, 2, 2, 2, 2, 7, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, + 2, 76, 9, 11, 11, 11, 11, 77, + 9, 78, 77, 79, 80, 75, 81, 77, + 82, 83, 84, 85, 86, 87, 88, 9, + 9, 89, 90, 91, 92, 93, 94, 95, + 9, 96, 97, 98, 99, 100, 101, 102, + 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, 117, 118, + 75, 119, 120, 121, 122, 123, 124, 125, + 126, 127, 128, 129, 130, 131, 132, 133, + 134, 135, 136, 137, 138, 139, 140, 141, + 142, 143, 144, 145, 146, 147, 148, 149, + 75, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 171, 172, + 173, 174, 175, 176, 177, 178, 179, 180, + 181, 182, 183, 184, 185, 186, 187, 188, + 189, 190, 191, 192, 193, 194, 195, 196, + 197, 198, 199, 200, 201, 202, 203, 204, + 205, 206, 207, 208, 209, 210, 211, 212, + 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, + 229, 230, 231, 232, 233, 234, 235, 236, + 237, 238, 239, 240, 241, 242, 243, 244, + 245, 246, 247, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, 266, 267, 268, + 269, 270, 271, 272, 273, 274, 275, 276, + 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, + 293, 294, 295, 296, 297, 298, 214, 299, + 300, 301, 302, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 214, 312, 313, 314, + 315, 316, 317, 318, 319, 320, 321, 322, + 323, 324, 325, 214, 214, 326, 327, 328, + 329, 330, 331, 332, 333, 334, 335, 336, + 337, 338, 339, 214, 340, 341, 342, 214, + 343, 340, 340, 340, 340, 344, 345, 346, + 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, 357, 358, 359, 360, 361, 362, + 363, 364, 365, 366, 367, 368, 369, 370, + 371, 372, 373, 374, 375, 376, 377, 378, + 379, 380, 381, 382, 383, 384, 385, 386, + 387, 388, 389, 390, 391, 392, 393, 394, + 395, 396, 397, 398, 399, 400, 401, 402, + 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 414, 415, 416, 417, 418, + 419, 420, 421, 422, 423, 424, 425, 426, + 427, 428, 429, 430, 431, 432, 433, 434, + 435, 436, 214, 437, 438, 439, 440, 441, + 442, 443, 444, 445, 446, 447, 448, 449, + 450, 451, 452, 453, 454, 214, 214, 214, + 214, 214, 214, 455, 456, 457, 458, 459, + 460, 461, 462, 463, 464, 465, 466, 467, + 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 214, 482, + 483, 214, 484, 214, 485, 486, 214, 214, + 214, 487, 488, 214, 489, 214, 490, 491, + 214, 492, 493, 494, 495, 496, 214, 214, + 497, 214, 498, 499, 214, 214, 500, 214, + 214, 214, 214, 214, 214, 214, 501, 214, + 214, 502, 214, 214, 503, 214, 214, 214, + 504, 505, 506, 507, 508, 509, 214, 214, + 214, 214, 214, 510, 214, 340, 214, 214, + 214, 214, 214, 214, 214, 214, 511, 512, + 214, 214, 214, 214, 214, 214, 214, 214, + 214, 214, 214, 214, 214, 214, 214, 214, + 214, 513, 514, 515, 516, 517, 518, 519, + 520, 521, 522, 522, 523, 523, 523, 523, + 523, 523, 523, 47, 47, 47, 47, 522, + 522, 522, 522, 522, 522, 522, 522, 522, + 522, 523, 523, 47, 47, 47, 47, 47, + 47, 524, 525, 526, 527, 528, 529, 47, + 47, 530, 531, 532, 533, 534, 47, 47, + 47, 47, 47, 47, 47, 522, 47, 523, + 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, + 47, 535, 536, 537, 538, 539, 540, 541, + 542, 543, 544, 545, 546, 547, 540, 540, + 548, 540, 549, 540, 550, 551, 552, 553, + 553, 553, 553, 552, 554, 553, 553, 553, + 553, 553, 555, 555, 556, 557, 558, 559, + 560, 561, 553, 553, 553, 553, 562, 563, + 553, 564, 565, 553, 553, 566, 566, 566, + 566, 567, 553, 553, 553, 553, 540, 540, + 540, 568, 569, 570, 571, 572, 573, 540, + 553, 553, 553, 540, 540, 540, 553, 553, + 574, 540, 540, 540, 553, 553, 553, 553, + 540, 552, 553, 553, 540, 575, 576, 576, + 575, 576, 576, 575, 540, 540, 540, 540, + 540, 540, 540, 540, 540, 540, 540, 540, + 540, 577, 578, 579, 580, 581, 47, 582, + 583, 0, 0, 584, 585, 586, 587, 588, + 589, 0, 0, 0, 0, 87, 590, 591, + 592, 593, 594, 595, 0, 596, 0, 597, + 598, 599, 600, 601, 602, 603, 604, 605, + 606, 607, 608, 609, 610, 611, 612, 613, + 614, 615, 616, 0, 617, 618, 619, 620, + 621, 622, 623, 624, 625, 626, 627, 628, + 629, 630, 631, 632, 633, 634, 635, 636, + 637, 638, 639, 640, 641, 642, 643, 644, + 645, 646, 647, 648, 649, 650, 651, 652, + 653, 654, 655, 656, 657, 658, 659, 660, + 661, 662, 663, 664, 665, 666, 667, 668, + 669, 670, 671, 672, 673, 674, 675, 676, + 677, 678, 679, 680, 681, 682, 683, 684, + 685, 686, 687, 688, 689, 690, 691, 692, + 693, 694, 695, 696, 697, 698, 699, 75, + 700, 701, 702, 703, 704, 214, 705, 706, + 707, 708, 709, 710, 711, 712, 713, 714, + 715, 716, 717, 718, 719, 720, 721, 722, + 723, 724, 725, 726, 727, 728, 729, 730, + 731, 732, 733, 734, 735, 736, 737, 738, + 739, 740, 741, 742, 743, 744, 745, 746, + 747, 748, 749, 750, 751, 752, 753, 754, + 755, 756, 757, 758, 759, 760, 761, 762, + 763, 764, 765, 766, 767, 768, 769, 770, + 771, 772, 773, 774, 775, 776, 777, 778, + 779, 780, 781, 782, 783, 784, 785, 786, + 787, 788, 789, 790, 791, 792, 793, 794, + 795, 796, 797, 798, 799, 800, 801, 802, + 803, 804, 805, 806, 807, 808, 809, 810, + 811, 812, 813, 814, 815, 816, 817, 818, + 819, 820, 821, 822, 823, 824, 825, 826, + 827, 828, 829, 830, 831, 832, 833, 834, + 835, 836, 837, 838, 540, 540, 540, 540, + 540, 839, 839, 840, 841, 842, 843, 844, + 845, 846, 847, 848, 849, 850, 851, 852, + 853, 854, 855, 856, 857, 858, 859, 860, + 861, 862, 863, 864, 865, 866, 867, 868, + 869, 870, 871, 872, 873, 874, 875, 876, + 877, 878, 879, 880, 881, 882, 883, 884, + 885, 886, 887, 888, 889, 890, 891, 892, + 893, 894, 895, 896, 897, 898, 899, 900, + 901, 902, 903, 904, 905, 906, 907, 908, + 909, 910, 911, 912, 913, 914, 915, 916, + 917, 918, 919, 920, 921, 922, 923, 924, + 925, 926, 927, 928, 929, 930, 931, 932, + 933, 934, 935, 936, 937, 938, 939, 940, + 941, 942, 943, 944, 945, 946, 947, 948, + 949, 950, 951, 952, 953, 954, 955, 956, + 957, 958, 959, 960, 961, 962, 963, 964, + 965, 966, 967, 968, 969, 970, 971, 972, + 973, 974, 975, 976, 977, 978, 979, 980, + 981, 982, 983, 984, 985, 986, 987, 988, + 989, 990, 991, 992, 993, 994, 995, 996, + 997, 998, 999, 1000, 1001, 1002, 1003, 1004, + 1005, 0, 1006, 1007, 1008, 1009, 1010, 1011, + 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, + 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, + 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, + 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, + 0, 0, 523, 1044, 1044, 1044, 1044, 1044, + 1044, 0, 1045, 1046, 1047, 1048, 1049, 1050, + 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, + 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, + 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, + 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, + 1083, 0, 1044, 1084, 0, 0, 1085, 1085, + 11, 0, 553, 540, 540, 540, 540, 553, + 540, 540, 540, 1086, 553, 540, 540, 540, + 540, 540, 540, 553, 553, 553, 553, 553, + 553, 540, 540, 553, 540, 540, 1086, 1087, + 540, 1088, 1089, 1090, 1091, 1092, 1093, 1094, + 1095, 1096, 1097, 1097, 1098, 1099, 1100, 1101, + 1102, 1103, 1104, 1105, 1103, 540, 553, 1103, + 1096, 0, 0, 0, 0, 0, 0, 0, + 0, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 0, 0, 0, 0, + 0, 1106, 1106, 1106, 1103, 1103, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1107, 1108, 1108, 1108, 1107, 1107, 1109, + 1109, 1110, 10, 10, 1111, 15, 1112, 1085, + 1085, 540, 540, 540, 540, 540, 540, 540, + 540, 1113, 1114, 1115, 1112, 1116, 0, 1117, + 1112, 1118, 1118, 1119, 1120, 1121, 1122, 1123, + 1124, 1118, 1118, 1118, 1118, 1118, 1118, 1118, + 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, + 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, + 1118, 1125, 1118, 1118, 1118, 1118, 1118, 1118, + 1126, 1127, 1118, 1128, 1129, 1130, 1131, 1113, + 1114, 1115, 1132, 1133, 1134, 1135, 1136, 553, + 540, 540, 540, 540, 540, 553, 540, 540, + 553, 1137, 1137, 1137, 1137, 1137, 1137, 1137, + 1137, 1137, 1137, 10, 1138, 1138, 1112, 1118, + 1118, 1139, 1118, 1118, 1118, 1118, 1140, 1141, + 1142, 1143, 1118, 1118, 1118, 1118, 1118, 1118, + 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, + 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, + 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, + 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, + 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, + 1118, 1118, 1118, 1126, 1118, 1118, 1118, 1118, + 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, + 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, + 1118, 1144, 1145, 1146, 1118, 1118, 1118, 1118, + 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, + 1118, 1118, 1118, 1147, 1148, 1112, 1149, 540, + 540, 540, 540, 540, 540, 540, 1108, 1085, + 540, 540, 540, 540, 553, 540, 1125, 1125, + 540, 540, 1085, 553, 540, 540, 553, 1118, + 1118, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 1118, 1118, 1118, 1150, 1150, + 1126, 1117, 1117, 1117, 1117, 1117, 1117, 1117, + 1117, 1117, 1117, 1117, 1117, 1117, 1117, 0, + 1151, 1126, 1152, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 1126, 1126, 1126, 1126, 1126, 1126, 1126, + 1126, 540, 553, 540, 540, 553, 540, 540, + 553, 553, 553, 540, 553, 553, 540, 553, + 540, 540, 540, 553, 540, 553, 540, 553, + 540, 553, 540, 540, 0, 0, 1126, 1126, + 1126, 1118, 1118, 1118, 1118, 1118, 1118, 1118, + 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, + 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, + 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, + 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, + 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, + 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, + 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, + 1118, 1126, 1118, 1118, 1118, 1118, 1118, 1118, + 1118, 1118, 1118, 1118, 1118, 1118, 1126, 1126, + 1126, 1118, 1118, 1118, 1118, 1118, 1118, 1153, + 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, + 1153, 1153, 1118, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1154, 1154, 1154, 1154, 1154, 1154, 1154, + 1154, 1154, 1154, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 540, 540, 540, 540, + 540, 540, 540, 553, 540, 1155, 1155, 77, + 9, 9, 9, 1155, 0, 0, 0, 0, + 0, 1156, 1156, 1156, 1156, 1156, 1156, 1156, + 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, + 1156, 1156, 1156, 1156, 1156, 1156, 1156, 540, + 540, 540, 540, 1157, 540, 540, 540, 540, + 540, 540, 540, 540, 540, 1157, 540, 540, + 540, 1157, 540, 540, 540, 540, 540, 0, + 0, 1158, 1158, 1158, 1158, 1158, 1158, 1158, + 1158, 1158, 1158, 1158, 1158, 1158, 1158, 1158, + 0, 1156, 1156, 1156, 1156, 1156, 1156, 1156, + 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, + 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, + 1156, 1156, 553, 553, 553, 0, 0, 1158, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1118, 1118, 1118, 1118, 1118, 1118, 1118, + 1118, 1118, 1118, 1118, 1118, 1118, 1118, 1118, + 1118, 1118, 1118, 1118, 1118, 1118, 0, 1118, + 1118, 1118, 1118, 1118, 1118, 1118, 1118, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 540, 540, 540, + 540, 540, 540, 540, 540, 540, 540, 540, + 540, 540, 540, 1107, 553, 540, 540, 553, + 540, 540, 553, 540, 540, 540, 553, 553, + 553, 1129, 1130, 1131, 540, 540, 540, 553, + 540, 540, 553, 553, 540, 540, 540, 540, + 540, 1153, 1153, 1153, 1159, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1161, 1162, 1160, 1160, 1160, 1160, 1160, + 1160, 1163, 1164, 1160, 1165, 1166, 1160, 1160, + 1160, 1160, 1160, 1153, 1159, 1167, 1160, 1159, + 1159, 1159, 1153, 1153, 1153, 1153, 1153, 1153, + 1153, 1153, 1159, 1159, 1159, 1159, 1168, 1159, + 1159, 1160, 540, 553, 540, 540, 1153, 1153, + 1153, 1169, 1170, 1171, 1172, 1173, 1174, 1175, + 1176, 1160, 1160, 1153, 1153, 1177, 1177, 1178, + 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1177, 1179, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1153, 1159, 1159, 0, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 0, 0, + 1160, 1160, 0, 0, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 0, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 0, 1160, 0, 0, 0, 1160, + 1160, 1160, 1160, 0, 0, 1180, 1160, 1181, + 1159, 1159, 1153, 1153, 1153, 1153, 0, 0, + 1182, 1159, 0, 0, 1183, 1184, 1168, 1160, + 0, 0, 0, 0, 0, 0, 0, 0, + 1185, 0, 0, 0, 0, 1186, 1187, 0, + 1188, 1160, 1160, 1153, 1153, 0, 0, 1178, + 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1160, 1160, 1189, 1189, 1190, 1190, 1190, + 1190, 1190, 1190, 1191, 1189, 0, 0, 0, + 0, 0, 1153, 1153, 1159, 0, 1160, 1160, + 1160, 1160, 1160, 1160, 0, 0, 0, 0, + 1160, 1160, 0, 0, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 0, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 0, 1160, 1192, 0, 1160, 1193, + 0, 1160, 1160, 0, 0, 1180, 0, 1159, + 1159, 1159, 1153, 1153, 0, 0, 0, 0, + 1153, 1153, 0, 0, 1153, 1153, 1168, 0, + 0, 0, 1153, 0, 0, 0, 0, 0, + 0, 0, 1194, 1195, 1196, 1160, 0, 1197, + 0, 0, 0, 0, 0, 0, 0, 1178, + 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1153, 1153, 1160, 1160, 1160, 1153, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1153, 1153, 1159, 0, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 0, + 1160, 1160, 1160, 0, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 0, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 0, 1160, 1160, 0, 1160, 1160, + 1160, 1160, 1160, 0, 0, 1180, 1160, 1159, + 1159, 1159, 1153, 1153, 1153, 1153, 1153, 0, + 1153, 1153, 1159, 0, 1159, 1159, 1168, 0, + 0, 1160, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1153, 1153, 0, 0, 1178, + 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1177, 1189, 0, 0, 0, 0, 0, + 0, 0, 1160, 0, 0, 0, 0, 0, + 0, 0, 1153, 1159, 1159, 0, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 0, 0, + 1160, 1160, 0, 0, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 0, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 0, 1160, 1160, 0, 1160, 1160, + 1160, 1160, 1160, 0, 0, 1180, 1160, 1198, + 1153, 1159, 1153, 1153, 1153, 1153, 0, 0, + 1199, 1200, 0, 0, 1201, 1202, 1168, 0, + 0, 0, 0, 0, 0, 0, 0, 1203, + 1204, 0, 0, 0, 0, 1205, 1206, 0, + 1160, 1160, 1160, 1153, 1153, 0, 0, 1178, + 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1191, 1160, 1190, 1190, 1190, 1190, 1190, + 1190, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1153, 1160, 0, 1160, 1160, + 1160, 1160, 1160, 1160, 0, 0, 0, 1160, + 1160, 1160, 0, 1207, 1160, 1208, 1160, 0, + 0, 0, 1160, 1160, 0, 1160, 0, 1160, + 1160, 0, 0, 0, 1160, 1160, 0, 0, + 0, 1160, 1160, 1160, 0, 0, 0, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 0, 0, 0, 0, 1209, + 1159, 1153, 1159, 1159, 0, 0, 0, 1210, + 1211, 1159, 0, 1212, 1213, 1214, 1168, 0, + 0, 1160, 0, 0, 0, 0, 0, 0, + 1215, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1178, + 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1190, 1190, 1190, 1085, 1085, 1085, 1085, + 1085, 1085, 1189, 1085, 0, 0, 0, 0, + 0, 1153, 1159, 1159, 1159, 0, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 0, 1160, + 1160, 1160, 0, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 0, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 0, 0, 0, 1160, 1153, + 1153, 1153, 1159, 1159, 1159, 1159, 0, 1216, + 1153, 1217, 0, 1153, 1153, 1153, 1168, 0, + 0, 0, 0, 0, 0, 0, 1218, 1219, + 0, 1160, 1160, 1160, 0, 0, 0, 0, + 0, 1160, 1160, 1153, 1153, 0, 0, 1178, + 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 0, 0, 0, 0, 0, 0, 0, + 0, 1220, 1220, 1220, 1220, 1220, 1220, 1220, + 1191, 1160, 1153, 1159, 1159, 0, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 0, 1160, + 1160, 1160, 0, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 0, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 0, 1160, 1160, + 1160, 1160, 1160, 0, 0, 1180, 1160, 1159, + 1221, 1222, 1159, 1223, 1159, 1159, 0, 1224, + 1225, 1226, 0, 1227, 1228, 1153, 1168, 0, + 0, 0, 0, 0, 0, 0, 1229, 1230, + 0, 0, 0, 0, 0, 0, 0, 1160, + 0, 1160, 1160, 1153, 1153, 0, 0, 1178, + 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 0, 1160, 1160, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1153, 1159, 1159, 0, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 0, 1160, + 1160, 1160, 0, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 0, 0, 1160, 1231, + 1159, 1159, 1153, 1153, 1153, 1153, 0, 1232, + 1233, 1159, 0, 1234, 1235, 1236, 1168, 1237, + 1191, 0, 0, 0, 0, 1160, 1160, 1160, + 1238, 1190, 1190, 1190, 1190, 1190, 1190, 1190, + 1160, 1160, 1160, 1153, 1153, 0, 0, 1178, + 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1190, 1190, 1190, 1190, 1190, 1190, 1190, + 1190, 1190, 1191, 1160, 1160, 1160, 1160, 1160, + 1160, 0, 0, 1159, 1159, 0, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 0, 0, 0, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 0, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 0, 1160, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 0, 0, 0, 1239, 0, 0, 0, 0, + 1240, 1159, 1159, 1153, 1153, 1153, 0, 1153, + 0, 1159, 1241, 1242, 1159, 1243, 1244, 1245, + 1246, 0, 0, 0, 0, 0, 0, 1178, + 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 0, 0, 1159, 1159, 1177, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 1153, 340, 1247, 1153, 1153, 1153, + 1153, 1248, 1248, 1168, 0, 0, 0, 0, + 11, 340, 340, 340, 340, 340, 340, 523, + 1153, 1249, 1249, 1249, 1249, 1153, 1153, 1153, + 1044, 1250, 1250, 1250, 1250, 1250, 1250, 1250, + 1250, 1250, 1250, 1044, 1044, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 340, 340, 0, 340, 0, 0, + 340, 340, 0, 340, 0, 0, 340, 0, + 0, 0, 0, 0, 0, 340, 340, 340, + 340, 0, 340, 340, 340, 340, 340, 340, + 340, 0, 340, 340, 340, 0, 340, 0, + 340, 0, 0, 340, 340, 0, 340, 340, + 340, 340, 1153, 340, 1251, 1153, 1153, 1153, + 1153, 1252, 1252, 0, 1153, 1153, 340, 0, + 0, 340, 340, 340, 340, 340, 0, 523, + 0, 1253, 1253, 1253, 1253, 1153, 1153, 0, + 0, 1250, 1250, 1250, 1250, 1250, 1250, 1250, + 1250, 1250, 1250, 0, 0, 1254, 1255, 340, + 340, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1191, 1191, 1191, 1177, 1177, 1177, + 1177, 1177, 1177, 1177, 1177, 1256, 1177, 1177, + 1177, 1177, 1177, 1177, 1191, 1177, 1191, 1191, + 1191, 553, 553, 1191, 1191, 1191, 1191, 1191, + 1191, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1178, 1178, 1190, 1190, 1190, 1190, 1190, + 1190, 1190, 1190, 1190, 1190, 1191, 553, 1191, + 553, 1191, 1257, 1258, 1259, 1258, 1259, 1159, + 1159, 1160, 1160, 1160, 1260, 1160, 1160, 1160, + 1160, 0, 1160, 1160, 1160, 1160, 1261, 1160, + 1160, 1160, 1160, 1262, 1160, 1160, 1160, 1160, + 1263, 1160, 1160, 1160, 1160, 1264, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1265, 1160, 1160, 1160, 0, 0, + 0, 0, 1266, 1267, 1268, 1269, 1270, 1271, + 1272, 1273, 1274, 1267, 1267, 1267, 1267, 1153, + 1159, 1267, 1275, 540, 540, 1168, 1177, 540, + 540, 1160, 1160, 1160, 1160, 1160, 1153, 1153, + 1153, 1153, 1153, 1153, 1276, 1153, 1153, 1153, + 1153, 0, 1153, 1153, 1153, 1153, 1277, 1153, + 1153, 1153, 1153, 1278, 1153, 1153, 1153, 1153, + 1279, 1153, 1153, 1153, 1153, 1280, 1153, 1153, + 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, + 1153, 1153, 1281, 1153, 1153, 1153, 0, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 553, + 1191, 1191, 1191, 1191, 1191, 1191, 0, 1191, + 1191, 1177, 1177, 1177, 1177, 1177, 1191, 1191, + 1191, 1191, 1177, 1177, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 340, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 340, 1160, 1160, 1160, 1160, 1282, 1283, + 1160, 1160, 1160, 1160, 1284, 1284, 1153, 1285, + 1153, 1153, 1159, 1153, 1153, 1153, 1153, 1153, + 1180, 1284, 1168, 1168, 1159, 1159, 1153, 1153, + 1160, 1178, 1178, 1250, 1250, 1178, 1178, 1178, + 1178, 1178, 1178, 1044, 1044, 1044, 1177, 1177, + 1177, 1160, 1160, 1160, 1160, 340, 1160, 1159, + 1159, 1153, 1153, 1160, 1160, 1160, 1160, 1153, + 1153, 1153, 1160, 1284, 1284, 1284, 1160, 1160, + 1284, 1284, 1284, 1284, 1284, 1284, 1284, 1160, + 1160, 1160, 1153, 1153, 1153, 1153, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1153, 1284, 1159, 1153, 1153, + 1284, 1284, 1284, 1284, 1284, 1284, 553, 1160, + 1284, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1178, 1178, 1284, 1284, 1284, 1153, 1191, + 1191, 1286, 1287, 1288, 1289, 1290, 1291, 1292, + 1293, 1294, 1295, 1296, 1297, 1298, 1299, 1300, + 1301, 1302, 1303, 1304, 1305, 1306, 1307, 1308, + 1309, 1310, 1311, 1312, 1313, 1314, 1315, 1316, + 1317, 1318, 1319, 1320, 1321, 1322, 1323, 0, + 1324, 0, 0, 0, 0, 0, 1325, 0, + 0, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 1044, 1326, 340, 340, + 340, 1327, 1327, 1327, 1327, 1327, 1327, 1327, + 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, + 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, + 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, + 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, + 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, + 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, + 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, + 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, + 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, + 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, + 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, + 1328, 1329, 1330, 1330, 1330, 1330, 1330, 1330, + 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, + 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, + 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, + 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, + 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, + 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, + 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, + 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, + 1330, 1331, 1331, 1331, 1331, 1331, 1331, 1331, + 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, + 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, + 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, + 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, + 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, + 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, + 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, + 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, + 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, + 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, + 1331, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 0, 1160, 1160, 1160, 1160, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 0, 1160, 0, 1160, 1160, 1160, 1160, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 0, 1160, 1160, 1160, 1160, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 0, 1160, 1160, 1160, 1160, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 0, 1160, 0, 1160, 1160, 1160, 1160, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 0, 1160, 1160, 1160, 1160, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 340, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 0, 0, 540, 540, + 540, 1177, 1044, 1177, 1177, 1177, 1177, 1177, + 1177, 1177, 1190, 1190, 1190, 1190, 1190, 1190, + 1190, 1190, 1190, 1190, 1190, 1190, 1190, 1190, + 1190, 1190, 1190, 1190, 1190, 1190, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 77, 77, 77, 77, 77, 1085, 77, + 1085, 1085, 77, 0, 0, 0, 0, 0, + 0, 1332, 1333, 1334, 1335, 1336, 1337, 1338, + 1339, 1340, 1341, 1342, 1343, 1344, 1345, 1346, + 1347, 1348, 1349, 1350, 1351, 1352, 1353, 1354, + 1355, 1356, 1357, 1358, 1359, 1360, 1361, 1362, + 1363, 1364, 1365, 1366, 1367, 1368, 1369, 1370, + 1371, 1372, 1373, 1374, 1375, 1376, 1377, 1378, + 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, + 1387, 1388, 1389, 1390, 1391, 1392, 1393, 1394, + 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, + 1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, + 1411, 1412, 1413, 1414, 1415, 1416, 1417, 0, + 0, 1418, 1419, 1420, 1421, 1422, 1423, 0, + 0, 1424, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 340, 340, 340, 340, + 340, 340, 340, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 340, 340, 340, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 340, + 1160, 1160, 1160, 1160, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 340, 340, 340, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 1160, 1160, 1160, 1160, 1160, + 1160, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 340, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 340, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 340, 340, 340, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 340, + 340, 340, 340, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 340, 340, 340, 340, 1160, 1160, 1160, 1160, + 340, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 340, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 340, 340, 340, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 340, + 340, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 340, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1177, 1044, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 1425, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1258, 1259, 0, 0, + 0, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 1160, 340, 1160, 340, 340, 340, 340, + 340, 340, 340, 340, 1044, 1044, 1044, 1426, + 1426, 1426, 340, 340, 340, 340, 340, 340, + 340, 340, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 0, 1160, + 1160, 1160, 1160, 1153, 1153, 1168, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1153, 1153, 1168, 1177, 1177, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1153, 1153, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 340, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 0, 1160, + 1160, 1160, 0, 1153, 1153, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 574, 574, 1159, + 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1159, + 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1153, + 1159, 1159, 1153, 1153, 1153, 1153, 1153, 1153, + 1153, 1153, 1153, 1168, 1153, 1177, 1177, 1044, + 1179, 1177, 1177, 1177, 1189, 340, 540, 0, + 0, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1178, 1178, 0, 0, 0, 0, 0, + 0, 1427, 1427, 1427, 1427, 1427, 1427, 1427, + 1427, 1427, 1427, 0, 0, 0, 0, 0, + 0, 1428, 1428, 1428, 1428, 1428, 1428, 1424, + 1428, 1428, 1428, 1428, 574, 574, 574, 81, + 0, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1178, 1178, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1179, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1153, 1153, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1087, 1160, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 340, 340, 340, + 1160, 340, 1160, 340, 1160, 1160, 1160, 340, + 340, 1160, 1160, 1160, 340, 340, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 340, 1160, 340, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 340, 340, 340, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 0, 1153, 1153, 1153, 1159, 1159, 1159, 1159, + 1153, 1153, 1159, 1159, 1159, 0, 0, 0, + 0, 1159, 1159, 1153, 1159, 1159, 1159, 1159, + 1159, 1159, 1086, 540, 553, 0, 0, 0, + 0, 1085, 0, 0, 0, 1428, 1428, 1178, + 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 0, + 0, 340, 340, 340, 340, 340, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 0, 0, 0, 0, 0, + 0, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1178, 1178, 1190, 0, 0, 0, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 540, 553, 1159, 1159, 1153, 0, 0, 1177, + 1177, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1159, 1153, + 1159, 1153, 1153, 1153, 1153, 1153, 1153, 1153, + 0, 1168, 1284, 1153, 1284, 1284, 1153, 1153, + 1153, 1153, 1153, 1153, 1153, 1153, 1159, 1159, + 1159, 1159, 1159, 1159, 1153, 1153, 540, 540, + 540, 540, 540, 540, 540, 540, 0, 0, + 553, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1178, 1178, 0, 0, 0, 0, 0, + 0, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1178, 1178, 0, 0, 0, 0, 0, + 0, 1177, 1177, 1177, 1177, 1177, 1177, 1177, + 1179, 1177, 1177, 1177, 1177, 1177, 1177, 0, + 0, 540, 540, 540, 540, 540, 553, 553, + 553, 553, 553, 553, 540, 540, 553, 839, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1153, 1153, 1153, 1153, 1159, 1429, 1430, + 1431, 1432, 1433, 1434, 1435, 1436, 1437, 1438, + 1160, 1160, 1439, 1440, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1180, 1441, 1153, + 1153, 1153, 1153, 1442, 1443, 1444, 1445, 1446, + 1447, 1448, 1449, 1450, 1451, 1452, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 0, 0, 0, + 0, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1178, 1178, 1177, 1177, 1177, 1177, 1177, + 1177, 1177, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 540, 553, 540, 540, + 540, 540, 540, 540, 540, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 0, 0, + 0, 1153, 1153, 1159, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1159, 1153, 1153, 1153, 1153, 1159, + 1159, 1153, 1153, 1452, 1168, 1153, 1153, 1160, + 1160, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1178, 1178, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1180, + 1159, 1153, 1153, 1159, 1159, 1159, 1153, 1159, + 1153, 1153, 1153, 1452, 1452, 0, 0, 0, + 0, 0, 0, 0, 0, 1177, 1177, 1177, + 1177, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1159, 1159, 1159, + 1159, 1159, 1159, 1159, 1159, 1153, 1153, 1153, + 1153, 1153, 1153, 1153, 1153, 1159, 1159, 1153, + 1180, 0, 0, 0, 1177, 1177, 1177, 1177, + 1177, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1178, 1178, 0, 0, 0, 1160, 1160, + 1160, 1250, 1250, 1250, 1250, 1250, 1250, 1250, + 1250, 1250, 1250, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 523, 523, 523, 523, 523, 523, 1044, + 1044, 1453, 1454, 1455, 1456, 1457, 1457, 1458, + 1459, 1460, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1177, 1177, 1177, 1177, 1177, 1177, 1177, + 1177, 0, 0, 0, 0, 0, 0, 0, + 0, 540, 540, 540, 1177, 566, 553, 553, + 553, 553, 553, 540, 540, 553, 553, 553, + 553, 540, 1159, 566, 566, 566, 566, 566, + 566, 566, 1160, 1160, 1160, 1160, 553, 1160, + 1160, 1160, 1160, 1159, 1159, 540, 1160, 1160, + 0, 540, 540, 0, 0, 0, 0, 0, + 0, 214, 214, 214, 214, 214, 214, 214, + 214, 214, 214, 214, 214, 214, 214, 214, + 214, 214, 214, 214, 214, 214, 214, 214, + 214, 214, 214, 214, 214, 214, 214, 214, + 214, 214, 214, 214, 214, 214, 214, 214, + 214, 214, 214, 214, 214, 1461, 1462, 1463, + 523, 1464, 1465, 1466, 1467, 1468, 1469, 1470, + 1471, 1472, 1473, 1474, 523, 1475, 1476, 1477, + 1478, 1479, 1480, 1481, 1482, 1483, 1484, 1485, + 1486, 1487, 1488, 1489, 1490, 1491, 1492, 523, + 1493, 1494, 1495, 1496, 1497, 1498, 1499, 1500, + 1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508, + 1509, 1510, 1511, 1512, 1513, 1514, 1515, 1516, + 1517, 1518, 1519, 1520, 214, 214, 214, 214, + 214, 214, 214, 214, 214, 214, 214, 214, + 214, 1521, 1522, 1523, 214, 214, 1524, 214, + 214, 214, 214, 214, 214, 214, 214, 214, + 214, 214, 214, 214, 214, 214, 214, 214, + 214, 214, 214, 214, 214, 214, 1523, 214, + 214, 214, 214, 214, 1525, 1526, 1527, 1528, + 1491, 1529, 1530, 1531, 1532, 1533, 1534, 1535, + 1536, 1537, 1538, 1539, 1540, 1541, 1542, 1543, + 1544, 1545, 1546, 1547, 1548, 1549, 1550, 1551, + 1552, 1553, 1554, 1555, 1556, 1557, 1558, 1559, + 1560, 540, 540, 553, 540, 540, 540, 540, + 540, 540, 540, 553, 540, 540, 576, 1561, + 553, 555, 540, 540, 540, 540, 540, 540, + 540, 540, 540, 540, 540, 540, 540, 540, + 540, 540, 540, 540, 540, 540, 540, 540, + 540, 540, 540, 540, 540, 540, 540, 540, + 540, 540, 540, 540, 540, 540, 540, 0, + 0, 0, 0, 0, 540, 575, 553, 540, + 553, 1562, 1563, 1564, 1565, 1566, 1567, 1568, + 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, + 1577, 1578, 1579, 1580, 1581, 1582, 1583, 1584, + 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, + 1593, 1594, 1595, 1596, 1597, 1598, 1599, 1600, + 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, + 1609, 1610, 1611, 1612, 1613, 1614, 1615, 1616, + 1617, 1618, 1619, 1620, 1621, 1622, 1623, 1624, + 1625, 1626, 1627, 1628, 1629, 1630, 1631, 1632, + 1633, 1634, 1635, 1636, 1637, 1638, 1639, 1640, + 1641, 1642, 1643, 1644, 1645, 1646, 1647, 1648, + 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, + 1657, 1658, 1659, 1660, 1661, 1662, 1663, 1664, + 1665, 1666, 1667, 1668, 1669, 1670, 1671, 1672, + 1673, 1674, 1675, 1676, 1677, 1678, 1679, 1680, + 1681, 1682, 1683, 1684, 1685, 1686, 1687, 1688, + 1689, 1690, 1691, 1692, 1693, 1694, 1695, 1696, + 1697, 1698, 1699, 1700, 1701, 1702, 1703, 1704, + 1705, 1706, 1707, 1708, 1709, 1710, 1711, 1712, + 1713, 1714, 1715, 1716, 1717, 214, 214, 1718, + 214, 1719, 1720, 1721, 1722, 1723, 1724, 1725, + 1726, 1727, 1728, 1729, 1730, 1731, 1732, 1733, + 1734, 1735, 1736, 1737, 1738, 1739, 1740, 1741, + 1742, 1743, 1744, 1745, 1746, 1747, 1748, 1749, + 1750, 1751, 1752, 1753, 1754, 1755, 1756, 1757, + 1758, 1759, 1760, 1761, 1762, 1763, 1764, 1765, + 1766, 1767, 1768, 1769, 1770, 1771, 1772, 1773, + 1774, 1775, 1776, 1777, 1778, 1779, 1780, 1781, + 1782, 1783, 1784, 1785, 1786, 1787, 1788, 1789, + 1790, 1791, 1792, 1793, 1794, 1795, 1796, 1797, + 1798, 1799, 1800, 1801, 1802, 1803, 1804, 1805, + 1806, 1807, 1808, 1809, 1810, 1811, 1812, 1813, + 1814, 1815, 1816, 1817, 1818, 1819, 1820, 1821, + 1822, 1823, 1824, 1825, 1826, 1827, 1828, 1829, + 1830, 1831, 1832, 1833, 1834, 1835, 1836, 0, + 0, 1837, 1838, 1839, 1840, 1841, 1842, 0, + 0, 1843, 1844, 1845, 1846, 1847, 1848, 1849, + 1850, 1851, 1852, 1853, 1854, 1855, 1856, 1857, + 1858, 1859, 1860, 1861, 1862, 1863, 1864, 1865, + 1866, 1867, 1868, 1869, 1870, 1871, 1872, 1873, + 1874, 1875, 1876, 1877, 1878, 1879, 1880, 0, + 0, 1881, 1882, 1883, 1884, 1885, 1886, 0, + 0, 1887, 1888, 1889, 1890, 1891, 1892, 1893, + 1894, 0, 1895, 0, 1896, 0, 1897, 0, + 1898, 1899, 1900, 1901, 1902, 1903, 1904, 1905, + 1906, 1907, 1908, 1909, 1910, 1911, 1912, 1913, + 1914, 1915, 1916, 1917, 1918, 1919, 1920, 1921, + 1922, 1923, 1924, 1925, 1926, 1927, 1928, 0, + 0, 1929, 1930, 1931, 1932, 1933, 1934, 1935, + 1936, 1937, 1938, 1939, 1940, 1941, 1942, 1943, + 1944, 1945, 1946, 1947, 1948, 1949, 1950, 1951, + 1952, 1953, 1954, 1955, 1956, 1957, 1958, 1959, + 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, + 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975, + 1976, 1977, 1978, 1979, 1980, 1981, 0, 1982, + 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, + 1991, 1992, 1993, 1994, 1995, 1996, 0, 1997, + 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + 2006, 2007, 2008, 2009, 2010, 0, 0, 2011, + 2012, 2013, 2014, 2015, 2016, 0, 2017, 2018, + 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026, + 2027, 2028, 2029, 2030, 2031, 2032, 2033, 2034, + 2035, 0, 0, 2036, 2037, 2038, 0, 2039, + 2040, 2041, 2042, 2043, 2044, 2045, 2046, 2047, + 0, 2048, 2049, 2050, 2051, 2050, 2050, 2050, + 2052, 2050, 2050, 2050, 81, 2053, 2054, 2055, + 2056, 1084, 2057, 1084, 1084, 1084, 1084, 9, + 2058, 2059, 2060, 2061, 2059, 2059, 2060, 2061, + 2059, 9, 9, 9, 9, 2062, 2063, 2064, + 9, 2065, 2066, 2067, 2068, 2069, 2070, 2071, + 76, 10, 10, 10, 2072, 2073, 9, 2074, + 2075, 9, 80, 92, 9, 2076, 9, 2077, + 48, 48, 9, 9, 9, 2078, 12, 13, + 2079, 2080, 2081, 9, 9, 9, 9, 9, + 9, 9, 9, 75, 9, 48, 9, 9, + 2082, 9, 9, 9, 9, 9, 9, 9, + 2050, 81, 81, 81, 81, 81, 0, 2083, + 2084, 2085, 2086, 81, 81, 81, 81, 81, + 81, 2087, 2088, 0, 0, 2089, 2090, 2091, + 2092, 2093, 2094, 2095, 2096, 2097, 2098, 2099, + 2100, 2101, 2102, 2103, 2104, 2105, 2106, 2107, + 2108, 2109, 2110, 2111, 2112, 2113, 2114, 2115, + 0, 2116, 2117, 2118, 2119, 2120, 2121, 2122, + 2123, 2124, 2125, 2126, 2127, 2128, 0, 0, + 0, 11, 11, 11, 11, 11, 11, 11, + 11, 2129, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 1189, 11, 11, 11, 11, 11, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 540, 540, 566, 566, 540, 540, 540, + 540, 566, 566, 566, 540, 540, 839, 839, + 839, 839, 540, 839, 839, 839, 566, 566, + 540, 553, 540, 566, 566, 553, 553, 553, + 553, 540, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2130, 2131, 2132, 2133, 77, 2134, 2135, + 2136, 77, 2137, 2138, 2139, 2139, 2139, 2140, + 2141, 2142, 2142, 2143, 2144, 77, 2145, 2146, + 77, 75, 2147, 2148, 2149, 2149, 2149, 77, + 77, 2150, 2151, 2152, 77, 2153, 77, 2154, + 77, 2153, 77, 2155, 2156, 2157, 2132, 83, + 2158, 2159, 2160, 2161, 2162, 2163, 2164, 2165, + 2166, 2167, 2168, 1085, 2169, 2170, 2171, 2172, + 2173, 2174, 75, 75, 75, 75, 2175, 2176, + 2158, 2168, 2177, 77, 75, 1085, 77, 2178, + 1191, 2179, 2180, 2181, 2182, 2183, 2184, 2185, + 2186, 2187, 2188, 2189, 2190, 2191, 2192, 2193, + 2194, 2195, 2196, 2197, 2198, 2199, 2200, 2201, + 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, + 2210, 2211, 2212, 2213, 2214, 2215, 2216, 2217, + 2218, 2219, 2220, 2221, 2222, 2223, 2224, 2225, + 2226, 1426, 1426, 2227, 2228, 2229, 1426, 1426, + 1426, 2227, 2230, 77, 77, 0, 0, 0, + 0, 2231, 75, 2232, 75, 2233, 77, 77, + 77, 77, 77, 2234, 2235, 77, 77, 77, + 77, 75, 77, 77, 75, 77, 77, 75, + 77, 77, 77, 77, 77, 77, 77, 2236, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 2237, 2238, + 2239, 2240, 77, 2241, 77, 2242, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 1109, 75, 75, + 75, 75, 1109, 1109, 1109, 1109, 75, 75, + 1109, 75, 2243, 2243, 2244, 2245, 75, 75, + 75, 2246, 2247, 2243, 2248, 2249, 2243, 75, + 75, 75, 2243, 14, 84, 75, 2243, 2243, + 75, 75, 75, 2243, 2243, 2243, 2243, 75, + 2243, 2243, 2243, 2243, 2250, 2251, 2252, 2253, + 75, 75, 75, 75, 2243, 2254, 2255, 2243, + 2256, 2257, 2243, 2243, 2243, 75, 75, 75, + 75, 75, 2243, 75, 2243, 2258, 2243, 2243, + 2243, 2243, 2259, 2243, 2260, 2261, 2262, 2243, + 2263, 2264, 2265, 2243, 2243, 2243, 2266, 75, + 75, 75, 75, 2243, 2243, 2243, 2243, 75, + 75, 75, 75, 75, 75, 75, 75, 75, + 2243, 2267, 2268, 2269, 75, 2270, 2271, 2243, + 2243, 2243, 2243, 2243, 2243, 75, 2272, 2273, + 2274, 2275, 2276, 2277, 2278, 2279, 2280, 2281, + 2282, 2283, 2284, 2285, 2286, 2287, 2288, 2243, + 2243, 2289, 2290, 2291, 2292, 2293, 2294, 2295, + 2296, 2297, 2298, 2243, 2243, 2243, 75, 75, + 2243, 2243, 2299, 2300, 75, 75, 75, 75, + 75, 2243, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 2301, 2243, 75, 75, 2243, + 2243, 2302, 2303, 2243, 2304, 2305, 2306, 2307, + 2308, 2243, 2243, 2309, 2310, 2311, 2312, 2243, + 2243, 2243, 75, 75, 75, 75, 75, 2243, + 2243, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 2243, 2243, 2243, 2243, 2243, 75, + 75, 2243, 2243, 75, 75, 75, 75, 2243, + 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, + 2243, 2313, 2314, 2315, 2316, 2243, 2243, 2243, + 2243, 2243, 2243, 2317, 2318, 2319, 2320, 75, + 75, 2243, 2243, 2321, 2321, 2243, 2321, 2321, + 2243, 2243, 2321, 2321, 2321, 2243, 2321, 2243, + 2321, 77, 77, 77, 77, 77, 77, 77, + 77, 12, 13, 12, 13, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 1085, 1085, 77, 77, 77, + 77, 2243, 2243, 77, 77, 77, 77, 77, + 77, 77, 2322, 2323, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 1085, 1109, 1085, 1085, + 77, 77, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 838, 77, + 1085, 1085, 1085, 1085, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 1109, 1109, 1085, 1085, 1085, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 77, 77, 1085, 1085, + 77, 77, 77, 77, 77, 1085, 1085, 1085, + 1085, 1085, 1085, 77, 1085, 1109, 1109, 1109, + 1109, 1109, 1109, 1085, 1085, 1085, 1085, 1085, + 1085, 77, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 0, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 77, 77, 77, 77, 77, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2324, 2325, 2326, 2327, 2328, 2329, 2330, + 2331, 2332, 2333, 2334, 2335, 2336, 2337, 2338, + 2339, 2340, 2341, 2342, 2343, 2344, 2345, 2346, + 2347, 2348, 2349, 2350, 2351, 2352, 2353, 2354, + 2355, 2356, 2357, 2358, 2359, 2360, 2361, 2362, + 2363, 2364, 2365, 2366, 2367, 2368, 2369, 2370, + 2371, 2372, 2373, 2374, 2375, 2376, 2377, 2378, + 2379, 2380, 2381, 2382, 2383, 2384, 2385, 2386, + 2387, 2388, 2389, 2390, 2391, 2392, 2393, 2394, + 2395, 2396, 2397, 2398, 2399, 2400, 2401, 2402, + 2403, 2404, 2405, 2406, 2407, 2408, 2409, 2410, + 2411, 2412, 2413, 2414, 2415, 2416, 2417, 2418, + 2419, 2420, 2421, 2422, 2423, 2424, 2425, 2426, + 2427, 2428, 2429, 2430, 2431, 2432, 2433, 2434, + 2435, 2436, 2437, 2438, 2439, 2440, 2441, 2442, + 2443, 2444, 2445, 2446, 2447, 2448, 2449, 2450, + 2451, 2452, 2453, 2454, 2455, 2456, 2457, 2458, + 2459, 2460, 2461, 2462, 1220, 1220, 1220, 1220, + 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, + 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, + 1220, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 75, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 75, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 75, 75, 75, 75, 75, 1109, 1109, + 75, 77, 77, 77, 1085, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 1085, 1085, 1085, + 1085, 1085, 1085, 77, 77, 77, 2463, 77, + 77, 77, 77, 1085, 1085, 1085, 77, 77, + 77, 77, 77, 77, 1085, 1085, 77, 77, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 75, 77, 77, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 77, 77, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 77, 1085, 1085, 1085, 838, 1085, 1085, + 1085, 1085, 1085, 77, 77, 77, 77, 1085, + 77, 77, 77, 77, 77, 77, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 77, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 2464, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 2464, 2464, 2464, 2464, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 2465, 1085, 1085, + 1085, 12, 13, 12, 13, 12, 13, 12, + 13, 12, 13, 12, 13, 12, 13, 1220, + 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, + 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, + 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, + 1220, 1220, 1220, 1220, 1220, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 2243, 1109, 75, 2321, 2321, 12, 13, + 75, 2321, 2321, 75, 2321, 2321, 2321, 1109, + 1109, 1109, 75, 1109, 2243, 2243, 2321, 2321, + 1109, 1109, 1109, 1109, 1109, 2321, 2321, 2321, + 1109, 75, 1109, 2321, 2321, 2321, 2321, 12, + 13, 12, 13, 12, 13, 12, 13, 12, + 13, 1109, 1109, 1109, 1109, 1109, 1109, 1109, + 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, + 1109, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 1109, 1109, 1109, 1109, 1109, 1109, 1109, + 1109, 75, 75, 1109, 1109, 1109, 1109, 1109, + 1109, 1109, 1109, 75, 75, 1109, 1109, 1109, + 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, + 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, + 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, + 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, + 1109, 75, 75, 1109, 1109, 1109, 1109, 1109, + 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, + 1109, 1109, 75, 1109, 1109, 75, 75, 1109, + 75, 1109, 75, 1109, 1109, 75, 75, 1109, + 1109, 75, 75, 1109, 1109, 75, 75, 1109, + 1109, 75, 75, 1109, 1109, 1109, 1109, 1109, + 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, + 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, + 1109, 1109, 1109, 1109, 1109, 75, 75, 1109, + 1109, 75, 1109, 75, 12, 13, 12, 13, + 12, 13, 12, 13, 12, 13, 12, 13, + 12, 13, 12, 13, 1258, 1259, 1258, 1259, + 12, 13, 75, 1109, 2321, 2321, 2321, 2321, + 2321, 2321, 2321, 2321, 2321, 2321, 2321, 2243, + 2243, 2321, 2321, 2321, 2321, 2321, 2321, 2321, + 2321, 1109, 1109, 1109, 1109, 1109, 1109, 1109, + 1109, 2321, 1109, 1109, 1109, 1109, 1109, 1109, + 1109, 2321, 2321, 2321, 2321, 2321, 2321, 1109, + 1109, 1109, 2321, 1109, 1109, 1109, 1109, 2321, + 2321, 2321, 2243, 2243, 75, 2243, 2243, 75, + 75, 12, 13, 1258, 1259, 2321, 1109, 1109, + 1109, 1109, 2321, 1109, 2321, 2321, 2321, 1109, + 1109, 2321, 2321, 1109, 75, 1109, 1109, 1109, + 1109, 1109, 1109, 1109, 1109, 2321, 2243, 2243, + 2243, 2243, 2243, 75, 75, 12, 13, 1109, + 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, + 1109, 1109, 1109, 2321, 2321, 2466, 2321, 2321, + 2321, 2321, 2321, 2321, 2321, 2321, 2321, 2321, + 2321, 2321, 2321, 2321, 2321, 2321, 1109, 2243, + 2243, 2321, 2243, 75, 75, 2243, 75, 2243, + 1109, 75, 2243, 75, 2243, 2243, 2321, 2321, + 75, 75, 75, 75, 1109, 2321, 2321, 1109, + 1109, 1109, 1109, 1109, 1109, 2243, 2243, 2243, + 1109, 1109, 1109, 1109, 1109, 1109, 1109, 75, + 75, 75, 75, 75, 75, 1109, 1109, 1109, + 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, + 2321, 2321, 1109, 1109, 1109, 1109, 1109, 1109, + 1109, 1109, 1109, 1109, 1109, 2321, 2321, 75, + 75, 1109, 1109, 2243, 2243, 2243, 2243, 1109, + 2243, 2243, 75, 75, 2243, 2467, 2468, 2469, + 75, 1109, 2321, 2321, 2321, 2321, 2321, 2321, + 2321, 2321, 2321, 2321, 2321, 2321, 2321, 2321, + 2321, 2321, 2321, 2321, 2243, 2243, 2321, 2321, + 2243, 2243, 2243, 2243, 2243, 2243, 2321, 2321, + 2321, 2321, 2321, 2321, 2321, 2321, 2321, 2321, + 2321, 2321, 2321, 2321, 2321, 1109, 1109, 2321, + 2321, 2321, 2321, 2321, 2321, 2321, 2321, 1109, + 2321, 2321, 2321, 2321, 2321, 2321, 2321, 2321, + 2321, 2321, 2321, 2321, 2321, 2321, 2321, 2321, + 2243, 2243, 2243, 2243, 2243, 2243, 2243, 2243, + 2321, 2321, 2243, 2243, 2243, 2243, 2321, 2321, + 2321, 2321, 2321, 2321, 2243, 2243, 2243, 2243, + 1109, 1109, 1109, 1109, 1109, 2470, 2471, 2243, + 1109, 1109, 1109, 2321, 2321, 2321, 2321, 2321, + 1109, 1109, 1109, 1109, 1109, 2321, 2321, 2243, + 75, 75, 75, 75, 2321, 1109, 1109, 75, + 2321, 2321, 2321, 2321, 2321, 1109, 2321, 75, + 75, 1085, 1085, 1085, 1085, 1085, 1085, 77, + 77, 1085, 1085, 1085, 1085, 1085, 77, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 77, 77, + 1085, 1085, 1085, 1085, 1085, 1085, 77, 77, + 77, 77, 77, 77, 77, 1085, 1085, 77, + 77, 1109, 1109, 1109, 1109, 1109, 1109, 1109, + 1109, 1109, 1109, 1109, 1109, 1109, 1109, 1109, + 1109, 1109, 1109, 1109, 1109, 1109, 1085, 1085, + 1109, 1109, 1109, 1109, 1109, 1109, 1085, 77, + 77, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 0, 0, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 0, + 0, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 0, 0, 0, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 0, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1085, 1085, 1085, + 1085, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2472, 2473, 2474, 2475, 2476, 2477, 2478, + 2479, 2480, 2481, 2482, 2483, 2484, 2485, 2486, + 2487, 2488, 2489, 2490, 2491, 2492, 2493, 2494, + 2495, 2496, 2497, 2498, 2499, 2500, 2501, 2502, + 2503, 2504, 2505, 2506, 2507, 2508, 2509, 2510, + 2511, 2512, 2513, 2514, 2515, 2516, 2517, 2518, + 0, 2519, 2520, 2521, 2522, 2523, 2524, 2525, + 2526, 2527, 2528, 2529, 2530, 2531, 2532, 2533, + 2534, 2535, 2536, 2537, 2538, 2539, 2540, 2541, + 2542, 2543, 2544, 2545, 2546, 2547, 2548, 2549, + 2550, 2551, 2552, 2553, 2554, 2555, 2556, 2557, + 2558, 2559, 2560, 2561, 2562, 2563, 2564, 2565, + 0, 2566, 2567, 2568, 2569, 2570, 2571, 2572, + 2573, 2574, 2575, 2576, 2577, 2578, 2579, 2580, + 2581, 2582, 214, 2583, 2584, 214, 2585, 2586, + 214, 214, 214, 214, 214, 2587, 2588, 2589, + 2590, 2591, 2592, 2593, 2594, 2595, 2596, 2597, + 2598, 2599, 2600, 2601, 2602, 2603, 2604, 2605, + 2606, 2607, 2608, 2609, 2610, 2611, 2612, 2613, + 2614, 2615, 2616, 2617, 2618, 2619, 2620, 2621, + 2622, 2623, 2624, 2625, 2626, 2627, 2628, 2629, + 2630, 2631, 2632, 2633, 2634, 2635, 2636, 2637, + 2638, 2639, 2640, 2641, 2642, 2643, 2644, 2645, + 2646, 2647, 2648, 2649, 2650, 2651, 2652, 2653, + 2654, 2655, 2656, 2657, 2658, 2659, 2660, 2661, + 2662, 2663, 2664, 2665, 2666, 2667, 2668, 2669, + 2670, 2671, 2672, 2673, 2674, 2675, 2676, 2677, + 2678, 2679, 2680, 2681, 2682, 2683, 2684, 2685, + 2686, 2687, 2688, 2689, 2690, 214, 77, 77, + 1085, 77, 77, 1085, 2691, 2692, 2693, 2694, + 540, 540, 540, 2695, 2696, 0, 0, 0, + 0, 0, 9, 9, 9, 9, 1427, 9, + 9, 2697, 2698, 2699, 2700, 2701, 2702, 2703, + 2704, 2705, 2706, 2707, 2708, 2709, 2710, 2711, + 2712, 2713, 2714, 2715, 2716, 2717, 2718, 2719, + 2720, 2721, 2722, 2723, 2724, 2725, 2726, 2727, + 2728, 2729, 2730, 2731, 2732, 2733, 2734, 0, + 2735, 0, 0, 0, 0, 0, 2736, 0, + 0, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 1160, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 0, 0, 0, 0, 0, 0, 0, + 2737, 1044, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1168, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 0, 540, 540, 540, 540, 540, 540, 540, + 540, 540, 540, 540, 540, 540, 540, 540, + 540, 540, 540, 540, 540, 540, 540, 540, + 540, 540, 540, 540, 540, 540, 540, 540, + 540, 9, 9, 80, 92, 80, 92, 9, + 9, 9, 80, 92, 9, 80, 92, 1428, + 1428, 1428, 1428, 9, 1428, 1428, 1428, 9, + 1084, 9, 9, 1084, 9, 80, 92, 9, + 9, 80, 92, 12, 13, 12, 13, 12, + 13, 12, 13, 9, 9, 9, 9, 9, + 522, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 1084, 1084, 9, 9, 9, + 9, 1084, 9, 2061, 1428, 9, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 0, 1085, 1085, 1085, 1085, + 2738, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 2739, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2740, 2741, 2742, 2743, 2744, 2745, 2746, + 2747, 2748, 2749, 2750, 2751, 2752, 2753, 2754, + 2755, 2756, 2757, 2758, 2759, 2760, 2761, 2762, + 2763, 2764, 2765, 2766, 2767, 2768, 2769, 2770, + 2771, 2772, 2773, 2774, 2775, 2776, 2777, 2778, + 2779, 2780, 2781, 2782, 2783, 2784, 2785, 2786, + 2787, 2788, 2789, 2790, 2791, 2792, 2793, 2794, + 2795, 2796, 2797, 2798, 2799, 2800, 2801, 2802, + 2803, 2804, 2805, 2806, 2807, 2808, 2809, 2810, + 2811, 2812, 2813, 2814, 2815, 2816, 2817, 2818, + 2819, 2820, 2821, 2822, 2823, 2824, 2825, 2826, + 2827, 2828, 2829, 2830, 2831, 2832, 2833, 2834, + 2835, 2836, 2837, 2838, 2839, 2840, 2841, 2842, + 2843, 2844, 2845, 2846, 2847, 2848, 2849, 2850, + 2851, 2852, 2853, 2854, 2855, 2856, 2857, 2858, + 2859, 2860, 2861, 2862, 2863, 2864, 2865, 2866, + 2867, 2868, 2869, 2870, 2871, 2872, 2873, 2874, + 2875, 2876, 2877, 2878, 2879, 2880, 2881, 2882, + 2883, 2884, 2885, 2886, 2887, 2888, 2889, 2890, + 2891, 2892, 2893, 2894, 2895, 2896, 2897, 2898, + 2899, 2900, 2901, 2902, 2903, 2904, 2905, 2906, + 2907, 2908, 2909, 2910, 2911, 2912, 2913, 2914, + 2915, 2916, 2917, 2918, 2919, 2920, 2921, 2922, + 2923, 2924, 2925, 2926, 2927, 2928, 2929, 2930, + 2931, 2932, 2933, 2934, 2935, 2936, 2937, 2938, + 2939, 2940, 2941, 2942, 2943, 2944, 2945, 2946, + 2947, 2948, 2949, 2950, 2951, 2952, 2953, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 0, 0, 0, + 0, 2954, 1428, 1428, 1428, 1085, 1179, 1160, + 2227, 1258, 1259, 1258, 1259, 1258, 1259, 1258, + 1259, 1258, 1259, 1085, 1085, 1258, 1259, 1258, + 1259, 1258, 1259, 1258, 1259, 1424, 2955, 2956, + 2956, 1085, 2227, 2227, 2227, 2227, 2227, 2227, + 2227, 2227, 2227, 2957, 1087, 552, 1086, 2958, + 2958, 1424, 1179, 1179, 1179, 1179, 1179, 2959, + 1085, 2960, 2961, 2962, 1179, 1160, 1428, 1085, + 77, 0, 1160, 1160, 1160, 1160, 1160, 2963, + 1160, 1160, 1160, 1160, 2964, 2965, 2966, 2967, + 2968, 2969, 2970, 2971, 2972, 2973, 2974, 2975, + 2976, 2977, 2978, 2979, 2980, 2981, 2982, 2983, + 2984, 2985, 2986, 2987, 1160, 2988, 2989, 2990, + 2991, 2992, 2993, 1160, 1160, 1160, 1160, 1160, + 2994, 2995, 2996, 2997, 2998, 2999, 3000, 3001, + 3002, 3003, 3004, 3005, 3006, 3007, 3008, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 3009, 1160, 1160, + 0, 0, 3010, 3011, 3012, 3013, 3014, 3015, + 3016, 1424, 1160, 1160, 1160, 1160, 1160, 3017, + 1160, 1160, 1160, 1160, 3018, 3019, 3020, 3021, + 3022, 3023, 3024, 3025, 3026, 3027, 3028, 3029, + 3030, 3031, 3032, 3033, 3034, 3035, 3036, 3037, + 3038, 3039, 3040, 3041, 1160, 3042, 3043, 3044, + 3045, 3046, 3047, 1160, 1160, 1160, 1160, 1160, + 3048, 3049, 3050, 3051, 3052, 3053, 3054, 3055, + 3056, 3057, 3058, 3059, 3060, 3061, 3062, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 3063, 3064, 3065, 3066, 1160, 3067, 1160, 1160, + 3068, 3069, 3070, 3071, 1428, 1179, 3072, 3073, + 3074, 0, 0, 0, 0, 0, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 0, + 0, 0, 3075, 3076, 3077, 3078, 3079, 3080, + 3081, 3082, 3083, 3084, 3085, 3086, 3087, 3088, + 3089, 3090, 3091, 3092, 3093, 3094, 3095, 3096, + 3097, 3098, 3099, 3100, 3101, 3102, 3103, 3104, + 3105, 3106, 3107, 3108, 3109, 3110, 3111, 3112, + 3113, 3114, 3115, 3116, 3117, 3118, 3119, 3120, + 3121, 3122, 3123, 3124, 3125, 3126, 3127, 3128, + 3129, 3130, 3131, 3132, 3133, 3134, 3135, 3136, + 3137, 3138, 3139, 3140, 3141, 3142, 3143, 3144, + 3145, 3146, 3147, 3148, 3149, 3150, 3151, 3152, + 3153, 3154, 3155, 3156, 3157, 3158, 3159, 3160, + 3161, 3162, 3163, 3164, 3165, 3166, 3167, 3168, + 0, 1191, 1191, 3169, 3170, 3171, 3172, 3173, + 3174, 3175, 3176, 3177, 3178, 3179, 3180, 3181, + 3182, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 0, 0, 0, 0, + 0, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 3183, 3184, 3185, 3186, 3187, 3188, 3189, + 3190, 3191, 3192, 3193, 3194, 3195, 3196, 3197, + 3198, 3199, 3200, 3201, 3202, 3203, 3204, 3205, + 3206, 3207, 3208, 3209, 3210, 3211, 3212, 3213, + 0, 3214, 3215, 3216, 3217, 3218, 3219, 3220, + 3221, 3222, 3223, 3224, 3225, 3226, 3227, 3228, + 3229, 3230, 3231, 3232, 3233, 3234, 3235, 3236, + 3237, 3238, 3239, 3240, 3241, 3242, 3243, 3244, + 3245, 3246, 3247, 3248, 3249, 3250, 3251, 3252, + 3253, 1190, 1190, 1190, 1190, 1190, 1190, 1190, + 1190, 3254, 3255, 3256, 3257, 3258, 3259, 3260, + 3261, 3262, 3263, 3264, 3265, 3266, 3267, 3268, + 3269, 3270, 3271, 3272, 3273, 3274, 3275, 3276, + 3277, 3278, 3279, 3280, 3281, 3282, 3283, 3284, + 3285, 3286, 3287, 3288, 3289, 3290, 3291, 3292, + 3293, 3294, 3295, 3296, 3297, 3298, 3299, 3300, + 1191, 3301, 3302, 3303, 3304, 3305, 3306, 3307, + 3308, 3309, 3310, 3311, 3312, 3313, 3314, 3315, + 3316, 3317, 3318, 3319, 3320, 3321, 3322, 3323, + 3324, 3325, 3326, 3327, 3328, 3329, 3330, 3331, + 3332, 3333, 3334, 3335, 3336, 3337, 3338, 3339, + 3340, 3341, 3342, 3343, 3344, 3345, 3346, 3347, + 3348, 3349, 3350, 3351, 3352, 3353, 3354, 3355, + 3356, 3357, 3358, 3359, 3360, 3361, 3362, 3363, + 3364, 3365, 3366, 3367, 3368, 3369, 3370, 3371, + 3372, 3373, 3374, 3375, 3376, 3377, 3378, 3379, + 3380, 3381, 3382, 3383, 3384, 3385, 3386, 3387, + 3388, 3389, 3390, 3391, 3392, 3393, 3394, 3395, + 3396, 3397, 3398, 3399, 3400, 3401, 3402, 3403, + 3404, 3405, 3406, 3407, 3408, 3409, 3410, 3411, + 3412, 3413, 3414, 3415, 3416, 3417, 3418, 3419, + 3420, 3421, 3422, 3423, 3424, 3425, 3426, 3427, + 0, 3428, 3429, 3430, 3431, 3432, 3433, 3434, + 3435, 3436, 3437, 3438, 3439, 3440, 3441, 3442, + 3443, 3444, 3445, 3446, 3447, 3448, 3449, 3450, + 3451, 3452, 3453, 3454, 3455, 3456, 3457, 3458, + 3459, 3460, 3461, 3462, 3463, 3464, 3465, 3466, + 3467, 3468, 3469, 3470, 3471, 3472, 3473, 3474, + 3475, 3476, 3477, 3478, 3479, 3480, 3481, 3482, + 3483, 3484, 3485, 3486, 3487, 3488, 3489, 3490, + 3491, 3492, 3493, 3494, 3495, 3496, 3497, 3498, + 3499, 3500, 3501, 3502, 3503, 3504, 3505, 3506, + 3507, 3508, 3509, 3510, 3511, 3512, 3513, 3514, + 3515, 3516, 3517, 3518, 3519, 3520, 3521, 3522, + 3523, 3524, 3525, 3526, 3527, 3528, 3529, 3530, + 3531, 3532, 3533, 3534, 3535, 3536, 3537, 3538, + 3539, 3540, 3541, 3542, 3543, 3544, 3545, 3546, + 3547, 3548, 3549, 3550, 3551, 3552, 3553, 3554, + 3555, 3556, 3557, 3558, 3559, 3560, 3561, 3562, + 3563, 3564, 3565, 3566, 3567, 3568, 3569, 3570, + 3571, 3572, 3573, 3574, 3575, 3576, 3577, 3578, + 3579, 3580, 3581, 3582, 3583, 3584, 3585, 3586, + 3587, 3588, 3589, 3590, 3591, 3592, 3593, 3594, + 3595, 3596, 3597, 3598, 3599, 3600, 3601, 3602, + 3603, 3604, 3605, 3606, 3607, 3608, 3609, 3610, + 3611, 3612, 3613, 3614, 3615, 3616, 3617, 3618, + 3619, 3620, 3621, 3622, 3623, 3624, 3625, 3626, + 3627, 3628, 3629, 3630, 3631, 3632, 3633, 3634, + 3635, 3636, 3637, 3638, 3639, 3640, 3641, 3642, + 3643, 3644, 3645, 3646, 3647, 3648, 3649, 3650, + 3651, 3652, 3653, 3654, 3655, 3656, 3657, 3658, + 3659, 3660, 3661, 3662, 3663, 3664, 3665, 3666, + 3667, 3668, 3669, 3670, 3671, 3672, 3673, 3674, + 3675, 3676, 3677, 3678, 3679, 3680, 3681, 3682, + 3683, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1179, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 0, 0, + 0, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 523, 523, 523, 523, 523, 523, 1044, + 1044, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1179, 1428, 1428, + 1428, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1178, 1178, 1160, 1160, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3684, 3685, 3686, 3687, 3688, 3689, 3690, + 3691, 3692, 3693, 3694, 3695, 3696, 3697, 3698, + 3699, 3700, 3701, 3702, 3703, 3704, 3705, 3706, + 3707, 3708, 3709, 3710, 3711, 3712, 3713, 3714, + 3715, 3716, 3717, 3718, 3719, 3720, 3721, 3722, + 3723, 3724, 3725, 3726, 3727, 3728, 3729, 1160, + 540, 839, 839, 839, 9, 540, 540, 540, + 540, 540, 540, 540, 540, 540, 540, 9, + 522, 3730, 3731, 3732, 3733, 3734, 3735, 3736, + 3737, 3738, 3739, 3740, 3741, 3742, 3743, 3744, + 3745, 3746, 3747, 3748, 3749, 3750, 3751, 3752, + 3753, 3754, 3755, 3756, 3757, 3758, 3759, 540, + 540, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 1426, + 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, + 1426, 540, 540, 1044, 1044, 1044, 1044, 1044, + 1044, 0, 0, 0, 0, 0, 0, 0, + 0, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, + 522, 522, 522, 522, 522, 522, 522, 522, + 522, 47, 47, 3760, 3761, 3762, 3763, 3764, + 3765, 3766, 3767, 3768, 3769, 3770, 3771, 3772, + 3773, 214, 214, 3774, 3775, 3776, 3777, 3778, + 3779, 3780, 3781, 3782, 3783, 3784, 3785, 3786, + 3787, 3788, 3789, 3790, 3791, 3792, 3793, 3794, + 3795, 3796, 3797, 3798, 3799, 3800, 3801, 3802, + 3803, 3804, 3805, 3806, 3807, 3808, 3809, 3810, + 3811, 3812, 3813, 3814, 3815, 3816, 3817, 3818, + 3819, 3820, 3821, 3822, 3823, 3824, 3825, 3826, + 3827, 3828, 3829, 3830, 3831, 3832, 3833, 3834, + 3835, 3836, 1523, 1523, 1523, 1523, 1523, 1523, + 1523, 214, 3837, 3838, 3839, 3840, 3841, 3842, + 3843, 3844, 3845, 3846, 3847, 3848, 3849, 3850, + 3851, 522, 3852, 3852, 3853, 3854, 3855, 214, + 340, 3856, 3857, 3858, 3859, 214, 214, 3860, + 3861, 3862, 3863, 3864, 3865, 3866, 3867, 3868, + 3869, 3870, 3871, 3872, 3873, 3874, 3875, 3876, + 3877, 3878, 3879, 3880, 3881, 3882, 3883, 3884, + 0, 3885, 3886, 3887, 3888, 3889, 3890, 3891, + 3892, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 340, 3893, 3894, 214, 340, 340, 340, 340, + 1160, 1160, 1160, 1153, 1160, 1160, 1160, 1168, + 1160, 1160, 1160, 1160, 1153, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1159, 1159, 1153, 1153, + 1159, 77, 77, 1085, 1085, 0, 0, 0, + 0, 1190, 1190, 1190, 1190, 1190, 1190, 1191, + 1191, 1189, 3895, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1428, 1428, 1428, + 1428, 0, 0, 0, 0, 0, 0, 0, + 0, 1159, 1159, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1159, 1159, 1159, + 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, + 1159, 1159, 1159, 1159, 1159, 1168, 1153, 0, + 0, 0, 0, 0, 0, 0, 0, 1177, + 1177, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1178, 1178, 0, 0, 0, 0, 0, + 0, 540, 540, 540, 540, 540, 540, 540, + 540, 540, 540, 540, 540, 540, 540, 540, + 540, 540, 540, 1160, 1160, 1160, 1160, 1160, + 1160, 1177, 1177, 1177, 1160, 1177, 1160, 0, + 0, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1178, 1178, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1153, + 1153, 1153, 1153, 1153, 553, 553, 553, 1177, + 1177, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, + 1153, 1153, 1153, 1159, 1452, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1177, 1327, 1327, 1327, 1327, 1327, 1327, 1327, + 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, + 1327, 1327, 1327, 1327, 1327, 1327, 1327, 1327, + 1327, 1327, 1327, 1327, 1327, 1327, 0, 0, + 0, 1153, 1153, 1153, 1159, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1180, 1159, 1159, 1153, + 1153, 1153, 1153, 1159, 1159, 1153, 1159, 1159, + 1159, 1452, 1177, 1177, 1177, 1177, 1177, 1177, + 1177, 1177, 1177, 1177, 1177, 1177, 1177, 0, + 1179, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1178, 1178, 0, 0, 0, 0, 1177, + 1177, 340, 1160, 1160, 1160, 1160, 1153, 523, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 340, 1250, 1250, 1250, 1250, 1250, 1250, 1250, + 1250, 1250, 1178, 1160, 1160, 1160, 340, 1160, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1153, 1153, 1153, 1153, 1153, 1153, + 1159, 1159, 1153, 1153, 1159, 1159, 1153, 1153, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1153, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1153, 1159, 0, + 0, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1178, 1178, 0, 0, 1177, 1177, 1177, + 1177, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1179, 1160, 1160, 1160, 1160, 1160, 1160, + 1191, 1191, 1191, 1160, 1284, 1153, 1284, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 540, 1160, 540, 540, 553, 1160, 1160, + 540, 540, 1160, 1160, 1160, 1160, 1160, 540, + 540, 1160, 540, 1160, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1160, 1160, 1179, 1177, + 1177, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1159, 1153, 1153, 1159, + 1159, 1177, 1177, 1160, 1179, 1179, 1159, 1168, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1160, 1160, 1160, 1160, 1160, 1160, + 0, 0, 1160, 1160, 1160, 1160, 1160, 1160, + 0, 0, 1160, 1160, 1160, 1160, 1160, 1160, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 0, 214, 214, 214, 214, 214, 214, 214, + 214, 214, 214, 214, 214, 214, 214, 214, + 214, 214, 214, 214, 214, 214, 214, 214, + 214, 214, 214, 214, 214, 214, 214, 214, + 214, 214, 214, 214, 3896, 214, 214, 214, + 214, 214, 214, 214, 3852, 3897, 3898, 3899, + 3900, 214, 214, 214, 214, 214, 214, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3901, 3902, 3903, 3904, 3905, 3906, 3907, + 3908, 3909, 3910, 3911, 3912, 3913, 3914, 3915, + 3916, 3917, 3918, 3919, 3920, 3921, 3922, 3923, + 3924, 3925, 3926, 3927, 3928, 3929, 3930, 3931, + 3932, 3933, 3934, 3935, 3936, 3937, 3938, 3939, + 3940, 3941, 3942, 3943, 3944, 3945, 3946, 3947, + 3948, 3949, 3950, 3951, 3952, 3953, 3954, 3955, + 3956, 3957, 3958, 3959, 3960, 3961, 3962, 3963, + 3964, 3965, 3966, 3967, 3968, 3969, 3970, 3971, + 3972, 3973, 3974, 3975, 3976, 3977, 3978, 3979, + 3980, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1159, 1159, 1153, 1159, + 1159, 1153, 1159, 1159, 1177, 1159, 1168, 0, + 0, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1178, 1178, 0, 0, 0, 0, 0, + 0, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3981, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3981, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 3982, 3982, 3982, + 3982, 3982, 3982, 3982, 3982, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1330, 1330, 1330, 1330, 1330, 1330, 1330, + 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, + 1330, 1330, 1330, 1330, 1330, 1330, 1330, 1330, + 0, 0, 0, 0, 1331, 1331, 1331, 1331, + 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, + 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, + 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, + 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, + 1331, 1331, 1331, 1331, 1331, 1331, 1331, 1331, + 1331, 1331, 1331, 1331, 1331, 0, 0, 0, + 0, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3983, 3983, 3983, 3983, 3983, 3983, 3983, + 3983, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3985, 3986, 3987, 3988, 3989, 3990, 3991, + 3992, 3992, 3993, 3994, 3995, 3996, 3997, 3998, + 3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, + 4007, 4008, 4009, 4010, 4011, 4012, 4013, 4014, + 4015, 4016, 4017, 4018, 4019, 4020, 4021, 4022, + 4023, 4024, 4025, 4026, 4027, 4028, 4029, 4030, + 4031, 4032, 4033, 4034, 4035, 4036, 4037, 4038, + 4039, 4040, 4041, 4042, 4043, 4044, 4045, 4046, + 4047, 4048, 4049, 4050, 4051, 4052, 4053, 4054, + 4055, 4056, 4057, 4058, 4059, 4060, 4061, 4062, + 4063, 4064, 4065, 4066, 4067, 4068, 4069, 4070, + 4071, 4072, 4073, 4074, 4075, 4004, 4076, 4077, + 4078, 4079, 4080, 4081, 4082, 4083, 4084, 4085, + 4086, 4087, 4088, 4089, 4090, 4091, 4092, 4093, + 4094, 4095, 4096, 4097, 4098, 4099, 4100, 4101, + 4102, 4103, 4104, 4105, 4106, 4107, 4108, 4109, + 4110, 4111, 4112, 4113, 4114, 4115, 4116, 4117, + 4118, 4119, 4120, 4121, 4122, 4123, 4124, 4125, + 4126, 4127, 4128, 4129, 4130, 4131, 4132, 4133, + 4134, 4135, 4136, 4137, 4138, 4139, 4140, 4141, + 4142, 4143, 4094, 4144, 4145, 4146, 4147, 4148, + 4149, 4150, 4151, 4078, 4152, 4153, 4154, 4155, + 4156, 4157, 4158, 4159, 4160, 4161, 4162, 4163, + 4164, 4165, 4166, 4167, 4168, 4169, 4170, 4171, + 4004, 4172, 4173, 4174, 4175, 4176, 4177, 4178, + 4179, 4180, 4181, 4182, 4183, 4184, 4185, 4186, + 4187, 4188, 4189, 4190, 4191, 4192, 4193, 4194, + 4195, 4196, 4197, 4198, 4080, 4199, 4200, 4201, + 4202, 4203, 4204, 4205, 4206, 4207, 4208, 4209, + 4210, 4211, 4212, 4213, 4214, 4215, 4216, 4217, + 4218, 4219, 4220, 4221, 4222, 4223, 4224, 4225, + 4226, 4227, 4228, 4229, 4230, 4231, 4232, 4233, + 4234, 4235, 4236, 4237, 4238, 4239, 4240, 4241, + 4242, 4243, 4244, 4245, 4246, 4247, 4248, 1160, + 1160, 4249, 1160, 4250, 1160, 1160, 4251, 4252, + 4253, 4254, 4255, 4256, 4257, 4258, 4259, 4260, + 1160, 4261, 1160, 4262, 1160, 1160, 4263, 4264, + 1160, 1160, 1160, 4265, 4266, 4267, 4268, 4269, + 4270, 4271, 4272, 4273, 4274, 4275, 4276, 4277, + 4278, 4279, 4280, 4281, 4282, 4283, 4284, 4285, + 4286, 4287, 4288, 4289, 4290, 4291, 4292, 4293, + 4294, 4295, 4296, 4297, 4298, 4299, 4300, 4301, + 4302, 4303, 4304, 4305, 4306, 4307, 4308, 4309, + 4133, 4310, 4311, 4312, 4313, 4314, 4315, 4315, + 4316, 4317, 4318, 4319, 4320, 4321, 4322, 4323, + 4263, 4324, 4325, 4326, 4327, 4328, 4329, 0, + 0, 4330, 4331, 4332, 4333, 4334, 4335, 4336, + 4337, 4277, 4338, 4339, 4340, 4249, 4341, 4342, + 4343, 4344, 4345, 4346, 4347, 4348, 4349, 4350, + 4351, 4352, 4286, 4353, 4287, 4354, 4355, 4356, + 4357, 4358, 4250, 4025, 4359, 4360, 4361, 4095, + 4182, 4362, 4363, 4294, 4364, 4295, 4365, 4366, + 4367, 4252, 4368, 4369, 4370, 4371, 4372, 4253, + 4373, 4374, 4375, 4376, 4377, 4378, 4309, 4379, + 4380, 4133, 4381, 4313, 4382, 4383, 4384, 4385, + 4386, 4318, 4387, 4262, 4388, 4319, 4076, 4389, + 4320, 4390, 4322, 4391, 4392, 4393, 4394, 4395, + 4324, 4258, 4396, 4325, 4397, 4326, 4398, 3992, + 4399, 4400, 4401, 4402, 4403, 4404, 4405, 4406, + 4407, 4408, 4409, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4410, 4411, 4412, 4413, 4414, 4415, 4416, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4417, 4418, 4419, 4420, + 4421, 0, 0, 0, 0, 0, 4422, 4423, + 4424, 4425, 4426, 4427, 4428, 4429, 4430, 4431, + 4432, 4433, 4434, 4435, 4436, 4437, 4438, 4439, + 4440, 4441, 4442, 4443, 4444, 4445, 4446, 4447, + 0, 4448, 4449, 4450, 4451, 4452, 0, 4453, + 0, 4454, 4455, 0, 4456, 4457, 0, 4458, + 4459, 4460, 4461, 4462, 4463, 4464, 4465, 4466, + 4467, 4468, 4469, 4470, 4471, 4472, 4473, 4474, + 4475, 4476, 4477, 4478, 4479, 4480, 4481, 4482, + 4483, 4484, 4485, 4486, 4487, 4488, 4489, 4490, + 4491, 4492, 4493, 4494, 4495, 4496, 4497, 4498, + 4499, 4500, 4501, 4502, 4503, 4504, 4505, 4506, + 4507, 4508, 4509, 4510, 4511, 4512, 4513, 4514, + 4515, 4516, 4517, 4518, 4519, 4520, 4521, 4522, + 4523, 4524, 4525, 4526, 4527, 4528, 4529, 4530, + 4531, 4532, 4533, 4534, 4535, 4536, 4537, 4538, + 4539, 4540, 4541, 4542, 4543, 4544, 4545, 4546, + 4547, 4548, 4549, 4550, 4551, 4552, 4553, 4554, + 4555, 4556, 4557, 4558, 4559, 4560, 4561, 4562, + 4563, 4564, 4565, 4566, 4566, 4566, 4566, 4566, + 4566, 4566, 4566, 4566, 4566, 4566, 4566, 4566, + 4566, 4566, 4566, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4567, 4568, 4569, 4570, + 4571, 4572, 4573, 4574, 4575, 4576, 4577, 4578, + 4579, 4580, 4581, 4582, 4583, 4584, 4585, 4586, + 4587, 4588, 4589, 4590, 4591, 4592, 4593, 4594, + 4595, 4596, 4597, 4598, 4599, 4600, 4601, 4602, + 4603, 4604, 4605, 4606, 4607, 4608, 4609, 4610, + 4611, 4612, 4613, 4614, 4605, 4615, 4616, 4617, + 4618, 4619, 4620, 4621, 4622, 4623, 4624, 4625, + 4626, 4627, 4628, 4629, 4630, 4631, 4632, 4633, + 4634, 4635, 4636, 4637, 4638, 4639, 4640, 4641, + 4642, 4643, 4644, 4645, 4646, 4647, 4648, 4649, + 4650, 4651, 4652, 4653, 4654, 4655, 4656, 4657, + 4658, 4659, 4660, 4661, 4662, 4663, 4664, 4665, + 4666, 4667, 4668, 4669, 4670, 4671, 4672, 4673, + 4674, 4675, 4676, 4677, 4678, 4679, 4680, 4681, + 4682, 4683, 4684, 4685, 4686, 4687, 4688, 4689, + 4690, 4691, 4692, 4693, 4694, 4695, 4696, 4697, + 4698, 4699, 4700, 4701, 4702, 4703, 4704, 4705, + 4706, 4707, 4708, 4709, 4710, 4711, 4712, 4713, + 4714, 4606, 4715, 4716, 4717, 4718, 4719, 4720, + 4721, 4722, 4723, 4724, 4725, 4726, 4727, 4728, + 4729, 4730, 4731, 4732, 4733, 4734, 4735, 4736, + 4737, 4738, 4739, 4740, 4741, 4742, 4743, 4744, + 4745, 4746, 4747, 4748, 4749, 4750, 4751, 4752, + 4753, 4754, 4755, 4756, 4757, 4758, 4759, 4760, + 4761, 4762, 4763, 4764, 4765, 4766, 4767, 4768, + 4769, 4770, 4771, 4772, 4773, 4774, 4775, 4776, + 4777, 4778, 4779, 4780, 4781, 4782, 4783, 4784, + 4785, 4786, 4787, 4788, 4789, 4790, 4791, 4792, + 4793, 4794, 4795, 4796, 4797, 4798, 4799, 4800, + 4801, 4802, 4803, 4804, 4805, 4806, 4807, 4808, + 4809, 4810, 4811, 4812, 4813, 4814, 4815, 4816, + 4817, 4818, 4819, 4820, 4821, 4822, 4823, 4824, + 4825, 4826, 4827, 4828, 4829, 4830, 4831, 4832, + 4833, 4834, 4835, 4836, 4837, 4838, 4839, 4840, + 4841, 4842, 4843, 4844, 4845, 4846, 4847, 4848, + 4849, 4850, 4851, 4852, 4853, 4854, 4855, 4856, + 4857, 4858, 4859, 4860, 4861, 4862, 4863, 4864, + 4865, 4866, 4867, 4868, 4869, 4870, 4871, 4872, + 4873, 4874, 4875, 4876, 4877, 4878, 4879, 4880, + 4881, 4882, 4883, 4884, 4885, 4886, 4887, 4888, + 4889, 4890, 4891, 4892, 4893, 4894, 4895, 4896, + 4897, 4898, 4899, 4900, 4901, 4902, 4903, 4904, + 4905, 4906, 4907, 4908, 4909, 4910, 4911, 4912, + 4913, 4914, 4915, 4916, 4917, 4918, 4919, 4920, + 4921, 4922, 4923, 4924, 4925, 4926, 4927, 2956, + 2955, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 4928, 4929, 4930, 4931, 4932, 4933, 4934, + 4935, 4936, 4937, 4938, 4939, 4940, 4941, 4942, + 4943, 4944, 4945, 4946, 4947, 4948, 4949, 4950, + 4951, 4952, 4953, 4954, 4955, 4956, 4957, 4958, + 4959, 4960, 4961, 4962, 4963, 4964, 4965, 4966, + 4967, 4968, 4969, 4970, 4971, 4972, 4973, 4974, + 4975, 4976, 4977, 4978, 4979, 4980, 4981, 4982, + 4983, 4984, 4985, 4986, 4987, 4988, 4989, 4990, + 4991, 0, 0, 4992, 4993, 4994, 4995, 4996, + 4997, 4998, 4999, 5000, 5001, 5002, 5003, 5004, + 5005, 5006, 5007, 5008, 5009, 5010, 5011, 5012, + 5013, 5014, 5015, 5016, 5017, 5018, 5019, 5020, + 5021, 5022, 5023, 5024, 5025, 5026, 5027, 5028, + 5029, 5030, 5031, 5032, 5033, 5034, 5035, 5036, + 5037, 5038, 5039, 5040, 5041, 5042, 5043, 5044, + 5045, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5046, 5047, 5048, 5049, 5050, 5051, 5052, + 5053, 5054, 5055, 5056, 5057, 5058, 1085, 0, + 0, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 5059, 5060, 5061, 5062, 5063, 5064, 5065, + 5066, 5067, 5068, 0, 0, 0, 0, 0, + 0, 540, 540, 540, 540, 540, 540, 540, + 553, 553, 553, 553, 553, 553, 553, 540, + 540, 5069, 5070, 5071, 5072, 5072, 5073, 5074, + 5075, 5076, 5077, 5078, 5079, 5080, 5081, 5082, + 5083, 5084, 5085, 5086, 5087, 5088, 1428, 1428, + 5089, 5090, 5091, 5091, 5091, 5091, 5092, 5092, + 5092, 5093, 5094, 5095, 0, 5096, 5097, 5098, + 5099, 5100, 5101, 5102, 5103, 5104, 5105, 5106, + 5107, 5108, 5109, 5110, 5111, 5112, 5113, 5114, + 0, 5115, 5116, 5117, 5118, 0, 0, 0, + 0, 5119, 5120, 5121, 1118, 5122, 0, 5123, + 5124, 5125, 5126, 5127, 5128, 5129, 5130, 5131, + 5132, 5133, 5134, 5135, 5136, 5137, 5138, 5139, + 5140, 5141, 5142, 5143, 5144, 5145, 5146, 5147, + 5148, 5149, 5150, 5151, 5152, 5153, 5154, 5155, + 5156, 5157, 5158, 5159, 5160, 5161, 5162, 5163, + 5164, 5165, 5166, 5167, 5168, 5169, 5170, 5171, + 5172, 5173, 5174, 5175, 5176, 5177, 5178, 5179, + 5180, 5181, 5182, 5183, 5184, 5185, 5186, 5187, + 5188, 5189, 5190, 5191, 5192, 5193, 5194, 5195, + 5196, 5197, 5198, 5199, 5200, 5201, 5202, 5203, + 5204, 5205, 5206, 5207, 5208, 5209, 5210, 5211, + 5212, 5213, 5214, 5215, 5216, 5217, 5218, 5219, + 5220, 5221, 5222, 5223, 5224, 5225, 5226, 5227, + 5228, 5229, 5230, 5231, 5232, 5233, 5234, 5235, + 5236, 5237, 5238, 5239, 5240, 5241, 5242, 5243, + 5244, 5245, 5246, 5247, 5248, 5249, 5250, 5251, + 5252, 5253, 5254, 5255, 5256, 5257, 0, 0, + 81, 0, 5258, 5259, 5260, 5261, 5262, 5263, + 5264, 5265, 5266, 5267, 5268, 5269, 5270, 5271, + 5272, 5273, 5274, 5275, 5276, 5277, 5278, 5279, + 5280, 5281, 5282, 5283, 5284, 5285, 5286, 5287, + 5288, 5289, 5290, 5291, 5292, 5293, 5294, 5295, + 5296, 5297, 5298, 5299, 5300, 5301, 5302, 5303, + 5304, 5305, 5306, 5307, 5308, 5309, 5310, 5311, + 5312, 5313, 5314, 5315, 5316, 5317, 5318, 5319, + 5320, 5321, 5322, 5323, 5324, 5325, 5326, 5327, + 5328, 5329, 5330, 5331, 5332, 5333, 5334, 5335, + 5336, 5337, 5338, 5339, 5340, 5341, 5342, 5343, + 5344, 5345, 5346, 5347, 5348, 5349, 5350, 5351, + 5352, 5353, 5354, 5355, 5356, 5357, 5358, 5359, + 5360, 5361, 5362, 5363, 5364, 5365, 5366, 5367, + 5368, 5369, 5370, 5371, 5372, 5373, 5374, 5375, + 5376, 5377, 5378, 5379, 5380, 5381, 5382, 5383, + 5384, 5385, 5386, 5387, 5388, 5389, 5390, 5391, + 5392, 5393, 5394, 5395, 5396, 5397, 5398, 5399, + 5400, 5401, 5402, 5403, 5404, 5405, 5406, 5407, + 5408, 5409, 5410, 5411, 5412, 5413, 5414, 5415, + 5416, 5417, 5418, 5419, 5420, 5421, 5422, 5423, + 5424, 5425, 5426, 5427, 5428, 5429, 5430, 5431, + 5432, 5433, 5434, 5435, 5436, 5437, 5438, 5439, + 5440, 5441, 5442, 5443, 5444, 5445, 5446, 5447, + 0, 0, 0, 5448, 5449, 5450, 5451, 5452, + 5453, 0, 0, 5454, 5455, 5456, 5457, 5458, + 5459, 0, 0, 5460, 5461, 5462, 5463, 5464, + 5465, 0, 0, 5466, 5467, 5468, 0, 0, + 0, 5469, 5470, 5471, 5472, 5473, 5474, 5475, + 0, 5476, 5477, 5478, 5479, 5480, 5481, 5482, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5483, 5483, 5483, 1085, 77, 0, + 0, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 0, 340, 1160, + 1160, 340, 340, 340, 1160, 340, 340, 340, + 340, 340, 340, 340, 340, 1160, 340, 340, + 340, 340, 340, 1160, 1160, 1160, 340, 340, + 0, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 1160, + 340, 340, 340, 340, 0, 340, 340, 0, + 340, 340, 1160, 340, 340, 1160, 1160, 1160, + 340, 340, 340, 1160, 1160, 340, 1160, 0, + 0, 340, 340, 1160, 340, 340, 1160, 340, + 1160, 1160, 1160, 340, 1160, 1160, 1160, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 340, 340, 1160, 1160, 1160, 1160, 340, + 340, 340, 340, 1160, 1160, 1160, 1160, 1160, + 340, 1160, 340, 340, 340, 340, 1160, 1160, + 1160, 1160, 1160, 340, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 340, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 340, 1160, 340, 1160, + 1160, 1160, 1160, 1160, 340, 340, 1160, 1160, + 1160, 1160, 1160, 1160, 340, 1160, 1160, 1160, + 1160, 1160, 340, 340, 340, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 340, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 0, 0, 0, 0, + 0, 1044, 9, 1044, 0, 0, 0, 0, + 5484, 5484, 5484, 5484, 5484, 5484, 5484, 5484, + 5484, 5484, 5484, 5484, 5484, 5484, 5484, 5484, + 5484, 5484, 5484, 5484, 5484, 5484, 5484, 5484, + 5484, 5484, 1190, 5484, 1190, 5484, 1190, 1190, + 1190, 1190, 1190, 1190, 5484, 1190, 5484, 1190, + 1190, 1190, 1190, 1190, 1190, 0, 0, 0, + 1191, 838, 1191, 838, 838, 838, 838, 838, + 1191, 5485, 5485, 5485, 5485, 5485, 5485, 5485, + 5485, 5485, 5485, 5485, 5485, 5485, 5485, 5485, + 5485, 5485, 5485, 5485, 5485, 5485, 5485, 5485, + 5485, 5485, 5485, 5485, 5485, 5485, 5485, 5485, + 5485, 5485, 5485, 5485, 5485, 5485, 5485, 5485, + 5485, 5485, 5486, 5486, 5486, 5486, 5486, 5486, + 5485, 5486, 5485, 5485, 5485, 5485, 1427, 1427, + 1220, 1427, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 1085, 77, 1427, 1427, 77, 838, 838, + 0, 77, 77, 77, 77, 77, 77, 77, + 1085, 1085, 1085, 77, 77, 0, 0, 0, + 0, 77, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 553, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 1160, + 1160, 340, 340, 340, 340, 340, 340, 340, + 340, 1160, 340, 1160, 340, 340, 0, 0, + 0, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 1160, 340, 340, 340, 340, 340, 340, + 1160, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 553, 5487, 5487, 5487, 5487, 5487, 5487, + 5487, 5487, 5487, 5487, 5487, 5487, 5487, 5487, + 5487, 5487, 5487, 5487, 5487, 5487, 5487, 5487, + 5487, 5487, 5487, 5487, 5487, 0, 0, 0, + 0, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 5484, 5484, 5484, 5484, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 1426, 340, 340, 340, 340, 340, + 340, 340, 340, 1426, 0, 0, 0, 0, + 0, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 540, + 540, 540, 540, 540, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 0, + 1177, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1177, 2227, 2227, 2227, 2227, 2227, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5488, 5489, 5490, 5491, 5492, 5493, 5494, + 5495, 5496, 5497, 5498, 5499, 5500, 5501, 5502, + 5503, 5504, 5505, 5506, 5507, 5508, 5509, 5510, + 5511, 5512, 5513, 5514, 5515, 5516, 5517, 5518, + 5519, 5520, 5521, 5522, 5523, 5524, 5525, 5526, + 5527, 5528, 5529, 5530, 5531, 5532, 5533, 5534, + 5535, 5536, 5537, 5538, 5539, 5540, 5541, 5542, + 5543, 5544, 5545, 5546, 5547, 5548, 5549, 5550, + 5551, 5552, 5553, 5554, 5555, 5556, 5557, 5558, + 5559, 5560, 5561, 5562, 5563, 5564, 5565, 5566, + 5567, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 1160, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 1160, + 340, 1160, 340, 340, 1160, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 1160, 0, + 0, 1250, 1250, 1250, 1250, 1250, 1250, 1250, + 1250, 1250, 1250, 0, 0, 0, 0, 0, + 0, 5568, 5569, 5570, 5571, 5572, 5573, 5574, + 5575, 5576, 5577, 5578, 5579, 5580, 5581, 5582, + 5583, 5584, 5585, 5586, 5587, 5588, 5589, 5590, + 5591, 5592, 5593, 5594, 5595, 5596, 5597, 5598, + 5599, 5600, 5601, 5602, 5603, 0, 0, 0, + 0, 5604, 5605, 5606, 5607, 5608, 5609, 5610, + 5611, 5612, 5613, 5614, 5615, 5616, 5617, 5618, + 5619, 5620, 5621, 5622, 5623, 5624, 5625, 5626, + 5627, 5628, 5629, 5630, 5631, 5632, 5633, 5634, + 5635, 5636, 5637, 5638, 5639, 0, 0, 0, + 0, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1044, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 1160, 340, 340, 340, + 340, 1160, 340, 1160, 1160, 1160, 340, 340, + 340, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 340, 340, 1160, 340, 340, 1160, 1160, + 340, 340, 1160, 1160, 1160, 1160, 340, 1160, + 340, 340, 340, 340, 340, 1160, 1160, 1160, + 340, 1160, 340, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 340, 1160, 1160, 1160, 340, + 1160, 1160, 340, 340, 1160, 1160, 1160, 1160, + 1160, 1160, 340, 340, 1160, 1160, 1160, 340, + 340, 340, 340, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 340, 1160, 1160, 1160, 1160, + 340, 1160, 1160, 340, 340, 340, 1160, 1160, + 1160, 1160, 340, 340, 340, 1160, 1160, 1160, + 1160, 340, 1160, 1160, 1160, 1160, 1160, 1160, + 340, 1160, 1160, 1160, 1160, 1160, 340, 340, + 1160, 1160, 340, 1160, 1160, 340, 1160, 1160, + 1160, 1160, 1160, 340, 1160, 1160, 1160, 340, + 1160, 1160, 340, 1160, 1160, 340, 1160, 340, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 340, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 340, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 340, 340, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 340, 1160, + 340, 340, 340, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 340, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 340, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 1160, 1160, 1160, 1160, 1160, 1160, + 340, 340, 1160, 1160, 340, 1160, 340, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1156, 1156, 1156, 1106, 1156, 1106, 0, + 0, 1156, 0, 1106, 1156, 1156, 1156, 1156, + 1156, 1106, 1156, 1106, 1156, 1156, 1156, 1156, + 1156, 1156, 1106, 1156, 1156, 1156, 1156, 1106, + 1156, 1106, 1156, 1156, 1106, 1106, 1156, 1106, + 1156, 1106, 1106, 1106, 1106, 1156, 1106, 1106, + 1106, 1106, 1106, 1156, 1106, 1156, 1106, 0, + 1156, 1106, 0, 0, 0, 1156, 0, 0, + 1156, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 1106, 1106, 1106, 0, + 1103, 5640, 5640, 5640, 5640, 5640, 5640, 5640, + 5640, 1156, 1156, 1156, 1106, 1106, 1106, 1106, + 1156, 1106, 1106, 1156, 1106, 1156, 1106, 1106, + 1156, 1156, 1106, 1156, 1156, 1106, 1156, 1156, + 5641, 5641, 5640, 5640, 5642, 5642, 5642, 5642, + 5640, 1156, 1106, 1156, 1156, 1156, 1106, 1106, + 1106, 1106, 1106, 1156, 1156, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1156, + 1156, 1106, 1156, 1156, 1106, 1106, 1106, 1106, + 0, 0, 0, 0, 0, 0, 0, 0, + 5640, 5640, 5640, 5640, 5640, 5640, 5640, 5640, + 5640, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 0, 1106, 1106, 0, + 0, 0, 0, 0, 5640, 5640, 5640, 5640, + 5640, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 1106, 1106, 1106, 5640, + 5640, 5640, 5640, 5640, 5640, 0, 0, 0, + 9, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 0, 0, 0, 0, 0, + 1103, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1156, 1106, 1156, 1156, 1156, 1156, 1156, + 1106, 1156, 1156, 1156, 1156, 1156, 1156, 1156, + 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, + 1106, 1156, 1156, 1156, 1156, 1156, 1156, 1106, + 1156, 1156, 1106, 1156, 1106, 1156, 1106, 1106, + 1106, 1106, 1156, 1106, 1156, 1106, 1156, 1106, + 1106, 1106, 1156, 1106, 1156, 1106, 1156, 1156, + 1106, 0, 0, 0, 0, 5642, 5640, 1106, + 1156, 5640, 5640, 5640, 5640, 5642, 5642, 5642, + 5640, 5640, 5642, 5642, 5642, 5642, 5642, 5642, + 5642, 0, 0, 5642, 5642, 5642, 5642, 5642, + 5642, 5642, 5642, 5642, 5642, 5642, 5642, 5642, + 5642, 5642, 5642, 5642, 5642, 5642, 5642, 5642, + 5642, 5642, 5642, 5642, 5642, 5642, 5642, 5642, + 5642, 5642, 5642, 5642, 5642, 5642, 5642, 5640, + 5640, 5640, 5640, 5642, 5640, 5642, 5642, 5642, + 5642, 1156, 1153, 1153, 1153, 0, 1153, 1153, + 0, 0, 0, 0, 0, 1153, 553, 1153, + 540, 1156, 1156, 1156, 1156, 0, 1156, 1156, + 1156, 0, 1156, 1156, 1156, 1156, 1156, 1156, + 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, + 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, + 1156, 1156, 1156, 1156, 1156, 0, 0, 0, + 0, 540, 566, 553, 0, 0, 0, 0, + 1168, 5642, 5642, 5642, 5642, 5642, 5642, 5642, + 5642, 0, 0, 0, 0, 0, 0, 0, + 0, 1158, 1158, 1158, 1158, 1158, 1158, 1158, + 1158, 1158, 0, 0, 0, 0, 0, 0, + 0, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 1106, 1106, 5640, 5640, + 1103, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 1106, 1106, 5640, 5640, + 5640, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1106, 1156, 1156, 1106, 1106, 1106, 1156, + 1106, 5643, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1156, 1156, 1156, 1106, 1156, 1156, 1156, + 1106, 1156, 1156, 1156, 1156, 1156, 1156, 1156, + 1156, 1156, 1106, 1156, 1156, 1106, 540, 553, + 0, 0, 0, 0, 5640, 5642, 5642, 5642, + 5642, 1158, 1158, 1158, 1158, 1103, 1103, 1103, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1106, 1156, 1156, 1156, 1156, 1106, 1106, + 1106, 1156, 1156, 1156, 1156, 1106, 1106, 1106, + 1106, 1106, 1156, 1156, 1156, 1156, 1106, 1156, + 1106, 1106, 1106, 1106, 1156, 1106, 1106, 1106, + 1106, 1156, 1156, 1106, 1106, 1106, 1106, 1106, + 1156, 1106, 1106, 1156, 1156, 1106, 1106, 1106, + 1106, 1106, 1156, 1156, 1156, 1156, 1156, 0, + 0, 0, 9, 9, 9, 9, 9, 9, + 9, 1156, 1156, 1106, 1106, 1156, 1106, 1106, + 1106, 1156, 1106, 1156, 1106, 1156, 1156, 1106, + 1106, 1156, 1156, 1106, 1106, 1106, 1106, 0, + 0, 5640, 5640, 5640, 5640, 5640, 5640, 5642, + 5640, 1106, 1106, 1106, 1106, 1156, 1106, 1106, + 1156, 1106, 1106, 1106, 1106, 1156, 1106, 1156, + 1106, 1106, 1156, 1106, 0, 0, 0, 0, + 0, 5640, 5640, 5640, 5640, 5640, 5640, 5640, + 5640, 1106, 1156, 1106, 1156, 1106, 1106, 1106, + 1156, 1106, 1156, 1106, 1106, 1106, 1156, 1106, + 1106, 1156, 1106, 0, 0, 0, 0, 0, + 0, 0, 1158, 1158, 1158, 1158, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 5640, 5640, 5640, 5642, 5640, 5640, + 5642, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, + 1106, 1106, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5644, 5645, 5646, 5647, 5648, 5649, 5650, + 5651, 5652, 5653, 5654, 5655, 5656, 5657, 5658, + 5659, 5660, 5661, 5662, 5663, 5664, 5665, 5666, + 5667, 5668, 5669, 5670, 5671, 5672, 5673, 5674, + 5675, 5676, 5677, 5678, 5679, 5680, 5681, 5682, + 5683, 5684, 5685, 5686, 5687, 5688, 5689, 5690, + 5691, 5692, 5693, 5694, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5695, 5696, 5697, 5698, 5699, 5700, 5701, + 5702, 5703, 5704, 5705, 5706, 5707, 5708, 5709, + 5710, 5711, 5712, 5713, 5714, 5715, 5716, 5717, + 5718, 5719, 5720, 5721, 5722, 5723, 5724, 5725, + 5726, 5727, 5728, 5729, 5730, 5731, 5732, 5733, + 5734, 5735, 5736, 5737, 5738, 5739, 5740, 5741, + 5742, 5743, 5744, 5745, 0, 0, 0, 0, + 0, 0, 0, 5640, 5640, 5640, 5640, 5640, + 5640, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5746, 5746, 5747, 5746, 5746, 5746, 5746, + 5746, 5747, 5746, 5746, 5747, 5747, 5747, 5746, + 5746, 5747, 5746, 5746, 5746, 5747, 5747, 5746, + 5747, 5747, 5746, 5746, 5747, 5747, 5747, 5747, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1159, 1153, 1159, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1153, 1153, 1153, 1153, 1153, 1153, 1153, + 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1168, + 1177, 1177, 1177, 1177, 1177, 1177, 1177, 0, + 0, 0, 0, 1220, 1220, 1220, 1220, 1220, + 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1220, + 1220, 1220, 1220, 1220, 1220, 1220, 1220, 1178, + 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1168, 1153, 1153, 1159, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 5748, 5749, 5750, 5751, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 5752, 1160, + 1160, 1160, 1160, 1160, 5753, 1160, 1160, 1160, + 1160, 1159, 1159, 1159, 1153, 1153, 1153, 1153, + 1159, 1159, 1168, 5754, 1177, 1177, 5755, 1177, + 1177, 1177, 1177, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 0, 0, 0, 0, 0, 0, + 0, 1250, 1250, 1250, 1250, 1250, 1250, 1250, + 1250, 1250, 1250, 0, 0, 0, 0, 0, + 0, 540, 540, 540, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 5756, 1153, 1153, 1153, 1153, 1159, 1153, 5757, + 5758, 1153, 5759, 5760, 1168, 1168, 0, 1178, + 1178, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1177, 1177, 1177, 1177, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 340, 340, 340, 1160, 340, 340, + 340, 340, 1160, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 1160, 340, 1160, + 1160, 1160, 1160, 1160, 340, 1160, 340, 1160, + 340, 340, 340, 340, 1180, 1044, 1044, 1160, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1153, 1153, 1159, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1159, 1159, 1159, 1153, + 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, + 1159, 1452, 1160, 1237, 1237, 1160, 1177, 1177, + 1177, 1177, 1177, 1180, 1153, 1153, 1177, 0, + 0, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1178, 1178, 1160, 1177, 1160, 1177, 1177, + 1177, 0, 1190, 1190, 1190, 1190, 1190, 1190, + 1190, 1190, 1190, 1190, 1190, 1190, 1190, 1190, + 1190, 1190, 1190, 1190, 1190, 1190, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 0, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1159, 1159, 1159, + 1153, 1153, 1153, 1159, 1159, 1153, 1452, 1180, + 1153, 1177, 1177, 1177, 1177, 1177, 1177, 1153, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 0, 1160, 0, 1160, 1160, 1160, 1160, 0, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 0, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1177, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1153, 1159, 1159, 1159, 1153, 1153, 1153, 1153, + 1153, 1153, 1180, 1168, 0, 0, 0, 0, + 0, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1178, 1178, 0, 0, 0, 0, 0, + 0, 1153, 1153, 1159, 1159, 0, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 0, 0, + 1160, 1160, 0, 0, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 0, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 0, 1160, 1160, 0, 1160, 1160, + 1160, 1160, 1160, 0, 0, 1180, 1160, 5761, + 1159, 1153, 1159, 1159, 1159, 1159, 0, 0, + 5762, 1159, 0, 0, 5763, 5764, 1452, 0, + 0, 1160, 0, 0, 0, 0, 0, 0, + 5765, 0, 0, 0, 0, 0, 1160, 1160, + 1160, 1160, 1160, 1159, 1159, 0, 0, 540, + 540, 540, 540, 540, 540, 540, 0, 0, + 0, 540, 540, 540, 540, 540, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1159, 1159, + 1159, 1153, 1153, 1153, 1153, 1153, 1153, 1153, + 1153, 1159, 1159, 1168, 1153, 1153, 1159, 1180, + 1160, 1160, 1160, 1160, 1177, 1177, 1177, 1177, + 1177, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1178, 1178, 0, 1177, 0, 1177, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 5766, 1159, 1159, 1153, 1153, 1153, 1153, + 1153, 1153, 5767, 5768, 5769, 5770, 5771, 5772, + 1153, 1153, 1159, 1168, 1180, 1160, 1160, 1177, + 1160, 0, 0, 0, 0, 0, 0, 0, + 0, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1178, 1178, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 5773, 1159, 1159, 1153, 1153, 1153, 1153, 0, + 0, 5774, 5775, 5776, 5777, 1153, 1153, 1159, + 1168, 1180, 1177, 1177, 1177, 1177, 1177, 1177, + 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, + 1177, 1177, 1177, 1177, 1177, 1177, 1177, 1177, + 1177, 1160, 1160, 1160, 1160, 1153, 1153, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1159, 1159, 1159, 1153, 1153, 1153, 1153, + 1153, 1153, 1153, 1153, 1159, 1159, 1153, 1159, + 1168, 1153, 1177, 1177, 1177, 1160, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1178, 1178, 0, 0, 0, 0, 0, + 0, 1428, 1428, 1428, 1428, 1428, 1428, 1428, + 1428, 1428, 1428, 1428, 1428, 1428, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1153, 1159, 1153, 1159, + 1159, 1153, 1153, 1153, 1153, 1153, 1153, 1452, + 1180, 0, 0, 0, 0, 0, 0, 0, + 0, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1178, 1178, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 0, 0, 0, 1153, 1153, + 1153, 1159, 1159, 1153, 1153, 1153, 1153, 1159, + 1153, 1153, 1153, 1153, 1168, 0, 0, 0, + 0, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1178, 1178, 1190, 1190, 1177, 1177, 1177, + 1191, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5778, 5779, 5780, 5781, 5782, 5783, 5784, + 5785, 5786, 5787, 5788, 5789, 5790, 5791, 5792, + 5793, 5794, 5795, 5796, 5797, 5798, 5799, 5800, + 5801, 5802, 5803, 5804, 5805, 5806, 5807, 5808, + 5809, 5810, 5811, 5812, 5813, 5814, 5815, 5816, + 5817, 5818, 5819, 5820, 5821, 5822, 5823, 5824, + 5825, 5826, 5827, 5828, 5829, 5830, 5831, 5832, + 5833, 5834, 5835, 5836, 5837, 5838, 5839, 5840, + 5841, 1250, 1250, 1250, 1250, 1250, 1250, 1250, + 1250, 1250, 1250, 5484, 5484, 5484, 5484, 5484, + 5484, 5484, 5484, 5484, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 340, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 0, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 5842, 1153, 1153, 1153, 1153, 1153, 1153, 1153, + 0, 1153, 1153, 1153, 1153, 1153, 1153, 1159, + 5843, 1160, 1177, 1177, 1177, 1177, 1177, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1178, 1178, 1178, 1178, 1178, 1178, 1178, + 1178, 1178, 1178, 1190, 1190, 1190, 1190, 1190, + 1190, 1190, 1190, 1190, 1190, 1190, 1190, 1190, + 1190, 1190, 1190, 1190, 1190, 1190, 0, 0, + 0, 1044, 1044, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 0, 0, 1153, 1153, 1153, 1153, 1153, + 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, + 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, + 1153, 0, 1159, 1153, 1153, 1153, 1153, 1153, + 1153, 1153, 1159, 1153, 1153, 1159, 1153, 1153, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1426, 1426, 1426, 1426, 1426, 1426, 1426, + 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, + 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, + 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, + 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, + 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, + 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, + 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, + 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, + 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, + 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, + 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, + 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, + 1426, 1426, 1426, 1426, 1426, 1426, 1426, 1426, + 0, 1044, 1044, 1044, 1044, 1044, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 0, 0, 0, 0, 0, 0, + 0, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 0, 1250, 1250, 1250, 1250, 1250, 1250, 1250, + 1250, 1250, 1250, 0, 0, 0, 0, 1044, + 1044, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 0, + 0, 566, 566, 566, 566, 566, 1044, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 540, 540, 540, 540, 540, 540, 540, + 1044, 1044, 1044, 1044, 1044, 838, 838, 838, + 838, 523, 523, 523, 523, 1044, 838, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1250, 1250, 1250, 1250, 1250, 1250, 1250, + 1250, 1250, 1250, 0, 5484, 5484, 5484, 5484, + 5484, 5484, 5484, 0, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 0, 0, 0, 0, 0, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1159, 1159, 1159, 1159, 1159, 1159, + 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, + 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, + 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, + 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, + 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1153, 1153, 1153, 1153, 1179, 1179, 1179, 1179, + 1179, 1179, 1179, 1179, 1179, 1179, 1179, 1179, + 1179, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1179, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 1160, 1160, + 1160, 1160, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 1160, 1160, 340, 340, + 1160, 1160, 340, 340, 1160, 1160, 1160, 1160, + 340, 340, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 1160, 1160, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 1160, 340, 340, 340, 1160, 340, 340, + 1160, 1160, 1160, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 340, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 340, 1160, 340, 340, 340, 340, 0, 0, + 0, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 0, 0, 0, 0, 0, 0, + 0, 340, 340, 340, 340, 340, 340, 340, + 340, 340, 340, 0, 0, 1191, 1153, 566, + 1177, 81, 81, 81, 81, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 838, 838, 838, 838, 838, 838, 838, + 838, 1191, 1191, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 1191, 838, 1191, 838, + 838, 838, 1191, 838, 838, 838, 1191, 1191, + 1191, 838, 1191, 838, 1191, 838, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 838, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 838, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 838, 838, 1191, 1191, 1191, 1191, 1191, 838, + 838, 838, 838, 1191, 838, 1191, 1191, 1191, + 838, 838, 838, 1191, 1191, 1191, 1191, 1191, + 838, 1191, 1191, 1191, 838, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 838, 1191, 1191, 1191, 838, + 838, 838, 1191, 1191, 838, 838, 838, 838, + 1191, 1191, 838, 838, 838, 1191, 1191, 838, + 838, 838, 838, 1191, 1191, 1191, 1191, 1191, + 838, 838, 838, 838, 838, 838, 1191, 838, + 838, 1191, 1191, 1191, 838, 1191, 1191, 1191, + 1191, 838, 838, 1191, 838, 1191, 838, 1191, + 1191, 1191, 1191, 1191, 1191, 838, 838, 838, + 1191, 1191, 838, 838, 838, 1191, 838, 1191, + 838, 1191, 838, 838, 1191, 1191, 1191, 1191, + 838, 1191, 1191, 1191, 838, 1191, 1191, 1191, + 1191, 838, 1191, 1191, 1191, 838, 1191, 1191, + 1191, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 1191, + 838, 1191, 838, 838, 838, 838, 838, 838, + 838, 1191, 838, 1191, 838, 838, 838, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 838, 1191, 838, 838, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 838, + 838, 838, 1191, 1191, 1191, 1191, 838, 838, + 0, 0, 1191, 838, 1191, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 1191, + 1191, 1191, 1191, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 5844, 5845, 1191, 838, 838, 1191, 838, 5846, + 5847, 5848, 5849, 5850, 5851, 5852, 5853, 5854, + 566, 566, 566, 1191, 1191, 1191, 5855, 5856, + 5857, 5858, 5859, 5860, 81, 81, 81, 81, + 81, 81, 81, 81, 553, 553, 553, 553, + 553, 553, 553, 553, 838, 838, 540, 540, + 540, 540, 540, 553, 553, 838, 838, 838, + 838, 838, 838, 1191, 1191, 838, 838, 1191, + 1191, 1191, 1191, 838, 838, 1191, 1191, 838, + 838, 838, 838, 838, 1191, 1191, 838, 1191, + 1191, 838, 838, 540, 540, 540, 540, 1191, + 1191, 1191, 1191, 1191, 1191, 838, 1191, 1191, + 1191, 1191, 5861, 5862, 5863, 5864, 5865, 5866, + 5867, 5868, 838, 838, 838, 838, 838, 838, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 838, 838, 838, 838, 838, 838, 838, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 540, 540, 540, 1085, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1190, 1190, 1190, 1190, 1190, 1190, 1190, + 1190, 1190, 5484, 1190, 1190, 1190, 1190, 1190, + 1190, 1190, 1190, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 5869, 2157, 2132, 5870, 2159, 2160, 5871, + 2139, 2142, 5872, 5873, 2143, 2162, 2145, 5874, + 2147, 2148, 2149, 5875, 5876, 5877, 5878, 5879, + 5880, 5881, 2153, 5882, 5883, 5884, 5885, 2158, + 5886, 2138, 2140, 2168, 2177, 5887, 2144, 5888, + 5889, 2163, 5890, 5891, 5892, 5893, 5894, 5895, + 5896, 5897, 5898, 5899, 5900, 5901, 5902, 5903, + 2175, 5904, 5905, 5906, 5907, 5908, 5909, 5910, + 5911, 5912, 5913, 5914, 5915, 5916, 5917, 5918, + 5919, 5920, 5921, 5922, 5923, 5924, 5925, 5926, + 5927, 5928, 2176, 5929, 5930, 5931, 0, 5932, + 5933, 5934, 5935, 5936, 5937, 5938, 5939, 5940, + 5941, 5942, 5943, 5944, 5945, 5946, 5947, 5948, + 5949, 5901, 5902, 5903, 2175, 5904, 5905, 5906, + 5907, 5908, 5909, 5910, 5911, 5912, 5913, 5914, + 5915, 5916, 5917, 5918, 5919, 5920, 5921, 5922, + 5923, 5924, 5925, 5926, 5927, 5928, 2176, 5929, + 5930, 5931, 5950, 5932, 5933, 5934, 5935, 5936, + 5937, 5938, 5939, 5940, 5941, 5942, 5943, 5944, + 5945, 5946, 5947, 5948, 5949, 5901, 0, 5903, + 2175, 0, 0, 5906, 0, 0, 5909, 5910, + 0, 0, 5913, 5914, 5915, 5916, 0, 5918, + 5919, 5920, 5921, 5922, 5923, 5924, 5925, 5926, + 5927, 5928, 2176, 0, 5930, 0, 5950, 5932, + 5933, 5934, 5935, 5936, 5937, 0, 5939, 5940, + 5941, 5942, 5943, 5944, 5945, 5946, 5947, 5948, + 5949, 5901, 5902, 5903, 2175, 5904, 5905, 5906, + 5907, 5908, 5909, 5910, 5911, 5912, 5913, 5914, + 5915, 5916, 5917, 5918, 5919, 5920, 5921, 5922, + 5923, 5924, 5925, 5926, 5927, 5928, 2176, 5929, + 5930, 5931, 5950, 5932, 5933, 5934, 5935, 5936, + 5937, 5938, 5939, 5940, 5941, 5942, 5943, 5944, + 5945, 5946, 5947, 5948, 5949, 5869, 2157, 0, + 5870, 2159, 2160, 5871, 0, 0, 5872, 5873, + 2143, 2162, 2145, 5874, 2147, 2148, 0, 5875, + 5876, 5877, 5878, 5879, 5880, 5881, 0, 5882, + 5883, 5884, 5885, 2158, 5886, 2138, 2140, 2168, + 2177, 5887, 2144, 5888, 5889, 2163, 5890, 5891, + 5892, 5893, 5894, 5895, 5896, 5897, 5898, 5899, + 5900, 5869, 2157, 0, 5870, 2159, 2160, 5871, + 0, 2142, 5872, 5873, 2143, 2162, 0, 5874, + 0, 0, 0, 5875, 5876, 5877, 5878, 5879, + 5880, 5881, 0, 5882, 5883, 5884, 5885, 2158, + 5886, 2138, 2140, 2168, 2177, 5887, 2144, 5888, + 5889, 2163, 5890, 5891, 5892, 5893, 5894, 5895, + 5896, 5897, 5898, 5899, 5900, 5869, 2157, 2132, + 5870, 2159, 2160, 5871, 2139, 2142, 5872, 5873, + 2143, 2162, 2145, 5874, 2147, 2148, 2149, 5875, + 5876, 5877, 5878, 5879, 5880, 5881, 2153, 5882, + 5883, 5884, 5885, 2158, 5886, 2138, 2140, 2168, + 2177, 5887, 2144, 5888, 5889, 2163, 5890, 5891, + 5892, 5893, 5894, 5895, 5896, 5897, 5898, 5899, + 5900, 5869, 2157, 2132, 5870, 2159, 2160, 5871, + 2139, 2142, 5872, 5873, 2143, 2162, 2145, 5874, + 2147, 2148, 2149, 5875, 5876, 5877, 5878, 5879, + 5880, 5881, 2153, 5882, 5883, 5884, 5885, 2158, + 5886, 2138, 2140, 2168, 2177, 5887, 2144, 5888, + 5889, 2163, 5890, 5891, 5892, 5893, 5894, 5895, + 5896, 5897, 5898, 5899, 5900, 5869, 2157, 2132, + 5870, 2159, 2160, 5871, 2139, 2142, 5872, 5873, + 2143, 2162, 2145, 5874, 2147, 2148, 2149, 5875, + 5876, 5877, 5878, 5879, 5880, 5881, 2153, 5882, + 5883, 5884, 5885, 2158, 5886, 2138, 2140, 2168, + 2177, 5887, 2144, 5888, 5889, 2163, 5890, 5891, + 5892, 5893, 5894, 5895, 5896, 5897, 5898, 5899, + 5900, 5901, 5902, 5903, 2175, 5904, 5905, 5906, + 5907, 5908, 5909, 5910, 5911, 5912, 5913, 5914, + 5915, 5916, 5917, 5918, 5919, 5920, 5921, 5922, + 5923, 5924, 5925, 5926, 5927, 5928, 2176, 5929, + 5930, 5931, 5950, 5932, 5933, 5934, 5935, 5936, + 5937, 5938, 5939, 5940, 5941, 5942, 5943, 5944, + 5945, 5946, 5947, 5948, 5949, 5901, 5902, 5903, + 2175, 5904, 5905, 5906, 5907, 5908, 5909, 5910, + 5911, 5912, 5913, 5914, 5915, 5916, 5917, 5918, + 5919, 5920, 5921, 5922, 5923, 5924, 5925, 5926, + 5927, 5928, 2176, 5929, 5930, 5931, 5950, 5932, + 5933, 5934, 5935, 5936, 5937, 5938, 5939, 5940, + 5941, 5942, 5943, 5944, 5945, 5946, 5947, 5948, + 5949, 5901, 5902, 5903, 2175, 5904, 5905, 5906, + 5907, 5908, 5909, 5910, 5911, 5912, 5913, 5914, + 5915, 5916, 5917, 5918, 5919, 5920, 5921, 5922, + 5923, 5924, 5925, 5926, 5927, 5928, 2176, 5929, + 5930, 5931, 5950, 5932, 5933, 5934, 5935, 5936, + 5937, 5938, 5939, 5940, 5941, 5942, 5943, 5944, + 5945, 5946, 5947, 5948, 5949, 5951, 5952, 0, + 0, 5953, 5954, 2172, 5955, 5956, 5957, 5958, + 5959, 5960, 5961, 5962, 5963, 5964, 5965, 5966, + 5967, 5968, 5969, 5970, 5971, 5972, 5973, 5974, + 5975, 5976, 5977, 5978, 5979, 5980, 5981, 5982, + 5983, 5984, 5985, 5986, 5987, 5988, 5989, 5990, + 5991, 5992, 5993, 5994, 5995, 5996, 5997, 5998, + 5999, 6000, 6001, 6002, 6003, 6004, 6005, 6006, + 6007, 6008, 6009, 6010, 6011, 6012, 6013, 6014, + 6015, 6016, 6017, 6018, 6019, 6020, 6021, 6022, + 6023, 6024, 2173, 6025, 6026, 6027, 6028, 6029, + 6030, 6031, 6032, 6033, 6034, 6035, 6036, 2171, + 6037, 6038, 6039, 6040, 6041, 6042, 6043, 6044, + 6045, 6046, 6047, 6048, 2170, 6049, 6050, 6051, + 6052, 6053, 6054, 6055, 6056, 6057, 6058, 6059, + 6005, 6060, 6061, 6062, 6063, 6010, 6011, 6012, + 6013, 6014, 6015, 6016, 6017, 6018, 6019, 6020, + 6021, 6022, 6023, 6024, 2173, 6025, 6026, 6027, + 6028, 6029, 6030, 6031, 6032, 6033, 6034, 6035, + 6036, 2171, 6037, 6038, 6039, 6040, 6041, 6042, + 6043, 6044, 6045, 6046, 6047, 6048, 2170, 6049, + 6050, 6051, 6052, 6053, 6054, 6055, 6056, 6057, + 6058, 6059, 6064, 6060, 6061, 6062, 6063, 5953, + 5954, 2172, 5955, 5956, 5957, 5958, 5959, 5960, + 5961, 5962, 5963, 5964, 5965, 5966, 5967, 5968, + 5969, 5970, 5971, 5972, 5973, 5974, 5975, 5976, + 5977, 5978, 5979, 5980, 5981, 5982, 5983, 5984, + 5985, 5986, 5987, 5988, 5989, 5990, 5991, 5992, + 5993, 5994, 5995, 5996, 5997, 5998, 5999, 6000, + 6001, 6002, 6003, 6004, 6005, 6006, 6007, 6008, + 6009, 6010, 6011, 6012, 6013, 6014, 6015, 6016, + 6017, 6018, 6019, 6020, 6021, 6022, 6023, 6024, + 2173, 6025, 6026, 6027, 6028, 6029, 6030, 6031, + 6032, 6033, 6034, 6035, 6036, 2171, 6037, 6038, + 6039, 6040, 6041, 6042, 6043, 6044, 6045, 6046, + 6047, 6048, 2170, 6049, 6050, 6051, 6052, 6053, + 6054, 6055, 6056, 6057, 6058, 6059, 6064, 6060, + 6061, 6062, 6063, 6065, 6066, 0, 0, 6067, + 6068, 6069, 6070, 6071, 6072, 6073, 6074, 6075, + 6076, 6067, 6068, 6069, 6070, 6071, 6072, 6073, + 6074, 6075, 6076, 6067, 6068, 6069, 6070, 6071, + 6072, 6073, 6074, 6075, 6076, 6067, 6068, 6069, + 6070, 6071, 6072, 6073, 6074, 6075, 6076, 6077, + 6078, 6079, 6080, 6081, 6082, 6083, 6084, 6085, + 6086, 1153, 1153, 1153, 1153, 1153, 1153, 1153, + 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, + 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, + 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, + 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, + 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, + 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, + 838, 838, 838, 838, 1153, 1153, 1153, 1153, + 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, + 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, + 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, + 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, + 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, + 1153, 1153, 1153, 1153, 1153, 1153, 838, 838, + 838, 838, 838, 838, 838, 838, 1153, 838, + 838, 838, 838, 838, 838, 838, 838, 838, + 838, 838, 838, 838, 838, 1153, 838, 838, + 1044, 1044, 1044, 1044, 1044, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1153, 1153, 1153, 1153, + 1153, 0, 1153, 1153, 1153, 1153, 1153, 1153, + 1153, 1153, 1153, 1153, 1153, 1153, 1153, 1153, + 1153, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 540, 540, 540, 540, 540, 540, 540, + 0, 540, 540, 540, 540, 540, 540, 540, + 540, 540, 540, 540, 540, 540, 540, 540, + 540, 540, 0, 0, 540, 540, 540, 540, + 540, 540, 540, 0, 540, 540, 0, 540, + 540, 540, 540, 540, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1156, 1156, 1156, 1156, 1156, 1156, 1156, + 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, + 1156, 1156, 1156, 1156, 1106, 1106, 1106, 1106, + 1106, 1156, 1156, 1106, 1106, 1106, 1106, 1106, + 1156, 1106, 1156, 1106, 1106, 1106, 1156, 1106, + 1156, 1156, 1106, 1106, 1106, 1106, 1156, 1106, + 1106, 1106, 1156, 1156, 1106, 1156, 1156, 1156, + 1156, 1156, 1156, 1156, 1106, 1106, 1156, 1156, + 1156, 1156, 1156, 1106, 1156, 1106, 1106, 1106, + 1106, 1106, 1156, 1156, 1106, 1106, 1106, 1106, + 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1156, + 1106, 1156, 1156, 1106, 1106, 1106, 1106, 1156, + 1156, 1156, 1156, 1106, 1156, 1156, 1156, 1156, + 1106, 1156, 1156, 1106, 1156, 1106, 1156, 1106, + 1156, 1156, 1106, 1106, 1106, 1106, 1106, 1156, + 1156, 1156, 1106, 1156, 1106, 1156, 1106, 1156, + 1156, 1156, 1156, 1106, 1156, 1156, 1156, 1156, + 1156, 1156, 1106, 1156, 1156, 1156, 1156, 1156, + 1156, 1106, 1106, 1156, 1156, 1156, 1106, 1106, + 1156, 1156, 1156, 1156, 1106, 1156, 1156, 1106, + 1156, 1156, 1156, 1156, 1106, 1156, 1156, 1106, + 1156, 1156, 1106, 1156, 1156, 1156, 1106, 1156, + 1156, 1156, 1156, 1106, 1106, 1156, 1156, 1106, + 1156, 1156, 1156, 1156, 1156, 1156, 1156, 1106, + 1156, 1156, 1156, 1156, 1156, 1156, 0, 0, + 5642, 5642, 5642, 5642, 5642, 5642, 5642, 5642, + 5642, 553, 553, 553, 553, 553, 553, 553, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6087, 6088, 6089, 6090, 6091, 6092, 6093, + 6094, 6095, 6096, 6097, 6098, 6099, 6100, 6101, + 6102, 6103, 6104, 6105, 6106, 6107, 6108, 6109, + 6110, 6111, 6112, 6113, 6114, 6115, 6116, 6117, + 6118, 6119, 6120, 6121, 6122, 6123, 6124, 6125, + 6126, 6127, 6128, 6129, 6130, 6131, 6132, 6133, + 6134, 6135, 6136, 6137, 6138, 6139, 6140, 6141, + 6142, 6143, 6144, 6145, 6146, 6147, 6148, 6149, + 6150, 6151, 6152, 6153, 6154, 540, 540, 540, + 540, 540, 540, 1180, 0, 0, 0, 0, + 0, 1154, 1154, 1154, 1154, 1154, 1154, 1154, + 1154, 1154, 1154, 0, 0, 0, 0, 1103, + 1103, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6155, 6156, 6157, 6158, 0, 6159, 6160, + 6161, 6162, 6163, 6164, 6165, 6166, 6167, 6168, + 6169, 6170, 6171, 6172, 6173, 6174, 6175, 6176, + 6177, 6178, 6179, 6180, 6181, 6182, 6183, 6184, + 6185, 0, 6156, 6157, 0, 6186, 0, 0, + 6161, 0, 6163, 6164, 6165, 6166, 6167, 6168, + 6169, 6170, 6171, 6172, 0, 6174, 6175, 6176, + 6177, 0, 6179, 0, 6181, 0, 0, 0, + 0, 0, 0, 6157, 0, 0, 0, 0, + 6161, 0, 6163, 0, 6165, 0, 6167, 6168, + 6169, 0, 6171, 6172, 0, 6174, 0, 0, + 6177, 0, 6179, 0, 6181, 0, 6183, 0, + 6185, 0, 6156, 6157, 0, 6187, 0, 0, + 6161, 6162, 6163, 6164, 0, 6166, 6167, 6168, + 6169, 6170, 6171, 6172, 0, 6174, 6175, 6176, + 6177, 0, 6179, 6180, 6181, 6182, 0, 6184, + 0, 6155, 6156, 6157, 6158, 6187, 6159, 6160, + 6161, 6162, 6163, 0, 6165, 6166, 6167, 6168, + 6169, 6170, 6171, 6172, 6173, 6174, 6175, 6176, + 6177, 6178, 6179, 6180, 6181, 0, 0, 0, + 0, 0, 6188, 6189, 6190, 0, 6191, 6192, + 6193, 6194, 6195, 0, 6196, 6197, 6198, 6199, + 6200, 6201, 6202, 6203, 6204, 6205, 6206, 6207, + 6208, 6209, 6210, 6211, 6212, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1109, 1109, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 0, 0, 0, + 0, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 0, 0, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 0, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 0, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6213, 6214, 6215, 6216, 6217, 6218, 6219, + 6220, 6221, 6222, 6223, 1220, 1220, 0, 0, + 0, 6224, 6225, 6226, 6227, 6228, 6229, 6230, + 6231, 6232, 6233, 6234, 6235, 6236, 6237, 6238, + 6239, 6240, 6241, 6242, 6243, 6244, 6245, 6246, + 6247, 6248, 6249, 6250, 6251, 6252, 6253, 6254, + 0, 6255, 6256, 6257, 6258, 6259, 6260, 6261, + 6262, 6263, 6264, 6265, 6266, 6267, 6268, 6269, + 6270, 6271, 6272, 6273, 6274, 6275, 6276, 6277, + 6278, 6279, 6280, 6281, 3613, 6282, 6283, 6284, + 6285, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 6286, 6287, 0, 0, 0, + 0, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 6288, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 1191, 1191, + 1191, 1191, 1191, 1191, 1191, 1191, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 6289, + 6289, 6289, 6289, 6289, 6289, 6289, 6289, 6289, + 6289, 6289, 6289, 6289, 6289, 6289, 6289, 6289, + 6289, 6289, 6289, 6289, 6289, 6289, 6289, 6289, + 6289, 6290, 6291, 6292, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6293, 6294, 6295, 6296, 6297, 6298, 6299, + 6300, 6301, 6302, 6303, 6304, 6305, 6306, 6307, + 6308, 6309, 6310, 6311, 6312, 6313, 6314, 6315, + 6316, 6317, 6318, 6319, 6320, 6321, 6322, 6323, + 6324, 6325, 6326, 6327, 6328, 6329, 6330, 6331, + 6332, 6333, 6334, 6335, 6336, 0, 0, 0, + 0, 6337, 6338, 6339, 6340, 6341, 6342, 6343, + 6344, 6345, 0, 0, 0, 0, 0, 0, + 0, 6346, 6347, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 2464, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 2464, 2464, 1085, 1085, + 1085, 1085, 1085, 2464, 2464, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 6348, 6348, 6348, 6348, + 6348, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 2464, 2464, 1085, 1085, 2464, + 2464, 2464, 2464, 2464, 2464, 2464, 2464, 2464, + 2464, 2464, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 6349, + 6349, 6349, 6349, 1085, 1085, 1085, 1085, 2464, + 1085, 2464, 2464, 2464, 2464, 2464, 2464, 2464, + 2464, 2464, 1085, 1085, 1085, 2464, 1085, 1085, + 1085, 1085, 2464, 2464, 2464, 1085, 2464, 2464, + 2464, 1085, 1085, 1085, 2465, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 2464, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 2464, 1085, + 1085, 1085, 1085, 2464, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 2464, 1085, 1085, 1085, 1085, 2464, 2464, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 77, 2465, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 2464, 2464, + 2464, 1085, 1085, 1085, 2464, 2464, 2464, 2464, + 2464, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 77, + 77, 77, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 2464, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 2464, 2464, 2464, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 2464, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 0, 0, + 0, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 77, 77, 1085, 77, 77, + 77, 1085, 1085, 1085, 1085, 77, 77, 77, + 1085, 1085, 77, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 77, 1085, 77, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1085, 1085, 1085, 1085, 77, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 77, 77, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 77, 77, 77, 1085, 1085, 1085, 77, 77, + 77, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 0, 0, 0, + 0, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 77, 77, 77, 77, 77, 77, 77, + 77, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 0, 0, 0, 0, 0, 0, 0, + 0, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 0, 0, 0, 0, 0, + 0, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 0, 0, 0, 0, 0, 0, 0, + 0, 77, 77, 77, 77, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 77, 77, 77, + 77, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 77, 77, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 2464, 2464, 2464, 2464, 2464, 2464, 2464, + 0, 1085, 1085, 1085, 1085, 1085, 1085, 2464, + 1085, 0, 0, 0, 0, 0, 0, 0, + 0, 2464, 0, 0, 2464, 2464, 2464, 2464, + 2464, 2464, 2464, 1085, 1085, 2464, 2464, 2464, + 0, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 0, 0, 0, + 0, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 1085, 1085, 1085, 1085, 1085, + 1085, 1085, 1085, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1085, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 0, + 0, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 1160, 1160, 1160, 1160, 1160, + 1160, 1160, 1160, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6350, 6351, 6352, 6353, 6354, 4271, 6355, + 6356, 6357, 6358, 4272, 6359, 6360, 6361, 4273, + 6362, 6363, 6364, 6365, 6366, 6367, 6368, 6369, + 6370, 6371, 6372, 6373, 4331, 6374, 6375, 6376, + 6377, 6378, 6379, 6380, 6381, 6382, 4336, 4274, + 4275, 4337, 6383, 6384, 4082, 6385, 4276, 6386, + 6387, 6388, 6389, 6389, 6389, 6390, 6391, 6392, + 6393, 6394, 6395, 6396, 6397, 6398, 6399, 6400, + 6401, 6402, 6403, 6404, 6405, 6406, 6407, 6407, + 4339, 6408, 6409, 6410, 6411, 4278, 6412, 6413, + 6414, 4235, 6415, 6416, 6417, 6418, 6419, 6420, + 6421, 6422, 6423, 6424, 6425, 6426, 6427, 6428, + 6429, 6430, 6431, 6432, 6433, 6434, 6435, 6436, + 6437, 6438, 6439, 6440, 6440, 6441, 6442, 6443, + 4078, 6444, 6445, 6446, 6447, 6448, 6449, 6450, + 6451, 4283, 6452, 6453, 6454, 6455, 6456, 6457, + 6458, 6459, 6460, 6461, 6462, 6463, 6464, 6465, + 6466, 6467, 6468, 6469, 6470, 6471, 6472, 4024, + 6473, 6474, 6475, 6475, 6476, 6477, 6477, 6478, + 6479, 6480, 6481, 6482, 6483, 6484, 6485, 6486, + 6487, 6488, 6489, 6490, 4284, 6491, 6492, 6493, + 6494, 4351, 6494, 6495, 4286, 6496, 6497, 6498, + 6499, 4287, 3997, 6500, 6501, 6502, 6503, 6504, + 6505, 6506, 6507, 6508, 6509, 6510, 6511, 6512, + 6513, 6514, 6515, 6516, 6517, 6518, 6519, 6520, + 6521, 4288, 6522, 6523, 6524, 6525, 6526, 6527, + 4290, 6528, 6529, 6530, 6531, 6532, 6533, 6534, + 6535, 4025, 4359, 6536, 6537, 6538, 6539, 6540, + 6541, 6542, 6543, 4291, 6544, 6545, 6546, 6547, + 4402, 6548, 6549, 6550, 6551, 6552, 6553, 6554, + 6555, 6556, 6557, 6558, 6559, 6560, 4095, 6561, + 6562, 6563, 6564, 6565, 6566, 6567, 6568, 6569, + 6570, 6571, 4292, 4182, 6572, 6573, 6574, 6575, + 6576, 6577, 6578, 6579, 4363, 6580, 6581, 6582, + 6583, 6584, 6585, 6586, 6587, 4364, 6588, 6589, + 6590, 6591, 6592, 6593, 6594, 6595, 6596, 6597, + 6598, 6599, 4366, 6600, 6601, 6602, 6603, 6604, + 6605, 6606, 6607, 6608, 6609, 6610, 6610, 6611, + 6612, 4368, 6613, 6614, 6615, 6616, 6617, 6618, + 6619, 4081, 6620, 6621, 6622, 6623, 6624, 6625, + 6626, 4374, 6627, 6628, 6629, 6630, 6631, 6632, + 6632, 4375, 4404, 6633, 6634, 6635, 6636, 6637, + 4043, 4377, 6638, 6639, 4303, 6640, 6641, 4257, + 6642, 6643, 4307, 6644, 6645, 6646, 6647, 6647, + 6648, 6649, 6650, 6651, 6652, 6653, 6654, 6655, + 6656, 6657, 6658, 6659, 6660, 6661, 6662, 6663, + 6664, 6665, 6666, 6667, 6668, 6669, 6670, 6671, + 6672, 6673, 6674, 4313, 6675, 6676, 6677, 6678, + 6679, 6680, 6681, 6682, 6683, 6684, 6685, 6686, + 6687, 6688, 6689, 6690, 6476, 6691, 6692, 6693, + 6694, 6695, 6696, 6697, 6698, 6699, 6700, 6701, + 6702, 4099, 6703, 6704, 6705, 6706, 6707, 6708, + 4316, 6709, 6710, 6711, 6712, 6713, 6714, 6715, + 6716, 6717, 6718, 6719, 6720, 6721, 6722, 6723, + 6724, 6725, 6726, 6727, 6728, 4038, 6729, 6730, + 6731, 6732, 6733, 6734, 4384, 6735, 6736, 6737, + 6738, 6739, 6740, 6741, 6742, 6743, 6744, 6745, + 6746, 6747, 6748, 6749, 6750, 6751, 6752, 6753, + 6754, 4389, 4390, 6755, 6756, 6757, 6758, 6759, + 6760, 6761, 6762, 6763, 6764, 6765, 6766, 6767, + 4391, 6768, 6769, 6770, 6771, 6772, 6773, 6774, + 6775, 6776, 6777, 6778, 6779, 6780, 6781, 6782, + 6783, 6784, 6785, 6786, 6787, 6788, 6789, 6790, + 6791, 6792, 6793, 6794, 6795, 6796, 6797, 4397, + 4397, 6798, 6799, 6800, 6801, 6802, 6803, 6804, + 6805, 6806, 6807, 4398, 6808, 6809, 6810, 6811, + 6812, 6813, 6814, 6815, 6816, 6817, 6818, 6819, + 6820, 6821, 6822, 6823, 6824, 6825, 6826, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 81, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2053, 2053, 2053, 2053, 2053, 2053, 2053, + 2053, 2053, 2053, 2053, 2053, 2053, 2053, 2053, + 2053, 2053, 2053, 2053, 2053, 2053, 2053, 2053, + 2053, 2053, 2053, 2053, 2053, 2053, 2053, 2053, + 2053, 2053, 2053, 2053, 2053, 2053, 2053, 2053, + 2053, 2053, 2053, 2053, 2053, 2053, 2053, 2053, + 2053, 2053, 2053, 2053, 2053, 2053, 2053, 2053, + 2053, 2053, 2053, 2053, 2053, 2053, 2053, 2053, + 2053, 2053, 2053, 2053, 2053, 2053, 2053, 2053, + 2053, 2053, 2053, 2053, 2053, 2053, 2053, 2053, + 2053, 2053, 2053, 2053, 2053, 2053, 2053, 2053, + 2053, 2053, 2053, 2053, 2053, 2053, 2053, 2053, + 2053, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 574, 574, 574, 574, + 574, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 3984, + 3984, 3984, 3984, 3984, 3984, 3984, 3984, 0, 0, }; UTF8PROC_DATA const utf8proc_property_t utf8proc_properties[] = { - {0, 0, 0, 0, NULL, false, -1, -1, -1, -1, -1, false}, - {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_BN, 0, NULL, false, -1, -1, -1, -1, -1, false, true, true, false, NULL}, - {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_S, 0, NULL, false, -1, -1, -1, -1, -1, false, false, true, false, NULL}, - {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_B, 0, NULL, false, -1, -1, -1, -1, -1, false, false, true, false, NULL}, - {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_WS, 0, NULL, false, -1, -1, -1, -1, -1, false, false, true, false, NULL}, - {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_B, 0, NULL, false, -1, -1, -1, -1, -1, false, true, true, false, NULL}, - {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_S, 0, NULL, false, -1, -1, -1, -1, -1, false, true, true, false, NULL}, - {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ES, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 17580, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, 17400, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 17640, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 97, -1, 0, -1, false, false, false, false, utf8proc_sequences + 0}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 98, -1, 8640, -1, false, false, false, false, utf8proc_sequences + 2}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 99, -1, 60, -1, false, false, false, false, utf8proc_sequences + 4}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 100, -1, 960, -1, false, false, false, false, utf8proc_sequences + 6}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 101, -1, 120, -1, false, false, false, false, utf8proc_sequences + 8}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 102, -1, 9120, -1, false, false, false, false, utf8proc_sequences + 10}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 103, -1, 1080, -1, false, false, false, false, utf8proc_sequences + 12}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 104, -1, 1200, -1, false, false, false, false, utf8proc_sequences + 14}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 105, -1, 180, -1, false, false, false, false, utf8proc_sequences + 16}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 106, -1, 1320, -1, false, false, false, false, utf8proc_sequences + 18}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 107, -1, 1440, -1, false, false, false, false, utf8proc_sequences + 20}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 108, -1, 1560, -1, false, false, false, false, utf8proc_sequences + 22}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 109, -1, 9480, -1, false, false, false, false, utf8proc_sequences + 24}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 110, -1, 240, -1, false, false, false, false, utf8proc_sequences + 26}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 111, -1, 300, -1, false, false, false, false, utf8proc_sequences + 28}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 112, -1, 9720, -1, false, false, false, false, utf8proc_sequences + 30}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 113, -1, -1, -1, false, false, false, false, utf8proc_sequences + 32}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 114, -1, 1680, -1, false, false, false, false, utf8proc_sequences + 34}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 115, -1, 1800, -1, false, false, false, false, utf8proc_sequences + 36}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 116, -1, 1920, -1, false, false, false, false, utf8proc_sequences + 38}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 117, -1, 360, -1, false, false, false, false, utf8proc_sequences + 40}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 118, -1, 10560, -1, false, false, false, false, utf8proc_sequences + 42}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 119, -1, 2040, -1, false, false, false, false, utf8proc_sequences + 44}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 120, -1, 10680, -1, false, false, false, false, utf8proc_sequences + 46}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 121, -1, 420, -1, false, false, false, false, utf8proc_sequences + 48}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 122, -1, 2160, -1, false, false, false, false, utf8proc_sequences + 50}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PC, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 65, -1, 65, 480, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66, -1, 66, 8700, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 67, -1, 67, 540, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 68, -1, 68, 1020, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 69, -1, 69, 600, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 70, -1, 70, 9180, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 71, -1, 71, 1140, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 72, -1, 72, 1260, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 73, -1, 73, 660, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 74, -1, 74, 1380, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 75, -1, 75, 1500, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 76, -1, 76, 1620, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 77, -1, 77, 9540, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 78, -1, 78, 720, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 79, -1, 79, 780, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 80, -1, 80, 9780, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 81, -1, 81, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 82, -1, 82, 1740, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 83, -1, 83, 1860, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 84, -1, 84, 1980, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 85, -1, 85, 840, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 86, -1, 86, 10620, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 87, -1, 87, 2100, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 88, -1, 88, 10740, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 89, -1, 89, 900, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 90, -1, 90, 2220, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_NOBREAK, utf8proc_sequences + 52, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 54, false, -1, -1, -1, 3600, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 0, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PI, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_BN, 0, NULL, false, -1, -1, -1, -1, -1, false, true, true, false, NULL}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 57, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ET, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ET, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 60, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 62, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 64, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 67, false, 924, -1, 924, -1, -1, false, false, false, false, utf8proc_sequences + 67}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 69, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 72, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 28, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PF, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 74, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 78, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 82, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 86, false, -1, 224, -1, -1, -1, false, false, false, false, utf8proc_sequences + 89}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 91, false, -1, 225, -1, -1, -1, false, false, false, false, utf8proc_sequences + 94}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 96, false, -1, 226, -1, 10860, -1, false, false, false, false, utf8proc_sequences + 99}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 101, false, -1, 227, -1, -1, -1, false, false, false, false, utf8proc_sequences + 104}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 106, false, -1, 228, -1, 2400, -1, false, false, false, false, utf8proc_sequences + 109}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 111, false, -1, 229, -1, 3000, -1, false, false, false, false, utf8proc_sequences + 114}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 230, -1, 2640, -1, false, false, false, false, utf8proc_sequences + 116}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 118, false, -1, 231, -1, 8760, -1, false, false, false, false, utf8proc_sequences + 121}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 123, false, -1, 232, -1, -1, -1, false, false, false, false, utf8proc_sequences + 126}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 128, false, -1, 233, -1, -1, -1, false, false, false, false, utf8proc_sequences + 131}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 133, false, -1, 234, -1, 11220, -1, false, false, false, false, utf8proc_sequences + 136}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 138, false, -1, 235, -1, -1, -1, false, false, false, false, utf8proc_sequences + 141}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 143, false, -1, 236, -1, -1, -1, false, false, false, false, utf8proc_sequences + 146}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 148, false, -1, 237, -1, -1, -1, false, false, false, false, utf8proc_sequences + 151}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 153, false, -1, 238, -1, -1, -1, false, false, false, false, utf8proc_sequences + 156}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 158, false, -1, 239, -1, 9240, -1, false, false, false, false, utf8proc_sequences + 161}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 240, -1, -1, -1, false, false, false, false, utf8proc_sequences + 163}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 165, false, -1, 241, -1, -1, -1, false, false, false, false, utf8proc_sequences + 168}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 170, false, -1, 242, -1, -1, -1, false, false, false, false, utf8proc_sequences + 173}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 175, false, -1, 243, -1, -1, -1, false, false, false, false, utf8proc_sequences + 178}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 180, false, -1, 244, -1, 11460, -1, false, false, false, false, utf8proc_sequences + 183}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 185, false, -1, 245, -1, 3360, -1, false, false, false, false, utf8proc_sequences + 188}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 190, false, -1, 246, -1, 3240, -1, false, false, false, false, utf8proc_sequences + 193}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 248, -1, 3120, -1, false, false, false, false, utf8proc_sequences + 195}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 197, false, -1, 249, -1, -1, -1, false, false, false, false, utf8proc_sequences + 200}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 202, false, -1, 250, -1, -1, -1, false, false, false, false, utf8proc_sequences + 205}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 207, false, -1, 251, -1, -1, -1, false, false, false, false, utf8proc_sequences + 210}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 212, false, -1, 252, -1, 2280, -1, false, false, false, false, utf8proc_sequences + 215}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 217, false, -1, 253, -1, -1, -1, false, false, false, false, utf8proc_sequences + 220}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 254, -1, -1, -1, false, false, false, false, utf8proc_sequences + 222}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 224}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 227, false, 192, -1, 192, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 230, false, 193, -1, 193, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 233, false, 194, -1, 194, 10920, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 236, false, 195, -1, 195, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 239, false, 196, -1, 196, 2460, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 242, false, 197, -1, 197, 3060, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 198, -1, 198, 2700, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 245, false, 199, -1, 199, 8820, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 248, false, 200, -1, 200, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 251, false, 201, -1, 201, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 254, false, 202, -1, 202, 11280, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 257, false, 203, -1, 203, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 260, false, 204, -1, 204, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 263, false, 205, -1, 205, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 266, false, 206, -1, 206, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 269, false, 207, -1, 207, 9300, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 208, -1, 208, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 272, false, 209, -1, 209, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 275, false, 210, -1, 210, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 278, false, 211, -1, 211, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 281, false, 212, -1, 212, 11520, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 284, false, 213, -1, 213, 3420, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 287, false, 214, -1, 214, 3300, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 216, -1, 216, 3180, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 290, false, 217, -1, 217, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 293, false, 218, -1, 218, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 296, false, 219, -1, 219, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 299, false, 220, -1, 220, 2340, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 302, false, 221, -1, 221, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 222, -1, 222, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 305, false, 376, -1, 376, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 308, false, -1, 257, -1, -1, -1, false, false, false, false, utf8proc_sequences + 311}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 313, false, 256, -1, 256, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 316, false, -1, 259, -1, 11100, -1, false, false, false, false, utf8proc_sequences + 319}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 321, false, 258, -1, 258, 11160, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 324, false, -1, 261, -1, -1, -1, false, false, false, false, utf8proc_sequences + 327}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 329, false, 260, -1, 260, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 332, false, -1, 263, -1, -1, -1, false, false, false, false, utf8proc_sequences + 335}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 337, false, 262, -1, 262, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 340, false, -1, 265, -1, -1, -1, false, false, false, false, utf8proc_sequences + 343}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 345, false, 264, -1, 264, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 348, false, -1, 267, -1, -1, -1, false, false, false, false, utf8proc_sequences + 351}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 353, false, 266, -1, 266, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 356, false, -1, 269, -1, -1, -1, false, false, false, false, utf8proc_sequences + 359}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 361, false, 268, -1, 268, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 364, false, -1, 271, -1, -1, -1, false, false, false, false, utf8proc_sequences + 367}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 369, false, 270, -1, 270, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 273, -1, -1, -1, false, false, false, false, utf8proc_sequences + 372}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 272, -1, 272, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 374, false, -1, 275, -1, 8880, -1, false, false, false, false, utf8proc_sequences + 377}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 379, false, 274, -1, 274, 8940, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 382, false, -1, 277, -1, -1, -1, false, false, false, false, utf8proc_sequences + 385}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 387, false, 276, -1, 276, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 390, false, -1, 279, -1, -1, -1, false, false, false, false, utf8proc_sequences + 393}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 395, false, 278, -1, 278, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 398, false, -1, 281, -1, -1, -1, false, false, false, false, utf8proc_sequences + 401}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 403, false, 280, -1, 280, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 406, false, -1, 283, -1, -1, -1, false, false, false, false, utf8proc_sequences + 409}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 411, false, 282, -1, 282, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 414, false, -1, 285, -1, -1, -1, false, false, false, false, utf8proc_sequences + 417}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 419, false, 284, -1, 284, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 422, false, -1, 287, -1, -1, -1, false, false, false, false, utf8proc_sequences + 425}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 427, false, 286, -1, 286, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 430, false, -1, 289, -1, -1, -1, false, false, false, false, utf8proc_sequences + 433}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 435, false, 288, -1, 288, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 438, false, -1, 291, -1, -1, -1, false, false, false, false, utf8proc_sequences + 441}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 443, false, 290, -1, 290, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 446, false, -1, 293, -1, -1, -1, false, false, false, false, utf8proc_sequences + 449}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 451, false, 292, -1, 292, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 295, -1, -1, -1, false, false, false, false, utf8proc_sequences + 454}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 294, -1, 294, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 456, false, -1, 297, -1, -1, -1, false, false, false, false, utf8proc_sequences + 459}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 461, false, 296, -1, 296, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 464, false, -1, 299, -1, -1, -1, false, false, false, false, utf8proc_sequences + 467}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 469, false, 298, -1, 298, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 472, false, -1, 301, -1, -1, -1, false, false, false, false, utf8proc_sequences + 475}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 477, false, 300, -1, 300, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 480, false, -1, 303, -1, -1, -1, false, false, false, false, utf8proc_sequences + 483}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 485, false, 302, -1, 302, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 488, false, -1, 105, -1, -1, -1, false, false, false, false, utf8proc_sequences + 491}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 73, -1, 73, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 494, false, -1, 307, -1, -1, -1, false, false, false, false, utf8proc_sequences + 497}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 499, false, 306, -1, 306, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 502, false, -1, 309, -1, -1, -1, false, false, false, false, utf8proc_sequences + 505}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 507, false, 308, -1, 308, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 510, false, -1, 311, -1, -1, -1, false, false, false, false, utf8proc_sequences + 513}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 515, false, 310, -1, 310, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 518, false, -1, 314, -1, -1, -1, false, false, false, false, utf8proc_sequences + 521}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 523, false, 313, -1, 313, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 526, false, -1, 316, -1, -1, -1, false, false, false, false, utf8proc_sequences + 529}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 531, false, 315, -1, 315, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 534, false, -1, 318, -1, -1, -1, false, false, false, false, utf8proc_sequences + 537}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 539, false, 317, -1, 317, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 542, false, -1, 320, -1, -1, -1, false, false, false, false, utf8proc_sequences + 545}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 547, false, 319, -1, 319, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 322, -1, -1, -1, false, false, false, false, utf8proc_sequences + 550}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 321, -1, 321, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 552, false, -1, 324, -1, -1, -1, false, false, false, false, utf8proc_sequences + 555}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 557, false, 323, -1, 323, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 560, false, -1, 326, -1, -1, -1, false, false, false, false, utf8proc_sequences + 563}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 565, false, 325, -1, 325, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 568, false, -1, 328, -1, -1, -1, false, false, false, false, utf8proc_sequences + 571}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 573, false, 327, -1, 327, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 576, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 576}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 331, -1, -1, -1, false, false, false, false, utf8proc_sequences + 579}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 330, -1, 330, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 581, false, -1, 333, -1, 9600, -1, false, false, false, false, utf8proc_sequences + 584}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 586, false, 332, -1, 332, 9660, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 589, false, -1, 335, -1, -1, -1, false, false, false, false, utf8proc_sequences + 592}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 594, false, 334, -1, 334, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 597, false, -1, 337, -1, -1, -1, false, false, false, false, utf8proc_sequences + 600}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 602, false, 336, -1, 336, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 339, -1, -1, -1, false, false, false, false, utf8proc_sequences + 605}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 338, -1, 338, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 607, false, -1, 341, -1, -1, -1, false, false, false, false, utf8proc_sequences + 610}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 612, false, 340, -1, 340, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 615, false, -1, 343, -1, -1, -1, false, false, false, false, utf8proc_sequences + 618}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 620, false, 342, -1, 342, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 623, false, -1, 345, -1, -1, -1, false, false, false, false, utf8proc_sequences + 626}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 628, false, 344, -1, 344, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 631, false, -1, 347, -1, 9960, -1, false, false, false, false, utf8proc_sequences + 634}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 636, false, 346, -1, 346, 10020, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 639, false, -1, 349, -1, -1, -1, false, false, false, false, utf8proc_sequences + 642}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 644, false, 348, -1, 348, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 647, false, -1, 351, -1, -1, -1, false, false, false, false, utf8proc_sequences + 650}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 652, false, 350, -1, 350, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 655, false, -1, 353, -1, 10080, -1, false, false, false, false, utf8proc_sequences + 658}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 660, false, 352, -1, 352, 10140, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 663, false, -1, 355, -1, -1, -1, false, false, false, false, utf8proc_sequences + 666}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 668, false, 354, -1, 354, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 671, false, -1, 357, -1, -1, -1, false, false, false, false, utf8proc_sequences + 674}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 676, false, 356, -1, 356, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 359, -1, -1, -1, false, false, false, false, utf8proc_sequences + 679}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 358, -1, 358, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 681, false, -1, 361, -1, 10320, -1, false, false, false, false, utf8proc_sequences + 684}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 686, false, 360, -1, 360, 10380, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 689, false, -1, 363, -1, 10440, -1, false, false, false, false, utf8proc_sequences + 692}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 694, false, 362, -1, 362, 10500, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 697, false, -1, 365, -1, -1, -1, false, false, false, false, utf8proc_sequences + 700}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 702, false, 364, -1, 364, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 705, false, -1, 367, -1, -1, -1, false, false, false, false, utf8proc_sequences + 708}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 710, false, 366, -1, 366, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 713, false, -1, 369, -1, -1, -1, false, false, false, false, utf8proc_sequences + 716}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 718, false, 368, -1, 368, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 721, false, -1, 371, -1, -1, -1, false, false, false, false, utf8proc_sequences + 724}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 726, false, 370, -1, 370, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 729, false, -1, 373, -1, -1, -1, false, false, false, false, utf8proc_sequences + 732}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 734, false, 372, -1, 372, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 737, false, -1, 375, -1, -1, -1, false, false, false, false, utf8proc_sequences + 740}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 742, false, 374, -1, 374, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 745, false, -1, 255, -1, -1, -1, false, false, false, false, utf8proc_sequences + 748}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 750, false, -1, 378, -1, -1, -1, false, false, false, false, utf8proc_sequences + 753}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 755, false, 377, -1, 377, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 758, false, -1, 380, -1, -1, -1, false, false, false, false, utf8proc_sequences + 761}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 763, false, 379, -1, 379, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 766, false, -1, 382, -1, -1, -1, false, false, false, false, utf8proc_sequences + 769}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 771, false, 381, -1, 381, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 36, false, 83, -1, 83, 10800, -1, false, false, false, false, utf8proc_sequences + 36}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 579, -1, 579, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 595, -1, -1, -1, false, false, false, false, utf8proc_sequences + 774}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 387, -1, -1, -1, false, false, false, false, utf8proc_sequences + 776}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 386, -1, 386, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 389, -1, -1, -1, false, false, false, false, utf8proc_sequences + 778}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 388, -1, 388, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 596, -1, -1, -1, false, false, false, false, utf8proc_sequences + 780}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 392, -1, -1, -1, false, false, false, false, utf8proc_sequences + 782}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 391, -1, 391, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 598, -1, -1, -1, false, false, false, false, utf8proc_sequences + 784}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 599, -1, -1, -1, false, false, false, false, utf8proc_sequences + 786}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 396, -1, -1, -1, false, false, false, false, utf8proc_sequences + 788}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 395, -1, 395, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 477, -1, -1, -1, false, false, false, false, utf8proc_sequences + 790}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 601, -1, -1, -1, false, false, false, false, utf8proc_sequences + 792}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 603, -1, -1, -1, false, false, false, false, utf8proc_sequences + 794}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 402, -1, -1, -1, false, false, false, false, utf8proc_sequences + 796}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 401, -1, 401, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 608, -1, -1, -1, false, false, false, false, utf8proc_sequences + 798}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 611, -1, -1, -1, false, false, false, false, utf8proc_sequences + 800}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 502, -1, 502, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 617, -1, -1, -1, false, false, false, false, utf8proc_sequences + 802}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 616, -1, -1, -1, false, false, false, false, utf8proc_sequences + 804}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 409, -1, -1, -1, false, false, false, false, utf8proc_sequences + 806}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 408, -1, 408, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 573, -1, 573, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 623, -1, -1, -1, false, false, false, false, utf8proc_sequences + 808}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 626, -1, -1, -1, false, false, false, false, utf8proc_sequences + 810}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 544, -1, 544, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 629, -1, -1, -1, false, false, false, false, utf8proc_sequences + 812}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 814, false, -1, 417, -1, 11700, -1, false, false, false, false, utf8proc_sequences + 817}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 819, false, 416, -1, 416, 11760, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 419, -1, -1, -1, false, false, false, false, utf8proc_sequences + 822}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 418, -1, 418, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 421, -1, -1, -1, false, false, false, false, utf8proc_sequences + 824}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 420, -1, 420, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 640, -1, -1, -1, false, false, false, false, utf8proc_sequences + 826}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 424, -1, -1, -1, false, false, false, false, utf8proc_sequences + 828}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 423, -1, 423, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 643, -1, -1, -1, false, false, false, false, utf8proc_sequences + 830}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 429, -1, -1, -1, false, false, false, false, utf8proc_sequences + 832}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 428, -1, 428, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 648, -1, -1, -1, false, false, false, false, utf8proc_sequences + 834}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 836, false, -1, 432, -1, 11820, -1, false, false, false, false, utf8proc_sequences + 839}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 841, false, 431, -1, 431, 11880, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 650, -1, -1, -1, false, false, false, false, utf8proc_sequences + 844}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 651, -1, -1, -1, false, false, false, false, utf8proc_sequences + 846}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 436, -1, -1, -1, false, false, false, false, utf8proc_sequences + 848}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 435, -1, 435, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 438, -1, -1, -1, false, false, false, false, utf8proc_sequences + 850}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 437, -1, 437, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 658, -1, 2880, -1, false, false, false, false, utf8proc_sequences + 852}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 441, -1, -1, -1, false, false, false, false, utf8proc_sequences + 854}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 440, -1, 440, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 445, -1, -1, -1, false, false, false, false, utf8proc_sequences + 856}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 444, -1, 444, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 503, -1, 503, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 858, false, -1, 454, 453, -1, -1, false, false, false, false, utf8proc_sequences + 861}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 863, false, 452, 454, 453, -1, -1, false, false, false, false, utf8proc_sequences + 861}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 866, false, 452, -1, 453, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 869, false, -1, 457, 456, -1, -1, false, false, false, false, utf8proc_sequences + 872}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 874, false, 455, 457, 456, -1, -1, false, false, false, false, utf8proc_sequences + 872}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 877, false, 455, -1, 456, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 880, false, -1, 460, 459, -1, -1, false, false, false, false, utf8proc_sequences + 883}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 885, false, 458, 460, 459, -1, -1, false, false, false, false, utf8proc_sequences + 883}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 888, false, 458, -1, 459, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 891, false, -1, 462, -1, -1, -1, false, false, false, false, utf8proc_sequences + 894}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 896, false, 461, -1, 461, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 899, false, -1, 464, -1, -1, -1, false, false, false, false, utf8proc_sequences + 902}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 904, false, 463, -1, 463, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 907, false, -1, 466, -1, -1, -1, false, false, false, false, utf8proc_sequences + 910}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 912, false, 465, -1, 465, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 915, false, -1, 468, -1, -1, -1, false, false, false, false, utf8proc_sequences + 918}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 920, false, 467, -1, 467, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 923, false, -1, 470, -1, -1, -1, false, false, false, false, utf8proc_sequences + 926}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 928, false, 469, -1, 469, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 931, false, -1, 472, -1, -1, -1, false, false, false, false, utf8proc_sequences + 934}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 936, false, 471, -1, 471, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 939, false, -1, 474, -1, -1, -1, false, false, false, false, utf8proc_sequences + 942}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 944, false, 473, -1, 473, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 947, false, -1, 476, -1, -1, -1, false, false, false, false, utf8proc_sequences + 950}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 952, false, 475, -1, 475, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 398, -1, 398, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 955, false, -1, 479, -1, -1, -1, false, false, false, false, utf8proc_sequences + 958}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 960, false, 478, -1, 478, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 963, false, -1, 481, -1, -1, -1, false, false, false, false, utf8proc_sequences + 966}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 968, false, 480, -1, 480, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 971, false, -1, 483, -1, -1, -1, false, false, false, false, utf8proc_sequences + 974}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 976, false, 482, -1, 482, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 485, -1, -1, -1, false, false, false, false, utf8proc_sequences + 979}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 484, -1, 484, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 981, false, -1, 487, -1, -1, -1, false, false, false, false, utf8proc_sequences + 984}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 986, false, 486, -1, 486, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 989, false, -1, 489, -1, -1, -1, false, false, false, false, utf8proc_sequences + 992}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 994, false, 488, -1, 488, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 997, false, -1, 491, -1, 2760, -1, false, false, false, false, utf8proc_sequences + 1000}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1002, false, 490, -1, 490, 2820, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1005, false, -1, 493, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1008}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1010, false, 492, -1, 492, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1013, false, -1, 495, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1016}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1018, false, 494, -1, 494, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1021, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1021}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1024, false, -1, 499, 498, -1, -1, false, false, false, false, utf8proc_sequences + 1027}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1029, false, 497, 499, 498, -1, -1, false, false, false, false, utf8proc_sequences + 1027}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1032, false, 497, -1, 498, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1035, false, -1, 501, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1038}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1040, false, 500, -1, 500, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 405, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1043}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 447, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1045}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1047, false, -1, 505, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1050}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1052, false, 504, -1, 504, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1055, false, -1, 507, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1058}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1060, false, 506, -1, 506, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1063, false, -1, 509, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1066}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1068, false, 508, -1, 508, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1071, false, -1, 511, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1074}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1076, false, 510, -1, 510, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1079, false, -1, 513, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1082}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1084, false, 512, -1, 512, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1087, false, -1, 515, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1090}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1092, false, 514, -1, 514, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1095, false, -1, 517, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1098}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1100, false, 516, -1, 516, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1103, false, -1, 519, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1106}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1108, false, 518, -1, 518, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1111, false, -1, 521, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1114}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1116, false, 520, -1, 520, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1119, false, -1, 523, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1122}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1124, false, 522, -1, 522, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1127, false, -1, 525, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1130}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1132, false, 524, -1, 524, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1135, false, -1, 527, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1138}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1140, false, 526, -1, 526, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1143, false, -1, 529, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1146}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1148, false, 528, -1, 528, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1151, false, -1, 531, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1154}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1156, false, 530, -1, 530, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1159, false, -1, 533, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1162}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1164, false, 532, -1, 532, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1167, false, -1, 535, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1170}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1172, false, 534, -1, 534, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1175, false, -1, 537, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1178}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1180, false, 536, -1, 536, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1183, false, -1, 539, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1186}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1188, false, 538, -1, 538, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 541, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1191}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 540, -1, 540, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1193, false, -1, 543, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1196}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1198, false, 542, -1, 542, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 414, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1201}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 547, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1203}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 546, -1, 546, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 549, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1205}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 548, -1, 548, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1207, false, -1, 551, -1, 2520, -1, false, false, false, false, utf8proc_sequences + 1210}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1212, false, 550, -1, 550, 2580, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1215, false, -1, 553, -1, 9000, -1, false, false, false, false, utf8proc_sequences + 1218}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1220, false, 552, -1, 552, 9060, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1223, false, -1, 555, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1226}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1228, false, 554, -1, 554, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1231, false, -1, 557, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1234}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1236, false, 556, -1, 556, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1239, false, -1, 559, -1, 3480, -1, false, false, false, false, utf8proc_sequences + 1242}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1244, false, 558, -1, 558, 3540, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1247, false, -1, 561, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1250}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1252, false, 560, -1, 560, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1255, false, -1, 563, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1258}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1260, false, 562, -1, 562, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11365, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1263}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 572, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1265}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 571, -1, 571, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 410, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1267}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11366, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1269}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 578, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1271}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 577, -1, 577, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 384, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1273}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 649, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1275}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 652, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1277}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 583, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1279}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 582, -1, 582, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 585, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1281}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 584, -1, 584, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 587, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1283}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 586, -1, 586, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 589, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1285}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 588, -1, 588, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 591, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1287}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 590, -1, 590, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 385, -1, 385, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 390, -1, 390, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 393, -1, 393, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 394, -1, 394, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 399, -1, 399, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 400, -1, 400, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 403, -1, 403, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 404, -1, 404, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 407, -1, 407, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 406, -1, 406, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11362, -1, 11362, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 412, -1, 412, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 413, -1, 413, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 415, -1, 415, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11364, -1, 11364, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 422, -1, 422, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 425, -1, 425, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 430, -1, 430, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 580, -1, 580, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 433, -1, 433, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 434, -1, 434, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 581, -1, 581, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 439, -1, 439, 2940, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 14, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 1289, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 18, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 34, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 1291, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 1293, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 1295, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 44, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 48, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1297, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1300, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1303, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1306, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1309, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1312, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 800, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 22, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 36, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 46, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 1315, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 0, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 2, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 3, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 7, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 8, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 10, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 4, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 46, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 5, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 12, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 11, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 14, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 15, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 47, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 48, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 232, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 216, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 13, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 202, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 40, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 45, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 39, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 16, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 202, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 6, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 202, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 9, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 42, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 44, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 43, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 41, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 1, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 1, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 51, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 1317, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 1319, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 49, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 1321, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 1323, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 240, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, 921, -1, 921, -1, 50, false, false, false, true, utf8proc_sequences + 1326}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, true, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 233, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 234, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 1328, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1330, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1021, -1, 1021, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1022, -1, 1022, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1023, -1, 1023, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 1333, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 1335, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1338, false, -1, 940, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1341}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 1343, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1345, false, -1, 941, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1348}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1350, false, -1, 942, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1353}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1355, false, -1, 943, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1358}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1360, false, -1, 972, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1363}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1365, false, -1, 973, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1368}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1370, false, -1, 974, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1373}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1375, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1378}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 945, -1, 3660, -1, false, false, false, false, utf8proc_sequences + 1382}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 946, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1384}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 947, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1386}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 948, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1388}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 949, -1, 3720, -1, false, false, false, false, utf8proc_sequences + 1390}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 950, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1392}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 951, -1, 3780, -1, false, false, false, false, utf8proc_sequences + 1394}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 952, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1396}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 953, -1, 3840, -1, false, false, false, false, utf8proc_sequences + 1326}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 954, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1398}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 955, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1400}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 956, -1, -1, -1, false, false, false, false, utf8proc_sequences + 67}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 957, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1402}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 958, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1404}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 959, -1, 3900, -1, false, false, false, false, utf8proc_sequences + 1406}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 960, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1408}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 961, -1, 16260, -1, false, false, false, false, utf8proc_sequences + 1410}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 963, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1412}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 964, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1414}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 965, -1, 3960, -1, false, false, false, false, utf8proc_sequences + 1416}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 966, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1418}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 967, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1420}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 968, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1422}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 969, -1, 4020, -1, false, false, false, false, utf8proc_sequences + 1424}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1426, false, -1, 970, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1429}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1431, false, -1, 971, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1434}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1436, false, 902, -1, 902, 15780, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1439, false, 904, -1, 904, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1442, false, 905, -1, 905, 15960, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1445, false, 906, -1, 906, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1448, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1451}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 913, -1, 913, 4140, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 914, -1, 914, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 915, -1, 915, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 916, -1, 916, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 917, -1, 917, 4200, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 918, -1, 918, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 919, -1, 919, 4260, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 920, -1, 920, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 921, -1, 921, 4320, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 922, -1, 922, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 923, -1, 923, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 924, -1, 924, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 925, -1, 925, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 926, -1, 926, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 927, -1, 927, 4500, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 928, -1, 928, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 929, -1, 929, 16200, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 931, -1, 931, -1, -1, false, false, false, false, utf8proc_sequences + 1412}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 931, -1, 931, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 932, -1, 932, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 933, -1, 933, 4440, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 934, -1, 934, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 935, -1, 935, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 936, -1, 936, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 937, -1, 937, 4560, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1455, false, 938, -1, 938, 4080, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1458, false, 939, -1, 939, 4380, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1461, false, 908, -1, 908, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1464, false, 910, -1, 910, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1467, false, 911, -1, 911, 16380, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1384, false, 914, -1, 914, -1, -1, false, false, false, false, utf8proc_sequences + 1384}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1396, false, 920, -1, 920, -1, -1, false, false, false, false, utf8proc_sequences + 1396}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1470, false, -1, -1, -1, 4620, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1472, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1475, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1418, false, 934, -1, 934, -1, -1, false, false, false, false, utf8proc_sequences + 1418}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1408, false, 928, -1, 928, -1, -1, false, false, false, false, utf8proc_sequences + 1408}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 985, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1478}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 984, -1, 984, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 987, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1480}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 986, -1, 986, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 989, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1482}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 988, -1, 988, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 991, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1484}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 990, -1, 990, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 993, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1486}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 992, -1, 992, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 995, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1488}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 994, -1, 994, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 997, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1490}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 996, -1, 996, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 999, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1492}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 998, -1, 998, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1001, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1494}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1000, -1, 1000, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1003, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1496}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1002, -1, 1002, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1005, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1498}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1004, -1, 1004, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1007, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1500}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1006, -1, 1006, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1398, false, 922, -1, 922, -1, -1, false, false, false, false, utf8proc_sequences + 1398}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1410, false, 929, -1, 929, -1, -1, false, false, false, false, utf8proc_sequences + 1410}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1502, false, 1017, -1, 1017, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1504, false, -1, 952, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1396}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1390, false, 917, -1, 917, -1, -1, false, false, false, false, utf8proc_sequences + 1390}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1016, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1506}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1015, -1, 1015, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 1508, false, -1, 1010, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1510}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1019, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1512}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1018, -1, 1018, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 891, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1514}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 892, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1516}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 893, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1518}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1520, false, -1, 1104, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1523}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1525, false, -1, 1105, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1528}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1106, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1530}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1532, false, -1, 1107, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1535}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1108, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1537}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1109, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1539}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1110, -1, 4800, -1, false, false, false, false, utf8proc_sequences + 1541}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1543, false, -1, 1111, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1546}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1112, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1548}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1113, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1550}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1114, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1552}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1115, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1554}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1556, false, -1, 1116, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1559}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1561, false, -1, 1117, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1564}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1566, false, -1, 1118, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1569}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1119, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1571}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1072, -1, 5640, -1, false, false, false, false, utf8proc_sequences + 1573}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1073, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1575}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1074, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1577}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1075, -1, 4740, -1, false, false, false, false, utf8proc_sequences + 1579}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1076, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1581}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1077, -1, 4680, -1, false, false, false, false, utf8proc_sequences + 1583}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1078, -1, 5520, -1, false, false, false, false, utf8proc_sequences + 1585}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1079, -1, 5880, -1, false, false, false, false, utf8proc_sequences + 1587}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1080, -1, 4920, -1, false, false, false, false, utf8proc_sequences + 1589}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1591, false, -1, 1081, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1594}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1082, -1, 4860, -1, false, false, false, false, utf8proc_sequences + 1596}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1083, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1598}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1084, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1600}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1085, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1602}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1086, -1, 6000, -1, false, false, false, false, utf8proc_sequences + 1604}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1087, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1606}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1088, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1608}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1089, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1610}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1090, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1612}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1091, -1, 4980, -1, false, false, false, false, utf8proc_sequences + 1614}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1092, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1616}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1093, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1618}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1094, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1620}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1095, -1, 6360, -1, false, false, false, false, utf8proc_sequences + 1622}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1096, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1624}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1097, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1626}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1098, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1628}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1099, -1, 6480, -1, false, false, false, false, utf8proc_sequences + 1630}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1100, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1632}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1101, -1, 6240, -1, false, false, false, false, utf8proc_sequences + 1634}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1102, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1636}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1103, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1638}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1040, -1, 1040, 5700, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1041, -1, 1041, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1042, -1, 1042, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1043, -1, 1043, 5160, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1044, -1, 1044, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1045, -1, 1045, 5100, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1046, -1, 1046, 5580, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1047, -1, 1047, 5940, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1048, -1, 1048, 5040, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1640, false, 1049, -1, 1049, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1050, -1, 1050, 5280, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1051, -1, 1051, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1052, -1, 1052, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1053, -1, 1053, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1054, -1, 1054, 6060, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1055, -1, 1055, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1056, -1, 1056, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1057, -1, 1057, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1058, -1, 1058, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1059, -1, 1059, 5340, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1060, -1, 1060, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1061, -1, 1061, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1062, -1, 1062, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1063, -1, 1063, 6420, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1064, -1, 1064, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1065, -1, 1065, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1066, -1, 1066, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1067, -1, 1067, 6540, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1068, -1, 1068, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1069, -1, 1069, 6300, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1070, -1, 1070, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1071, -1, 1071, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1643, false, 1024, -1, 1024, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1646, false, 1025, -1, 1025, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1026, -1, 1026, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1649, false, 1027, -1, 1027, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1028, -1, 1028, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1029, -1, 1029, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1030, -1, 1030, 5220, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1652, false, 1031, -1, 1031, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1032, -1, 1032, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1033, -1, 1033, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1034, -1, 1034, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1035, -1, 1035, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1655, false, 1036, -1, 1036, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1658, false, 1037, -1, 1037, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1661, false, 1038, -1, 1038, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1039, -1, 1039, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1121, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1664}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1120, -1, 1120, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1123, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1666}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1122, -1, 1122, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1125, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1668}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1124, -1, 1124, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1127, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1670}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1126, -1, 1126, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1129, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1672}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1128, -1, 1128, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1131, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1674}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1130, -1, 1130, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1133, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1676}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1132, -1, 1132, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1135, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1678}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1134, -1, 1134, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1137, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1680}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1136, -1, 1136, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1139, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1682}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1138, -1, 1138, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1141, -1, 5400, -1, false, false, false, false, utf8proc_sequences + 1684}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1140, -1, 1140, 5460, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1686, false, -1, 1143, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1689}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1691, false, 1142, -1, 1142, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1145, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1694}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1144, -1, 1144, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1147, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1696}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1146, -1, 1146, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1149, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1698}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1148, -1, 1148, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1151, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1700}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1150, -1, 1150, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1153, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1702}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1152, -1, 1152, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ME, 0, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1163, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1704}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1162, -1, 1162, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1165, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1706}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1164, -1, 1164, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1167, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1708}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1166, -1, 1166, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1169, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1710}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1168, -1, 1168, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1171, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1712}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1170, -1, 1170, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1173, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1714}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1172, -1, 1172, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1175, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1716}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1174, -1, 1174, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1177, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1718}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1176, -1, 1176, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1179, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1720}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1178, -1, 1178, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1181, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1722}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1180, -1, 1180, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1183, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1724}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1182, -1, 1182, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1185, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1726}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1184, -1, 1184, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1187, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1728}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1186, -1, 1186, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1189, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1730}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1188, -1, 1188, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1191, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1732}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1190, -1, 1190, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1193, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1734}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1192, -1, 1192, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1195, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1736}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1194, -1, 1194, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1197, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1738}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1196, -1, 1196, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1199, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1740}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1198, -1, 1198, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1201, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1742}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1200, -1, 1200, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1203, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1744}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1202, -1, 1202, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1205, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1746}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1204, -1, 1204, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1207, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1748}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1206, -1, 1206, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1209, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1750}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1208, -1, 1208, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1211, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1752}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1210, -1, 1210, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1213, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1754}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1212, -1, 1212, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1215, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1756}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1214, -1, 1214, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1231, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1758}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1760, false, -1, 1218, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1763}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1765, false, 1217, -1, 1217, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1220, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1768}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1219, -1, 1219, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1222, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1770}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1221, -1, 1221, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1224, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1772}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1223, -1, 1223, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1226, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1774}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1225, -1, 1225, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1228, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1776}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1227, -1, 1227, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1230, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1778}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1229, -1, 1229, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1216, -1, 1216, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1780, false, -1, 1233, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1783}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1785, false, 1232, -1, 1232, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1788, false, -1, 1235, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1791}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1793, false, 1234, -1, 1234, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1237, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1796}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1236, -1, 1236, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1798, false, -1, 1239, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1801}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1803, false, 1238, -1, 1238, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1241, -1, 5760, -1, false, false, false, false, utf8proc_sequences + 1806}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1240, -1, 1240, 5820, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1808, false, -1, 1243, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1811}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1813, false, 1242, -1, 1242, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1816, false, -1, 1245, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1819}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1821, false, 1244, -1, 1244, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1824, false, -1, 1247, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1827}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1829, false, 1246, -1, 1246, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1249, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1832}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1248, -1, 1248, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1834, false, -1, 1251, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1837}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1839, false, 1250, -1, 1250, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1842, false, -1, 1253, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1845}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1847, false, 1252, -1, 1252, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1850, false, -1, 1255, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1853}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1855, false, 1254, -1, 1254, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1257, -1, 6120, -1, false, false, false, false, utf8proc_sequences + 1858}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1256, -1, 1256, 6180, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1860, false, -1, 1259, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1863}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1865, false, 1258, -1, 1258, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1868, false, -1, 1261, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1871}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1873, false, 1260, -1, 1260, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1876, false, -1, 1263, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1879}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1881, false, 1262, -1, 1262, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1884, false, -1, 1265, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1887}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1889, false, 1264, -1, 1264, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1892, false, -1, 1267, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1895}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1897, false, 1266, -1, 1266, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1900, false, -1, 1269, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1903}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1905, false, 1268, -1, 1268, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1271, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1908}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1270, -1, 1270, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1910, false, -1, 1273, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1913}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1915, false, 1272, -1, 1272, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1275, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1918}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1274, -1, 1274, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1277, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1920}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1276, -1, 1276, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1279, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1922}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1278, -1, 1278, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1281, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1924}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1280, -1, 1280, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1283, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1926}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1282, -1, 1282, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1285, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1928}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1284, -1, 1284, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1287, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1930}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1286, -1, 1286, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1289, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1932}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1288, -1, 1288, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1291, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1934}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1290, -1, 1290, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1293, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1936}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1292, -1, 1292, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1295, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1938}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1294, -1, 1294, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1297, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1940}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1296, -1, 1296, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1299, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1942}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1298, -1, 1298, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1377, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1944}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1378, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1946}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1379, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1948}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1380, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1950}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1381, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1952}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1382, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1954}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1383, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1956}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1384, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1958}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1385, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1960}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1386, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1962}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1387, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1964}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1388, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1966}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1389, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1968}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1390, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1970}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1391, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1972}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1392, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1974}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1393, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1976}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1394, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1978}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1395, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1980}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1396, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1982}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1397, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1984}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1398, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1986}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1399, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1988}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1400, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1990}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1401, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1992}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1402, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1994}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1403, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1996}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1404, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1998}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1405, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2000}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1406, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2002}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1407, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2004}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1408, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2006}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1409, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2008}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1410, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2010}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1411, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2012}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1412, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2014}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1413, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2016}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 1414, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2018}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1329, -1, 1329, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1330, -1, 1330, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1331, -1, 1331, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1332, -1, 1332, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1333, -1, 1333, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1334, -1, 1334, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1335, -1, 1335, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1336, -1, 1336, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1337, -1, 1337, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1338, -1, 1338, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1339, -1, 1339, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1340, -1, 1340, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1341, -1, 1341, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1342, -1, 1342, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1343, -1, 1343, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1344, -1, 1344, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1345, -1, 1345, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1346, -1, 1346, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1347, -1, 1347, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1348, -1, 1348, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1349, -1, 1349, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1350, -1, 1350, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1351, -1, 1351, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1352, -1, 1352, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1353, -1, 1353, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1354, -1, 1354, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1355, -1, 1355, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1356, -1, 1356, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1357, -1, 1357, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1358, -1, 1358, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1359, -1, 1359, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1360, -1, 1360, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1361, -1, 1361, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1362, -1, 1362, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1363, -1, 1363, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1364, -1, 1364, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1365, -1, 1365, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 1366, -1, 1366, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2020, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2020}, - {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MN, 222, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 228, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 10, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 11, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 12, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 13, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 14, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 15, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 16, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 17, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 18, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 19, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 20, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 21, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 22, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_R, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MN, 23, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 24, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 25, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_AL, 0, NULL, false, -1, -1, -1, -1, -1, false, true, true, false, NULL}, - {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_AL, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_AL, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, utf8proc_sequences + 2023, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, utf8proc_sequences + 2026, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, utf8proc_sequences + 2029, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, utf8proc_sequences + 2032, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, utf8proc_sequences + 2035, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, NULL, false, -1, -1, -1, 6600, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_AL, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, NULL, false, -1, -1, -1, 6660, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, NULL, false, -1, -1, -1, 6720, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MN, 27, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 28, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 29, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 30, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 31, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 32, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 33, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 34, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 17, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 18, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 19, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_AN, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_AN, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MN, 35, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2038, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2041, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2044, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2047, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, utf8proc_sequences + 2050, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, NULL, false, -1, -1, -1, 6840, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, utf8proc_sequences + 2053, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, NULL, false, -1, -1, -1, 6900, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, utf8proc_sequences + 2056, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, NULL, false, -1, -1, -1, 6780, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_AL, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MN, 36, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_R, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_R, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 6960, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2059, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 7020, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2062, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 7080, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2065, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MN, 7, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 20, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 9, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2068, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2071, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2074, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2077, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2080, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2083, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2086, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2089, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MN, 7, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 21, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 7140, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2092, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2095, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 22, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2098, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2101, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2104, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2107, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2110, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2113, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2116, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2119, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2122, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 24, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 7200, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2125, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2128, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2131, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 23, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 25, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2134, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2137, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 7260, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2140, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 27, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 7320, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 7380, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2143, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2146, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2149, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 26, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, 7440, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 2152, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 84, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 91, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 28, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 7500, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2155, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 31, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 7560, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2158, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2161, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2164, false, -1, -1, -1, 7620, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2167, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 29, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 30, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 32, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 7680, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 7740, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2170, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2173, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2176, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 33, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 9, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 34, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 35, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 7800, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2179, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2182, false, -1, -1, -1, 7860, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2185, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2188, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 36, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2191, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MN, 103, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 107, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2194, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MN, 118, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 122, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2197, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2200, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NOBREAK, utf8proc_sequences + 2203, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MN, 216, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2205, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2208, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2211, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2214, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2217, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2220, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MN, 129, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 130, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 2223, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 132, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 2226, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 2229, false, -1, -1, -1, -1, -1, true, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2232, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 2235, false, -1, -1, -1, -1, -1, true, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2238, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 2241, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 2244, false, -1, -1, -1, -1, -1, true, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 2247, false, -1, -1, -1, -1, -1, true, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 2250, false, -1, -1, -1, -1, -1, true, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 2253, false, -1, -1, -1, -1, -1, true, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 2256, false, -1, -1, -1, -1, -1, true, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, utf8proc_sequences + 2259, false, -1, -1, -1, -1, -1, true, false, false, true, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 7920, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2262, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 37, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11520, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2265}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11521, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2267}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11522, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2269}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11523, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2271}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11524, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2273}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11525, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2275}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11526, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2277}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11527, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2279}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11528, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2281}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11529, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2283}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11530, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2285}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11531, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2287}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11532, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2289}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11533, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2291}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11534, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2293}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11535, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2295}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11536, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2297}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11537, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2299}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11538, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2301}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11539, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2303}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11540, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2305}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11541, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2307}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11542, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2309}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11543, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2311}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11544, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2313}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11545, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2315}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11546, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2317}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11547, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2319}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11548, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2321}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11549, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2323}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11550, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2325}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11551, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2327}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11552, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2329}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11553, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2331}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11554, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2333}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11555, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2335}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11556, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2337}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11557, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2339}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2341, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, true, false, false, NULL}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, true, true, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 7980, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2343, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 8040, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2346, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 8100, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2349, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 8160, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2352, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 8220, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2355, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 8280, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2358, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 38, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, 8340, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2361, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, 8400, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2364, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 8460, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 8520, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2367, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2370, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, 8580, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2373, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 9, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2376, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2378, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2380, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2382, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2384, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2386, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2388, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2390, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2392, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2394, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2396, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2398, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2400, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2402, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2404, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2406, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2408, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2410, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2412, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2414, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2416, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 0, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2418, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2420, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2422, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 6, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 8, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 792, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 794, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2424, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 12, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 20, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 24, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 579, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 28, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 780, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2426, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2428, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 30, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 38, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 40, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2430, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 808, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 42, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2432, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 1384, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 1386, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 1388, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 1418, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 1420, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 16, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 34, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 40, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 42, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 1384, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 1386, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 1410, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 1418, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 1420, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 1602, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11363, -1, 11363, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2434, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2436, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 163, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 10, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2438, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2440, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2442, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 804, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 802, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2444, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2446, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2448, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2450, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2452, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2454, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2456, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2458, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 810, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2460, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2462, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 812, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2464, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2466, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 830, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2468, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 1275, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 844, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2470, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 846, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 1277, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 50, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2472, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 2474, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 852, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 1396, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2476, false, -1, 7681, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2479}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2481, false, 7680, -1, 7680, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2484, false, -1, 7683, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2487}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2489, false, 7682, -1, 7682, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2492, false, -1, 7685, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2495}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2497, false, 7684, -1, 7684, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2500, false, -1, 7687, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2503}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2505, false, 7686, -1, 7686, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2508, false, -1, 7689, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2511}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2513, false, 7688, -1, 7688, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2516, false, -1, 7691, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2519}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2521, false, 7690, -1, 7690, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2524, false, -1, 7693, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2527}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2529, false, 7692, -1, 7692, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2532, false, -1, 7695, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2535}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2537, false, 7694, -1, 7694, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2540, false, -1, 7697, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2543}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2545, false, 7696, -1, 7696, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2548, false, -1, 7699, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2551}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2553, false, 7698, -1, 7698, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2556, false, -1, 7701, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2559}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2561, false, 7700, -1, 7700, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2564, false, -1, 7703, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2567}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2569, false, 7702, -1, 7702, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2572, false, -1, 7705, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2575}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2577, false, 7704, -1, 7704, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2580, false, -1, 7707, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2583}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2585, false, 7706, -1, 7706, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2588, false, -1, 7709, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2591}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2593, false, 7708, -1, 7708, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2596, false, -1, 7711, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2599}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2601, false, 7710, -1, 7710, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2604, false, -1, 7713, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2607}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2609, false, 7712, -1, 7712, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2612, false, -1, 7715, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2615}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2617, false, 7714, -1, 7714, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2620, false, -1, 7717, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2623}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2625, false, 7716, -1, 7716, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2628, false, -1, 7719, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2631}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2633, false, 7718, -1, 7718, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2636, false, -1, 7721, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2639}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2641, false, 7720, -1, 7720, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2644, false, -1, 7723, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2647}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2649, false, 7722, -1, 7722, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2652, false, -1, 7725, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2655}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2657, false, 7724, -1, 7724, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2660, false, -1, 7727, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2663}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2665, false, 7726, -1, 7726, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2668, false, -1, 7729, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2671}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2673, false, 7728, -1, 7728, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2676, false, -1, 7731, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2679}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2681, false, 7730, -1, 7730, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2684, false, -1, 7733, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2687}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2689, false, 7732, -1, 7732, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2692, false, -1, 7735, -1, 9360, -1, false, false, false, false, utf8proc_sequences + 2695}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2697, false, 7734, -1, 7734, 9420, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2700, false, -1, 7737, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2703}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2705, false, 7736, -1, 7736, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2708, false, -1, 7739, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2711}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2713, false, 7738, -1, 7738, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2716, false, -1, 7741, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2719}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2721, false, 7740, -1, 7740, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2724, false, -1, 7743, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2727}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2729, false, 7742, -1, 7742, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2732, false, -1, 7745, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2735}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2737, false, 7744, -1, 7744, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2740, false, -1, 7747, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2743}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2745, false, 7746, -1, 7746, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2748, false, -1, 7749, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2751}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2753, false, 7748, -1, 7748, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2756, false, -1, 7751, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2759}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2761, false, 7750, -1, 7750, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2764, false, -1, 7753, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2767}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2769, false, 7752, -1, 7752, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2772, false, -1, 7755, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2775}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2777, false, 7754, -1, 7754, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2780, false, -1, 7757, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2783}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2785, false, 7756, -1, 7756, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2788, false, -1, 7759, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2791}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2793, false, 7758, -1, 7758, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2796, false, -1, 7761, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2799}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2801, false, 7760, -1, 7760, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2804, false, -1, 7763, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2807}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2809, false, 7762, -1, 7762, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2812, false, -1, 7765, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2815}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2817, false, 7764, -1, 7764, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2820, false, -1, 7767, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2823}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2825, false, 7766, -1, 7766, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2828, false, -1, 7769, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2831}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2833, false, 7768, -1, 7768, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2836, false, -1, 7771, -1, 9840, -1, false, false, false, false, utf8proc_sequences + 2839}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2841, false, 7770, -1, 7770, 9900, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2844, false, -1, 7773, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2847}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2849, false, 7772, -1, 7772, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2852, false, -1, 7775, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2855}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2857, false, 7774, -1, 7774, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2860, false, -1, 7777, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2863}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2865, false, 7776, -1, 7776, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2868, false, -1, 7779, -1, 10200, -1, false, false, false, false, utf8proc_sequences + 2871}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2873, false, 7778, -1, 7778, 10260, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2876, false, -1, 7781, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2879}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2881, false, 7780, -1, 7780, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2884, false, -1, 7783, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2887}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2889, false, 7782, -1, 7782, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2892, false, -1, 7785, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2895}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2897, false, 7784, -1, 7784, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2900, false, -1, 7787, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2903}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2905, false, 7786, -1, 7786, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2908, false, -1, 7789, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2911}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2913, false, 7788, -1, 7788, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2916, false, -1, 7791, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2919}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2921, false, 7790, -1, 7790, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2924, false, -1, 7793, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2927}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2929, false, 7792, -1, 7792, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2932, false, -1, 7795, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2935}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2937, false, 7794, -1, 7794, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2940, false, -1, 7797, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2943}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2945, false, 7796, -1, 7796, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2948, false, -1, 7799, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2951}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2953, false, 7798, -1, 7798, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2956, false, -1, 7801, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2959}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2961, false, 7800, -1, 7800, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2964, false, -1, 7803, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2967}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2969, false, 7802, -1, 7802, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2972, false, -1, 7805, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2975}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2977, false, 7804, -1, 7804, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2980, false, -1, 7807, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2983}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2985, false, 7806, -1, 7806, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2988, false, -1, 7809, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2991}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2993, false, 7808, -1, 7808, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2996, false, -1, 7811, -1, -1, -1, false, false, false, false, utf8proc_sequences + 2999}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3001, false, 7810, -1, 7810, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3004, false, -1, 7813, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3007}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3009, false, 7812, -1, 7812, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3012, false, -1, 7815, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3015}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3017, false, 7814, -1, 7814, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3020, false, -1, 7817, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3023}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3025, false, 7816, -1, 7816, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3028, false, -1, 7819, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3031}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3033, false, 7818, -1, 7818, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3036, false, -1, 7821, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3039}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3041, false, 7820, -1, 7820, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3044, false, -1, 7823, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3047}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3049, false, 7822, -1, 7822, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3052, false, -1, 7825, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3055}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3057, false, 7824, -1, 7824, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3060, false, -1, 7827, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3063}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3065, false, 7826, -1, 7826, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3068, false, -1, 7829, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3071}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3073, false, 7828, -1, 7828, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3076, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3076}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3079, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3079}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3082, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3082}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3085, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3085}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 3088, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3088}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3091, false, 7776, -1, 7776, -1, -1, false, false, false, false, utf8proc_sequences + 2863}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3094, false, -1, 7841, -1, 10980, -1, false, false, false, false, utf8proc_sequences + 3097}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3099, false, 7840, -1, 7840, 11040, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3102, false, -1, 7843, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3105}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3107, false, 7842, -1, 7842, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3110, false, -1, 7845, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3113}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3115, false, 7844, -1, 7844, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3118, false, -1, 7847, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3121}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3123, false, 7846, -1, 7846, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3126, false, -1, 7849, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3129}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3131, false, 7848, -1, 7848, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3134, false, -1, 7851, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3137}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3139, false, 7850, -1, 7850, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3142, false, -1, 7853, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3145}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3147, false, 7852, -1, 7852, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3150, false, -1, 7855, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3153}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3155, false, 7854, -1, 7854, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3158, false, -1, 7857, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3161}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3163, false, 7856, -1, 7856, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3166, false, -1, 7859, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3169}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3171, false, 7858, -1, 7858, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3174, false, -1, 7861, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3177}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3179, false, 7860, -1, 7860, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3182, false, -1, 7863, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3185}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3187, false, 7862, -1, 7862, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3190, false, -1, 7865, -1, 11340, -1, false, false, false, false, utf8proc_sequences + 3193}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3195, false, 7864, -1, 7864, 11400, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3198, false, -1, 7867, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3201}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3203, false, 7866, -1, 7866, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3206, false, -1, 7869, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3209}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3211, false, 7868, -1, 7868, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3214, false, -1, 7871, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3217}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3219, false, 7870, -1, 7870, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3222, false, -1, 7873, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3225}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3227, false, 7872, -1, 7872, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3230, false, -1, 7875, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3233}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3235, false, 7874, -1, 7874, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3238, false, -1, 7877, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3241}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3243, false, 7876, -1, 7876, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3246, false, -1, 7879, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3249}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3251, false, 7878, -1, 7878, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3254, false, -1, 7881, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3257}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3259, false, 7880, -1, 7880, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3262, false, -1, 7883, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3265}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3267, false, 7882, -1, 7882, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3270, false, -1, 7885, -1, 11580, -1, false, false, false, false, utf8proc_sequences + 3273}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3275, false, 7884, -1, 7884, 11640, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3278, false, -1, 7887, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3281}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3283, false, 7886, -1, 7886, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3286, false, -1, 7889, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3289}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3291, false, 7888, -1, 7888, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3294, false, -1, 7891, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3297}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3299, false, 7890, -1, 7890, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3302, false, -1, 7893, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3305}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3307, false, 7892, -1, 7892, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3310, false, -1, 7895, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3313}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3315, false, 7894, -1, 7894, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3318, false, -1, 7897, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3321}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3323, false, 7896, -1, 7896, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3326, false, -1, 7899, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3329}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3331, false, 7898, -1, 7898, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3334, false, -1, 7901, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3337}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3339, false, 7900, -1, 7900, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3342, false, -1, 7903, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3345}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3347, false, 7902, -1, 7902, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3350, false, -1, 7905, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3353}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3355, false, 7904, -1, 7904, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3358, false, -1, 7907, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3361}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3363, false, 7906, -1, 7906, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3366, false, -1, 7909, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3369}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3371, false, 7908, -1, 7908, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3374, false, -1, 7911, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3377}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3379, false, 7910, -1, 7910, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3382, false, -1, 7913, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3385}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3387, false, 7912, -1, 7912, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3390, false, -1, 7915, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3393}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3395, false, 7914, -1, 7914, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3398, false, -1, 7917, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3401}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3403, false, 7916, -1, 7916, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3406, false, -1, 7919, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3409}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3411, false, 7918, -1, 7918, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3414, false, -1, 7921, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3417}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3419, false, 7920, -1, 7920, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3422, false, -1, 7923, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3425}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3427, false, 7922, -1, 7922, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3430, false, -1, 7925, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3433}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3435, false, 7924, -1, 7924, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3438, false, -1, 7927, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3441}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3443, false, 7926, -1, 7926, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3446, false, -1, 7929, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3449}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3451, false, 7928, -1, 7928, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3454, false, 7944, -1, 7944, 11940, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3457, false, 7945, -1, 7945, 12000, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3460, false, 7946, -1, 7946, 13560, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3463, false, 7947, -1, 7947, 13620, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3466, false, 7948, -1, 7948, 13680, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3469, false, 7949, -1, 7949, 13740, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3472, false, 7950, -1, 7950, 13800, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3475, false, 7951, -1, 7951, 13860, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3478, false, -1, 7936, -1, 12060, -1, false, false, false, false, utf8proc_sequences + 3481}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3483, false, -1, 7937, -1, 12120, -1, false, false, false, false, utf8proc_sequences + 3486}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3488, false, -1, 7938, -1, 13920, -1, false, false, false, false, utf8proc_sequences + 3491}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3493, false, -1, 7939, -1, 13980, -1, false, false, false, false, utf8proc_sequences + 3496}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3498, false, -1, 7940, -1, 14040, -1, false, false, false, false, utf8proc_sequences + 3501}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3503, false, -1, 7941, -1, 14100, -1, false, false, false, false, utf8proc_sequences + 3506}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3508, false, -1, 7942, -1, 14160, -1, false, false, false, false, utf8proc_sequences + 3511}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3513, false, -1, 7943, -1, 14220, -1, false, false, false, false, utf8proc_sequences + 3516}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3518, false, 7960, -1, 7960, 12180, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3521, false, 7961, -1, 7961, 12240, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3524, false, 7962, -1, 7962, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3527, false, 7963, -1, 7963, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3530, false, 7964, -1, 7964, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3533, false, 7965, -1, 7965, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3536, false, -1, 7952, -1, 12300, -1, false, false, false, false, utf8proc_sequences + 3539}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3541, false, -1, 7953, -1, 12360, -1, false, false, false, false, utf8proc_sequences + 3544}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3546, false, -1, 7954, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3549}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3551, false, -1, 7955, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3554}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3556, false, -1, 7956, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3559}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3561, false, -1, 7957, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3564}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3566, false, 7976, -1, 7976, 12420, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3569, false, 7977, -1, 7977, 12480, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3572, false, 7978, -1, 7978, 14280, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3575, false, 7979, -1, 7979, 14340, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3578, false, 7980, -1, 7980, 14400, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3581, false, 7981, -1, 7981, 14460, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3584, false, 7982, -1, 7982, 14520, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3587, false, 7983, -1, 7983, 14580, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3590, false, -1, 7968, -1, 12540, -1, false, false, false, false, utf8proc_sequences + 3593}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3595, false, -1, 7969, -1, 12600, -1, false, false, false, false, utf8proc_sequences + 3598}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3600, false, -1, 7970, -1, 14640, -1, false, false, false, false, utf8proc_sequences + 3603}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3605, false, -1, 7971, -1, 14700, -1, false, false, false, false, utf8proc_sequences + 3608}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3610, false, -1, 7972, -1, 14760, -1, false, false, false, false, utf8proc_sequences + 3613}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3615, false, -1, 7973, -1, 14820, -1, false, false, false, false, utf8proc_sequences + 3618}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3620, false, -1, 7974, -1, 14880, -1, false, false, false, false, utf8proc_sequences + 3623}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3625, false, -1, 7975, -1, 14940, -1, false, false, false, false, utf8proc_sequences + 3628}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3630, false, 7992, -1, 7992, 12660, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3633, false, 7993, -1, 7993, 12720, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3636, false, 7994, -1, 7994, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3639, false, 7995, -1, 7995, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3642, false, 7996, -1, 7996, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3645, false, 7997, -1, 7997, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3648, false, 7998, -1, 7998, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3651, false, 7999, -1, 7999, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3654, false, -1, 7984, -1, 12780, -1, false, false, false, false, utf8proc_sequences + 3657}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3659, false, -1, 7985, -1, 12840, -1, false, false, false, false, utf8proc_sequences + 3662}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3664, false, -1, 7986, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3667}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3669, false, -1, 7987, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3672}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3674, false, -1, 7988, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3677}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3679, false, -1, 7989, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3682}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3684, false, -1, 7990, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3687}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3689, false, -1, 7991, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3692}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3694, false, 8008, -1, 8008, 12900, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3697, false, 8009, -1, 8009, 12960, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3700, false, 8010, -1, 8010, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3703, false, 8011, -1, 8011, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3706, false, 8012, -1, 8012, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3709, false, 8013, -1, 8013, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3712, false, -1, 8000, -1, 13020, -1, false, false, false, false, utf8proc_sequences + 3715}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3717, false, -1, 8001, -1, 13080, -1, false, false, false, false, utf8proc_sequences + 3720}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3722, false, -1, 8002, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3725}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3727, false, -1, 8003, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3730}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3732, false, -1, 8004, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3735}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3737, false, -1, 8005, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3740}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3742, false, -1, -1, -1, 13140, -1, false, false, false, false, utf8proc_sequences + 3742}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3745, false, 8025, -1, 8025, 13200, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3748, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3751}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3755, false, 8027, -1, 8027, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3758, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3761}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3765, false, 8029, -1, 8029, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3768, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3771}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3775, false, 8031, -1, 8031, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3778, false, -1, 8017, -1, 13260, -1, false, false, false, false, utf8proc_sequences + 3781}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3783, false, -1, 8019, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3786}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3788, false, -1, 8021, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3791}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3793, false, -1, 8023, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3796}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3798, false, 8040, -1, 8040, 13320, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3801, false, 8041, -1, 8041, 13380, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3804, false, 8042, -1, 8042, 15000, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3807, false, 8043, -1, 8043, 15060, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3810, false, 8044, -1, 8044, 15120, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3813, false, 8045, -1, 8045, 15180, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3816, false, 8046, -1, 8046, 15240, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3819, false, 8047, -1, 8047, 15300, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3822, false, -1, 8032, -1, 13440, -1, false, false, false, false, utf8proc_sequences + 3825}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3827, false, -1, 8033, -1, 13500, -1, false, false, false, false, utf8proc_sequences + 3830}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3832, false, -1, 8034, -1, 15360, -1, false, false, false, false, utf8proc_sequences + 3835}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3837, false, -1, 8035, -1, 15420, -1, false, false, false, false, utf8proc_sequences + 3840}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3842, false, -1, 8036, -1, 15480, -1, false, false, false, false, utf8proc_sequences + 3845}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3847, false, -1, 8037, -1, 15540, -1, false, false, false, false, utf8proc_sequences + 3850}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3852, false, -1, 8038, -1, 15600, -1, false, false, false, false, utf8proc_sequences + 3855}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3857, false, -1, 8039, -1, 15660, -1, false, false, false, false, utf8proc_sequences + 3860}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3862, false, 8122, -1, 8122, 15720, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1341, false, 8123, -1, 8123, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3865, false, 8136, -1, 8136, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1348, false, 8137, -1, 8137, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3868, false, 8138, -1, 8138, 15900, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1353, false, 8139, -1, 8139, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3871, false, 8154, -1, 8154, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1358, false, 8155, -1, 8155, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3874, false, 8184, -1, 8184, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1363, false, 8185, -1, 8185, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3877, false, 8170, -1, 8170, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1368, false, 8171, -1, 8171, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3880, false, 8186, -1, 8186, 16320, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1373, false, 8187, -1, 8187, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3883, false, 8072, -1, 8072, -1, -1, false, false, false, false, utf8proc_sequences + 3886}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3889, false, 8073, -1, 8073, -1, -1, false, false, false, false, utf8proc_sequences + 3892}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3895, false, 8074, -1, 8074, -1, -1, false, false, false, false, utf8proc_sequences + 3898}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3901, false, 8075, -1, 8075, -1, -1, false, false, false, false, utf8proc_sequences + 3904}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3907, false, 8076, -1, 8076, -1, -1, false, false, false, false, utf8proc_sequences + 3910}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3913, false, 8077, -1, 8077, -1, -1, false, false, false, false, utf8proc_sequences + 3916}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3919, false, 8078, -1, 8078, -1, -1, false, false, false, false, utf8proc_sequences + 3922}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3925, false, 8079, -1, 8079, -1, -1, false, false, false, false, utf8proc_sequences + 3928}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3931, false, -1, 8064, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3934}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3936, false, -1, 8065, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3939}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3941, false, -1, 8066, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3944}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3946, false, -1, 8067, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3949}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3951, false, -1, 8068, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3954}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3956, false, -1, 8069, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3959}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3961, false, -1, 8070, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3964}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3966, false, -1, 8071, -1, -1, -1, false, false, false, false, utf8proc_sequences + 3969}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3971, false, 8088, -1, 8088, -1, -1, false, false, false, false, utf8proc_sequences + 3974}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3977, false, 8089, -1, 8089, -1, -1, false, false, false, false, utf8proc_sequences + 3980}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3983, false, 8090, -1, 8090, -1, -1, false, false, false, false, utf8proc_sequences + 3986}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3989, false, 8091, -1, 8091, -1, -1, false, false, false, false, utf8proc_sequences + 3992}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 3995, false, 8092, -1, 8092, -1, -1, false, false, false, false, utf8proc_sequences + 3998}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4001, false, 8093, -1, 8093, -1, -1, false, false, false, false, utf8proc_sequences + 4004}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4007, false, 8094, -1, 8094, -1, -1, false, false, false, false, utf8proc_sequences + 4010}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4013, false, 8095, -1, 8095, -1, -1, false, false, false, false, utf8proc_sequences + 4016}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4019, false, -1, 8080, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4022}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4024, false, -1, 8081, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4027}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4029, false, -1, 8082, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4032}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4034, false, -1, 8083, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4037}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4039, false, -1, 8084, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4042}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4044, false, -1, 8085, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4047}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4049, false, -1, 8086, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4052}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4054, false, -1, 8087, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4057}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4059, false, 8104, -1, 8104, -1, -1, false, false, false, false, utf8proc_sequences + 4062}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4065, false, 8105, -1, 8105, -1, -1, false, false, false, false, utf8proc_sequences + 4068}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4071, false, 8106, -1, 8106, -1, -1, false, false, false, false, utf8proc_sequences + 4074}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4077, false, 8107, -1, 8107, -1, -1, false, false, false, false, utf8proc_sequences + 4080}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4083, false, 8108, -1, 8108, -1, -1, false, false, false, false, utf8proc_sequences + 4086}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4089, false, 8109, -1, 8109, -1, -1, false, false, false, false, utf8proc_sequences + 4092}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4095, false, 8110, -1, 8110, -1, -1, false, false, false, false, utf8proc_sequences + 4098}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4101, false, 8111, -1, 8111, -1, -1, false, false, false, false, utf8proc_sequences + 4104}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4107, false, -1, 8096, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4110}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4112, false, -1, 8097, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4115}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4117, false, -1, 8098, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4120}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4122, false, -1, 8099, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4125}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4127, false, -1, 8100, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4130}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4132, false, -1, 8101, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4135}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4137, false, -1, 8102, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4140}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4142, false, -1, 8103, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4145}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4147, false, 8120, -1, 8120, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4150, false, 8121, -1, 8121, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4153, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4156}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4159, false, 8124, -1, 8124, -1, -1, false, false, false, false, utf8proc_sequences + 4162}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4165, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4168}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4171, false, -1, -1, -1, 15840, -1, false, false, false, false, utf8proc_sequences + 4171}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4174, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4177}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4181, false, -1, 8112, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4184}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4186, false, -1, 8113, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4189}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4191, false, -1, 8048, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4194}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4196, false, -1, 8049, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4198}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4200, false, -1, 8115, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4203}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4205, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 1326, false, 921, -1, 921, -1, -1, false, false, false, false, utf8proc_sequences + 1326}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4205, false, -1, -1, -1, 16080, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4208, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4211, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4214, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4217}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4220, false, 8140, -1, 8140, -1, -1, false, false, false, false, utf8proc_sequences + 4223}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4226, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4229}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4232, false, -1, -1, -1, 16020, -1, false, false, false, false, utf8proc_sequences + 4232}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4235, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4238}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4242, false, -1, 8050, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4245}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4247, false, -1, 8051, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4249}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4251, false, -1, 8052, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4254}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4256, false, -1, 8053, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4258}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4260, false, -1, 8131, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4263}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4265, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4268, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4271, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4274, false, 8152, -1, 8152, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4277, false, 8153, -1, 8153, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4280, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4283}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4287, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1378}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4289, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4289}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4292, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4295}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4299, false, -1, 8144, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4302}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4304, false, -1, 8145, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4307}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4309, false, -1, 8054, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4312}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4314, false, -1, 8055, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4316}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4318, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4321, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4324, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4327, false, 8168, -1, 8168, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4330, false, 8169, -1, 8169, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4333, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4336}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4340, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1451}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4342, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4342}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4345, false, 8172, -1, 8172, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4348, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4348}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4351, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4354}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4358, false, -1, 8160, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4361}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4363, false, -1, 8161, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4366}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4368, false, -1, 8058, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4371}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4373, false, -1, 8059, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4375}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4377, false, -1, 8165, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4380}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4382, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4385, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4387, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4389, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4392}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4395, false, 8188, -1, 8188, -1, -1, false, false, false, false, utf8proc_sequences + 4398}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4401, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4404}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4407, false, -1, -1, -1, 16440, -1, false, false, false, false, utf8proc_sequences + 4407}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4410, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4413}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4417, false, -1, 8056, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4420}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4422, false, -1, 8057, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4424}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4426, false, -1, 8060, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4429}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4431, false, -1, 8061, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4433}, - {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4435, false, -1, 8179, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4438}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4440, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4442, false, -1, -1, -1, 16140, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, 0, utf8proc_sequences + 4445, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, 0, utf8proc_sequences + 4447, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 52, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, UTF8PROC_DECOMP_TYPE_NOBREAK, utf8proc_sequences + 52, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_BN, 0, NULL, false, -1, -1, -1, -1, -1, false, true, true, true, NULL}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_R, 0, NULL, false, -1, -1, -1, -1, -1, false, true, true, false, NULL}, - {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NOBREAK, utf8proc_sequences + 4449, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4451, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4454, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4456, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4459, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ZL, 0, UTF8PROC_BIDI_CLASS_WS, 0, NULL, false, -1, -1, -1, -1, -1, false, false, true, false, NULL}, - {UTF8PROC_CATEGORY_ZP, 0, UTF8PROC_BIDI_CLASS_B, 0, NULL, false, -1, -1, -1, -1, -1, false, false, true, false, NULL}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_LRE, 0, NULL, false, -1, -1, -1, -1, -1, false, true, true, false, NULL}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_RLE, 0, NULL, false, -1, -1, -1, -1, -1, false, true, true, false, NULL}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_PDF, 0, NULL, false, -1, -1, -1, -1, -1, false, true, true, false, NULL}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_LRO, 0, NULL, false, -1, -1, -1, -1, -1, false, true, true, false, NULL}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_RLO, 0, NULL, false, -1, -1, -1, -1, -1, false, true, true, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4463, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4466, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4470, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4473, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4477, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4480, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_CS, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4483, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4486, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4489, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4492, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4497, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 16, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4499, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4501, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4503, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4505, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4507, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4509, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4511, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4513, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4515, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4517, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4519, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 26, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 4497, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 72, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 60, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 62, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 4499, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 4501, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 4503, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 4505, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 4507, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 4509, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 4511, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 4513, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 4515, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 4517, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 4519, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 0, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 8, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 28, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 46, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, utf8proc_sequences + 792, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4521, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4524, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4528, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4532, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4534, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4537, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4541, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4545, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4547, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 12, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2390, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 14, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 454, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2392, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2398, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 22, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2402, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4550, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2408, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4553, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2410, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4555, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4558, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 4562, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4565, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4567, false, -1, 969, -1, -1, -1, false, false, false, false, utf8proc_sequences + 1424}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 2396, false, -1, 107, -1, -1, -1, false, false, false, false, utf8proc_sequences + 20}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 4569, false, -1, 229, -1, -1, -1, false, false, false, false, utf8proc_sequences + 114}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2380, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 8, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2384, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4571, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 8526, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4573}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2400, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 28, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4575, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4577, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4579, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4581, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 16, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4583, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1408, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1386, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4587, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4589, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4591, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2382, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 6, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 18, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 8498, -1, 8498, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 4593, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 4597, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 4601, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 4605, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 4609, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 4613, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 4617, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 4621, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 4625, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 4629, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 4633, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 4637, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, utf8proc_sequences + 4641, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2392, false, -1, 8560, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4644}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4646, false, -1, 8561, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4649}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4651, false, -1, 8562, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4655}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4657, false, -1, 8563, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4660}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4662, false, -1, 8564, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4664}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4666, false, -1, 8565, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4669}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4671, false, -1, 8566, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4675}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4677, false, -1, 8567, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4682}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4684, false, -1, 8568, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4687}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4689, false, -1, 8569, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4691}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4693, false, -1, 8570, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4696}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4698, false, -1, 8571, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4702}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2398, false, -1, 8572, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4704}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4532, false, -1, 8573, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4706}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2382, false, -1, 8574, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4708}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 2400, false, -1, 8575, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4710}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 16, false, 8544, -1, 8544, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4712, false, 8545, -1, 8545, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4715, false, 8546, -1, 8546, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4719, false, 8547, -1, 8547, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 42, false, 8548, -1, 8548, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4722, false, 8549, -1, 8549, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4725, false, 8550, -1, 8550, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4729, false, 8551, -1, 8551, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4734, false, 8552, -1, 8552, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 46, false, 8553, -1, 8553, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4737, false, 8554, -1, 8554, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4740, false, 8555, -1, 8555, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 22, false, 8556, -1, 8556, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4, false, 8557, -1, 8557, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6, false, 8558, -1, 8558, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 24, false, 8559, -1, 8559, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 8580, -1, -1, -1, false, false, false, false, utf8proc_sequences + 4744}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 8579, -1, 8579, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, 16500, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, 16560, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, 16620, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4746, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4749, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4752, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4755, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4758, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4761, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, 16680, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, 16800, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, 16740, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 16860, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4764, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 16920, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4767, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 16980, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4770, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, 17040, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4773, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, 17100, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4776, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4779, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4782, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4786, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4789, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 17160, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4793, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 17220, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4796, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 17280, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4799, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 17340, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4802, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, 17520, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4805, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, 17460, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4808, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 17700, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 17760, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4811, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4814, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4817, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4820, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4823, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 17820, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 17880, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4826, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4829, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 17940, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18000, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4832, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4835, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18060, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18120, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18660, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18720, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4838, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4841, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18180, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18240, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4844, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4847, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18300, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18360, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4850, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4853, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18780, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18840, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18420, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18480, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18540, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18600, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4856, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4859, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4862, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4865, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18900, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 18960, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 19020, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, true, -1, -1, -1, 19080, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4868, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4871, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4874, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4877, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4880, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4883, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4886, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4889, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4892, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 4894, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 72, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 60, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 62, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4499, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4501, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4503, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4505, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4507, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4509, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4896, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4899, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4902, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4905, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4908, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4911, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4914, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4917, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4920, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4923, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4926, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4929, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4933, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4937, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4941, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4945, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4949, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4953, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4957, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4961, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4965, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4970, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4975, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4980, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4985, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4990, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 4995, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5000, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5005, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5010, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5015, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5020, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5023, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5026, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5029, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5032, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5035, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5038, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5041, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5044, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5047, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5051, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5055, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5059, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5063, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5067, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5071, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5075, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5079, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5083, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5087, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5091, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5095, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5099, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5103, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5107, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5111, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5115, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5119, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5123, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5127, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5131, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5135, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5139, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5143, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5147, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5151, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5155, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5159, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5163, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5167, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5171, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5175, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5179, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5183, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5187, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5191, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2376, false, -1, 9424, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5195}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2380, false, -1, 9425, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5197}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4532, false, -1, 9426, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5199}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2382, false, -1, 9427, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5201}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2384, false, -1, 9428, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5203}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4571, false, -1, 9429, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5205}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2388, false, -1, 9430, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5207}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2390, false, -1, 9431, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5209}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2392, false, -1, 9432, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5211}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2394, false, -1, 9433, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5213}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2396, false, -1, 9434, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5215}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2398, false, -1, 9435, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5217}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2400, false, -1, 9436, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5219}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2402, false, -1, 9437, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5221}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2404, false, -1, 9438, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5223}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2408, false, -1, 9439, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5225}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4553, false, -1, 9440, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5227}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2410, false, -1, 9441, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5229}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 5231, false, -1, 9442, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5233}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2412, false, -1, 9443, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5235}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2414, false, -1, 9444, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5237}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4662, false, -1, 9445, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5239}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2416, false, -1, 9446, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5241}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4689, false, -1, 9447, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5243}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 5245, false, -1, 9448, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5247}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4565, false, -1, 9449, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5249}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 0, false, 9398, -1, 9398, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 2, false, 9399, -1, 9399, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4, false, 9400, -1, 9400, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6, false, 9401, -1, 9401, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 8, false, 9402, -1, 9402, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 10, false, 9403, -1, 9403, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 12, false, 9404, -1, 9404, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 14, false, 9405, -1, 9405, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 16, false, 9406, -1, 9406, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 18, false, 9407, -1, 9407, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 20, false, 9408, -1, 9408, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 22, false, 9409, -1, 9409, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 24, false, 9410, -1, 9410, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 26, false, 9411, -1, 9411, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 28, false, 9412, -1, 9412, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 30, false, 9413, -1, 9413, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 32, false, 9414, -1, 9414, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 34, false, 9415, -1, 9415, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 36, false, 9416, -1, 9416, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 38, false, 9417, -1, 9417, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 40, false, 9418, -1, 9418, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 42, false, 9419, -1, 9419, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 44, false, 9420, -1, 9420, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 46, false, 9421, -1, 9421, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 48, false, 9422, -1, 9422, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 50, false, 9423, -1, 9423, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 4497, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5251, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5256, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5260, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5263, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, utf8proc_sequences + 5267, true, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, 19140, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11312, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5270}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11313, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5272}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11314, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5274}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11315, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5276}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11316, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5278}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11317, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5280}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11318, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5282}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11319, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5284}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11320, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5286}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11321, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5288}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11322, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5290}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11323, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5292}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11324, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5294}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11325, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5296}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11326, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5298}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11327, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5300}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11328, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5302}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11329, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5304}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11330, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5306}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11331, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5308}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11332, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5310}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11333, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5312}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11334, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5314}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11335, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5316}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11336, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5318}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11337, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5320}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11338, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5322}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11339, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5324}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11340, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5326}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11341, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5328}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11342, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5330}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11343, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5332}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11344, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5334}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11345, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5336}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11346, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5338}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11347, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5340}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11348, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5342}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11349, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5344}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11350, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5346}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11351, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5348}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11352, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5350}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11353, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5352}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11354, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5354}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11355, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5356}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11356, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5358}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11357, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5360}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11358, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5362}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11264, -1, 11264, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11265, -1, 11265, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11266, -1, 11266, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11267, -1, 11267, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11268, -1, 11268, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11269, -1, 11269, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11270, -1, 11270, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11271, -1, 11271, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11272, -1, 11272, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11273, -1, 11273, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11274, -1, 11274, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11275, -1, 11275, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11276, -1, 11276, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11277, -1, 11277, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11278, -1, 11278, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11279, -1, 11279, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11280, -1, 11280, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11281, -1, 11281, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11282, -1, 11282, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11283, -1, 11283, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11284, -1, 11284, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11285, -1, 11285, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11286, -1, 11286, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11287, -1, 11287, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11288, -1, 11288, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11289, -1, 11289, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11290, -1, 11290, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11291, -1, 11291, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11292, -1, 11292, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11293, -1, 11293, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11294, -1, 11294, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11295, -1, 11295, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11296, -1, 11296, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11297, -1, 11297, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11298, -1, 11298, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11299, -1, 11299, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11300, -1, 11300, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11301, -1, 11301, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11302, -1, 11302, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11303, -1, 11303, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11304, -1, 11304, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11305, -1, 11305, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11306, -1, 11306, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11307, -1, 11307, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11308, -1, 11308, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11309, -1, 11309, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11310, -1, 11310, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11361, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5364}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11360, -1, 11360, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 619, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5366}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 7549, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5368}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 637, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5370}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 570, -1, 570, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 574, -1, 574, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11368, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5372}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11367, -1, 11367, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11370, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5374}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11369, -1, 11369, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11372, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5376}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11371, -1, 11371, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11382, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5378}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11381, -1, 11381, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11393, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5380}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11392, -1, 11392, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11395, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5382}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11394, -1, 11394, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11397, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5384}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11396, -1, 11396, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11399, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5386}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11398, -1, 11398, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11401, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5388}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11400, -1, 11400, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11403, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5390}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11402, -1, 11402, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11405, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5392}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11404, -1, 11404, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11407, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5394}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11406, -1, 11406, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11409, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5396}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11408, -1, 11408, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11411, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5398}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11410, -1, 11410, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11413, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5400}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11412, -1, 11412, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11415, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5402}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11414, -1, 11414, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11417, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5404}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11416, -1, 11416, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11419, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5406}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11418, -1, 11418, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11421, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5408}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11420, -1, 11420, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11423, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5410}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11422, -1, 11422, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11425, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5412}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11424, -1, 11424, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11427, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5414}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11426, -1, 11426, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11429, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5416}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11428, -1, 11428, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11431, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5418}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11430, -1, 11430, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11433, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5420}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11432, -1, 11432, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11435, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5422}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11434, -1, 11434, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11437, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5424}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11436, -1, 11436, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11439, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5426}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11438, -1, 11438, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11441, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5428}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11440, -1, 11440, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11443, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5430}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11442, -1, 11442, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11445, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5432}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11444, -1, 11444, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11447, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5434}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11446, -1, 11446, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11449, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5436}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11448, -1, 11448, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11451, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5438}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11450, -1, 11450, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11453, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5440}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11452, -1, 11452, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11455, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5442}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11454, -1, 11454, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11457, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5444}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11456, -1, 11456, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11459, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5446}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11458, -1, 11458, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11461, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5448}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11460, -1, 11460, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11463, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5450}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11462, -1, 11462, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11465, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5452}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11464, -1, 11464, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11467, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5454}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11466, -1, 11466, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11469, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5456}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11468, -1, 11468, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11471, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5458}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11470, -1, 11470, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11473, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5460}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11472, -1, 11472, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11475, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5462}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11474, -1, 11474, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11477, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5464}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11476, -1, 11476, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11479, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5466}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11478, -1, 11478, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11481, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5468}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11480, -1, 11480, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11483, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5470}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11482, -1, 11482, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11485, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5472}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11484, -1, 11484, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11487, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5474}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11486, -1, 11486, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11489, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5476}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11488, -1, 11488, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 11491, -1, -1, -1, false, false, false, false, utf8proc_sequences + 5478}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 11490, -1, 11490, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4256, -1, 4256, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4257, -1, 4257, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4258, -1, 4258, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4259, -1, 4259, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4260, -1, 4260, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4261, -1, 4261, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4262, -1, 4262, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4263, -1, 4263, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4264, -1, 4264, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4265, -1, 4265, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4266, -1, 4266, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4267, -1, 4267, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4268, -1, 4268, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4269, -1, 4269, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4270, -1, 4270, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4271, -1, 4271, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4272, -1, 4272, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4273, -1, 4273, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4274, -1, 4274, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4275, -1, 4275, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4276, -1, 4276, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4277, -1, 4277, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4278, -1, 4278, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4279, -1, 4279, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4280, -1, 4280, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4281, -1, 4281, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4282, -1, 4282, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4283, -1, 4283, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4284, -1, 4284, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4285, -1, 4285, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4286, -1, 4286, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4287, -1, 4287, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4288, -1, 4288, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4289, -1, 4289, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4290, -1, 4290, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4291, -1, 4291, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4292, -1, 4292, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 4293, -1, 4293, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 5480, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5482, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5484, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5486, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5488, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5490, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5492, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5494, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5496, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5498, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5500, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5502, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5504, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5506, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5508, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5510, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5512, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5514, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5516, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5518, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5520, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5522, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5524, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5526, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5528, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5530, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5532, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5534, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5536, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5538, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5540, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5542, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5544, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5546, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5548, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5550, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5552, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5554, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5556, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5558, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5560, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5562, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5564, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5566, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5568, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5570, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5572, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5574, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5576, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5578, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5580, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5582, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5584, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5586, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5588, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5590, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5592, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5594, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5596, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5598, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5600, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5602, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5604, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5606, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5608, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5610, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5612, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5614, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5616, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5618, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5620, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5622, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5624, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5626, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5628, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5630, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5632, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5634, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5636, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5638, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5640, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5642, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5644, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5646, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5648, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5650, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5652, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5654, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5656, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5658, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5660, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5662, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5664, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5666, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5668, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5670, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5672, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5674, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5676, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5678, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5680, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5682, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5684, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5686, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5688, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5690, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5692, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5694, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5696, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5698, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5700, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5702, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5704, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5706, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5708, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5710, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5712, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5714, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5716, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5718, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5720, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5722, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5724, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5726, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5728, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5730, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5732, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5734, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5736, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5738, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5740, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5742, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5744, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5746, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5748, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5750, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5752, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5754, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5756, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5758, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5760, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5762, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5764, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5766, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5768, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5770, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5772, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5774, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5776, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5778, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5780, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5782, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5784, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5786, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5788, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5790, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5792, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5794, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5796, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5798, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5800, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5802, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5804, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5806, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5808, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5810, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5812, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5814, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5816, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5818, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5820, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5822, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5824, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5826, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5828, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5830, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5832, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5834, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5836, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5838, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5840, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5842, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5844, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5846, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5848, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5850, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5852, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5854, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5856, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5858, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5860, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5862, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5864, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5866, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5868, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5870, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5872, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5874, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5876, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5878, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5880, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5882, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5884, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5886, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5888, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5890, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5892, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5894, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5896, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5898, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5900, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5902, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5904, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5906, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5908, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5910, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5912, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 52, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MN, 218, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 224, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5914, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5532, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5916, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5918, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20400, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 19200, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5920, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 19260, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5923, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 19320, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5926, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 19380, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5929, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 19440, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5932, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 19500, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5935, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 19560, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5938, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 19620, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5941, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 19680, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5944, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 19740, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5947, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 19800, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5950, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 19860, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5953, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 19920, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5956, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 19980, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5959, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20040, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5962, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20100, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5965, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5968, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20160, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5971, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5974, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20220, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5977, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5980, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20280, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5983, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5986, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20340, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5989, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5992, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5995, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MN, 8, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 52, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MN, 8, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, 53, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 5998, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6001, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20460, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6004, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 6007, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21720, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20520, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6010, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20580, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6013, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20640, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6016, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20700, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6019, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20760, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6022, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20820, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6025, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20880, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6028, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 20940, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6031, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21000, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6034, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21060, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6037, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21120, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6040, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21180, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6043, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21240, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6046, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21300, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6049, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21360, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6052, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21420, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6055, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6058, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21480, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6061, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6064, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21540, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6067, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6070, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21600, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6073, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6076, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21660, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6079, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6082, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21780, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21840, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21900, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 21960, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6085, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6088, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6091, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6094, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6097, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 22020, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6100, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 6103, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6106, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6108, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6110, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6112, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6114, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6116, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6118, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6120, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6122, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6124, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6126, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6128, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6130, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6132, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6134, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6136, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6138, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6140, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6142, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6144, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6146, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6148, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6150, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6152, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6154, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6156, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6158, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6160, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6162, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6164, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6166, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6168, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6170, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6172, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6174, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6176, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6178, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6180, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6182, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6184, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6186, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6188, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6190, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6192, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6194, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6196, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6198, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6200, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6202, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6204, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6206, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6208, false, -1, -1, -1, -1, -1, false, true, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6210, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6212, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6214, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6216, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6218, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6220, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6222, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6224, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6226, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6228, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6230, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6232, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6234, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6236, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6238, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6240, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6242, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6244, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6246, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6248, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6250, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6252, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6254, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6256, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6258, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6260, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6262, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6264, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6266, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6268, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6270, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6272, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6274, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6276, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6278, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6280, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6282, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6284, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6286, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6288, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6290, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6292, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 5486, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 5498, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 6294, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 6296, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 6298, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 6300, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 6302, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 6304, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 5494, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 6306, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 6308, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 6310, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 6312, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, utf8proc_sequences + 5502, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6314, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6318, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6322, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6326, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6330, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6334, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6338, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6342, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6346, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6350, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6354, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6358, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6362, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6366, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6370, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6375, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6380, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6385, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6390, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6395, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6400, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6405, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6410, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6415, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6420, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6425, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6430, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6435, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6440, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6445, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6453, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6460, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6464, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6468, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6472, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6476, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6480, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6484, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6488, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6492, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6496, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6500, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6504, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6508, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6512, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6516, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6520, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6524, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6528, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6532, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6536, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6540, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6544, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6548, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6552, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6556, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6560, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6564, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6568, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6572, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6576, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6580, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6584, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6588, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6592, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6596, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6600, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 6604, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6608, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6611, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6614, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6617, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6620, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6623, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6626, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6629, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6632, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6635, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6638, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6641, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6644, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6647, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6650, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6106, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6112, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6118, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6122, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6138, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6140, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6146, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6150, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6152, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6156, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6158, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6160, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6162, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6164, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6653, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6656, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6659, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6662, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6665, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6668, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6671, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6674, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6677, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6680, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6683, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6686, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6689, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6692, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6695, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6701, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6706, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 5486, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 5498, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6294, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6296, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6709, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6711, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6713, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 5508, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6715, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 5532, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 5632, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 5656, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 5654, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 5634, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 5818, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 5548, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 5628, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6717, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6719, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6721, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6723, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6725, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6727, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6729, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6731, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6733, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6735, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 5560, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6737, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6739, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6741, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6743, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6745, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6747, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6749, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6751, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6298, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6300, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6302, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6753, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6755, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6757, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6759, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6761, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6763, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6765, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6767, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6769, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6771, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6773, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6776, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6779, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6782, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6785, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6788, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6791, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6794, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6797, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6800, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6803, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6806, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6809, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6812, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6815, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6818, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6821, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6824, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6827, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6830, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6833, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6836, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6839, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6842, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6845, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6849, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 6853, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 6857, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 6860, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 6864, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 6867, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6871, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6873, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6875, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6877, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6879, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6881, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6883, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6885, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6887, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6889, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6891, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6893, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6895, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6897, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6899, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6901, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6903, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6905, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6907, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6909, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6911, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6913, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6915, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6917, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6919, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6921, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6923, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6925, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6927, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6929, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6931, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6933, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6935, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6937, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6939, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6941, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6943, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6945, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6947, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6949, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6951, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6953, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6955, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6957, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6959, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6961, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, utf8proc_sequences + 6963, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 6965, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 6970, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 6975, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 6980, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 6984, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 6989, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 6993, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 6997, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7003, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7008, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7012, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7016, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7020, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7025, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7030, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7034, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7038, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7041, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7045, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7050, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7055, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7058, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7064, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7071, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7077, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7081, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7087, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7093, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7098, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7102, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7106, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7110, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7115, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7121, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7126, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7130, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7134, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7138, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7141, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7144, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7147, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7150, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7154, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7158, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7164, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7168, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7173, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7179, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7183, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7186, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7189, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7195, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7200, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7206, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7210, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7216, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7219, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7223, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7227, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7231, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7235, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7239, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7244, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7248, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7251, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7255, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7259, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7263, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7268, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7272, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7276, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7280, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7286, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7291, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7294, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7300, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7303, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7308, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7313, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7317, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7321, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7325, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7330, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7333, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7337, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7342, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7345, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7351, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7355, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7358, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7361, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7364, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7367, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7370, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7373, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7376, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7379, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7382, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7385, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7389, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7393, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7397, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7401, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7405, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7409, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7413, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7417, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7421, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7425, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7429, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7433, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7437, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7441, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7445, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7449, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7452, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7455, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7459, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7462, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7465, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7468, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7472, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7476, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7479, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7482, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7485, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7488, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7491, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7496, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7499, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7502, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7505, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7508, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7511, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7514, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7517, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7520, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7524, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7529, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7532, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7535, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7538, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7541, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7544, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7547, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7550, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7554, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7558, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7562, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7566, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7569, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7572, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7575, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7578, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7581, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7584, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7587, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7590, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7593, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7596, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7600, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7604, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7607, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7611, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7615, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7619, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7622, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7626, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7630, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7635, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7638, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7642, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7646, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7650, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7654, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7660, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7667, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7670, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7673, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7676, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7679, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7682, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7685, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7688, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7691, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7694, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7697, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7700, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7703, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7706, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7709, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7712, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7715, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7718, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7721, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7726, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7729, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7732, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7735, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7740, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7744, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7747, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7750, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7753, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7756, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7759, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7762, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7765, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7768, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7771, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7774, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7778, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7781, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7784, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7788, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7792, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7795, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7800, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7804, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7807, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7810, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7813, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7816, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7820, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7824, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7827, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7830, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7833, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7836, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7839, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7842, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7845, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7848, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7851, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7855, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7859, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7863, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7867, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7871, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7875, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7879, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7883, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7887, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7891, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7895, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7899, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7903, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7907, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7911, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7915, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7919, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7923, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7927, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7931, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 7935, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, utf8proc_sequences + 7939, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_CS, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, true, false, false, NULL}, - {UTF8PROC_CATEGORY_CO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7943, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7945, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5802, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7947, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7949, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7951, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7953, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5910, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7955, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5818, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7957, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7959, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7961, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7963, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7965, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7967, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7969, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7971, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7973, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7975, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7977, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7979, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7981, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7983, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7985, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7987, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7989, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7991, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7993, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7995, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7997, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 7999, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8001, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8003, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8005, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8007, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8009, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8011, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8013, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8015, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8017, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8019, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8021, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8023, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8025, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8027, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8029, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8031, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8033, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8035, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8037, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5734, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8039, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8041, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8043, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8045, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8047, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8049, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8051, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8053, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8055, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8057, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8059, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5880, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8061, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8063, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8065, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8067, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8069, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8071, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8073, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8075, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8077, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8079, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8081, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8083, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8085, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8087, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8089, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8091, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8093, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8095, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8097, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8099, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8101, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8103, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8105, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8107, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8109, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8111, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8113, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8115, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8117, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8119, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8121, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8123, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8125, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8127, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8129, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8131, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8133, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8135, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8137, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8139, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8141, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8143, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8145, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8147, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8149, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8151, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8153, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5806, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8155, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8157, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8159, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8161, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8163, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8165, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8167, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8169, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8171, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8173, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8175, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8177, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8179, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8181, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8183, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5560, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8185, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8187, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8189, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8191, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8193, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8195, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8197, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8199, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5522, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8201, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8203, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8205, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8207, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8209, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8211, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8213, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8215, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8217, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8219, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8221, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8223, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8225, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8227, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8229, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8231, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8233, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8235, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8237, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8239, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8241, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8243, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8245, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8247, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8249, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8251, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8253, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8255, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8257, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8259, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8261, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8263, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8265, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8267, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8269, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8271, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8273, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8275, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8277, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8279, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8281, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8283, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8285, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8287, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8289, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8291, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8293, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8295, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8297, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8299, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8301, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8303, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8305, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8307, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5908, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8309, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8311, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8313, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8315, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8317, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8319, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8321, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8323, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8325, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8327, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8329, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8331, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6711, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8333, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8335, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8337, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8339, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8341, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8343, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8345, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8347, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8349, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8351, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8353, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8355, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8357, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8359, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8361, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8363, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8365, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8367, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8369, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8371, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8373, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8375, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5816, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8377, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8379, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8381, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8383, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8385, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8387, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8389, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8391, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8393, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8395, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8397, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8399, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8401, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5718, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8403, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8405, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8407, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8409, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8411, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8413, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8415, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8417, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8419, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8421, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8423, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8425, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8427, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8429, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8431, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8433, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5772, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8435, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5778, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8437, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8439, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8441, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8443, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8445, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8447, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8449, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8451, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8453, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8455, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8457, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8459, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8461, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8463, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5732, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8465, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8467, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8469, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8471, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8473, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8475, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8477, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8479, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8481, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8483, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8485, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8487, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8489, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8491, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8493, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8495, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8497, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8499, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8501, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8503, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5574, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8505, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8507, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8509, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8511, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8513, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8515, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8517, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8519, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8521, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8523, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8525, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8527, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8529, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8531, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8533, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6721, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8535, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8537, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8539, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8541, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 6729, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8543, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8545, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8547, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8549, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8551, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8553, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8555, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8557, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8559, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8561, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8563, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8565, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8567, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8569, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8571, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8573, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8575, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8577, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8579, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8581, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8583, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8585, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8587, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8589, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8591, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8593, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8595, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8597, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8599, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8601, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8603, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8605, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8607, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8609, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8611, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8613, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8615, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8617, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8619, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8621, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8623, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8625, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8627, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8629, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8631, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8633, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8635, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8637, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8639, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8641, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8643, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8645, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8647, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5640, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8649, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8651, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8653, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8655, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8657, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8659, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8661, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8663, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8665, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8667, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8669, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8671, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8673, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8675, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8677, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8679, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8681, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8683, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8685, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8687, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8689, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8691, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8693, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8695, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8697, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8699, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8701, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8703, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8705, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8707, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8709, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8711, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8713, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8715, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8717, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8719, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8721, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8723, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8725, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8727, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8729, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8731, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8733, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8735, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8737, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8739, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8741, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 8743, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 8745, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 8745}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 8748, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 8748}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 8751, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 8751}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 8754, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 8754}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 8758, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 8758}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 8762, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 8765}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 8765, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 8765}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 8768, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 8768}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 8771, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 8771}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 8774, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 8774}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 8777, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 8777}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 8780, false, -1, -1, -1, -1, -1, false, false, false, false, utf8proc_sequences + 8780}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8783, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MN, 26, UTF8PROC_BIDI_CLASS_NSM, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8786, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 8789, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4575, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4581, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 8791, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 8793, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 8795, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 8797, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 8799, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 8801, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4511, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8803, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8806, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8809, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8812, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8815, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8818, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8821, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8824, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8827, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8830, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8833, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8836, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8839, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8842, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8845, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8848, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8851, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8854, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8857, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8860, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8863, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8866, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8869, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8872, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8875, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8878, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8881, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8884, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8887, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8890, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8893, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, utf8proc_sequences + 8896, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 8899, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8902, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8902, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8904, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8904, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8904, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8904, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8906, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8906, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8906, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8906, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8908, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8908, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8908, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8908, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8910, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8910, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8910, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8910, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8912, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8912, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8912, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8912, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8914, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8914, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8914, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8914, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8916, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8916, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8916, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8916, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8918, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8918, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8918, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8918, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8920, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8920, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8920, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8920, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8922, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8922, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8922, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8922, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8924, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8924, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8924, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8924, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8926, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8926, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8926, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8926, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8928, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8928, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8930, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8930, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8932, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8932, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8934, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8934, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8936, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8936, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8938, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8938, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8940, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8940, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8940, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8940, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8942, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8942, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8942, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8942, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8944, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8944, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8944, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8944, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8946, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8946, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8946, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8946, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8948, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8948, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8950, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8950, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8950, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8950, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8952, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8952, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8954, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8954, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8954, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8954, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8956, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8956, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8956, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8956, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8958, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8958, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8960, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8960, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8962, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8962, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8962, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8962, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8964, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8964, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8966, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8966, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8968, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8968, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8970, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8972, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8972, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8974, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8974, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8976, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8976, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8978, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8978, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8978, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8978, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 8980, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 8980, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8982, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8982, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8985, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8985, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8988, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8988, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8991, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8991, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8994, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8994, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8997, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8997, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9000, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9000, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9000, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9003, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9003, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9003, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9006, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9006, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9006, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9006, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9008, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9011, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9014, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9017, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9020, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9023, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9026, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9029, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9032, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9035, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9038, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9041, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9044, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9047, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9050, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9053, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9056, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9059, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9062, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9065, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9068, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9071, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9074, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9077, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9080, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9083, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9086, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9089, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9092, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9095, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9098, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9101, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9104, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9107, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9110, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9113, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9116, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9119, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9122, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9125, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9128, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9131, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9134, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9137, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9140, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9143, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9146, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9149, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9152, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9155, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9158, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9161, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9164, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9167, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9170, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9173, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9176, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9179, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9182, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9185, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9188, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9191, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9194, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9197, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9200, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9203, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9206, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9209, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9212, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9215, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9218, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9221, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9224, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9227, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9230, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9233, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9236, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9239, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9242, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9245, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9248, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9251, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9254, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9257, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9260, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9263, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9266, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9269, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9272, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9275, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9278, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9281, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9284, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9287, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9291, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9295, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9299, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9303, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9307, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9311, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9314, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9014, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9317, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9017, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9320, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9323, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9029, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9326, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9032, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9035, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9329, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9332, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9047, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9335, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9050, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9053, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9338, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9341, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9059, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9344, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9062, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9065, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9152, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9155, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9164, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9167, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9170, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9182, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9185, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9188, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9191, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9203, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9206, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9209, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9347, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9221, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9350, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9353, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9239, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9356, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9242, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9245, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9284, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9359, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9362, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9269, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9365, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9272, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9275, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9008, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9011, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9368, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9014, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9371, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9020, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9023, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9026, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9029, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9374, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9038, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9041, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9044, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9047, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9377, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9059, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9068, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9071, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9074, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9077, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9080, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9086, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9089, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9092, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9095, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9098, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9101, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9380, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9104, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9107, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9110, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9113, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9116, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9119, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9125, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9128, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9131, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9134, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9137, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9140, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9143, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9146, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9149, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9158, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9161, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9173, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9176, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9179, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9182, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9185, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9194, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9197, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9200, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9203, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9383, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9212, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9215, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9218, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9221, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9230, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9233, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9236, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9239, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9386, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9248, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9251, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9389, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9260, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9263, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9266, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9269, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9392, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9014, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9371, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9029, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9374, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9047, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9377, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9059, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9395, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9098, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9398, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9401, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9404, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9182, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9185, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9203, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9239, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9386, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9269, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9392, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9407, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9411, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9415, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9419, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9422, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9425, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9428, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9431, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9434, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9437, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9440, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9443, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9446, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9449, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9452, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9455, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9458, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9461, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9464, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9467, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9470, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9473, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9476, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9479, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9482, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9485, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9401, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9488, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9491, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9494, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9497, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9419, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9422, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9425, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9428, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9431, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9434, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9437, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9440, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9443, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9446, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9449, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9452, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9455, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9458, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9461, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9464, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9467, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9470, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9473, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9476, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9479, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9482, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9485, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9401, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9488, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9491, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9494, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9497, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9479, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9482, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9485, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9401, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9398, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9404, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9122, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9089, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9092, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9095, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9479, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9482, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9485, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9122, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 9125, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9500, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9500, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9503, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9507, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9507, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9511, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9515, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9519, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9523, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9527, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9531, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9531, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9535, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9539, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9543, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9547, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9551, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9555, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9555, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9559, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9563, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9563, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9567, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9567, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9571, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9575, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9575, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9579, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9583, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9583, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9587, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9587, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9591, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9595, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9595, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9599, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9599, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9603, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9607, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9611, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9615, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9615, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9619, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9623, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9627, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9631, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9635, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9635, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9639, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9643, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9647, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9651, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9655, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9659, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9659, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9663, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9663, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9667, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9667, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9671, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9675, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9679, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9683, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9687, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9691, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9695, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9699, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9703, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9707, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9711, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9715, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9719, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9719, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9723, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9727, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9731, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9735, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9735, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9739, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9743, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9747, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9751, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9755, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9759, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9763, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9767, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9771, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9775, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9779, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9783, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9787, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9791, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9795, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9799, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9803, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9807, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9811, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9815, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9819, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9823, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9639, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9647, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9827, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9831, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9835, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9839, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9843, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9847, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9843, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9835, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9851, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9855, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9859, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9863, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9867, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9847, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9611, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 9571, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9871, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 9875, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9879, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9883, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9887, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9892, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9897, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9902, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9907, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9912, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9917, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9922, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9926, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9945, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 9954, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9959, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9961, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9963, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9965, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 1333, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9967, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9969, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9971, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9973, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9975, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9977, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9979, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9981, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PC, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9983, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 4517, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 4519, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9985, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9987, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9989, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9991, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9993, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9995, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9997, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 9999, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 4892, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 4894, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 10001, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 10003, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 10005, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 10007, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 10009, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, utf8proc_sequences + 10011, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 10013, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PC, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, utf8proc_sequences + 9983, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 9959, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 9961, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 4454, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 1333, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 9965, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 9969, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 9967, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 9979, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 4517, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 4519, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 9985, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 9987, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 9989, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 9991, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 10015, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 10017, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 10019, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 4511, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 10021, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 10023, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 10025, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 4515, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 10027, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 10029, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 10031, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, utf8proc_sequences + 10033, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10035, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10038, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10041, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10044, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10047, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10050, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10053, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10056, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10059, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10062, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10065, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10068, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10071, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10074, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10077, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10079, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10079, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10081, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10081, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10083, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10083, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10085, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10085, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10087, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10087, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10087, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10087, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10089, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10089, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10091, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10091, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10091, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10091, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10093, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10093, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10095, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10095, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10095, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10095, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10097, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10097, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10097, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10097, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10099, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10099, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10099, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10099, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10101, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10101, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10101, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10101, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10103, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10103, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10103, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10103, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10105, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10105, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10107, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10107, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10109, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10109, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10111, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10111, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10113, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10113, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10113, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10113, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10115, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10115, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10115, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10115, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10117, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10117, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10117, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10117, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10119, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10119, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10119, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10119, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10121, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10121, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10121, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10121, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10123, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10123, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10123, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10123, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10125, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10125, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10125, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10125, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10127, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10127, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10127, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10127, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10129, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10129, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10129, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10129, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10131, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10131, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10131, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10131, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10133, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10133, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10133, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10133, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10135, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10135, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10135, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10135, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10137, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10137, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10137, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10137, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10139, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10139, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10139, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10139, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10141, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10141, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10141, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10141, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10143, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10143, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 8980, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 8980, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10145, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10145, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, utf8proc_sequences + 10145, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, utf8proc_sequences + 10145, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10147, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10147, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10150, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10150, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10153, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10153, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, utf8proc_sequences + 10156, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, utf8proc_sequences + 10156, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 9967, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10159, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10015, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10029, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10031, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10017, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10161, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4517, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4519, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10019, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4511, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 9959, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10021, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4454, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10163, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4497, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 72, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 60, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 62, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4499, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4501, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4503, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4505, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4507, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4509, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 9965, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 1333, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10023, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4515, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10025, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 9969, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10033, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2376, false, -1, 65345, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10165}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2380, false, -1, 65346, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10167}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4532, false, -1, 65347, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10169}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2382, false, -1, 65348, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10171}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2384, false, -1, 65349, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10173}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4571, false, -1, 65350, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10175}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2388, false, -1, 65351, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10177}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2390, false, -1, 65352, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10179}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2392, false, -1, 65353, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10181}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2394, false, -1, 65354, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10183}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2396, false, -1, 65355, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10185}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2398, false, -1, 65356, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10187}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2400, false, -1, 65357, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10189}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2402, false, -1, 65358, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10191}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2404, false, -1, 65359, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10193}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2408, false, -1, 65360, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10195}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4553, false, -1, 65361, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10197}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2410, false, -1, 65362, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10199}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 5231, false, -1, 65363, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10201}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2412, false, -1, 65364, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10203}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2414, false, -1, 65365, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10205}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4662, false, -1, 65366, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10207}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2416, false, -1, 65367, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10209}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4689, false, -1, 65368, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10211}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 5245, false, -1, 65369, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10213}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4565, false, -1, 65370, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10215}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10009, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10027, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10011, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10217, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PC, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 9983, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4387, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 0, false, 65313, -1, 65313, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 2, false, 65314, -1, 65314, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 4, false, 65315, -1, 65315, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 6, false, 65316, -1, 65316, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 8, false, 65317, -1, 65317, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10, false, 65318, -1, 65318, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 12, false, 65319, -1, 65319, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 14, false, 65320, -1, 65320, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 16, false, 65321, -1, 65321, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 18, false, 65322, -1, 65322, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 20, false, 65323, -1, 65323, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 22, false, 65324, -1, 65324, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 24, false, 65325, -1, 65325, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 26, false, 65326, -1, 65326, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 28, false, 65327, -1, 65327, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 30, false, 65328, -1, 65328, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 32, false, 65329, -1, 65329, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 34, false, 65330, -1, 65330, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 36, false, 65331, -1, 65331, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 38, false, 65332, -1, 65332, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 40, false, 65333, -1, 65333, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 42, false, 65334, -1, 65334, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 44, false, 65335, -1, 65335, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 46, false, 65336, -1, 65336, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 48, false, 65337, -1, 65337, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 50, false, 65338, -1, 65338, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 9985, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10219, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 9987, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10221, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10223, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10225, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 9963, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10001, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10003, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 9961, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10227, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6963, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10229, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10231, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10233, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10235, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10237, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10239, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10241, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10243, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10245, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10247, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6871, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6873, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6875, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6877, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6879, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6881, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6883, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6885, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6887, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6889, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6891, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6893, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6895, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6897, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6899, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6901, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6903, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6905, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6907, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6909, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6911, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6913, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6915, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6917, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6919, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6921, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6923, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6925, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6927, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6929, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6931, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6933, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6935, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6937, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6939, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6941, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6943, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6945, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6947, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6949, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6951, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6953, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6955, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 6957, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10249, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10251, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10253, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10255, false, -1, -1, -1, -1, -1, false, true, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10257, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10259, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10261, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10263, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10265, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10267, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10269, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10271, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10273, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10275, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10277, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10279, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10281, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10283, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10285, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10287, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10289, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10291, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10293, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10295, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10297, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10299, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10301, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10303, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10305, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10307, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10309, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10311, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10313, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10315, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10317, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10319, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10321, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10323, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10325, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10327, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10329, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10331, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10333, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10335, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10337, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10339, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10341, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10343, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10345, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10347, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10349, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10351, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10353, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10355, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10357, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10359, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10361, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10363, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10365, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10367, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10369, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, utf8proc_sequences + 10371, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10373, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10375, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10377, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10379, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10381, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10383, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, utf8proc_sequences + 10385, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, -1, -1, false, false, true, false, NULL}, - {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_ON, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66600, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10387}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66601, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10389}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66602, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10391}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66603, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10393}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66604, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10395}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66605, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10397}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66606, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10399}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66607, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10401}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66608, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10403}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66609, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10405}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66610, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10407}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66611, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10409}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66612, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10411}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66613, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10413}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66614, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10415}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66615, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10417}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66616, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10419}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66617, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10421}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66618, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10423}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66619, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10425}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66620, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10427}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66621, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10429}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66622, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10431}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66623, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10433}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66624, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10435}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66625, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10437}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66626, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10439}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66627, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10441}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66628, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10443}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66629, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10445}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66630, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10447}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66631, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10449}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66632, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10451}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66633, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10453}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66634, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10455}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66635, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10457}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66636, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10459}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66637, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10461}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66638, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10463}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, 66639, -1, -1, -1, false, false, false, false, utf8proc_sequences + 10465}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66560, -1, 66560, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66561, -1, 66561, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66562, -1, 66562, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66563, -1, 66563, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66564, -1, 66564, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66565, -1, 66565, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66566, -1, 66566, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66567, -1, 66567, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66568, -1, 66568, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66569, -1, 66569, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66570, -1, 66570, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66571, -1, 66571, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66572, -1, 66572, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66573, -1, 66573, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66574, -1, 66574, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66575, -1, 66575, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66576, -1, 66576, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66577, -1, 66577, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66578, -1, 66578, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66579, -1, 66579, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66580, -1, 66580, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66581, -1, 66581, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66582, -1, 66582, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66583, -1, 66583, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66584, -1, 66584, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66585, -1, 66585, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66586, -1, 66586, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66587, -1, 66587, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66588, -1, 66588, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66589, -1, 66589, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66590, -1, 66590, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66591, -1, 66591, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66592, -1, 66592, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66593, -1, 66593, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66594, -1, 66594, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66595, -1, 66595, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66596, -1, 66596, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66597, -1, 66597, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66598, -1, 66598, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, 66599, -1, 66599, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_R, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 22080, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 22140, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10467, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10470, false, -1, -1, -1, 22200, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10473, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10476, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10479, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10482, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10485, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 54, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 226, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 55, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 56, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 57, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 58, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, -1, 59, false, false, false, true, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 22260, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, NULL, false, -1, -1, -1, 22320, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10488, false, -1, -1, -1, 22380, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10491, false, -1, -1, -1, 22440, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10494, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10497, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10500, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10503, false, -1, -1, -1, -1, -1, true, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2376, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2388, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2394, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2396, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2404, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 5231, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2412, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2414, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4662, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2416, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4689, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 5245, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 0, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 2, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 20, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 24, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 26, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 30, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 32, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 34, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 36, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 38, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 40, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 42, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 44, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 46, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 48, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 50, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10506, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10508, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10510, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10512, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10514, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10516, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10518, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10520, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1504, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10522, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10524, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10526, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10528, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10530, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10532, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10534, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10536, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10538, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1508, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10540, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1470, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10542, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10544, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10546, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4567, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10548, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1382, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1384, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1388, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1390, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1392, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1394, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1396, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1326, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1398, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1400, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 67, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1402, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1404, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1406, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1410, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1502, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1412, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1414, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1416, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1418, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1420, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1422, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1424, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10550, true, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10552, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10554, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10556, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10558, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10560, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10562, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 10564, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 1482, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4497, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 72, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 60, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 62, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4499, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4501, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4503, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4505, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4507, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, utf8proc_sequences + 4509, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10566, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10568, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10570, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10572, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10574, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10576, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10578, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10580, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10582, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10584, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10586, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10588, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10590, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10592, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10594, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10596, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10598, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10600, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10602, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10604, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10606, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10608, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10610, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10612, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10614, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5518, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10616, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10618, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10620, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10622, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10624, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10626, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10628, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10630, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10632, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10634, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10636, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10638, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10640, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10642, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10644, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10646, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10648, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10650, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10652, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10654, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10656, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10658, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10660, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10662, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10664, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10666, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10668, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10670, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10672, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10674, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10676, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10678, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10680, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10682, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10684, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10686, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10688, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10690, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10692, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10694, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10696, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10698, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10700, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10702, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10704, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10706, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10708, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10710, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10712, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10714, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10716, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10718, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10720, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10722, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10724, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10726, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10728, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10730, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10732, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10734, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10736, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10738, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10740, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10742, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10744, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10746, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10748, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10750, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10752, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10754, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10756, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10758, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10760, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5570, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10762, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10764, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10766, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10768, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10770, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10772, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10774, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10776, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10778, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10780, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10782, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10784, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10786, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10788, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10790, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10792, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10794, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10796, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10798, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10800, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10802, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10804, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10806, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10808, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5594, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10810, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10812, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10814, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10816, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10818, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10820, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10822, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10824, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10826, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10828, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10830, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10832, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10834, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10836, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10838, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10840, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10842, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10844, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10846, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10848, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10850, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10852, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10854, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10856, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10858, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10860, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10862, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10864, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10866, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10868, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10870, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10872, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10874, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10876, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10878, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10880, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10882, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10884, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10886, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10888, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10890, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10892, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10894, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10896, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10898, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10900, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10902, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10904, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10906, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10908, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10910, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10912, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10914, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10916, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10918, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10920, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10922, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10924, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10926, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10928, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10930, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10932, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10934, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10936, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10938, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10940, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10942, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10944, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10946, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10948, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10950, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10952, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10954, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10956, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10958, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10960, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10962, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10964, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10966, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10968, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10970, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10972, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10974, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10976, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10978, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10980, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10982, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10984, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10986, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10988, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10990, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10992, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10994, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10996, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 10998, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11000, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11002, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11004, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11006, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11008, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11010, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11012, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11014, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11016, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11018, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11020, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11022, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11024, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11026, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11028, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11030, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11032, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11034, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11036, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11038, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11040, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11042, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11044, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11046, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11048, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11050, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11052, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11054, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11056, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11058, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11060, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11062, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11064, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11066, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11068, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11070, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11072, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11074, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11076, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11078, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11080, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11082, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11084, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11086, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11088, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11090, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11092, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11094, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11096, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11098, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11100, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11102, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11104, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11106, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11108, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11110, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11112, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11114, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11116, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11118, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11120, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11122, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11124, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11126, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11128, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11130, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11132, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11134, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11136, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11138, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11140, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11142, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11144, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11146, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11148, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11150, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11152, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11154, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11156, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11158, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11160, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11162, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11164, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11166, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11168, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11170, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11172, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11174, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11176, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11178, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11180, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11182, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11184, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11186, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11188, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11190, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11192, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11194, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11196, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11198, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11200, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11202, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11204, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11206, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11208, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11210, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11212, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11214, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11216, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11218, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11220, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11222, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11224, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11226, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11228, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11230, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11232, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11234, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11236, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11238, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11240, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11242, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11244, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11246, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11248, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11250, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11252, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11254, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11256, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11258, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11260, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11262, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11264, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11266, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11268, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11270, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11272, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11274, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11276, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11278, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11280, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11282, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11284, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11286, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11288, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11290, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11292, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11294, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11296, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11298, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11300, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11302, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11304, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11306, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11308, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11310, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11312, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11314, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11316, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11318, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11320, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11322, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11324, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11326, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11328, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11330, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11332, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11334, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11336, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11338, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11340, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11342, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11344, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5774, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11346, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11348, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11350, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11352, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11354, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11356, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11358, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11360, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11362, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11364, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11366, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5788, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11368, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11370, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11372, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11374, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11376, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11378, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11380, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11382, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11384, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11386, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11388, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11390, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11392, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11394, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11396, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11398, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11400, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11402, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11404, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11406, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11408, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11410, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11412, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11414, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11416, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11418, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11420, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11422, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11424, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11426, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11428, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11430, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11432, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11434, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11436, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11438, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11440, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11442, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11444, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11446, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11448, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11450, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11452, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11454, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11456, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11458, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11460, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11462, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11464, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11466, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11468, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11470, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11472, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11474, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11476, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11478, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11480, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11482, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11484, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11486, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11488, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11490, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5884, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11492, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5892, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11494, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11496, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11498, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11500, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 5902, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, - {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, utf8proc_sequences + 11502, false, -1, -1, -1, -1, -1, false, false, false, false, NULL}, + {0, 0, 0, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false,false,false,false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_BN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, + {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_BN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, + {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_S, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, + {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_B, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_LF}, + {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_WS, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, + {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_B, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CR}, + {UTF8PROC_CATEGORY_CC, 0, UTF8PROC_BIDI_CLASS_B, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, + {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ES, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5093, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5084, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5096, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 0, UINT16_MAX, 0, UINT16_MAX, 0, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1, UINT16_MAX, 1, UINT16_MAX, 2784, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2, UINT16_MAX, 2, UINT16_MAX, 49, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3, UINT16_MAX, 3, UINT16_MAX, 704, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 4, UINT16_MAX, 4, UINT16_MAX, 62, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5, UINT16_MAX, 5, UINT16_MAX, 2872, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6, UINT16_MAX, 6, UINT16_MAX, 782, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7, UINT16_MAX, 7, UINT16_MAX, 808, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8, UINT16_MAX, 8, UINT16_MAX, 111, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 9, UINT16_MAX, 9, UINT16_MAX, 898, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 10, UINT16_MAX, 10, UINT16_MAX, 913, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 11, UINT16_MAX, 11, UINT16_MAX, 999, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 12, UINT16_MAX, 12, UINT16_MAX, 2890, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 13, UINT16_MAX, 13, UINT16_MAX, 160, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 14, UINT16_MAX, 14, UINT16_MAX, 205, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 15, UINT16_MAX, 15, UINT16_MAX, 2982, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 16, UINT16_MAX, 16, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 17, UINT16_MAX, 17, UINT16_MAX, 1087, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 18, UINT16_MAX, 18, UINT16_MAX, 1173, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 19, UINT16_MAX, 19, UINT16_MAX, 1257, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 20, UINT16_MAX, 20, UINT16_MAX, 254, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 21, UINT16_MAX, 21, UINT16_MAX, 3042, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 22, UINT16_MAX, 22, UINT16_MAX, 1337, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 23, UINT16_MAX, 23, UINT16_MAX, 3122, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 24, UINT16_MAX, 24, UINT16_MAX, 303, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 25, UINT16_MAX, 25, UINT16_MAX, 1423, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PC, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1446, UINT16_MAX, 1446, 352, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1448, UINT16_MAX, 1448, 2818, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2795, UINT16_MAX, 2795, 401, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1449, UINT16_MAX, 1449, 743, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1450, UINT16_MAX, 1450, 414, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2820, UINT16_MAX, 2820, 2875, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1452, UINT16_MAX, 1452, 795, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1453, UINT16_MAX, 1453, 853, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1454, UINT16_MAX, 1454, 463, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1455, UINT16_MAX, 1455, 901, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1456, UINT16_MAX, 1456, 956, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1457, UINT16_MAX, 1457, 1043, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1458, UINT16_MAX, 1458, 2932, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1459, UINT16_MAX, 1459, 512, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1460, UINT16_MAX, 1460, 557, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1462, UINT16_MAX, 1462, 2994, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2809, UINT16_MAX, 2809, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1463, UINT16_MAX, 1463, 1130, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 3288, UINT16_MAX, 3288, 1215, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1464, UINT16_MAX, 1464, 1296, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1465, UINT16_MAX, 1465, 606, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2891, UINT16_MAX, 2891, 3082, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1466, UINT16_MAX, 1466, 1380, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2908, UINT16_MAX, 2908, 3131, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 3295, UINT16_MAX, 3295, 655, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2817, UINT16_MAX, 2817, 1466, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_NOBREAK, 26, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 8219, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 1621, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PI, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_BN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 8221, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ET, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ET, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 31, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 32, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 8225, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 35, 35, 7130, UINT16_MAX, 7130, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 8228, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 38, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 14, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PF, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 16423, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 16426, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 16429, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8240, 50, UINT16_MAX, 50, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8243, 53, UINT16_MAX, 53, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8246, 56, UINT16_MAX, 56, UINT16_MAX, 3143, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8249, 59, UINT16_MAX, 59, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8252, 62, UINT16_MAX, 62, UINT16_MAX, 1537, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8255, 65, UINT16_MAX, 65, UINT16_MAX, 1579, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 66, UINT16_MAX, 66, UINT16_MAX, 1549, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8259, 69, UINT16_MAX, 69, UINT16_MAX, 2852, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8262, 72, UINT16_MAX, 72, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8265, 75, UINT16_MAX, 75, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8268, 78, UINT16_MAX, 78, UINT16_MAX, 3357, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8271, 81, UINT16_MAX, 81, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8274, 84, UINT16_MAX, 84, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8277, 87, UINT16_MAX, 87, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8280, 90, UINT16_MAX, 90, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8283, 93, UINT16_MAX, 93, UINT16_MAX, 2878, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 94, UINT16_MAX, 94, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8287, 97, UINT16_MAX, 97, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8290, 100, UINT16_MAX, 100, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8293, 103, UINT16_MAX, 103, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8296, 106, UINT16_MAX, 106, UINT16_MAX, 3461, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8299, 109, UINT16_MAX, 109, UINT16_MAX, 1597, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8302, 112, UINT16_MAX, 112, UINT16_MAX, 1591, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 113, UINT16_MAX, 113, UINT16_MAX, 1585, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8306, 116, UINT16_MAX, 116, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8309, 119, UINT16_MAX, 119, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8312, 122, UINT16_MAX, 122, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8315, 125, UINT16_MAX, 125, UINT16_MAX, 1509, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8318, 128, UINT16_MAX, 128, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 129, UINT16_MAX, 129, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 8322, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8324, UINT16_MAX, 7977, UINT16_MAX, 7977, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8326, UINT16_MAX, 7978, UINT16_MAX, 7978, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8328, UINT16_MAX, 7979, UINT16_MAX, 7979, 3192, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8330, UINT16_MAX, 7980, UINT16_MAX, 7980, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8332, UINT16_MAX, 7981, UINT16_MAX, 7981, 1540, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8334, UINT16_MAX, 2819, UINT16_MAX, 2819, 1582, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1447, UINT16_MAX, 1447, 1558, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8336, UINT16_MAX, 7982, UINT16_MAX, 7982, 2855, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8338, UINT16_MAX, 7983, UINT16_MAX, 7983, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8340, UINT16_MAX, 7984, UINT16_MAX, 7984, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8342, UINT16_MAX, 7985, UINT16_MAX, 7985, 3406, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8344, UINT16_MAX, 7986, UINT16_MAX, 7986, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8346, UINT16_MAX, 7987, UINT16_MAX, 7987, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8348, UINT16_MAX, 7988, UINT16_MAX, 7988, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8350, UINT16_MAX, 7989, UINT16_MAX, 7989, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8352, UINT16_MAX, 7990, UINT16_MAX, 7990, 2881, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7991, UINT16_MAX, 7991, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8354, UINT16_MAX, 7992, UINT16_MAX, 7992, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8356, UINT16_MAX, 7993, UINT16_MAX, 7993, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8358, UINT16_MAX, 7994, UINT16_MAX, 7994, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8360, UINT16_MAX, 7995, UINT16_MAX, 7995, 3510, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8362, UINT16_MAX, 7996, UINT16_MAX, 7996, 1606, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8364, UINT16_MAX, 7997, UINT16_MAX, 7997, 1594, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7998, UINT16_MAX, 7998, 1588, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8366, UINT16_MAX, 7999, UINT16_MAX, 7999, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8368, UINT16_MAX, 8000, UINT16_MAX, 8000, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8370, UINT16_MAX, 8001, UINT16_MAX, 8001, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8372, UINT16_MAX, 8002, UINT16_MAX, 8002, 1523, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8374, UINT16_MAX, 8003, UINT16_MAX, 8003, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8004, UINT16_MAX, 8004, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8376, UINT16_MAX, 8005, UINT16_MAX, 8005, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8378, 188, UINT16_MAX, 188, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8381, UINT16_MAX, 8006, UINT16_MAX, 8006, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8383, 193, UINT16_MAX, 193, UINT16_MAX, 3259, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8386, UINT16_MAX, 8007, UINT16_MAX, 8007, 3308, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8388, 198, UINT16_MAX, 198, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8391, UINT16_MAX, 8008, UINT16_MAX, 8008, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8393, 203, UINT16_MAX, 203, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8396, UINT16_MAX, 8009, UINT16_MAX, 8009, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8398, 208, UINT16_MAX, 208, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8401, UINT16_MAX, 8010, UINT16_MAX, 8010, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8403, 213, UINT16_MAX, 213, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8406, UINT16_MAX, 8011, UINT16_MAX, 8011, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8408, 218, UINT16_MAX, 218, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8411, UINT16_MAX, 8012, UINT16_MAX, 8012, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8413, 223, UINT16_MAX, 223, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8416, UINT16_MAX, 8013, UINT16_MAX, 8013, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 226, UINT16_MAX, 226, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8014, UINT16_MAX, 8014, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8419, 229, UINT16_MAX, 229, UINT16_MAX, 2858, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8422, UINT16_MAX, 8015, UINT16_MAX, 8015, 2862, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8424, 234, UINT16_MAX, 234, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8427, UINT16_MAX, 8016, UINT16_MAX, 8016, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8429, 239, UINT16_MAX, 239, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8432, UINT16_MAX, 8017, UINT16_MAX, 8017, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8434, 244, UINT16_MAX, 244, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8437, UINT16_MAX, 8018, UINT16_MAX, 8018, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8439, 249, UINT16_MAX, 249, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8442, UINT16_MAX, 8019, UINT16_MAX, 8019, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8444, 254, UINT16_MAX, 254, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8447, UINT16_MAX, 8020, UINT16_MAX, 8020, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8449, 259, UINT16_MAX, 259, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8452, UINT16_MAX, 8021, UINT16_MAX, 8021, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8454, 264, UINT16_MAX, 264, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8457, UINT16_MAX, 8022, UINT16_MAX, 8022, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8459, 269, UINT16_MAX, 269, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8462, UINT16_MAX, 8023, UINT16_MAX, 8023, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8464, 274, UINT16_MAX, 274, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8467, UINT16_MAX, 8024, UINT16_MAX, 8024, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 277, UINT16_MAX, 277, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 5138, UINT16_MAX, 5138, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8470, 280, UINT16_MAX, 280, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8473, UINT16_MAX, 8025, UINT16_MAX, 8025, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8475, 285, UINT16_MAX, 285, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8478, UINT16_MAX, 8026, UINT16_MAX, 8026, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8480, 290, UINT16_MAX, 290, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8483, UINT16_MAX, 8027, UINT16_MAX, 8027, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8485, 295, UINT16_MAX, 295, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8488, UINT16_MAX, 8028, UINT16_MAX, 8028, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8490, 8492, UINT16_MAX, 8, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1454, UINT16_MAX, 1454, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8494, 304, UINT16_MAX, 304, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8497, UINT16_MAX, 8029, UINT16_MAX, 8029, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8499, 309, UINT16_MAX, 309, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8502, UINT16_MAX, 8030, UINT16_MAX, 8030, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8504, 314, UINT16_MAX, 314, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8507, UINT16_MAX, 8031, UINT16_MAX, 8031, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8509, 319, UINT16_MAX, 319, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8512, UINT16_MAX, 8032, UINT16_MAX, 8032, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8514, 324, UINT16_MAX, 324, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8517, UINT16_MAX, 8033, UINT16_MAX, 8033, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8519, 329, UINT16_MAX, 329, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8522, UINT16_MAX, 8034, UINT16_MAX, 8034, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8524, 334, UINT16_MAX, 334, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8527, UINT16_MAX, 8035, UINT16_MAX, 8035, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 337, UINT16_MAX, 337, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8036, UINT16_MAX, 8036, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8530, 340, UINT16_MAX, 340, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8533, UINT16_MAX, 8037, UINT16_MAX, 8037, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8535, 345, UINT16_MAX, 345, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8538, UINT16_MAX, 8038, UINT16_MAX, 8038, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8540, 350, UINT16_MAX, 350, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8543, UINT16_MAX, 8039, UINT16_MAX, 8039, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8545, 8545, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 355, UINT16_MAX, 355, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8040, UINT16_MAX, 8040, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8548, 358, UINT16_MAX, 358, UINT16_MAX, 2974, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8551, UINT16_MAX, 8041, UINT16_MAX, 8041, 2978, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8553, 363, UINT16_MAX, 363, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8556, UINT16_MAX, 8042, UINT16_MAX, 8042, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8558, 368, UINT16_MAX, 368, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8561, UINT16_MAX, 8043, UINT16_MAX, 8043, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 371, UINT16_MAX, 371, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8044, UINT16_MAX, 8044, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8564, 374, UINT16_MAX, 374, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8567, UINT16_MAX, 8045, UINT16_MAX, 8045, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8569, 379, UINT16_MAX, 379, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8572, UINT16_MAX, 8046, UINT16_MAX, 8046, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8574, 384, UINT16_MAX, 384, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8577, UINT16_MAX, 8047, UINT16_MAX, 8047, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8579, 389, UINT16_MAX, 389, UINT16_MAX, 3012, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8582, UINT16_MAX, 8048, UINT16_MAX, 8048, 3015, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8584, 394, UINT16_MAX, 394, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8587, UINT16_MAX, 8049, UINT16_MAX, 8049, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8589, 399, UINT16_MAX, 399, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8592, UINT16_MAX, 8050, UINT16_MAX, 8050, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8594, 404, UINT16_MAX, 404, UINT16_MAX, 3018, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8597, UINT16_MAX, 8051, UINT16_MAX, 8051, 3021, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8599, 409, UINT16_MAX, 409, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8602, UINT16_MAX, 8052, UINT16_MAX, 8052, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8604, 414, UINT16_MAX, 414, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8607, UINT16_MAX, 8053, UINT16_MAX, 8053, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 417, UINT16_MAX, 417, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8054, UINT16_MAX, 8054, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8610, 420, UINT16_MAX, 420, UINT16_MAX, 3030, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8613, UINT16_MAX, 8055, UINT16_MAX, 8055, 3033, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8615, 425, UINT16_MAX, 425, UINT16_MAX, 3036, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8618, UINT16_MAX, 8056, UINT16_MAX, 8056, 3039, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8620, 430, UINT16_MAX, 430, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8623, UINT16_MAX, 8057, UINT16_MAX, 8057, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8625, 435, UINT16_MAX, 435, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8628, UINT16_MAX, 8058, UINT16_MAX, 8058, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8630, 440, UINT16_MAX, 440, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8633, UINT16_MAX, 8059, UINT16_MAX, 8059, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8635, 445, UINT16_MAX, 445, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8638, UINT16_MAX, 8060, UINT16_MAX, 8060, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8640, 450, UINT16_MAX, 450, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8643, UINT16_MAX, 8061, UINT16_MAX, 8061, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8645, 455, UINT16_MAX, 455, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8648, UINT16_MAX, 8062, UINT16_MAX, 8062, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8650, 460, UINT16_MAX, 460, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8653, 463, UINT16_MAX, 463, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8656, UINT16_MAX, 8063, UINT16_MAX, 8063, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8658, 468, UINT16_MAX, 468, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8661, UINT16_MAX, 8064, UINT16_MAX, 8064, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8663, 473, UINT16_MAX, 473, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8666, UINT16_MAX, 8065, UINT16_MAX, 8065, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 18, 18, 3288, UINT16_MAX, 3288, 3140, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8066, UINT16_MAX, 8066, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 476, UINT16_MAX, 476, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 477, UINT16_MAX, 477, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8067, UINT16_MAX, 8067, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 478, UINT16_MAX, 478, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8068, UINT16_MAX, 8068, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 479, UINT16_MAX, 479, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 480, UINT16_MAX, 480, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8069, UINT16_MAX, 8069, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 481, UINT16_MAX, 481, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 482, UINT16_MAX, 482, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 483, UINT16_MAX, 483, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8070, UINT16_MAX, 8070, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 484, UINT16_MAX, 484, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 485, UINT16_MAX, 485, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 486, UINT16_MAX, 486, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 487, UINT16_MAX, 487, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8071, UINT16_MAX, 8071, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 488, UINT16_MAX, 488, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 489, UINT16_MAX, 489, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8072, UINT16_MAX, 8072, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 490, UINT16_MAX, 490, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 491, UINT16_MAX, 491, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 492, UINT16_MAX, 492, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8073, UINT16_MAX, 8073, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8074, UINT16_MAX, 8074, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 493, UINT16_MAX, 493, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 494, UINT16_MAX, 494, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8075, UINT16_MAX, 8075, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 495, UINT16_MAX, 495, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8688, 498, UINT16_MAX, 498, UINT16_MAX, 3565, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8691, UINT16_MAX, 8076, UINT16_MAX, 8076, 3614, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 501, UINT16_MAX, 501, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8077, UINT16_MAX, 8077, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 502, UINT16_MAX, 502, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8078, UINT16_MAX, 8078, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 503, UINT16_MAX, 503, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 504, UINT16_MAX, 504, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8079, UINT16_MAX, 8079, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 505, UINT16_MAX, 505, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 506, UINT16_MAX, 506, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8080, UINT16_MAX, 8080, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 507, UINT16_MAX, 507, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8700, 510, UINT16_MAX, 510, UINT16_MAX, 3663, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8703, UINT16_MAX, 8081, UINT16_MAX, 8081, 3712, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 513, UINT16_MAX, 513, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 514, UINT16_MAX, 514, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 515, UINT16_MAX, 515, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8082, UINT16_MAX, 8082, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 516, UINT16_MAX, 516, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8083, UINT16_MAX, 8083, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 517, UINT16_MAX, 517, UINT16_MAX, 1573, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 518, UINT16_MAX, 518, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8084, UINT16_MAX, 8084, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 519, UINT16_MAX, 519, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8085, UINT16_MAX, 8085, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8086, UINT16_MAX, 8086, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8712, 522, UINT16_MAX, 522, 8087, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8715, 522, 8088, 522, 8087, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8717, UINT16_MAX, 8088, UINT16_MAX, 8087, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8719, 529, UINT16_MAX, 529, 8089, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8722, 529, 8090, 529, 8089, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8724, UINT16_MAX, 8090, UINT16_MAX, 8089, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8726, 536, UINT16_MAX, 536, 8091, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8729, 536, 8092, 536, 8091, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8731, UINT16_MAX, 8092, UINT16_MAX, 8091, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8733, 543, UINT16_MAX, 543, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8736, UINT16_MAX, 8093, UINT16_MAX, 8093, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8738, 548, UINT16_MAX, 548, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8741, UINT16_MAX, 8094, UINT16_MAX, 8094, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8743, 553, UINT16_MAX, 553, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8746, UINT16_MAX, 8095, UINT16_MAX, 8095, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8748, 558, UINT16_MAX, 558, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8751, UINT16_MAX, 8096, UINT16_MAX, 8096, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8753, 563, UINT16_MAX, 563, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8756, UINT16_MAX, 8097, UINT16_MAX, 8097, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8758, 568, UINT16_MAX, 568, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8761, UINT16_MAX, 8098, UINT16_MAX, 8098, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8763, 573, UINT16_MAX, 573, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8766, UINT16_MAX, 8099, UINT16_MAX, 8099, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8768, 578, UINT16_MAX, 578, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8771, UINT16_MAX, 8100, UINT16_MAX, 8100, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1451, UINT16_MAX, 1451, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8773, 583, UINT16_MAX, 583, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8776, UINT16_MAX, 8101, UINT16_MAX, 8101, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8778, 588, UINT16_MAX, 588, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8781, UINT16_MAX, 8102, UINT16_MAX, 8102, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8783, 593, UINT16_MAX, 593, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8786, UINT16_MAX, 8103, UINT16_MAX, 8103, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 596, UINT16_MAX, 596, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8104, UINT16_MAX, 8104, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8789, 599, UINT16_MAX, 599, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8792, UINT16_MAX, 8105, UINT16_MAX, 8105, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8794, 604, UINT16_MAX, 604, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8797, UINT16_MAX, 8106, UINT16_MAX, 8106, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8799, 609, UINT16_MAX, 609, UINT16_MAX, 1567, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8802, UINT16_MAX, 8107, UINT16_MAX, 8107, 1570, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8804, 614, UINT16_MAX, 614, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8807, UINT16_MAX, 8108, UINT16_MAX, 8108, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8809, 619, UINT16_MAX, 619, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8812, UINT16_MAX, 8109, UINT16_MAX, 8109, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8814, 8814, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8816, 626, UINT16_MAX, 626, 8110, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8819, 626, 8111, 626, 8110, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8821, UINT16_MAX, 8111, UINT16_MAX, 8110, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8823, 633, UINT16_MAX, 633, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8826, UINT16_MAX, 8112, UINT16_MAX, 8112, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 636, UINT16_MAX, 636, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 637, UINT16_MAX, 637, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8830, 640, UINT16_MAX, 640, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8833, UINT16_MAX, 8113, UINT16_MAX, 8113, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8835, 645, UINT16_MAX, 645, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8838, UINT16_MAX, 8114, UINT16_MAX, 8114, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8840, 650, UINT16_MAX, 650, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8843, UINT16_MAX, 8115, UINT16_MAX, 8115, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8845, 655, UINT16_MAX, 655, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8848, UINT16_MAX, 8116, UINT16_MAX, 8116, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8850, 660, UINT16_MAX, 660, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8853, UINT16_MAX, 8117, UINT16_MAX, 8117, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8855, 665, UINT16_MAX, 665, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8858, UINT16_MAX, 8118, UINT16_MAX, 8118, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8860, 670, UINT16_MAX, 670, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8863, UINT16_MAX, 8119, UINT16_MAX, 8119, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8865, 675, UINT16_MAX, 675, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8868, UINT16_MAX, 8120, UINT16_MAX, 8120, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8870, 680, UINT16_MAX, 680, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8873, UINT16_MAX, 8121, UINT16_MAX, 8121, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8875, 685, UINT16_MAX, 685, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8878, UINT16_MAX, 8122, UINT16_MAX, 8122, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8880, 690, UINT16_MAX, 690, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8883, UINT16_MAX, 8123, UINT16_MAX, 8123, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8885, 695, UINT16_MAX, 695, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8888, UINT16_MAX, 8124, UINT16_MAX, 8124, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8890, 700, UINT16_MAX, 700, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8893, UINT16_MAX, 8125, UINT16_MAX, 8125, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8895, 705, UINT16_MAX, 705, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8898, UINT16_MAX, 8126, UINT16_MAX, 8126, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8900, 710, UINT16_MAX, 710, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8903, UINT16_MAX, 8127, UINT16_MAX, 8127, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8905, 715, UINT16_MAX, 715, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8908, UINT16_MAX, 8128, UINT16_MAX, 8128, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8910, 720, UINT16_MAX, 720, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8913, UINT16_MAX, 8129, UINT16_MAX, 8129, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8915, 725, UINT16_MAX, 725, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8918, UINT16_MAX, 8130, UINT16_MAX, 8130, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 728, UINT16_MAX, 728, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8131, UINT16_MAX, 8131, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8921, 731, UINT16_MAX, 731, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8924, UINT16_MAX, 8132, UINT16_MAX, 8132, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 734, UINT16_MAX, 734, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 735, UINT16_MAX, 735, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 1461, UINT16_MAX, 1461, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 736, UINT16_MAX, 736, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8133, UINT16_MAX, 8133, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8929, 739, UINT16_MAX, 739, UINT16_MAX, 1543, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8932, UINT16_MAX, 8134, UINT16_MAX, 8134, 1546, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8934, 744, UINT16_MAX, 744, UINT16_MAX, 2866, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8937, UINT16_MAX, 8135, UINT16_MAX, 8135, 2869, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8939, 749, UINT16_MAX, 749, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8942, UINT16_MAX, 8136, UINT16_MAX, 8136, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8944, 754, UINT16_MAX, 754, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8947, UINT16_MAX, 8137, UINT16_MAX, 8137, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8949, 759, UINT16_MAX, 759, UINT16_MAX, 1615, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8952, UINT16_MAX, 8138, UINT16_MAX, 8138, 1618, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8954, 764, UINT16_MAX, 764, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8957, UINT16_MAX, 8139, UINT16_MAX, 8139, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 8959, 769, UINT16_MAX, 769, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 8962, UINT16_MAX, 8140, UINT16_MAX, 8140, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 772, UINT16_MAX, 772, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 773, UINT16_MAX, 773, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8141, UINT16_MAX, 8141, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 774, UINT16_MAX, 774, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 775, UINT16_MAX, 775, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8142, UINT16_MAX, 8142, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8143, UINT16_MAX, 8143, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 776, UINT16_MAX, 776, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8144, UINT16_MAX, 8144, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 777, UINT16_MAX, 777, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 778, UINT16_MAX, 778, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 779, UINT16_MAX, 779, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 780, UINT16_MAX, 780, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8145, UINT16_MAX, 8145, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 781, UINT16_MAX, 781, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8146, UINT16_MAX, 8146, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 782, UINT16_MAX, 782, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8147, UINT16_MAX, 8147, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 783, UINT16_MAX, 783, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8148, UINT16_MAX, 8148, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 784, UINT16_MAX, 784, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8149, UINT16_MAX, 8149, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8150, UINT16_MAX, 8150, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8151, UINT16_MAX, 8151, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8152, UINT16_MAX, 8152, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8153, UINT16_MAX, 8153, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8154, UINT16_MAX, 8154, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8155, UINT16_MAX, 8155, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8156, UINT16_MAX, 8156, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8157, UINT16_MAX, 8157, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2804, UINT16_MAX, 2804, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8158, UINT16_MAX, 8158, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8159, UINT16_MAX, 8159, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8160, UINT16_MAX, 8160, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8161, UINT16_MAX, 8161, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8162, UINT16_MAX, 8162, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8163, UINT16_MAX, 8163, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8164, UINT16_MAX, 8164, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8165, UINT16_MAX, 8165, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8166, UINT16_MAX, 8166, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8167, UINT16_MAX, 8167, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8168, UINT16_MAX, 8168, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8169, UINT16_MAX, 8169, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8170, UINT16_MAX, 8170, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8171, UINT16_MAX, 8171, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8172, UINT16_MAX, 8172, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8173, UINT16_MAX, 8173, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8174, UINT16_MAX, 8174, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8175, UINT16_MAX, 8175, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8176, UINT16_MAX, 8176, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8177, UINT16_MAX, 8177, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8178, UINT16_MAX, 8178, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8179, UINT16_MAX, 8179, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8180, UINT16_MAX, 8180, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8181, UINT16_MAX, 8181, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8182, UINT16_MAX, 8182, 1576, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8183, UINT16_MAX, 8183, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8184, UINT16_MAX, 8184, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 7, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 785, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 9, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 17, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 786, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 787, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 788, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 22, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 24, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 8981, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 8983, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 8985, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 8987, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 8989, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 8991, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 489, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 11, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 18, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 23, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32768, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32769, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32770, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32771, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32775, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32776, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32778, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32772, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32814, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32773, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32780, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32779, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32782, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32783, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32815, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32816, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 232, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 216, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32781, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 202, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32808, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32813, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32807, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32784, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 202, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32774, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 202, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32777, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32810, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32812, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32811, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32809, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 1, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 1, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32819, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, 802, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, 803, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32817, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, 804, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, 8997, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 240, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, 807, 7127, UINT16_MAX, 7127, 32818, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 233, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 234, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 808, UINT16_MAX, 808, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8185, UINT16_MAX, 8185, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 809, UINT16_MAX, 809, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8186, UINT16_MAX, 8186, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 810, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 811, UINT16_MAX, 811, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8187, UINT16_MAX, 8187, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 9004, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8188, UINT16_MAX, 8188, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8189, UINT16_MAX, 8189, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8190, UINT16_MAX, 8190, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, 0, 814, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 815, UINT16_MAX, 815, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 9008, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9010, 820, UINT16_MAX, 820, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, 0, 821, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9014, 824, UINT16_MAX, 824, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9017, 827, UINT16_MAX, 827, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9020, 830, UINT16_MAX, 830, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9023, 833, UINT16_MAX, 833, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9026, 836, UINT16_MAX, 836, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9029, 839, UINT16_MAX, 839, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9032, 17226, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 845, UINT16_MAX, 845, UINT16_MAX, 1673, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 846, UINT16_MAX, 846, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 847, UINT16_MAX, 847, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 848, UINT16_MAX, 848, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 849, UINT16_MAX, 849, UINT16_MAX, 1726, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 850, UINT16_MAX, 850, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 851, UINT16_MAX, 851, UINT16_MAX, 1777, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 852, UINT16_MAX, 852, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 807, UINT16_MAX, 807, UINT16_MAX, 1830, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 853, UINT16_MAX, 853, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 854, UINT16_MAX, 854, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 35, UINT16_MAX, 35, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 855, UINT16_MAX, 855, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 856, UINT16_MAX, 856, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 857, UINT16_MAX, 857, UINT16_MAX, 1881, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 858, UINT16_MAX, 858, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 859, UINT16_MAX, 859, UINT16_MAX, 5027, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 860, UINT16_MAX, 860, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 861, UINT16_MAX, 861, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 862, UINT16_MAX, 862, UINT16_MAX, 1932, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 863, UINT16_MAX, 863, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 864, UINT16_MAX, 864, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 865, UINT16_MAX, 865, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 866, UINT16_MAX, 866, UINT16_MAX, 1983, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9059, 869, UINT16_MAX, 869, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9062, 872, UINT16_MAX, 872, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9065, UINT16_MAX, 2583, UINT16_MAX, 2583, 4904, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9067, UINT16_MAX, 2616, UINT16_MAX, 2616, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9069, UINT16_MAX, 2621, UINT16_MAX, 2621, 4913, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9071, UINT16_MAX, 2658, UINT16_MAX, 2658, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9073, 17267, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7121, UINT16_MAX, 7121, 2088, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7122, UINT16_MAX, 7122, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2829, UINT16_MAX, 2829, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7123, UINT16_MAX, 7123, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7124, UINT16_MAX, 7124, 2141, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7125, UINT16_MAX, 7125, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7126, UINT16_MAX, 7126, 2192, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 915, UINT16_MAX, 915, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7127, UINT16_MAX, 7127, 2245, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7128, UINT16_MAX, 7128, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7129, UINT16_MAX, 7129, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7130, UINT16_MAX, 7130, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7131, UINT16_MAX, 7131, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7132, UINT16_MAX, 7132, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7133, UINT16_MAX, 7133, 2401, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2830, UINT16_MAX, 2830, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7134, UINT16_MAX, 7134, 5023, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 860, 917, UINT16_MAX, 917, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 917, UINT16_MAX, 917, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7136, UINT16_MAX, 7136, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 897, UINT16_MAX, 897, 2349, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7137, UINT16_MAX, 7137, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7138, UINT16_MAX, 7138, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7139, UINT16_MAX, 7139, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 2818, UINT16_MAX, 2818, 2452, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9078, UINT16_MAX, 8191, UINT16_MAX, 8191, 2036, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9080, UINT16_MAX, 8192, UINT16_MAX, 8192, 2297, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9082, UINT16_MAX, 2727, UINT16_MAX, 2727, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9084, UINT16_MAX, 2696, UINT16_MAX, 2696, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9086, UINT16_MAX, 2732, UINT16_MAX, 2732, 5033, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 896, UINT16_MAX, 896, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 846, 846, 7122, UINT16_MAX, 7122, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 852, 852, 915, UINT16_MAX, 915, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 897, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2505, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9090, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9092, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 863, 863, 7137, UINT16_MAX, 7137, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 858, 858, 2830, UINT16_MAX, 2830, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8193, UINT16_MAX, 8193, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 902, UINT16_MAX, 902, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8194, UINT16_MAX, 8194, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 903, UINT16_MAX, 903, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8195, UINT16_MAX, 8195, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 904, UINT16_MAX, 904, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 7148, UINT16_MAX, 7148, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 905, UINT16_MAX, 905, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8196, UINT16_MAX, 8196, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 906, UINT16_MAX, 906, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8197, UINT16_MAX, 8197, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 907, UINT16_MAX, 907, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8198, UINT16_MAX, 8198, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 908, UINT16_MAX, 908, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8199, UINT16_MAX, 8199, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 909, UINT16_MAX, 909, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8200, UINT16_MAX, 8200, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 910, UINT16_MAX, 910, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8201, UINT16_MAX, 8201, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 911, UINT16_MAX, 911, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8202, UINT16_MAX, 8202, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 912, UINT16_MAX, 912, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8203, UINT16_MAX, 8203, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 913, UINT16_MAX, 913, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8204, UINT16_MAX, 8204, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 853, 853, 7128, UINT16_MAX, 7128, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 859, 859, 7134, UINT16_MAX, 7134, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 914, UINT16_MAX, 8205, UINT16_MAX, 8205, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8206, UINT16_MAX, 8206, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 915, 852, UINT16_MAX, 852, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 849, 849, 7124, UINT16_MAX, 7124, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 916, UINT16_MAX, 916, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8207, UINT16_MAX, 8207, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 917, 918, UINT16_MAX, 918, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 919, UINT16_MAX, 919, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8208, UINT16_MAX, 8208, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 920, UINT16_MAX, 920, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 921, UINT16_MAX, 921, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 922, UINT16_MAX, 922, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9115, 925, UINT16_MAX, 925, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9118, 928, UINT16_MAX, 928, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 929, UINT16_MAX, 929, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9122, 932, UINT16_MAX, 932, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 933, UINT16_MAX, 933, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 934, UINT16_MAX, 934, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 935, UINT16_MAX, 935, UINT16_MAX, 2525, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9128, 938, UINT16_MAX, 938, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 939, UINT16_MAX, 939, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 940, UINT16_MAX, 940, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 941, UINT16_MAX, 941, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 942, UINT16_MAX, 942, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9135, 945, UINT16_MAX, 945, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9138, 948, UINT16_MAX, 948, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9141, 951, UINT16_MAX, 951, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 952, UINT16_MAX, 952, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 953, UINT16_MAX, 953, UINT16_MAX, 2615, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 954, UINT16_MAX, 954, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 955, UINT16_MAX, 955, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 956, UINT16_MAX, 956, UINT16_MAX, 2522, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 957, UINT16_MAX, 957, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 958, UINT16_MAX, 958, UINT16_MAX, 2511, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 959, UINT16_MAX, 959, UINT16_MAX, 2601, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 960, UINT16_MAX, 960, UINT16_MAX, 2635, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 961, UINT16_MAX, 961, UINT16_MAX, 2531, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9154, 964, UINT16_MAX, 964, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 965, UINT16_MAX, 965, UINT16_MAX, 2528, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 966, UINT16_MAX, 966, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 967, UINT16_MAX, 967, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 968, UINT16_MAX, 968, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 969, UINT16_MAX, 969, UINT16_MAX, 2641, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 970, UINT16_MAX, 970, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 971, UINT16_MAX, 971, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 972, UINT16_MAX, 972, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 973, UINT16_MAX, 973, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 974, UINT16_MAX, 974, UINT16_MAX, 2542, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 975, UINT16_MAX, 975, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 976, UINT16_MAX, 976, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 977, UINT16_MAX, 977, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 978, UINT16_MAX, 978, UINT16_MAX, 2659, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 979, UINT16_MAX, 979, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 980, UINT16_MAX, 980, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 981, UINT16_MAX, 981, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 982, UINT16_MAX, 982, UINT16_MAX, 2665, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 983, UINT16_MAX, 983, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 984, UINT16_MAX, 984, UINT16_MAX, 2653, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 985, UINT16_MAX, 985, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 986, UINT16_MAX, 986, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8209, UINT16_MAX, 8209, 2622, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8210, UINT16_MAX, 8210, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8211, UINT16_MAX, 8211, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8212, UINT16_MAX, 8212, 2575, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8213, UINT16_MAX, 8213, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8214, UINT16_MAX, 8214, 2564, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8215, UINT16_MAX, 8215, 2608, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8216, UINT16_MAX, 8216, 2638, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8217, UINT16_MAX, 8217, 2553, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9179, UINT16_MAX, 8218, UINT16_MAX, 8218, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8219, UINT16_MAX, 8219, 2581, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8220, UINT16_MAX, 8220, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8221, UINT16_MAX, 8221, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8222, UINT16_MAX, 8222, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8223, UINT16_MAX, 8223, 2644, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8224, UINT16_MAX, 8224, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8225, UINT16_MAX, 8225, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8226, UINT16_MAX, 8226, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8227, UINT16_MAX, 8227, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8228, UINT16_MAX, 8228, 2584, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8229, UINT16_MAX, 8229, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8230, UINT16_MAX, 8230, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8231, UINT16_MAX, 8231, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8232, UINT16_MAX, 8232, 2662, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8233, UINT16_MAX, 8233, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8234, UINT16_MAX, 8234, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8235, UINT16_MAX, 8235, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8236, UINT16_MAX, 8236, 2668, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8237, UINT16_MAX, 8237, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8238, UINT16_MAX, 8238, 2656, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8239, UINT16_MAX, 8239, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8240, UINT16_MAX, 8240, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9181, UINT16_MAX, 8241, UINT16_MAX, 8241, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9183, UINT16_MAX, 8242, UINT16_MAX, 8242, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8243, UINT16_MAX, 8243, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9185, UINT16_MAX, 8244, UINT16_MAX, 8244, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8245, UINT16_MAX, 8245, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8246, UINT16_MAX, 8246, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8247, UINT16_MAX, 8247, 2578, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9187, UINT16_MAX, 8248, UINT16_MAX, 8248, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8249, UINT16_MAX, 8249, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8250, UINT16_MAX, 8250, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8251, UINT16_MAX, 8251, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8252, UINT16_MAX, 8252, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9189, UINT16_MAX, 8253, UINT16_MAX, 8253, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9191, UINT16_MAX, 8254, UINT16_MAX, 8254, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9193, UINT16_MAX, 8255, UINT16_MAX, 8255, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8256, UINT16_MAX, 8256, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1003, UINT16_MAX, 1003, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8257, UINT16_MAX, 8257, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1004, UINT16_MAX, 1004, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8258, UINT16_MAX, 8258, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1005, UINT16_MAX, 1005, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8259, UINT16_MAX, 8259, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1006, UINT16_MAX, 1006, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8260, UINT16_MAX, 8260, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1007, UINT16_MAX, 1007, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8261, UINT16_MAX, 8261, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1008, UINT16_MAX, 1008, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8262, UINT16_MAX, 8262, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1009, UINT16_MAX, 1009, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8263, UINT16_MAX, 8263, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1010, UINT16_MAX, 1010, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8264, UINT16_MAX, 8264, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1011, UINT16_MAX, 1011, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8265, UINT16_MAX, 8265, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1012, UINT16_MAX, 1012, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8266, UINT16_MAX, 8266, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1013, UINT16_MAX, 1013, UINT16_MAX, 2595, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8267, UINT16_MAX, 8267, 2598, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9206, 1016, UINT16_MAX, 1016, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9209, UINT16_MAX, 8268, UINT16_MAX, 8268, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1019, UINT16_MAX, 1019, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8269, UINT16_MAX, 8269, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1020, UINT16_MAX, 1020, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8270, UINT16_MAX, 8270, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1021, UINT16_MAX, 1021, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8271, UINT16_MAX, 8271, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1022, UINT16_MAX, 1022, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8272, UINT16_MAX, 8272, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1023, UINT16_MAX, 1023, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8273, UINT16_MAX, 8273, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ME, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1024, UINT16_MAX, 1024, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8274, UINT16_MAX, 8274, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1025, UINT16_MAX, 1025, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8275, UINT16_MAX, 8275, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1026, UINT16_MAX, 1026, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8276, UINT16_MAX, 8276, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1027, UINT16_MAX, 1027, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8277, UINT16_MAX, 8277, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1028, UINT16_MAX, 1028, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8278, UINT16_MAX, 8278, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1029, UINT16_MAX, 1029, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8279, UINT16_MAX, 8279, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1030, UINT16_MAX, 1030, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8280, UINT16_MAX, 8280, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1031, UINT16_MAX, 1031, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8281, UINT16_MAX, 8281, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1032, UINT16_MAX, 1032, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8282, UINT16_MAX, 8282, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1033, UINT16_MAX, 1033, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8283, UINT16_MAX, 8283, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1034, UINT16_MAX, 1034, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8284, UINT16_MAX, 8284, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1035, UINT16_MAX, 1035, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8285, UINT16_MAX, 8285, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1036, UINT16_MAX, 1036, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8286, UINT16_MAX, 8286, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1037, UINT16_MAX, 1037, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8287, UINT16_MAX, 8287, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1038, UINT16_MAX, 1038, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8288, UINT16_MAX, 8288, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1039, UINT16_MAX, 1039, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8289, UINT16_MAX, 8289, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1040, UINT16_MAX, 1040, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8290, UINT16_MAX, 8290, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1041, UINT16_MAX, 1041, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8291, UINT16_MAX, 8291, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1042, UINT16_MAX, 1042, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8292, UINT16_MAX, 8292, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1043, UINT16_MAX, 1043, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8293, UINT16_MAX, 8293, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1044, UINT16_MAX, 1044, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8294, UINT16_MAX, 8294, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1045, UINT16_MAX, 1045, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8295, UINT16_MAX, 8295, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1046, UINT16_MAX, 1046, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8296, UINT16_MAX, 8296, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1047, UINT16_MAX, 1047, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8297, UINT16_MAX, 8297, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1048, UINT16_MAX, 1048, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8298, UINT16_MAX, 8298, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1049, UINT16_MAX, 1049, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8299, UINT16_MAX, 8299, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1050, UINT16_MAX, 1050, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8300, UINT16_MAX, 8300, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1051, UINT16_MAX, 1051, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9244, 1054, UINT16_MAX, 1054, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9247, UINT16_MAX, 8301, UINT16_MAX, 8301, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1057, UINT16_MAX, 1057, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8302, UINT16_MAX, 8302, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1058, UINT16_MAX, 1058, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8303, UINT16_MAX, 8303, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1059, UINT16_MAX, 1059, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8304, UINT16_MAX, 8304, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1060, UINT16_MAX, 1060, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8305, UINT16_MAX, 8305, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1061, UINT16_MAX, 1061, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8306, UINT16_MAX, 8306, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1062, UINT16_MAX, 1062, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8307, UINT16_MAX, 8307, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8308, UINT16_MAX, 8308, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9255, 1065, UINT16_MAX, 1065, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9258, UINT16_MAX, 8309, UINT16_MAX, 8309, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9260, 1070, UINT16_MAX, 1070, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9263, UINT16_MAX, 8310, UINT16_MAX, 8310, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1073, UINT16_MAX, 1073, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8311, UINT16_MAX, 8311, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9266, 1076, UINT16_MAX, 1076, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9269, UINT16_MAX, 8312, UINT16_MAX, 8312, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1079, UINT16_MAX, 1079, UINT16_MAX, 2629, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8313, UINT16_MAX, 8313, 2632, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9272, 1082, UINT16_MAX, 1082, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9275, UINT16_MAX, 8314, UINT16_MAX, 8314, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9277, 1087, UINT16_MAX, 1087, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9280, UINT16_MAX, 8315, UINT16_MAX, 8315, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9282, 1092, UINT16_MAX, 1092, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9285, UINT16_MAX, 8316, UINT16_MAX, 8316, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1095, UINT16_MAX, 1095, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8317, UINT16_MAX, 8317, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9288, 1098, UINT16_MAX, 1098, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9291, UINT16_MAX, 8318, UINT16_MAX, 8318, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9293, 1103, UINT16_MAX, 1103, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9296, UINT16_MAX, 8319, UINT16_MAX, 8319, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9298, 1108, UINT16_MAX, 1108, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9301, UINT16_MAX, 8320, UINT16_MAX, 8320, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1111, UINT16_MAX, 1111, UINT16_MAX, 2647, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8321, UINT16_MAX, 8321, 2650, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9304, 1114, UINT16_MAX, 1114, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9307, UINT16_MAX, 8322, UINT16_MAX, 8322, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9309, 1119, UINT16_MAX, 1119, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9312, UINT16_MAX, 8323, UINT16_MAX, 8323, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9314, 1124, UINT16_MAX, 1124, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9317, UINT16_MAX, 8324, UINT16_MAX, 8324, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9319, 1129, UINT16_MAX, 1129, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9322, UINT16_MAX, 8325, UINT16_MAX, 8325, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9324, 1134, UINT16_MAX, 1134, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9327, UINT16_MAX, 8326, UINT16_MAX, 8326, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9329, 1139, UINT16_MAX, 1139, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9332, UINT16_MAX, 8327, UINT16_MAX, 8327, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1142, UINT16_MAX, 1142, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8328, UINT16_MAX, 8328, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9335, 1145, UINT16_MAX, 1145, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9338, UINT16_MAX, 8329, UINT16_MAX, 8329, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1148, UINT16_MAX, 1148, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8330, UINT16_MAX, 8330, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1149, UINT16_MAX, 1149, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8331, UINT16_MAX, 8331, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1150, UINT16_MAX, 1150, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8332, UINT16_MAX, 8332, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1151, UINT16_MAX, 1151, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8333, UINT16_MAX, 8333, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1152, UINT16_MAX, 1152, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8334, UINT16_MAX, 8334, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1153, UINT16_MAX, 1153, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8335, UINT16_MAX, 8335, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1154, UINT16_MAX, 1154, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8336, UINT16_MAX, 8336, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1155, UINT16_MAX, 1155, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8337, UINT16_MAX, 8337, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1156, UINT16_MAX, 1156, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8338, UINT16_MAX, 8338, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1157, UINT16_MAX, 1157, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8339, UINT16_MAX, 8339, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1158, UINT16_MAX, 1158, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8340, UINT16_MAX, 8340, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1159, UINT16_MAX, 1159, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8341, UINT16_MAX, 8341, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1160, UINT16_MAX, 1160, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8342, UINT16_MAX, 8342, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1161, UINT16_MAX, 1161, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8343, UINT16_MAX, 8343, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1162, UINT16_MAX, 1162, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8344, UINT16_MAX, 8344, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1163, UINT16_MAX, 1163, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8345, UINT16_MAX, 8345, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1164, UINT16_MAX, 1164, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8346, UINT16_MAX, 8346, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1165, UINT16_MAX, 1165, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8347, UINT16_MAX, 8347, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1166, UINT16_MAX, 1166, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8348, UINT16_MAX, 8348, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1167, UINT16_MAX, 1167, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8349, UINT16_MAX, 8349, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1168, UINT16_MAX, 1168, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8350, UINT16_MAX, 8350, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1169, UINT16_MAX, 1169, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8351, UINT16_MAX, 8351, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1170, UINT16_MAX, 1170, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8352, UINT16_MAX, 8352, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1171, UINT16_MAX, 1171, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8353, UINT16_MAX, 8353, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1172, UINT16_MAX, 1172, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8354, UINT16_MAX, 8354, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1173, UINT16_MAX, 1173, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8355, UINT16_MAX, 8355, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1174, UINT16_MAX, 1174, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8356, UINT16_MAX, 8356, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1175, UINT16_MAX, 1175, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1176, UINT16_MAX, 1176, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1177, UINT16_MAX, 1177, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1178, UINT16_MAX, 1178, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1179, UINT16_MAX, 1179, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1180, UINT16_MAX, 1180, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1181, UINT16_MAX, 1181, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1182, UINT16_MAX, 1182, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1183, UINT16_MAX, 1183, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1184, UINT16_MAX, 1184, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1185, UINT16_MAX, 1185, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1186, UINT16_MAX, 1186, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1187, UINT16_MAX, 1187, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1188, UINT16_MAX, 1188, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1189, UINT16_MAX, 1189, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1190, UINT16_MAX, 1190, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1191, UINT16_MAX, 1191, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1192, UINT16_MAX, 1192, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1193, UINT16_MAX, 1193, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1194, UINT16_MAX, 1194, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1195, UINT16_MAX, 1195, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1196, UINT16_MAX, 1196, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1197, UINT16_MAX, 1197, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1198, UINT16_MAX, 1198, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1199, UINT16_MAX, 1199, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1200, UINT16_MAX, 1200, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1201, UINT16_MAX, 1201, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1202, UINT16_MAX, 1202, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1203, UINT16_MAX, 1203, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1204, UINT16_MAX, 1204, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1205, UINT16_MAX, 1205, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1206, UINT16_MAX, 1206, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1207, UINT16_MAX, 1207, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1208, UINT16_MAX, 1208, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1209, UINT16_MAX, 1209, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1210, UINT16_MAX, 1210, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1211, UINT16_MAX, 1211, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1212, UINT16_MAX, 1212, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8357, UINT16_MAX, 8357, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8358, UINT16_MAX, 8358, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8359, UINT16_MAX, 8359, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8360, UINT16_MAX, 8360, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8361, UINT16_MAX, 8361, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8362, UINT16_MAX, 8362, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8363, UINT16_MAX, 8363, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8364, UINT16_MAX, 8364, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8365, UINT16_MAX, 8365, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8366, UINT16_MAX, 8366, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8367, UINT16_MAX, 8367, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8368, UINT16_MAX, 8368, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8369, UINT16_MAX, 8369, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8370, UINT16_MAX, 8370, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8371, UINT16_MAX, 8371, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8372, UINT16_MAX, 8372, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8373, UINT16_MAX, 8373, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8374, UINT16_MAX, 8374, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8375, UINT16_MAX, 8375, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8376, UINT16_MAX, 8376, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8377, UINT16_MAX, 8377, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8378, UINT16_MAX, 8378, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8379, UINT16_MAX, 8379, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8380, UINT16_MAX, 8380, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8381, UINT16_MAX, 8381, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8382, UINT16_MAX, 8382, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8383, UINT16_MAX, 8383, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8384, UINT16_MAX, 8384, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8385, UINT16_MAX, 8385, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8386, UINT16_MAX, 8386, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8387, UINT16_MAX, 8387, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8388, UINT16_MAX, 8388, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8389, UINT16_MAX, 8389, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8390, UINT16_MAX, 8390, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8391, UINT16_MAX, 8391, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8392, UINT16_MAX, 8392, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8393, UINT16_MAX, 8393, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8394, UINT16_MAX, 8394, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 9405, 9405, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_MN, 222, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 228, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 10, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 11, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 12, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 13, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 14, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 15, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 16, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 17, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 18, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 19, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 20, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 21, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 22, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_MN, 23, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_MN, 24, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 25, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_AN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_PREPEND}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_AN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 2, 0, UTF8PROC_BOUNDCLASS_PREPEND}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_MN, 30, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 31, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 32, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 9407, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 9409, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 9411, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 9413, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 9415, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2671, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2676, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2679, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_MN, 27, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 28, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 29, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 33, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 34, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32785, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 230, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32786, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 220, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32787, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_AN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_AN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_MN, 35, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_COMPAT, 9417, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_COMPAT, 9419, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_COMPAT, 9421, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_COMPAT, 9423, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 9425, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2685, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 9427, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2688, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, 9429, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2682, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_PREPEND}, + {UTF8PROC_CATEGORY_MN, 36, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2691, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9431, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2694, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9433, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2697, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9435, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_MN, 7, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32788, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 9, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9437, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9439, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9441, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9443, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9445, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9447, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9449, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9451, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_MN, 7, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32789, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2700, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9453, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9455, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32790, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9457, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9459, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9461, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9463, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9465, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9467, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9469, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9471, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9473, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32792, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2704, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9475, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9477, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9479, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32791, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32793, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9481, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9483, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2709, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9485, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32795, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2712, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2716, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9487, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9489, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9491, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32794, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2719, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 9493, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 84, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 91, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32796, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2722, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9495, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32799, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2725, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9497, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9499, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9501, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2730, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9503, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32797, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32798, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32800, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2733, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2737, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9505, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9507, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9509, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_PREPEND}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32801, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 9, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32802, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32803, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2740, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9511, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9513, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2745, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9515, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9517, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32804, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 9519, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MN, 103, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 107, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 9521, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MN, 118, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 122, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 9523, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 9525, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NOBREAK, 1335, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_MN, 216, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9528, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9530, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9532, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9534, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9536, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9538, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_MN, 129, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 130, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 9540, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 132, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 9542, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 9544, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, UTF8PROC_DECOMP_TYPE_COMPAT, 9546, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 9548, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, UTF8PROC_DECOMP_TYPE_COMPAT, 9550, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 9552, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 9554, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 9556, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 9558, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 9560, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 9562, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 9564, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2748, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9566, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32805, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1376, UINT16_MAX, 1376, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1377, UINT16_MAX, 1377, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1378, UINT16_MAX, 1378, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1379, UINT16_MAX, 1379, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1380, UINT16_MAX, 1380, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1381, UINT16_MAX, 1381, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1382, UINT16_MAX, 1382, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1383, UINT16_MAX, 1383, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1384, UINT16_MAX, 1384, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1385, UINT16_MAX, 1385, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1386, UINT16_MAX, 1386, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1387, UINT16_MAX, 1387, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1388, UINT16_MAX, 1388, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1389, UINT16_MAX, 1389, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1390, UINT16_MAX, 1390, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1391, UINT16_MAX, 1391, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1392, UINT16_MAX, 1392, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1393, UINT16_MAX, 1393, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1394, UINT16_MAX, 1394, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1395, UINT16_MAX, 1395, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1396, UINT16_MAX, 1396, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1397, UINT16_MAX, 1397, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1398, UINT16_MAX, 1398, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1399, UINT16_MAX, 1399, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1400, UINT16_MAX, 1400, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1401, UINT16_MAX, 1401, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1402, UINT16_MAX, 1402, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1403, UINT16_MAX, 1403, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1404, UINT16_MAX, 1404, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1405, UINT16_MAX, 1405, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1406, UINT16_MAX, 1406, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1407, UINT16_MAX, 1407, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1408, UINT16_MAX, 1408, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1409, UINT16_MAX, 1409, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1410, UINT16_MAX, 1410, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1411, UINT16_MAX, 1411, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1412, UINT16_MAX, 1412, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1413, UINT16_MAX, 1413, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1414, UINT16_MAX, 1414, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1415, UINT16_MAX, 1415, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1416, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_L}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, false, 2, 0, UTF8PROC_BOUNDCLASS_L}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, false, 2, 0, UTF8PROC_BOUNDCLASS_V}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_V}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_T}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8395, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8396, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8397, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8398, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8399, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8400, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8401, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8402, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8403, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8404, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8405, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8406, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8407, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8408, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8409, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8410, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8411, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8412, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8413, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8414, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8415, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8416, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8417, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8418, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8419, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8420, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8421, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8422, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8423, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8424, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8425, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8426, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8427, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8428, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8429, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8430, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8431, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8432, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8433, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8434, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8435, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8436, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8437, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8438, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8439, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8440, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8441, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8442, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8443, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8444, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8445, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8446, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8447, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8448, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8449, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8450, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8451, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8452, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8453, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8454, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8455, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8456, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8457, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8458, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8459, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8460, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8461, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8462, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8463, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8464, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8465, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8466, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8467, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8468, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8469, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8470, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8471, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8472, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8473, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8474, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8475, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8476, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8477, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8478, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8479, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, 8480, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1417, 1417, UINT16_MAX, 1417, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1418, 1418, UINT16_MAX, 1418, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1419, 1419, UINT16_MAX, 1419, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1420, 1420, UINT16_MAX, 1420, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1421, 1421, UINT16_MAX, 1421, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1422, 1422, UINT16_MAX, 1422, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2751, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9615, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2754, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9617, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2757, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9619, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2760, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9621, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2763, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9623, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2766, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 9625, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32806, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2769, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9627, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2772, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9629, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2775, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2778, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9631, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9633, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 2781, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 9635, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 9, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 955, 8211, UINT16_MAX, 8211, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 957, 8213, UINT16_MAX, 8213, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 969, 8223, UINT16_MAX, 8223, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 972, 8226, UINT16_MAX, 8226, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 973, 8227, UINT16_MAX, 8227, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 981, 8235, UINT16_MAX, 8235, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1004, 8258, UINT16_MAX, 8258, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1445, 8481, UINT16_MAX, 8481, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1446, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1447, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1448, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1449, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1450, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1451, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1452, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1453, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1454, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1455, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1456, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1457, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1458, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1459, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1460, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1461, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1462, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1463, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1464, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1465, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1466, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1467, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1468, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1469, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 4, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 485, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 486, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1470, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 6, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 10, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 12, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 355, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 14, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 479, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1471, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1472, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 15, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 19, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 20, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1473, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 493, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 21, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1474, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 846, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 847, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 848, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 863, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 864, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 8, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 17, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 20, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 21, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 846, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 847, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 859, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 863, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 864, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 968, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8482, UINT16_MAX, 8482, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8483, UINT16_MAX, 8483, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1475, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1476, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 94, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1477, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1478, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1479, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 491, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 490, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1480, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1481, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1482, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1483, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1484, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1485, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1486, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1487, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 494, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1488, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1489, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 495, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1490, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1491, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 505, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1492, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 778, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 513, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1493, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 514, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 779, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 25, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1494, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 1495, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 517, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 852, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_MN, 214, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9688, 1498, UINT16_MAX, 1498, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9691, UINT16_MAX, 8484, UINT16_MAX, 8484, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9693, 1503, UINT16_MAX, 1503, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9696, UINT16_MAX, 8485, UINT16_MAX, 8485, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9698, 1508, UINT16_MAX, 1508, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9701, UINT16_MAX, 8486, UINT16_MAX, 8486, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9703, 1513, UINT16_MAX, 1513, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9706, UINT16_MAX, 8487, UINT16_MAX, 8487, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9708, 1518, UINT16_MAX, 1518, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9711, UINT16_MAX, 8488, UINT16_MAX, 8488, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9713, 1523, UINT16_MAX, 1523, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9716, UINT16_MAX, 8489, UINT16_MAX, 8489, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9718, 1528, UINT16_MAX, 1528, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9721, UINT16_MAX, 8490, UINT16_MAX, 8490, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9723, 1533, UINT16_MAX, 1533, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9726, UINT16_MAX, 8491, UINT16_MAX, 8491, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9728, 1538, UINT16_MAX, 1538, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9731, UINT16_MAX, 8492, UINT16_MAX, 8492, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9733, 1543, UINT16_MAX, 1543, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9736, UINT16_MAX, 8493, UINT16_MAX, 8493, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9738, 1548, UINT16_MAX, 1548, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9741, UINT16_MAX, 8494, UINT16_MAX, 8494, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9743, 1553, UINT16_MAX, 1553, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9746, UINT16_MAX, 8495, UINT16_MAX, 8495, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9748, 1558, UINT16_MAX, 1558, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9751, UINT16_MAX, 8496, UINT16_MAX, 8496, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9753, 1563, UINT16_MAX, 1563, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9756, UINT16_MAX, 8497, UINT16_MAX, 8497, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9758, 1568, UINT16_MAX, 1568, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9761, UINT16_MAX, 8498, UINT16_MAX, 8498, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9763, 1573, UINT16_MAX, 1573, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9766, UINT16_MAX, 8499, UINT16_MAX, 8499, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9768, 1578, UINT16_MAX, 1578, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9771, UINT16_MAX, 8500, UINT16_MAX, 8500, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9773, 1583, UINT16_MAX, 1583, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9776, UINT16_MAX, 8501, UINT16_MAX, 8501, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9778, 1588, UINT16_MAX, 1588, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9781, UINT16_MAX, 8502, UINT16_MAX, 8502, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9783, 1593, UINT16_MAX, 1593, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9786, UINT16_MAX, 8503, UINT16_MAX, 8503, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9788, 1598, UINT16_MAX, 1598, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9791, UINT16_MAX, 8504, UINT16_MAX, 8504, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9793, 1603, UINT16_MAX, 1603, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9796, UINT16_MAX, 8505, UINT16_MAX, 8505, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9798, 1608, UINT16_MAX, 1608, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9801, UINT16_MAX, 8506, UINT16_MAX, 8506, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9803, 1613, UINT16_MAX, 1613, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9806, UINT16_MAX, 8507, UINT16_MAX, 8507, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9808, 1618, UINT16_MAX, 1618, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9811, UINT16_MAX, 8508, UINT16_MAX, 8508, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9813, 1623, UINT16_MAX, 1623, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9816, UINT16_MAX, 8509, UINT16_MAX, 8509, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9818, 1628, UINT16_MAX, 1628, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9821, UINT16_MAX, 8510, UINT16_MAX, 8510, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9823, 1633, UINT16_MAX, 1633, UINT16_MAX, 2884, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9826, UINT16_MAX, 8511, UINT16_MAX, 8511, 2887, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9828, 1638, UINT16_MAX, 1638, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9831, UINT16_MAX, 8512, UINT16_MAX, 8512, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9833, 1643, UINT16_MAX, 1643, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9836, UINT16_MAX, 8513, UINT16_MAX, 8513, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9838, 1648, UINT16_MAX, 1648, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9841, UINT16_MAX, 8514, UINT16_MAX, 8514, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9843, 1653, UINT16_MAX, 1653, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9846, UINT16_MAX, 8515, UINT16_MAX, 8515, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9848, 1658, UINT16_MAX, 1658, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9851, UINT16_MAX, 8516, UINT16_MAX, 8516, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9853, 1663, UINT16_MAX, 1663, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9856, UINT16_MAX, 8517, UINT16_MAX, 8517, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9858, 1668, UINT16_MAX, 1668, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9861, UINT16_MAX, 8518, UINT16_MAX, 8518, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9863, 1673, UINT16_MAX, 1673, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9866, UINT16_MAX, 8519, UINT16_MAX, 8519, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9868, 1678, UINT16_MAX, 1678, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9871, UINT16_MAX, 8520, UINT16_MAX, 8520, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9873, 1683, UINT16_MAX, 1683, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9876, UINT16_MAX, 8521, UINT16_MAX, 8521, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9878, 1688, UINT16_MAX, 1688, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9881, UINT16_MAX, 8522, UINT16_MAX, 8522, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9883, 1693, UINT16_MAX, 1693, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9886, UINT16_MAX, 8523, UINT16_MAX, 8523, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9888, 1698, UINT16_MAX, 1698, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9891, UINT16_MAX, 8524, UINT16_MAX, 8524, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9893, 1703, UINT16_MAX, 1703, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9896, UINT16_MAX, 8525, UINT16_MAX, 8525, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9898, 1708, UINT16_MAX, 1708, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9901, UINT16_MAX, 8526, UINT16_MAX, 8526, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9903, 1713, UINT16_MAX, 1713, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9906, UINT16_MAX, 8527, UINT16_MAX, 8527, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9908, 1718, UINT16_MAX, 1718, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9911, UINT16_MAX, 8528, UINT16_MAX, 8528, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9913, 1723, UINT16_MAX, 1723, UINT16_MAX, 3006, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9916, UINT16_MAX, 8529, UINT16_MAX, 8529, 3009, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9918, 1728, UINT16_MAX, 1728, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9921, UINT16_MAX, 8530, UINT16_MAX, 8530, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9923, 1733, UINT16_MAX, 1733, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9926, UINT16_MAX, 8531, UINT16_MAX, 8531, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9928, 1738, UINT16_MAX, 1738, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9931, UINT16_MAX, 8532, UINT16_MAX, 8532, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9933, 1743, UINT16_MAX, 1743, UINT16_MAX, 3024, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9936, UINT16_MAX, 8533, UINT16_MAX, 8533, 3027, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9938, 1748, UINT16_MAX, 1748, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9941, UINT16_MAX, 8534, UINT16_MAX, 8534, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9943, 1753, UINT16_MAX, 1753, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9946, UINT16_MAX, 8535, UINT16_MAX, 8535, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9948, 1758, UINT16_MAX, 1758, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9951, UINT16_MAX, 8536, UINT16_MAX, 8536, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9953, 1763, UINT16_MAX, 1763, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9956, UINT16_MAX, 8537, UINT16_MAX, 8537, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9958, 1768, UINT16_MAX, 1768, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9961, UINT16_MAX, 8538, UINT16_MAX, 8538, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9963, 1773, UINT16_MAX, 1773, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9966, UINT16_MAX, 8539, UINT16_MAX, 8539, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9968, 1778, UINT16_MAX, 1778, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9971, UINT16_MAX, 8540, UINT16_MAX, 8540, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9973, 1783, UINT16_MAX, 1783, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9976, UINT16_MAX, 8541, UINT16_MAX, 8541, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9978, 1788, UINT16_MAX, 1788, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9981, UINT16_MAX, 8542, UINT16_MAX, 8542, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9983, 1793, UINT16_MAX, 1793, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9986, UINT16_MAX, 8543, UINT16_MAX, 8543, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9988, 1798, UINT16_MAX, 1798, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9991, UINT16_MAX, 8544, UINT16_MAX, 8544, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9993, 1803, UINT16_MAX, 1803, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 9996, UINT16_MAX, 8545, UINT16_MAX, 8545, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 9998, 1808, UINT16_MAX, 1808, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10001, UINT16_MAX, 8546, UINT16_MAX, 8546, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10003, 1813, UINT16_MAX, 1813, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10006, UINT16_MAX, 8547, UINT16_MAX, 8547, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10008, 1818, UINT16_MAX, 1818, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10011, UINT16_MAX, 8548, UINT16_MAX, 8548, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10013, 1823, UINT16_MAX, 1823, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10016, UINT16_MAX, 8549, UINT16_MAX, 8549, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10018, 1828, UINT16_MAX, 1828, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10021, UINT16_MAX, 8550, UINT16_MAX, 8550, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10023, 1833, UINT16_MAX, 1833, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10026, UINT16_MAX, 8551, UINT16_MAX, 8551, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10028, 1838, UINT16_MAX, 1838, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10031, UINT16_MAX, 8552, UINT16_MAX, 8552, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10033, 1843, UINT16_MAX, 1843, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10036, UINT16_MAX, 8553, UINT16_MAX, 8553, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10038, 1848, UINT16_MAX, 1848, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10041, UINT16_MAX, 8554, UINT16_MAX, 8554, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10043, 1853, UINT16_MAX, 1853, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10046, UINT16_MAX, 8555, UINT16_MAX, 8555, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10048, 1858, UINT16_MAX, 1858, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10051, UINT16_MAX, 8556, UINT16_MAX, 8556, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10053, 1863, UINT16_MAX, 1863, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10056, UINT16_MAX, 8557, UINT16_MAX, 8557, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10058, 1868, UINT16_MAX, 1868, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10061, UINT16_MAX, 8558, UINT16_MAX, 8558, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10063, 10063, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10065, 10065, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10067, 10067, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10069, 10069, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 10071, 10071, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10073, 1738, 8532, UINT16_MAX, 8532, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1883, UINT16_MAX, 1883, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10076, 1886, UINT16_MAX, 1886, UINT16_MAX, 3241, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10079, UINT16_MAX, 8559, UINT16_MAX, 8559, 3250, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10081, 1891, UINT16_MAX, 1891, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10084, UINT16_MAX, 8560, UINT16_MAX, 8560, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10086, 1896, UINT16_MAX, 1896, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10089, UINT16_MAX, 8561, UINT16_MAX, 8561, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10091, 1901, UINT16_MAX, 1901, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10094, UINT16_MAX, 8562, UINT16_MAX, 8562, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10096, 1906, UINT16_MAX, 1906, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10099, UINT16_MAX, 8563, UINT16_MAX, 8563, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10101, 1911, UINT16_MAX, 1911, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10104, UINT16_MAX, 8564, UINT16_MAX, 8564, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10106, 1916, UINT16_MAX, 1916, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10109, UINT16_MAX, 8565, UINT16_MAX, 8565, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10111, 1921, UINT16_MAX, 1921, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10114, UINT16_MAX, 8566, UINT16_MAX, 8566, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10116, 1926, UINT16_MAX, 1926, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10119, UINT16_MAX, 8567, UINT16_MAX, 8567, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10121, 1931, UINT16_MAX, 1931, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10124, UINT16_MAX, 8568, UINT16_MAX, 8568, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10126, 1936, UINT16_MAX, 1936, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10129, UINT16_MAX, 8569, UINT16_MAX, 8569, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10131, 1941, UINT16_MAX, 1941, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10134, UINT16_MAX, 8570, UINT16_MAX, 8570, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10136, 1946, UINT16_MAX, 1946, UINT16_MAX, 3455, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10139, UINT16_MAX, 8571, UINT16_MAX, 8571, 3458, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10141, 1951, UINT16_MAX, 1951, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10144, UINT16_MAX, 8572, UINT16_MAX, 8572, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10146, 1956, UINT16_MAX, 1956, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10149, UINT16_MAX, 8573, UINT16_MAX, 8573, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10151, 1961, UINT16_MAX, 1961, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10154, UINT16_MAX, 8574, UINT16_MAX, 8574, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10156, 1966, UINT16_MAX, 1966, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10159, UINT16_MAX, 8575, UINT16_MAX, 8575, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10161, 1971, UINT16_MAX, 1971, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10164, UINT16_MAX, 8576, UINT16_MAX, 8576, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10166, 1976, UINT16_MAX, 1976, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10169, UINT16_MAX, 8577, UINT16_MAX, 8577, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10171, 1981, UINT16_MAX, 1981, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10174, UINT16_MAX, 8578, UINT16_MAX, 8578, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10176, 1986, UINT16_MAX, 1986, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10179, UINT16_MAX, 8579, UINT16_MAX, 8579, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10181, 1991, UINT16_MAX, 1991, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10184, UINT16_MAX, 8580, UINT16_MAX, 8580, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10186, 1996, UINT16_MAX, 1996, UINT16_MAX, 3559, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10189, UINT16_MAX, 8581, UINT16_MAX, 8581, 3562, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10191, 2001, UINT16_MAX, 2001, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10194, UINT16_MAX, 8582, UINT16_MAX, 8582, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10196, 2006, UINT16_MAX, 2006, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10199, UINT16_MAX, 8583, UINT16_MAX, 8583, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10201, 2011, UINT16_MAX, 2011, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10204, UINT16_MAX, 8584, UINT16_MAX, 8584, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10206, 2016, UINT16_MAX, 2016, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10209, UINT16_MAX, 8585, UINT16_MAX, 8585, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10211, 2021, UINT16_MAX, 2021, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10214, UINT16_MAX, 8586, UINT16_MAX, 8586, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10216, 2026, UINT16_MAX, 2026, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10219, UINT16_MAX, 8587, UINT16_MAX, 8587, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10221, 2031, UINT16_MAX, 2031, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10224, UINT16_MAX, 8588, UINT16_MAX, 8588, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10226, 2036, UINT16_MAX, 2036, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10229, UINT16_MAX, 8589, UINT16_MAX, 8589, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10231, 2041, UINT16_MAX, 2041, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10234, UINT16_MAX, 8590, UINT16_MAX, 8590, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10236, 2046, UINT16_MAX, 2046, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10239, UINT16_MAX, 8591, UINT16_MAX, 8591, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10241, 2051, UINT16_MAX, 2051, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10244, UINT16_MAX, 8592, UINT16_MAX, 8592, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10246, 2056, UINT16_MAX, 2056, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10249, UINT16_MAX, 8593, UINT16_MAX, 8593, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10251, 2061, UINT16_MAX, 2061, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10254, UINT16_MAX, 8594, UINT16_MAX, 8594, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10256, 2066, UINT16_MAX, 2066, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10259, UINT16_MAX, 8595, UINT16_MAX, 8595, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10261, 2071, UINT16_MAX, 2071, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10264, UINT16_MAX, 8596, UINT16_MAX, 8596, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10266, 2076, UINT16_MAX, 2076, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10269, UINT16_MAX, 8597, UINT16_MAX, 8597, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10271, 2081, UINT16_MAX, 2081, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10274, UINT16_MAX, 8598, UINT16_MAX, 8598, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10276, 2086, UINT16_MAX, 2086, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10279, UINT16_MAX, 8599, UINT16_MAX, 8599, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10281, 2091, UINT16_MAX, 2091, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10284, UINT16_MAX, 8600, UINT16_MAX, 8600, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10286, 2096, UINT16_MAX, 2096, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10289, UINT16_MAX, 8601, UINT16_MAX, 8601, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10291, 2101, UINT16_MAX, 2101, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10294, UINT16_MAX, 8602, UINT16_MAX, 8602, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10296, 2106, UINT16_MAX, 2106, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10299, UINT16_MAX, 8603, UINT16_MAX, 8603, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2109, UINT16_MAX, 2109, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8604, UINT16_MAX, 8604, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2110, UINT16_MAX, 2110, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8605, UINT16_MAX, 8605, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2111, UINT16_MAX, 2111, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8606, UINT16_MAX, 8606, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10304, UINT16_MAX, 8607, UINT16_MAX, 8607, 3761, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10306, UINT16_MAX, 8608, UINT16_MAX, 8608, 3814, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10308, UINT16_MAX, 8609, UINT16_MAX, 8609, 4793, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10310, UINT16_MAX, 8610, UINT16_MAX, 8610, 4796, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10312, UINT16_MAX, 8611, UINT16_MAX, 8611, 4799, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10314, UINT16_MAX, 8612, UINT16_MAX, 8612, 4802, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10316, UINT16_MAX, 8613, UINT16_MAX, 8613, 4805, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10318, UINT16_MAX, 8614, UINT16_MAX, 8614, 4808, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10320, 2130, UINT16_MAX, 2130, UINT16_MAX, 3867, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10323, 2133, UINT16_MAX, 2133, UINT16_MAX, 3920, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10326, 2136, UINT16_MAX, 2136, UINT16_MAX, 4811, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10329, 2139, UINT16_MAX, 2139, UINT16_MAX, 4814, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10332, 2142, UINT16_MAX, 2142, UINT16_MAX, 4817, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10335, 2145, UINT16_MAX, 2145, UINT16_MAX, 4820, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10338, 2148, UINT16_MAX, 2148, UINT16_MAX, 4823, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10341, 2151, UINT16_MAX, 2151, UINT16_MAX, 4826, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10344, UINT16_MAX, 8615, UINT16_MAX, 8615, 3973, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10346, UINT16_MAX, 8616, UINT16_MAX, 8616, 3977, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10348, UINT16_MAX, 8617, UINT16_MAX, 8617, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10350, UINT16_MAX, 8618, UINT16_MAX, 8618, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10352, UINT16_MAX, 8619, UINT16_MAX, 8619, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10354, UINT16_MAX, 8620, UINT16_MAX, 8620, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10356, 2166, UINT16_MAX, 2166, UINT16_MAX, 3981, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10359, 2169, UINT16_MAX, 2169, UINT16_MAX, 3985, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10362, 2172, UINT16_MAX, 2172, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10365, 2175, UINT16_MAX, 2175, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10368, 2178, UINT16_MAX, 2178, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10371, 2181, UINT16_MAX, 2181, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10374, UINT16_MAX, 8621, UINT16_MAX, 8621, 3989, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10376, UINT16_MAX, 8622, UINT16_MAX, 8622, 4042, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10378, UINT16_MAX, 8623, UINT16_MAX, 8623, 4829, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10380, UINT16_MAX, 8624, UINT16_MAX, 8624, 4832, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10382, UINT16_MAX, 8625, UINT16_MAX, 8625, 4835, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10384, UINT16_MAX, 8626, UINT16_MAX, 8626, 4838, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10386, UINT16_MAX, 8627, UINT16_MAX, 8627, 4841, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10388, UINT16_MAX, 8628, UINT16_MAX, 8628, 4844, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10390, 2200, UINT16_MAX, 2200, UINT16_MAX, 4095, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10393, 2203, UINT16_MAX, 2203, UINT16_MAX, 4148, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10396, 2206, UINT16_MAX, 2206, UINT16_MAX, 4847, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10399, 2209, UINT16_MAX, 2209, UINT16_MAX, 4850, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10402, 2212, UINT16_MAX, 2212, UINT16_MAX, 4853, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10405, 2215, UINT16_MAX, 2215, UINT16_MAX, 4856, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10408, 2218, UINT16_MAX, 2218, UINT16_MAX, 4859, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10411, 2221, UINT16_MAX, 2221, UINT16_MAX, 4862, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10414, UINT16_MAX, 8629, UINT16_MAX, 8629, 4201, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10416, UINT16_MAX, 8630, UINT16_MAX, 8630, 4253, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10418, UINT16_MAX, 8631, UINT16_MAX, 8631, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10420, UINT16_MAX, 8632, UINT16_MAX, 8632, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10422, UINT16_MAX, 8633, UINT16_MAX, 8633, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10424, UINT16_MAX, 8634, UINT16_MAX, 8634, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10426, UINT16_MAX, 8635, UINT16_MAX, 8635, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10428, UINT16_MAX, 8636, UINT16_MAX, 8636, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10430, 2240, UINT16_MAX, 2240, UINT16_MAX, 4305, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10433, 2243, UINT16_MAX, 2243, UINT16_MAX, 4357, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10436, 2246, UINT16_MAX, 2246, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10439, 2249, UINT16_MAX, 2249, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10442, 2252, UINT16_MAX, 2252, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10445, 2255, UINT16_MAX, 2255, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10448, 2258, UINT16_MAX, 2258, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10451, 2261, UINT16_MAX, 2261, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10454, UINT16_MAX, 8637, UINT16_MAX, 8637, 4409, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10456, UINT16_MAX, 8638, UINT16_MAX, 8638, 4413, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10458, UINT16_MAX, 8639, UINT16_MAX, 8639, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10460, UINT16_MAX, 8640, UINT16_MAX, 8640, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10462, UINT16_MAX, 8641, UINT16_MAX, 8641, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10464, UINT16_MAX, 8642, UINT16_MAX, 8642, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10466, 2276, UINT16_MAX, 2276, UINT16_MAX, 4417, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10469, 2279, UINT16_MAX, 2279, UINT16_MAX, 4421, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10472, 2282, UINT16_MAX, 2282, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10475, 2285, UINT16_MAX, 2285, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10478, 2288, UINT16_MAX, 2288, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10481, 2291, UINT16_MAX, 2291, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10484, 10484, UINT16_MAX, UINT16_MAX, UINT16_MAX, 4425, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10486, UINT16_MAX, 8643, UINT16_MAX, 8643, 4477, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10488, 18682, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10493, UINT16_MAX, 8644, UINT16_MAX, 8644, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10495, 18689, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10500, UINT16_MAX, 8645, UINT16_MAX, 8645, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10502, 18696, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10507, UINT16_MAX, 8646, UINT16_MAX, 8646, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10509, 2319, UINT16_MAX, 2319, UINT16_MAX, 4529, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10512, 2322, UINT16_MAX, 2322, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10515, 2325, UINT16_MAX, 2325, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10518, 2328, UINT16_MAX, 2328, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10521, UINT16_MAX, 8647, UINT16_MAX, 8647, 4581, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10523, UINT16_MAX, 8648, UINT16_MAX, 8648, 4634, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10525, UINT16_MAX, 8649, UINT16_MAX, 8649, 4865, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10527, UINT16_MAX, 8650, UINT16_MAX, 8650, 4868, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10529, UINT16_MAX, 8651, UINT16_MAX, 8651, 4871, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10531, UINT16_MAX, 8652, UINT16_MAX, 8652, 4874, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10533, UINT16_MAX, 8653, UINT16_MAX, 8653, 4877, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10535, UINT16_MAX, 8654, UINT16_MAX, 8654, 4880, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10537, 2347, UINT16_MAX, 2347, UINT16_MAX, 4687, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10540, 2350, UINT16_MAX, 2350, UINT16_MAX, 4740, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10543, 2353, UINT16_MAX, 2353, UINT16_MAX, 4883, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10546, 2356, UINT16_MAX, 2356, UINT16_MAX, 4886, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10549, 2359, UINT16_MAX, 2359, UINT16_MAX, 4889, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10552, 2362, UINT16_MAX, 2362, UINT16_MAX, 4892, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10555, 2365, UINT16_MAX, 2365, UINT16_MAX, 4895, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10558, 2368, UINT16_MAX, 2368, UINT16_MAX, 4898, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10561, UINT16_MAX, 8655, UINT16_MAX, 8655, 4901, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 820, UINT16_MAX, 8656, UINT16_MAX, 8656, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10563, UINT16_MAX, 8657, UINT16_MAX, 8657, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 824, UINT16_MAX, 8658, UINT16_MAX, 8658, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10565, UINT16_MAX, 8659, UINT16_MAX, 8659, 4910, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 827, UINT16_MAX, 8660, UINT16_MAX, 8660, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10567, UINT16_MAX, 8661, UINT16_MAX, 8661, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 830, UINT16_MAX, 8662, UINT16_MAX, 8662, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10569, UINT16_MAX, 8663, UINT16_MAX, 8663, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 833, UINT16_MAX, 8664, UINT16_MAX, 8664, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10571, UINT16_MAX, 8665, UINT16_MAX, 8665, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 836, UINT16_MAX, 8666, UINT16_MAX, 8666, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10573, UINT16_MAX, 8667, UINT16_MAX, 8667, 5030, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 839, UINT16_MAX, 8668, UINT16_MAX, 8668, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10575, 10577, 8669, UINT16_MAX, 8669, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10579, 10581, 8670, UINT16_MAX, 8670, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10583, 10585, 8671, UINT16_MAX, 8671, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10587, 10589, 8672, UINT16_MAX, 8672, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10591, 10593, 8673, UINT16_MAX, 8673, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10595, 10597, 8674, UINT16_MAX, 8674, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10599, 10601, 8675, UINT16_MAX, 8675, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10603, 10605, 8676, UINT16_MAX, 8676, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10607, 2417, UINT16_MAX, 2417, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10610, 2420, UINT16_MAX, 2420, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10613, 2423, UINT16_MAX, 2423, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10616, 2426, UINT16_MAX, 2426, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10619, 2429, UINT16_MAX, 2429, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10622, 2432, UINT16_MAX, 2432, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10625, 2435, UINT16_MAX, 2435, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10628, 2438, UINT16_MAX, 2438, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10631, 10633, 8677, UINT16_MAX, 8677, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10635, 10637, 8678, UINT16_MAX, 8678, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10639, 10641, 8679, UINT16_MAX, 8679, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10643, 10645, 8680, UINT16_MAX, 8680, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10647, 10649, 8681, UINT16_MAX, 8681, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10651, 10653, 8682, UINT16_MAX, 8682, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10655, 10657, 8683, UINT16_MAX, 8683, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10659, 10661, 8684, UINT16_MAX, 8684, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10663, 2473, UINT16_MAX, 2473, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10666, 2476, UINT16_MAX, 2476, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10669, 2479, UINT16_MAX, 2479, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10672, 2482, UINT16_MAX, 2482, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10675, 2485, UINT16_MAX, 2485, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10678, 2488, UINT16_MAX, 2488, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10681, 2491, UINT16_MAX, 2491, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10684, 2494, UINT16_MAX, 2494, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10687, 10689, 8685, UINT16_MAX, 8685, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10691, 10693, 8686, UINT16_MAX, 8686, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10695, 10697, 8687, UINT16_MAX, 8687, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10699, 10701, 8688, UINT16_MAX, 8688, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10703, 10705, 8689, UINT16_MAX, 8689, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10707, 10709, 8690, UINT16_MAX, 8690, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10711, 10713, 8691, UINT16_MAX, 8691, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10715, 10717, 8692, UINT16_MAX, 8692, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10719, 2529, UINT16_MAX, 2529, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10722, 2532, UINT16_MAX, 2532, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10725, 2535, UINT16_MAX, 2535, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10728, 2538, UINT16_MAX, 2538, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10731, 2541, UINT16_MAX, 2541, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10734, 2544, UINT16_MAX, 2544, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10737, 2547, UINT16_MAX, 2547, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10740, 2550, UINT16_MAX, 2550, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10743, UINT16_MAX, 8693, UINT16_MAX, 8693, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10745, UINT16_MAX, 8694, UINT16_MAX, 8694, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10747, 10749, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10751, 10753, 8695, UINT16_MAX, 8695, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10755, 10757, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10759, 10759, UINT16_MAX, UINT16_MAX, UINT16_MAX, 4907, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10761, 18955, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10766, 2576, UINT16_MAX, 2576, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10769, 2579, UINT16_MAX, 2579, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10772, 2582, UINT16_MAX, 2582, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 2583, 2584, UINT16_MAX, 2584, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10777, 2587, UINT16_MAX, 2587, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 10780, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 807, 807, 7127, UINT16_MAX, 7127, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 10780, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 4919, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 10782, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 10784, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10786, 10788, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10790, 10792, 8696, UINT16_MAX, 8696, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10794, 10796, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10798, 10798, UINT16_MAX, UINT16_MAX, UINT16_MAX, 4916, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10800, 18994, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10805, 2615, UINT16_MAX, 2615, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 2616, 2617, UINT16_MAX, 2617, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10810, 2620, UINT16_MAX, 2620, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 2621, 2622, UINT16_MAX, 2622, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10815, 2625, UINT16_MAX, 2625, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 10818, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 10820, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 10822, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10824, UINT16_MAX, 8697, UINT16_MAX, 8697, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10826, UINT16_MAX, 8698, UINT16_MAX, 8698, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10828, 19022, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 2641, 17226, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10834, 10834, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10836, 19030, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10841, 2651, UINT16_MAX, 2651, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10844, 2654, UINT16_MAX, 2654, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10847, 2657, UINT16_MAX, 2657, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 2658, 2659, UINT16_MAX, 2659, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 10852, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 10854, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 10856, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10858, UINT16_MAX, 8699, UINT16_MAX, 8699, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10860, UINT16_MAX, 8700, UINT16_MAX, 8700, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10862, 19056, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 2675, 17267, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10868, 10868, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10870, UINT16_MAX, 8701, UINT16_MAX, 8701, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10872, 10872, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10874, 19068, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10879, 2689, UINT16_MAX, 2689, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10882, 2692, UINT16_MAX, 2692, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10885, 2695, UINT16_MAX, 2695, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 2696, 2697, UINT16_MAX, 2697, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10890, 2700, UINT16_MAX, 2700, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 10893, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 2703, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 2704, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10897, 10899, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10901, 10903, 8702, UINT16_MAX, 8702, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10905, 10907, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10909, 10909, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5036, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, 10911, 19105, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10916, 2726, UINT16_MAX, 2726, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 2727, 2728, UINT16_MAX, 2728, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 10921, 2731, UINT16_MAX, 2731, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 2732, 2733, UINT16_MAX, 2733, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LT, 0, UTF8PROC_BIDI_CLASS_L, 0, 10926, 2736, UINT16_MAX, 2736, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, 2737, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 10930, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 4971, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, 0, 2740, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, 0, 2741, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, UTF8PROC_DECOMP_TYPE_COMPAT, 26, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, UTF8PROC_DECOMP_TYPE_COMPAT, 26, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, UTF8PROC_DECOMP_TYPE_NOBREAK, 26, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_BN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_BN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_ZWJ}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NOBREAK, 2742, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 10935, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PI, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PF, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 2745, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 10938, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19132, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ZL, 0, UTF8PROC_BIDI_CLASS_WS, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, + {UTF8PROC_CATEGORY_ZP, 0, UTF8PROC_BIDI_CLASS_B, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_LRE, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_RLE, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_PDF, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_LRO, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_RLO, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_COMPAT, 10943, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_COMPAT, 19137, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 10948, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19142, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 10953, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 10955, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_CS, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 10957, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 10959, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 10961, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 27347, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_LRI, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_RLI, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_FSI, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_PDI, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 2775, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 8, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 2776, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 2777, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 2778, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 2779, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 2780, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUPER, 2781, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SUPER, 2782, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SUPER, 2783, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 2784, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 2785, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 2786, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 13, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 2775, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 38, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 31, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 32, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 2776, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 2777, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 2778, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 2779, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 2780, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_SUB, 2781, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SUB, 2782, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SUB, 2783, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUB, 2784, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUB, 2785, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUB, 2786, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 4, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 14, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 23, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 485, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 7, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 10, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 11, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 12, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 13, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 15, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 18, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 19, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_COMPAT, 10979, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19173, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19176, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2795, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 10988, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19182, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19185, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 2804, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 10997, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 6, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1453, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 277, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1454, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1457, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1459, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 10999, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1462, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2809, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1463, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 11002, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19196, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 11007, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2817, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 2818, 866, UINT16_MAX, 866, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 1456, 10, UINT16_MAX, 10, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, 2819, 65, UINT16_MAX, 65, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1448, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1450, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2820, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2821, UINT16_MAX, 2821, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1458, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 14, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 2822, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 2823, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 2824, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 2825, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19210, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 858, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 847, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2829, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2830, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FONT, 2831, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1449, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8703, UINT16_MAX, 8703, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19216, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19219, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 27414, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19226, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19229, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19232, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19235, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19238, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19241, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19244, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19247, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19250, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19253, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19256, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19259, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 11070, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 1454, 2880, UINT16_MAX, 2880, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 11073, 2883, UINT16_MAX, 2883, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19268, 2887, UINT16_MAX, 2887, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 11080, 2890, UINT16_MAX, 2890, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 2891, 2892, UINT16_MAX, 2892, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 11085, 2895, UINT16_MAX, 2895, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19280, 2899, UINT16_MAX, 2899, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 27476, 2904, UINT16_MAX, 2904, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 11097, 2907, UINT16_MAX, 2907, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 2908, 2909, UINT16_MAX, 2909, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 11102, 2912, UINT16_MAX, 2912, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19297, 2916, UINT16_MAX, 2916, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 1457, 2917, UINT16_MAX, 2917, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 2795, 2918, UINT16_MAX, 2918, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 1449, 2919, UINT16_MAX, 2919, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 1458, 2920, UINT16_MAX, 2920, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 8, UINT16_MAX, 8704, UINT16_MAX, 8704, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 11113, UINT16_MAX, 8705, UINT16_MAX, 8705, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19307, UINT16_MAX, 8706, UINT16_MAX, 8706, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 11118, UINT16_MAX, 8707, UINT16_MAX, 8707, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21, UINT16_MAX, 8708, UINT16_MAX, 8708, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 11120, UINT16_MAX, 8709, UINT16_MAX, 8709, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19314, UINT16_MAX, 8710, UINT16_MAX, 8710, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 27509, UINT16_MAX, 8711, UINT16_MAX, 8711, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 11129, UINT16_MAX, 8712, UINT16_MAX, 8712, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23, UINT16_MAX, 8713, UINT16_MAX, 8713, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 11131, UINT16_MAX, 8714, UINT16_MAX, 8714, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19325, UINT16_MAX, 8715, UINT16_MAX, 8715, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 11, UINT16_MAX, 8716, UINT16_MAX, 8716, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 2, UINT16_MAX, 8717, UINT16_MAX, 8717, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3, UINT16_MAX, 8718, UINT16_MAX, 8718, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12, UINT16_MAX, 8719, UINT16_MAX, 8719, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 2944, UINT16_MAX, 2944, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8720, UINT16_MAX, 8720, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FRACTION, 19329, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5039, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5042, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5045, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11140, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11142, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11144, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11146, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11148, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11150, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5048, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5054, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5051, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5057, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11152, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5060, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11154, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5063, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11156, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5066, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11158, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5069, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11160, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 11162, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19356, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 11167, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19361, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5072, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11172, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5075, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11174, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5078, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11176, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5081, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11178, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5090, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11180, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5087, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11182, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5099, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5102, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11184, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11186, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11188, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11190, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11192, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5105, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5108, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11194, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11196, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5111, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5114, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11198, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11200, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5117, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5120, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5147, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5150, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11202, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11204, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5123, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5126, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11206, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11208, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5129, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5132, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11210, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11212, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5153, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5156, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5135, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5138, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5141, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5144, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11214, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11216, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11218, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11220, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5159, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5162, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5165, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5168, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11222, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11224, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11226, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11228, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11230, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11232, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11234, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11236, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, 0, 3046, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, 0, 3047, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 38, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 31, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 32, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 2776, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 2777, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 2778, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 2779, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 2780, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 2781, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 11240, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 11242, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 11244, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 11246, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 11248, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 11250, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 11252, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 11254, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 11256, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 11258, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 11260, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19454, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19457, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19460, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19463, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19466, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19469, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19472, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19475, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19478, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 27673, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 27677, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 27681, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 27685, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 27689, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 27693, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 27697, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 27701, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 27705, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 27709, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 27713, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 11333, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 11335, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 11337, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 11339, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 11341, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 11343, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 11345, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 11347, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 11349, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19543, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19546, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19549, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19552, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19555, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19558, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19561, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19564, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19567, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19570, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 19573, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19576, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19579, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19582, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19585, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19588, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19591, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19594, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19597, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19600, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19603, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19606, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19609, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19612, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19615, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19618, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19621, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19624, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19627, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19630, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19633, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19636, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19639, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19642, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19645, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19648, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 19651, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1446, 3270, UINT16_MAX, 3270, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1448, 3271, UINT16_MAX, 3271, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 2795, 3272, UINT16_MAX, 3272, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1449, 3273, UINT16_MAX, 3273, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1450, 3274, UINT16_MAX, 3274, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 2820, 3275, UINT16_MAX, 3275, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1452, 3276, UINT16_MAX, 3276, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1453, 3277, UINT16_MAX, 3277, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1454, 3278, UINT16_MAX, 3278, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1455, 3279, UINT16_MAX, 3279, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1456, 3280, UINT16_MAX, 3280, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1457, 3281, UINT16_MAX, 3281, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1458, 3282, UINT16_MAX, 3282, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1459, 3283, UINT16_MAX, 3283, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1460, 3284, UINT16_MAX, 3284, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1462, 3285, UINT16_MAX, 3285, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 2809, 3286, UINT16_MAX, 3286, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1463, 3287, UINT16_MAX, 3287, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3288, 3289, UINT16_MAX, 3289, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1464, 3290, UINT16_MAX, 3290, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1465, 3291, UINT16_MAX, 3291, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 2891, 3292, UINT16_MAX, 3292, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1466, 3293, UINT16_MAX, 3293, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 2908, 3294, UINT16_MAX, 3294, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3295, 3296, UINT16_MAX, 3296, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 2817, 3297, UINT16_MAX, 3297, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 0, UINT16_MAX, 8721, UINT16_MAX, 8721, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1, UINT16_MAX, 8722, UINT16_MAX, 8722, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 2, UINT16_MAX, 8723, UINT16_MAX, 8723, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3, UINT16_MAX, 8724, UINT16_MAX, 8724, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4, UINT16_MAX, 8725, UINT16_MAX, 8725, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 5, UINT16_MAX, 8726, UINT16_MAX, 8726, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 6, UINT16_MAX, 8727, UINT16_MAX, 8727, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 7, UINT16_MAX, 8728, UINT16_MAX, 8728, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 8, UINT16_MAX, 8729, UINT16_MAX, 8729, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 9, UINT16_MAX, 8730, UINT16_MAX, 8730, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 10, UINT16_MAX, 8731, UINT16_MAX, 8731, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 11, UINT16_MAX, 8732, UINT16_MAX, 8732, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12, UINT16_MAX, 8733, UINT16_MAX, 8733, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 13, UINT16_MAX, 8734, UINT16_MAX, 8734, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 14, UINT16_MAX, 8735, UINT16_MAX, 8735, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 15, UINT16_MAX, 8736, UINT16_MAX, 8736, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 16, UINT16_MAX, 8737, UINT16_MAX, 8737, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 17, UINT16_MAX, 8738, UINT16_MAX, 8738, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 18, UINT16_MAX, 8739, UINT16_MAX, 8739, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 19, UINT16_MAX, 8740, UINT16_MAX, 8740, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 20, UINT16_MAX, 8741, UINT16_MAX, 8741, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 21, UINT16_MAX, 8742, UINT16_MAX, 8742, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 22, UINT16_MAX, 8743, UINT16_MAX, 8743, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 23, UINT16_MAX, 8744, UINT16_MAX, 8744, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 24, UINT16_MAX, 8745, UINT16_MAX, 8745, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 25, UINT16_MAX, 8746, UINT16_MAX, 8746, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 2775, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_E_BASE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_E_BASE}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_GLUE_AFTER_ZWJ}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 27874, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19686, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 11497, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 19691, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, 11502, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, true, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5171, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3312, UINT16_MAX, 3312, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3313, UINT16_MAX, 3313, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3314, UINT16_MAX, 3314, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3315, UINT16_MAX, 3315, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3316, UINT16_MAX, 3316, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3317, UINT16_MAX, 3317, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3318, UINT16_MAX, 3318, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3319, UINT16_MAX, 3319, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3320, UINT16_MAX, 3320, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3321, UINT16_MAX, 3321, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3322, UINT16_MAX, 3322, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3323, UINT16_MAX, 3323, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3324, UINT16_MAX, 3324, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3325, UINT16_MAX, 3325, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3326, UINT16_MAX, 3326, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3327, UINT16_MAX, 3327, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3328, UINT16_MAX, 3328, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3329, UINT16_MAX, 3329, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3330, UINT16_MAX, 3330, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3331, UINT16_MAX, 3331, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3332, UINT16_MAX, 3332, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3333, UINT16_MAX, 3333, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3334, UINT16_MAX, 3334, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3335, UINT16_MAX, 3335, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3336, UINT16_MAX, 3336, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3337, UINT16_MAX, 3337, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3338, UINT16_MAX, 3338, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3339, UINT16_MAX, 3339, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3340, UINT16_MAX, 3340, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3341, UINT16_MAX, 3341, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3342, UINT16_MAX, 3342, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3343, UINT16_MAX, 3343, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3344, UINT16_MAX, 3344, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3345, UINT16_MAX, 3345, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3346, UINT16_MAX, 3346, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3347, UINT16_MAX, 3347, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3348, UINT16_MAX, 3348, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3349, UINT16_MAX, 3349, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3350, UINT16_MAX, 3350, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3351, UINT16_MAX, 3351, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3352, UINT16_MAX, 3352, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3353, UINT16_MAX, 3353, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3354, UINT16_MAX, 3354, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3355, UINT16_MAX, 3355, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3356, UINT16_MAX, 3356, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3357, UINT16_MAX, 3357, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3358, UINT16_MAX, 3358, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8747, UINT16_MAX, 8747, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8748, UINT16_MAX, 8748, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8749, UINT16_MAX, 8749, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8750, UINT16_MAX, 8750, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8751, UINT16_MAX, 8751, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8752, UINT16_MAX, 8752, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8753, UINT16_MAX, 8753, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8754, UINT16_MAX, 8754, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8755, UINT16_MAX, 8755, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8756, UINT16_MAX, 8756, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8757, UINT16_MAX, 8757, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8758, UINT16_MAX, 8758, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8759, UINT16_MAX, 8759, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8760, UINT16_MAX, 8760, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8761, UINT16_MAX, 8761, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8762, UINT16_MAX, 8762, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8763, UINT16_MAX, 8763, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8764, UINT16_MAX, 8764, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8765, UINT16_MAX, 8765, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8766, UINT16_MAX, 8766, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8767, UINT16_MAX, 8767, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8768, UINT16_MAX, 8768, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8769, UINT16_MAX, 8769, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8770, UINT16_MAX, 8770, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8771, UINT16_MAX, 8771, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8772, UINT16_MAX, 8772, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8773, UINT16_MAX, 8773, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8774, UINT16_MAX, 8774, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8775, UINT16_MAX, 8775, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8776, UINT16_MAX, 8776, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8777, UINT16_MAX, 8777, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8778, UINT16_MAX, 8778, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8779, UINT16_MAX, 8779, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8780, UINT16_MAX, 8780, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8781, UINT16_MAX, 8781, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8782, UINT16_MAX, 8782, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8783, UINT16_MAX, 8783, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8784, UINT16_MAX, 8784, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8785, UINT16_MAX, 8785, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8786, UINT16_MAX, 8786, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8787, UINT16_MAX, 8787, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8788, UINT16_MAX, 8788, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8789, UINT16_MAX, 8789, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8790, UINT16_MAX, 8790, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8791, UINT16_MAX, 8791, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8792, UINT16_MAX, 8792, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8793, UINT16_MAX, 8793, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3359, UINT16_MAX, 3359, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8794, UINT16_MAX, 8794, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3360, UINT16_MAX, 3360, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3361, UINT16_MAX, 3361, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3362, UINT16_MAX, 3362, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8795, UINT16_MAX, 8795, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8796, UINT16_MAX, 8796, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3363, UINT16_MAX, 3363, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8797, UINT16_MAX, 8797, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3364, UINT16_MAX, 3364, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8798, UINT16_MAX, 8798, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3365, UINT16_MAX, 3365, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8799, UINT16_MAX, 8799, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1468, UINT16_MAX, 1468, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1486, UINT16_MAX, 1486, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1467, UINT16_MAX, 1467, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1475, UINT16_MAX, 1475, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3366, UINT16_MAX, 3366, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8800, UINT16_MAX, 8800, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3367, UINT16_MAX, 3367, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8801, UINT16_MAX, 8801, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUB, 9, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 2891, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3368, UINT16_MAX, 3368, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3369, UINT16_MAX, 3369, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3370, UINT16_MAX, 3370, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8802, UINT16_MAX, 8802, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3371, UINT16_MAX, 3371, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8803, UINT16_MAX, 8803, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3372, UINT16_MAX, 3372, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8804, UINT16_MAX, 8804, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3373, UINT16_MAX, 3373, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8805, UINT16_MAX, 8805, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3374, UINT16_MAX, 3374, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8806, UINT16_MAX, 8806, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3375, UINT16_MAX, 3375, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8807, UINT16_MAX, 8807, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3376, UINT16_MAX, 3376, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8808, UINT16_MAX, 8808, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3377, UINT16_MAX, 3377, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8809, UINT16_MAX, 8809, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3378, UINT16_MAX, 3378, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8810, UINT16_MAX, 8810, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3379, UINT16_MAX, 3379, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8811, UINT16_MAX, 8811, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3380, UINT16_MAX, 3380, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8812, UINT16_MAX, 8812, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3381, UINT16_MAX, 3381, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8813, UINT16_MAX, 8813, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3382, UINT16_MAX, 3382, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8814, UINT16_MAX, 8814, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3383, UINT16_MAX, 3383, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8815, UINT16_MAX, 8815, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3384, UINT16_MAX, 3384, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8816, UINT16_MAX, 8816, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3385, UINT16_MAX, 3385, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8817, UINT16_MAX, 8817, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3386, UINT16_MAX, 3386, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8818, UINT16_MAX, 8818, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3387, UINT16_MAX, 3387, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8819, UINT16_MAX, 8819, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3388, UINT16_MAX, 3388, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8820, UINT16_MAX, 8820, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3389, UINT16_MAX, 3389, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8821, UINT16_MAX, 8821, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3390, UINT16_MAX, 3390, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8822, UINT16_MAX, 8822, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3391, UINT16_MAX, 3391, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8823, UINT16_MAX, 8823, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3392, UINT16_MAX, 3392, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8824, UINT16_MAX, 8824, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3393, UINT16_MAX, 3393, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8825, UINT16_MAX, 8825, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3394, UINT16_MAX, 3394, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8826, UINT16_MAX, 8826, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3395, UINT16_MAX, 3395, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8827, UINT16_MAX, 8827, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3396, UINT16_MAX, 3396, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8828, UINT16_MAX, 8828, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3397, UINT16_MAX, 3397, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8829, UINT16_MAX, 8829, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3398, UINT16_MAX, 3398, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8830, UINT16_MAX, 8830, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3399, UINT16_MAX, 3399, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8831, UINT16_MAX, 8831, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3400, UINT16_MAX, 3400, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8832, UINT16_MAX, 8832, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3401, UINT16_MAX, 3401, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8833, UINT16_MAX, 8833, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3402, UINT16_MAX, 3402, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8834, UINT16_MAX, 8834, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3403, UINT16_MAX, 3403, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8835, UINT16_MAX, 8835, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3404, UINT16_MAX, 3404, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8836, UINT16_MAX, 8836, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3405, UINT16_MAX, 3405, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8837, UINT16_MAX, 8837, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3406, UINT16_MAX, 3406, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8838, UINT16_MAX, 8838, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3407, UINT16_MAX, 3407, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8839, UINT16_MAX, 8839, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3408, UINT16_MAX, 3408, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8840, UINT16_MAX, 8840, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3409, UINT16_MAX, 3409, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8841, UINT16_MAX, 8841, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3410, UINT16_MAX, 3410, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8842, UINT16_MAX, 8842, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3411, UINT16_MAX, 3411, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8843, UINT16_MAX, 8843, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3412, UINT16_MAX, 3412, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8844, UINT16_MAX, 8844, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3413, UINT16_MAX, 3413, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8845, UINT16_MAX, 8845, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3414, UINT16_MAX, 3414, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8846, UINT16_MAX, 8846, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3415, UINT16_MAX, 3415, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8847, UINT16_MAX, 8847, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3416, UINT16_MAX, 3416, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8848, UINT16_MAX, 8848, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3417, UINT16_MAX, 3417, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8849, UINT16_MAX, 8849, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3418, UINT16_MAX, 3418, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8850, UINT16_MAX, 8850, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3419, UINT16_MAX, 3419, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8851, UINT16_MAX, 8851, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3420, UINT16_MAX, 3420, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8852, UINT16_MAX, 8852, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3421, UINT16_MAX, 3421, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8853, UINT16_MAX, 8853, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 3422, UINT16_MAX, 3422, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8854, UINT16_MAX, 8854, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8855, UINT16_MAX, 8855, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8856, UINT16_MAX, 8856, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8857, UINT16_MAX, 8857, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8858, UINT16_MAX, 8858, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8859, UINT16_MAX, 8859, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8860, UINT16_MAX, 8860, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8861, UINT16_MAX, 8861, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8862, UINT16_MAX, 8862, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8863, UINT16_MAX, 8863, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8864, UINT16_MAX, 8864, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8865, UINT16_MAX, 8865, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8866, UINT16_MAX, 8866, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8867, UINT16_MAX, 8867, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8868, UINT16_MAX, 8868, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8869, UINT16_MAX, 8869, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8870, UINT16_MAX, 8870, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8871, UINT16_MAX, 8871, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8872, UINT16_MAX, 8872, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8873, UINT16_MAX, 8873, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8874, UINT16_MAX, 8874, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8875, UINT16_MAX, 8875, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8876, UINT16_MAX, 8876, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8877, UINT16_MAX, 8877, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8878, UINT16_MAX, 8878, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8879, UINT16_MAX, 8879, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8880, UINT16_MAX, 8880, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8881, UINT16_MAX, 8881, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8882, UINT16_MAX, 8882, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8883, UINT16_MAX, 8883, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8884, UINT16_MAX, 8884, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8885, UINT16_MAX, 8885, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8886, UINT16_MAX, 8886, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8887, UINT16_MAX, 8887, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8888, UINT16_MAX, 8888, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8889, UINT16_MAX, 8889, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8890, UINT16_MAX, 8890, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8891, UINT16_MAX, 8891, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8892, UINT16_MAX, 8892, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8893, UINT16_MAX, 8893, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8894, UINT16_MAX, 8894, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3423, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3424, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3425, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3426, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3427, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3428, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3429, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3430, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3431, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3432, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3433, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3434, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3435, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3436, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3437, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3438, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3439, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3440, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3441, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3442, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3443, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3444, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3445, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3446, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3447, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3448, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3449, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3450, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3451, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3452, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3453, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3454, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3455, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3456, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3457, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3458, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3459, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3460, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3461, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3462, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3463, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3464, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3465, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3466, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3467, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3468, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3469, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3470, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3471, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3472, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3473, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3474, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3475, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3476, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3477, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3478, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3479, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3480, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3481, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3482, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3483, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3484, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3485, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3486, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3487, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3488, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3489, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3490, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3491, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3492, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3493, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3494, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3495, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3496, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3497, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3498, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3499, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3500, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3501, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3502, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3503, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3504, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3505, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3506, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3507, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3508, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3509, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3510, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3511, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3512, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3513, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3514, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3515, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3516, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3517, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3518, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3519, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3520, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3521, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3522, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3523, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3524, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3525, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3526, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3527, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3528, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3529, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3530, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3531, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3532, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3533, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3534, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3535, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3536, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3537, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3538, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3539, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3540, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3541, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3542, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3543, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3544, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3545, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3546, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3547, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3548, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3549, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3550, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3551, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3552, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3553, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3554, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3555, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3556, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3557, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3558, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3559, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3560, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3561, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3562, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3563, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3564, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3565, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3566, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3567, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3568, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3569, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3570, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3571, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3572, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3573, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3574, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3575, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3576, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3577, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3578, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3579, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3580, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3581, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3582, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3583, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3584, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3585, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3586, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3587, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3588, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3589, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3590, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3591, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3592, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3593, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3594, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3595, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3596, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3597, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3598, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3599, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3600, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3601, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3602, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3603, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3604, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3605, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3606, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3607, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3608, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3609, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3610, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3611, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3612, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3613, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3614, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3615, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3616, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3617, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3618, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3619, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3620, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3621, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3622, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3623, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3624, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3625, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3626, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3627, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3628, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3629, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3630, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3631, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3632, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3633, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3634, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3635, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3636, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3637, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3638, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3639, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ZS, 0, UTF8PROC_BIDI_CLASS_WS, UTF8PROC_DECOMP_TYPE_WIDE, 26, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_MN, 218, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MC, 224, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 3640, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3449, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3641, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3642, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5239, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5174, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11835, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5177, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11837, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5180, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11839, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5183, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11841, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5186, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11843, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5189, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11845, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5192, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11847, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5195, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11849, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5198, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11851, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5201, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11853, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5204, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11855, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5207, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11857, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5210, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11859, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5213, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11861, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5216, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11863, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5219, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11865, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11867, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5223, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11869, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11871, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5227, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11873, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11875, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5231, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11877, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11879, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5235, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11881, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11883, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11885, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_MN, 8, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32820, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 8, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 32821, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 11887, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 11889, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5242, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, 11891, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_VERTICAL, 11893, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5310, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5245, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11895, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5248, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11897, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5251, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11899, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5254, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11901, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5257, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11903, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5260, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11905, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5263, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11907, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5266, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11909, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5269, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11911, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5272, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11913, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5275, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11915, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5278, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11917, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5281, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11919, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5284, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11921, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5287, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11923, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5290, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11925, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11927, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5294, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11929, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11931, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5298, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11933, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11935, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5302, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11937, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11939, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5306, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11941, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11943, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5313, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5316, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5319, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5322, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11945, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11947, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11949, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11951, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 11953, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5325, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, 0, 11955, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_VERTICAL, 11957, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3767, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3768, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3769, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3770, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3771, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3772, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3773, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3774, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3775, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3776, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3777, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3778, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3779, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3780, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3781, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3782, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3783, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3784, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3785, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3786, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3787, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3788, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3789, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3790, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3791, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3792, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3793, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3794, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3795, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3796, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3797, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3798, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3799, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3800, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3802, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3803, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3804, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3805, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3806, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3807, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3808, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3809, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3810, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3811, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3812, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3813, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3814, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3815, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3816, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3817, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3818, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3819, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3820, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3821, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3822, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3823, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3824, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3825, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3826, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3827, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3828, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3829, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3830, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3831, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3832, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3833, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3834, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3835, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3836, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3837, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3838, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3839, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3840, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3841, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3842, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3843, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3844, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3845, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3846, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3847, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3848, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3849, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3850, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3851, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3852, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3853, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3854, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3855, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3856, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3857, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3858, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3859, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 3860, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3426, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3432, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3861, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3862, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3863, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3864, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3865, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3866, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3430, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3867, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3868, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3869, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3870, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3434, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20255, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20258, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20261, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20264, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20267, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20270, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20273, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20276, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20279, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20282, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20285, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20288, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20291, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20294, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28489, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28493, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28497, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28501, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28505, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28509, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28513, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28517, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28521, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28525, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28529, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28533, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28537, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28541, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 28545, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 53125, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 44940, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20370, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20373, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20376, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20379, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20382, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20385, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20388, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20391, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20394, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20397, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20400, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20403, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20406, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20409, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20412, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20415, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20418, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20421, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20424, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20427, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20430, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20433, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20436, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20439, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20442, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20445, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20448, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20451, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20454, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20457, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20460, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20463, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20466, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20469, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20472, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20475, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4094, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4095, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3492, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4096, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 20481, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12292, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12294, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12296, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12298, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12300, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12302, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12304, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12306, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12308, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12310, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12312, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12314, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12316, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12318, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12320, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3767, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3770, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3773, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3775, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3783, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3784, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3787, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3789, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3790, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3792, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3793, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3794, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3795, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3796, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12322, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12324, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12326, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12328, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12330, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12332, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12334, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12336, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12338, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12340, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12342, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12344, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12346, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 12348, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 36926, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 28739, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12359, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3426, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3432, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3861, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3862, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4169, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4170, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4171, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3437, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4172, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3449, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3499, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3511, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3510, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3500, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3592, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3457, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3497, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4173, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4174, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4175, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4176, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4177, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4178, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4179, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4180, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4181, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4182, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3463, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4183, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4184, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4185, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4186, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4187, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4188, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4189, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4190, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3863, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3864, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 3865, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4191, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4192, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4193, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4194, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4195, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4196, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4197, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4198, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4199, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4200, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12393, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12395, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12397, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12399, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12401, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12403, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12405, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12407, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12409, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12411, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12413, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12415, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12417, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12419, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_CIRCLE, 12421, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12423, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12425, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12427, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12429, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12431, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12433, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12435, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12437, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12439, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20633, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20636, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 20639, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 12450, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 20644, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 12455, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 20649, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4268, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4269, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4270, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4271, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4272, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4273, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4274, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4275, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4276, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4277, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4278, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4279, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4280, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4281, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4282, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4283, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4284, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4285, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4286, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4287, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4288, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4289, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4290, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4291, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4292, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4293, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4294, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4295, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4296, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4297, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4298, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4299, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4300, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4301, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4302, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4303, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4304, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4305, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4306, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4307, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4308, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4309, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4310, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4311, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4312, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4313, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 4314, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 28891, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 28895, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 28899, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20711, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 28906, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20718, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20721, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37108, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 28921, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20733, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20736, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20739, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 28934, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 28938, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20750, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20753, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12564, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20758, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 28953, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 28957, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12577, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37155, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 45352, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37166, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20787, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37174, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37179, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 28992, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20804, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20807, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20810, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29005, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37201, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29014, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20826, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20829, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20832, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12643, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12645, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12647, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12649, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20843, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20846, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37233, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20854, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29049, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37245, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20866, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12677, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12679, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37257, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29070, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37266, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20887, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37274, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12703, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20897, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20900, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20903, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20906, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20909, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29104, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20916, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12727, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20921, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20924, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20927, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29122, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20934, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20937, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20940, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37327, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29140, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12760, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37338, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12767, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29153, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29157, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20969, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20972, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20975, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29170, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12790, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20984, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29179, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12799, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37377, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 20998, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12809, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12811, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12813, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12815, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12817, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12819, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12821, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12823, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12825, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 12827, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21021, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21024, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21027, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21030, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21033, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21036, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21039, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21042, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21045, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21048, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21051, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21054, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21057, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21060, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21063, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21066, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12877, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12879, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21073, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12884, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12886, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 12888, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 21082, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 21085, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 12896, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12898, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12900, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12902, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12904, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29290, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12910, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12912, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12914, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12916, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12918, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12920, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12922, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12924, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21118, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29313, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12933, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12935, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12937, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12939, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12941, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12943, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12945, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21139, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21142, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21145, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21148, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12959, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12961, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12963, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12965, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12967, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12969, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12971, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12973, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12975, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12977, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21171, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21174, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12985, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21179, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21182, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21185, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 12996, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21190, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21193, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29388, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13008, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21202, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21205, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21208, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21211, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 37598, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 45795, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13033, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13035, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13037, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13039, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13041, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13043, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13045, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13047, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13049, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13051, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13053, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13055, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13057, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13059, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13061, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13063, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13065, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13067, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29453, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13073, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13075, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13077, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29463, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21275, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13086, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13088, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13090, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13092, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13094, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13096, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13098, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13100, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13102, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13104, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21298, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13109, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13111, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21305, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21308, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13119, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 29505, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 21317, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13128, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13130, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13132, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 13134, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 21328, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 21331, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13142, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13144, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13146, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13148, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13150, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13152, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13154, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13156, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13158, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21352, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21355, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21358, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21361, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21364, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21367, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21370, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21373, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21376, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21379, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21382, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21385, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21388, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21391, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21394, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21397, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21400, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21403, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21406, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21409, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21412, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 21415, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SQUARE, 21418, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5037, UINT16_MAX, 5037, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8895, UINT16_MAX, 8895, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5038, UINT16_MAX, 5038, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8896, UINT16_MAX, 8896, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5039, UINT16_MAX, 5039, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8897, UINT16_MAX, 8897, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5040, UINT16_MAX, 5040, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8898, UINT16_MAX, 8898, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5041, UINT16_MAX, 5041, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8899, UINT16_MAX, 8899, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1445, UINT16_MAX, 1445, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8481, UINT16_MAX, 8481, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5042, UINT16_MAX, 5042, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8900, UINT16_MAX, 8900, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5043, UINT16_MAX, 5043, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8901, UINT16_MAX, 8901, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5044, UINT16_MAX, 5044, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8902, UINT16_MAX, 8902, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5045, UINT16_MAX, 5045, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8903, UINT16_MAX, 8903, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5046, UINT16_MAX, 5046, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8904, UINT16_MAX, 8904, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5047, UINT16_MAX, 5047, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8905, UINT16_MAX, 8905, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5048, UINT16_MAX, 5048, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8906, UINT16_MAX, 8906, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5049, UINT16_MAX, 5049, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8907, UINT16_MAX, 8907, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5050, UINT16_MAX, 5050, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8908, UINT16_MAX, 8908, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5051, UINT16_MAX, 5051, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8909, UINT16_MAX, 8909, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5052, UINT16_MAX, 5052, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8910, UINT16_MAX, 8910, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5053, UINT16_MAX, 5053, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8911, UINT16_MAX, 8911, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5054, UINT16_MAX, 5054, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8912, UINT16_MAX, 8912, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5055, UINT16_MAX, 5055, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8913, UINT16_MAX, 8913, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5056, UINT16_MAX, 5056, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8914, UINT16_MAX, 8914, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5057, UINT16_MAX, 5057, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8915, UINT16_MAX, 8915, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5058, UINT16_MAX, 5058, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8916, UINT16_MAX, 8916, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5059, UINT16_MAX, 5059, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8917, UINT16_MAX, 8917, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5060, UINT16_MAX, 5060, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8918, UINT16_MAX, 8918, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5061, UINT16_MAX, 5061, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8919, UINT16_MAX, 8919, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5062, UINT16_MAX, 5062, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8920, UINT16_MAX, 8920, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5063, UINT16_MAX, 5063, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8921, UINT16_MAX, 8921, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5064, UINT16_MAX, 5064, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8922, UINT16_MAX, 8922, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5065, UINT16_MAX, 5065, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8923, UINT16_MAX, 8923, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5066, UINT16_MAX, 5066, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8924, UINT16_MAX, 8924, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5067, UINT16_MAX, 5067, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8925, UINT16_MAX, 8925, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5068, UINT16_MAX, 5068, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8926, UINT16_MAX, 8926, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5069, UINT16_MAX, 5069, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8927, UINT16_MAX, 8927, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5070, UINT16_MAX, 5070, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8928, UINT16_MAX, 8928, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5071, UINT16_MAX, 5071, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8929, UINT16_MAX, 8929, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5072, UINT16_MAX, 5072, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8930, UINT16_MAX, 8930, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 981, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 983, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5073, UINT16_MAX, 5073, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8931, UINT16_MAX, 8931, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5074, UINT16_MAX, 5074, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8932, UINT16_MAX, 8932, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5075, UINT16_MAX, 5075, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8933, UINT16_MAX, 8933, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5076, UINT16_MAX, 5076, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8934, UINT16_MAX, 8934, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5077, UINT16_MAX, 5077, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8935, UINT16_MAX, 8935, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5078, UINT16_MAX, 5078, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8936, UINT16_MAX, 8936, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5079, UINT16_MAX, 5079, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8937, UINT16_MAX, 8937, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5080, UINT16_MAX, 5080, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8938, UINT16_MAX, 8938, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5081, UINT16_MAX, 5081, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8939, UINT16_MAX, 8939, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5082, UINT16_MAX, 5082, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8940, UINT16_MAX, 8940, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5083, UINT16_MAX, 5083, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8941, UINT16_MAX, 8941, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5084, UINT16_MAX, 5084, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8942, UINT16_MAX, 8942, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5085, UINT16_MAX, 5085, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8943, UINT16_MAX, 8943, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5086, UINT16_MAX, 5086, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8944, UINT16_MAX, 8944, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5087, UINT16_MAX, 5087, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8945, UINT16_MAX, 8945, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5088, UINT16_MAX, 5088, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8946, UINT16_MAX, 8946, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5089, UINT16_MAX, 5089, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8947, UINT16_MAX, 8947, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5090, UINT16_MAX, 5090, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8948, UINT16_MAX, 8948, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5091, UINT16_MAX, 5091, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8949, UINT16_MAX, 8949, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5092, UINT16_MAX, 5092, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8950, UINT16_MAX, 8950, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5093, UINT16_MAX, 5093, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8951, UINT16_MAX, 8951, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5094, UINT16_MAX, 5094, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8952, UINT16_MAX, 8952, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5095, UINT16_MAX, 5095, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8953, UINT16_MAX, 8953, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5096, UINT16_MAX, 5096, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8954, UINT16_MAX, 8954, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5097, UINT16_MAX, 5097, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8955, UINT16_MAX, 8955, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5098, UINT16_MAX, 5098, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8956, UINT16_MAX, 8956, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5099, UINT16_MAX, 5099, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8957, UINT16_MAX, 8957, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5100, UINT16_MAX, 5100, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8958, UINT16_MAX, 8958, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5101, UINT16_MAX, 5101, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8959, UINT16_MAX, 8959, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5102, UINT16_MAX, 5102, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8960, UINT16_MAX, 8960, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5103, UINT16_MAX, 5103, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8961, UINT16_MAX, 8961, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5104, UINT16_MAX, 5104, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8962, UINT16_MAX, 8962, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5105, UINT16_MAX, 5105, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8963, UINT16_MAX, 8963, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5106, UINT16_MAX, 5106, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8964, UINT16_MAX, 8964, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5107, UINT16_MAX, 5107, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8965, UINT16_MAX, 8965, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5108, UINT16_MAX, 5108, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8966, UINT16_MAX, 8966, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5109, UINT16_MAX, 5109, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8967, UINT16_MAX, 8967, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5110, UINT16_MAX, 5110, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8968, UINT16_MAX, 8968, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5110, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5111, UINT16_MAX, 5111, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8969, UINT16_MAX, 8969, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5112, UINT16_MAX, 5112, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8970, UINT16_MAX, 8970, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5113, UINT16_MAX, 5113, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5114, UINT16_MAX, 5114, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8971, UINT16_MAX, 8971, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5115, UINT16_MAX, 5115, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8972, UINT16_MAX, 8972, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5116, UINT16_MAX, 5116, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8973, UINT16_MAX, 8973, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5117, UINT16_MAX, 5117, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8974, UINT16_MAX, 8974, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5118, UINT16_MAX, 5118, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8975, UINT16_MAX, 8975, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5119, UINT16_MAX, 5119, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8976, UINT16_MAX, 8976, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1479, UINT16_MAX, 1479, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5120, UINT16_MAX, 5120, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8977, UINT16_MAX, 8977, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5121, UINT16_MAX, 5121, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8978, UINT16_MAX, 8978, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5122, UINT16_MAX, 5122, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8979, UINT16_MAX, 8979, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5123, UINT16_MAX, 5123, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8980, UINT16_MAX, 8980, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5124, UINT16_MAX, 5124, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8981, UINT16_MAX, 8981, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5125, UINT16_MAX, 5125, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8982, UINT16_MAX, 8982, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5126, UINT16_MAX, 5126, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8983, UINT16_MAX, 8983, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5127, UINT16_MAX, 5127, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8984, UINT16_MAX, 8984, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5128, UINT16_MAX, 5128, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8985, UINT16_MAX, 8985, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5129, UINT16_MAX, 5129, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8986, UINT16_MAX, 8986, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5130, UINT16_MAX, 5130, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8987, UINT16_MAX, 8987, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5131, UINT16_MAX, 5131, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8988, UINT16_MAX, 8988, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 785, UINT16_MAX, 785, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1470, UINT16_MAX, 1470, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1478, UINT16_MAX, 1478, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5132, UINT16_MAX, 5132, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1480, UINT16_MAX, 1480, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5133, UINT16_MAX, 5133, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5134, UINT16_MAX, 5134, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 1482, UINT16_MAX, 1482, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5135, UINT16_MAX, 5135, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5136, UINT16_MAX, 5136, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8989, UINT16_MAX, 8989, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5137, UINT16_MAX, 5137, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8990, UINT16_MAX, 8990, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5138, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 371, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ET, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 8991, UINT16_MAX, 8991, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5075, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5139, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 3360, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SUPER, 5140, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5141, 5141, UINT16_MAX, 5141, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5142, 5142, UINT16_MAX, 5142, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5143, 5143, UINT16_MAX, 5143, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5144, 5144, UINT16_MAX, 5144, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5145, 5145, UINT16_MAX, 5145, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5146, 5146, UINT16_MAX, 5146, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5147, 5147, UINT16_MAX, 5147, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5148, 5148, UINT16_MAX, 5148, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5149, 5149, UINT16_MAX, 5149, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5150, 5150, UINT16_MAX, 5150, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5151, 5151, UINT16_MAX, 5151, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5152, 5152, UINT16_MAX, 5152, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5153, 5153, UINT16_MAX, 5153, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5154, 5154, UINT16_MAX, 5154, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5155, 5155, UINT16_MAX, 5155, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5156, 5156, UINT16_MAX, 5156, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5157, 5157, UINT16_MAX, 5157, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5158, 5158, UINT16_MAX, 5158, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5159, 5159, UINT16_MAX, 5159, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5160, 5160, UINT16_MAX, 5160, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5161, 5161, UINT16_MAX, 5161, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5162, 5162, UINT16_MAX, 5162, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5163, 5163, UINT16_MAX, 5163, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5164, 5164, UINT16_MAX, 5164, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5165, 5165, UINT16_MAX, 5165, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5166, 5166, UINT16_MAX, 5166, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5167, 5167, UINT16_MAX, 5167, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5168, 5168, UINT16_MAX, 5168, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5169, 5169, UINT16_MAX, 5169, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5170, 5170, UINT16_MAX, 5170, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5171, 5171, UINT16_MAX, 5171, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5172, 5172, UINT16_MAX, 5172, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5173, 5173, UINT16_MAX, 5173, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5174, 5174, UINT16_MAX, 5174, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5175, 5175, UINT16_MAX, 5175, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5176, 5176, UINT16_MAX, 5176, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5177, 5177, UINT16_MAX, 5177, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5178, 5178, UINT16_MAX, 5178, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5179, 5179, UINT16_MAX, 5179, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5180, 5180, UINT16_MAX, 5180, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5181, 5181, UINT16_MAX, 5181, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5182, 5182, UINT16_MAX, 5182, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5183, 5183, UINT16_MAX, 5183, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5184, 5184, UINT16_MAX, 5184, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5185, 5185, UINT16_MAX, 5185, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5186, 5186, UINT16_MAX, 5186, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5187, 5187, UINT16_MAX, 5187, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5188, 5188, UINT16_MAX, 5188, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5189, 5189, UINT16_MAX, 5189, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5190, 5190, UINT16_MAX, 5190, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5191, 5191, UINT16_MAX, 5191, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5192, 5192, UINT16_MAX, 5192, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5193, 5193, UINT16_MAX, 5193, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5194, 5194, UINT16_MAX, 5194, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5195, 5195, UINT16_MAX, 5195, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5196, 5196, UINT16_MAX, 5196, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5197, 5197, UINT16_MAX, 5197, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5198, 5198, UINT16_MAX, 5198, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5199, 5199, UINT16_MAX, 5199, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5200, 5200, UINT16_MAX, 5200, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5201, 5201, UINT16_MAX, 5201, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5202, 5202, UINT16_MAX, 5202, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5203, 5203, UINT16_MAX, 5203, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5204, 5204, UINT16_MAX, 5204, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5205, 5205, UINT16_MAX, 5205, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5206, 5206, UINT16_MAX, 5206, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5207, 5207, UINT16_MAX, 5207, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5208, 5208, UINT16_MAX, 5208, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5209, 5209, UINT16_MAX, 5209, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5210, 5210, UINT16_MAX, 5210, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5211, 5211, UINT16_MAX, 5211, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5212, 5212, UINT16_MAX, 5212, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5213, 5213, UINT16_MAX, 5213, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5214, 5214, UINT16_MAX, 5214, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5215, 5215, UINT16_MAX, 5215, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5216, 5216, UINT16_MAX, 5216, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5217, 5217, UINT16_MAX, 5217, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5218, 5218, UINT16_MAX, 5218, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5219, 5219, UINT16_MAX, 5219, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 5220, 5220, UINT16_MAX, 5220, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_LV}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_LVT}, + {UTF8PROC_CATEGORY_CS, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, + {UTF8PROC_CATEGORY_CO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5221, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5222, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3584, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5223, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5224, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5225, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5226, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3638, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5227, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3592, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5228, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5229, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5230, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5231, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5232, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5233, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5234, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5235, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5236, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5237, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5238, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5239, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5240, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5241, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5242, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5243, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5244, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5245, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5246, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5247, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5248, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5249, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5250, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5251, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5252, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5253, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5254, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5255, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5256, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5257, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5258, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5259, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5260, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5261, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5262, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5263, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5264, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5265, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5266, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5267, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5268, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3550, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5269, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5270, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5271, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5272, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5273, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5274, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5275, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5276, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5277, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5278, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5279, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3623, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5280, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5281, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5282, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5283, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5284, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5285, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5286, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5287, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5288, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5289, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5290, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5291, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5292, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5293, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5294, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5295, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5296, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5297, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5298, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5299, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5300, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5301, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5302, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5303, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5304, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5305, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5306, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5307, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5308, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5309, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5310, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5311, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5312, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5313, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5314, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5315, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5316, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5317, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5318, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5319, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5320, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5321, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5322, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5323, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5324, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5325, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5326, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3586, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5327, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5328, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5329, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5330, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5331, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5332, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5333, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5334, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5335, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5336, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5337, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5338, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5339, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5340, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5341, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3463, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5342, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5343, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5344, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5345, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5346, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5347, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5348, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5349, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3444, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5350, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5351, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5352, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5353, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5354, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5355, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5356, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5357, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5358, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5359, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5360, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5361, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5362, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5363, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5364, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5365, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5366, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5367, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5368, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5369, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5370, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5371, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5372, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5373, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5374, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5375, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5376, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5377, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5378, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5379, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5380, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5381, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5382, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5383, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5384, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5385, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5386, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5387, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5388, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5389, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5390, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5391, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5392, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5393, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5394, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5395, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5396, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5397, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5398, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5399, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5400, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5401, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5402, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5403, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3637, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5404, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5405, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5406, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5407, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5408, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5409, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5410, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5411, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5412, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5413, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5414, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5415, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 4170, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5416, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5417, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5418, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5419, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5420, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5421, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5422, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5423, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5424, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5425, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5426, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5427, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5428, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5429, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5430, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5431, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5432, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5433, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5434, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5435, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5436, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5437, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3591, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5438, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5439, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5440, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5441, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5442, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5443, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5444, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5445, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5446, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5447, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5448, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5449, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5450, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3542, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5451, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5452, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5453, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5454, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5455, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5456, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5457, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5458, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5459, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5460, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5461, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5462, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5463, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5464, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5465, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5466, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3569, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5467, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3572, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5468, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5469, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5470, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5471, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5472, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5473, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5474, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5475, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5476, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5477, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5478, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5479, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5480, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5481, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3549, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5482, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5483, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5484, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5485, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5486, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5487, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5488, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5489, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5490, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5491, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5492, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5493, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5494, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5495, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5496, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5497, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5498, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5499, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5500, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5501, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5502, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5503, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3470, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5504, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5505, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5506, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5507, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5508, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5509, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5510, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5511, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5512, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5513, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5514, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5515, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5516, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5517, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5518, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 4175, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5519, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5520, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5521, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5522, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 4179, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5523, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5524, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5525, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5526, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5527, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5528, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5529, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5530, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5531, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5532, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5533, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5534, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5535, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5536, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5537, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5538, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5539, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5540, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5541, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5542, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5543, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5544, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5545, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5546, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5548, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5549, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5550, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5551, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5552, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5553, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5554, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5555, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5556, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5557, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5558, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5559, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5560, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5561, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5562, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5563, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5564, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5565, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5566, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5567, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5568, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5569, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5570, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5571, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5572, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5573, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5574, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5575, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5576, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5577, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5578, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5579, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3503, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5580, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5581, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5582, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5583, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5584, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5585, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5586, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5587, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5588, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5589, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5590, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5591, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5592, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5593, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5594, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5595, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5596, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5597, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5598, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5599, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5600, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5601, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5602, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5603, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5604, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5605, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5606, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5607, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5608, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5609, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5610, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5611, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5612, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5613, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5614, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5615, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5616, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5617, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5619, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5621, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5623, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5624, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5625, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5626, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5628, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5630, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5632, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 5633, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13826, 13826, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13828, 13828, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13830, 13830, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22024, 22024, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 22027, 22027, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13838, 13840, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13840, 13840, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13842, 13842, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13844, 13844, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13846, 13846, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13848, 13848, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 13850, 13850, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13852, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_MN, 26, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13854, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 5664, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 2822, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 2825, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 5665, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 5666, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 5667, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 5668, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 5669, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_FONT, 5670, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_FONT, 2782, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13863, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13865, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13867, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13869, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13871, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13873, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13875, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13877, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13879, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13881, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13883, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13885, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13887, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13889, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13891, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13893, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13895, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13897, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13899, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13901, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13903, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13905, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13907, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13909, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13911, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13913, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13915, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13917, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13919, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13921, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13923, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, 0, 13925, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_R, UTF8PROC_DECOMP_TYPE_COMPAT, 13927, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5737, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5737, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5738, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5738, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5738, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5738, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5739, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5739, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5739, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5739, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5740, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5740, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5740, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5740, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5741, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5741, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5741, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5741, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5742, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5742, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5742, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5742, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5743, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5743, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5743, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5743, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5744, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5744, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5744, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5744, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5745, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5745, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5745, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5745, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5746, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5746, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5746, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5746, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5747, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5747, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5747, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5747, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5748, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5748, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5748, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5748, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5749, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5749, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5749, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5749, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5750, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5750, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5751, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5751, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5752, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5752, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5753, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5753, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5754, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5754, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5755, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5755, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5756, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5756, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5756, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5756, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5757, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5757, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5757, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5757, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5758, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5758, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5758, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5758, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5759, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5759, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5759, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5759, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5760, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5760, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5761, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5761, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5761, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5761, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5762, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5762, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5763, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5763, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5763, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5763, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5764, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5764, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5764, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5764, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5765, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5765, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5766, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5766, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_AL, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5767, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5767, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5767, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5767, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5768, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5768, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5769, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5769, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5770, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5770, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5771, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5772, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5772, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5773, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5773, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5774, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5774, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5775, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5775, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5775, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5775, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5776, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5776, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 13969, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 13969, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 13971, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 13971, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 13973, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 13973, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 13975, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 13975, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 13977, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 13977, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 13979, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 13979, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 13981, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 13981, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 13981, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 13983, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 13983, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 13983, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5793, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5793, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 5793, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 5793, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 13986, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 13988, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 13990, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 13992, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 13994, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 13996, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 13998, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14000, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14002, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14004, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14006, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14008, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14010, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14012, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14014, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14016, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14018, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14020, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14022, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14024, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14026, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14028, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14030, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14032, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14034, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14036, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14038, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14040, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14042, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14044, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14046, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14048, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14050, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14052, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14054, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14056, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14058, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14060, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14062, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14064, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14066, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14068, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14070, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14072, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14074, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14076, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14078, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14080, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14082, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14084, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14086, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14088, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14090, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14092, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14094, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14096, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14098, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14100, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14102, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14104, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14106, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14108, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14110, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14112, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14114, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14116, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14118, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14120, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14122, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14124, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14126, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14128, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14130, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14132, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14134, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14136, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14138, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14140, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14142, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14144, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14146, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14148, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14150, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14152, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14154, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14156, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14158, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14160, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14162, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14164, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14166, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14168, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14170, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22364, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22367, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22370, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22373, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22376, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22379, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14190, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14192, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 13990, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14194, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 13992, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14196, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14198, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14000, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14200, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14002, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14004, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14202, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14204, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14012, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14206, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14014, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14016, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14208, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14210, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14020, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14212, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14022, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14024, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14082, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14084, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14090, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14092, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14094, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14102, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14104, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14106, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14108, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14116, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14118, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14120, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14214, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14128, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14216, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14218, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14140, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14220, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14142, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14144, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14170, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14222, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14224, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14160, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14226, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14162, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14164, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 13986, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 13988, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14228, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 13990, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14230, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 13994, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 13996, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 13998, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14000, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14232, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14006, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14008, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14010, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14012, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14234, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14020, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14026, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14028, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14030, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14032, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14034, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14038, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14040, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14042, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14044, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14046, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14048, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14236, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14050, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14052, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14054, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14056, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14058, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14060, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14064, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14066, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14068, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14070, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14072, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14074, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14076, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14078, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14080, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14086, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14088, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14096, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14098, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14100, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14102, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14104, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14110, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14112, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14114, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14116, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14238, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14122, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14124, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14126, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14128, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14134, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14136, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14138, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14140, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14240, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14146, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14148, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14242, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14154, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14156, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14158, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14160, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14244, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 13990, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14230, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14000, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14232, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14012, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14234, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14020, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14246, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14046, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14248, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14250, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14252, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14102, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14104, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14116, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14140, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14240, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14160, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14244, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22446, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22449, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 22452, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14263, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14265, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14267, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14269, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14271, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14273, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14275, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14277, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14279, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14281, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14283, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14285, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14287, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14289, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14291, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14293, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14295, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14297, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14299, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14301, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14303, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14305, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14307, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14250, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14309, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14311, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14313, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14315, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14263, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14265, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14267, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14269, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14271, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14273, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14275, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14277, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14279, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14281, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14283, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14285, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14287, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14289, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14291, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14293, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14295, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14297, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14299, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14301, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14303, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14305, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14307, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14250, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14309, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14311, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14313, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14315, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14303, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14305, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14307, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14250, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14248, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14252, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 14062, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14040, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14042, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14044, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14303, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14305, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14307, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14062, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14064, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14317, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14317, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22511, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22514, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22514, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22517, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22520, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22523, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22526, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22529, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22532, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22532, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22535, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22538, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22541, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22544, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22547, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22550, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22550, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22553, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22556, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22556, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22559, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22559, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22562, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22565, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22565, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22568, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22571, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22571, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22574, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22574, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22577, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22580, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22580, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22583, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22583, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22586, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22589, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22592, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22595, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22595, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22598, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22601, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22604, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22607, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22610, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22610, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22613, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22616, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22619, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22622, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22625, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22628, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22628, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22631, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22631, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22634, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22634, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22637, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22640, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22643, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22646, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22649, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22652, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22655, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22658, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22661, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22664, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22667, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22670, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22673, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22673, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22676, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22679, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22682, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22685, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22685, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22688, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22691, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22694, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22697, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22700, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22703, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22706, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22709, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22712, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22715, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22718, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22721, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22724, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22727, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22730, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22733, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22736, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22739, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22742, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22745, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22748, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22751, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22613, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22619, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22754, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22757, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22760, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22763, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22766, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22769, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22766, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22760, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22772, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22775, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22778, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22781, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22784, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22769, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22592, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 22562, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22787, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 22790, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22793, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22796, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 30991, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 30995, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 30999, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 31003, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 31007, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 31011, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 31015, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 22827, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 63790, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 63809, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 31050, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6478, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6479, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6480, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6481, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 814, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6482, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6483, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6484, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6485, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6486, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6487, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6488, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6489, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PC, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6490, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 2785, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 2786, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6491, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6492, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6493, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6494, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6495, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6496, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6497, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6498, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 3046, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 3047, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6499, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6500, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6501, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6502, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6503, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_VERTICAL, 6504, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 6505, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PC, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_COMPAT, 6490, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_SMALL, 6478, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6479, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_SMALL, 2745, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 814, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_SMALL, 6481, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6483, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6482, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6488, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 2785, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 2786, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6491, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6492, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6493, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6494, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_SMALL, 6506, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6507, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6508, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SMALL, 2782, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_SMALL, 6509, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6510, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6511, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 2784, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6512, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_SMALL, 6513, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_SMALL, 6514, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SMALL, 6515, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14708, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14710, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14712, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14714, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14716, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14718, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14720, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14722, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14724, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14726, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14728, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14730, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14732, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 14734, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6544, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6545, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6545, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6546, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6546, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6547, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6547, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6548, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6548, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6549, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6549, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6549, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6549, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6550, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6550, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6551, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6551, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6551, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6551, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6552, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6552, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6553, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6553, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6553, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6553, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6554, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6554, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6554, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6554, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6555, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6555, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6555, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6555, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6556, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6556, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6556, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6556, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6557, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6557, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6557, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6557, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6558, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6558, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6559, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6559, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6560, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6560, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6561, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6561, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6562, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6562, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6562, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6562, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6563, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6563, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6563, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6563, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6564, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6564, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6564, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6564, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6565, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6565, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6565, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6565, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6566, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6566, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6566, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6566, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6567, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6567, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6567, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6567, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6568, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6568, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6568, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6568, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6569, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6569, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6569, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6569, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6570, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6570, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6570, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6570, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6571, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6571, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6571, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6571, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6572, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6572, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6572, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6572, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6573, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6573, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6573, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6573, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6574, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6574, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6574, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6574, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6575, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6575, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6575, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6575, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6576, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6576, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6576, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6576, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6577, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6577, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 5776, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 5776, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 6578, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 6578, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_INITIAL, 6578, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_MEDIAL, 6578, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14771, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14771, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14773, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14773, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14775, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14775, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_ISOLATED, 14777, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FINAL, 14777, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6482, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6587, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, 6506, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, 6513, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, 6514, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6507, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6588, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 2785, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 2786, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6508, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_WIDE, 2782, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_WIDE, 6478, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PD, 0, UTF8PROC_BIDI_CLASS_ES, UTF8PROC_DECOMP_TYPE_WIDE, 6509, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_WIDE, 2745, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_WIDE, 6589, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 2775, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 38, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 31, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 32, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 2776, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 2777, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 2778, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 2779, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 2780, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_WIDE, 2781, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_CS, UTF8PROC_DECOMP_TYPE_WIDE, 6481, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 814, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6510, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 2784, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6511, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6483, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6515, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1446, 6590, UINT16_MAX, 6590, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1448, 6591, UINT16_MAX, 6591, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 2795, 6592, UINT16_MAX, 6592, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1449, 6593, UINT16_MAX, 6593, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1450, 6594, UINT16_MAX, 6594, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 2820, 6595, UINT16_MAX, 6595, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1452, 6596, UINT16_MAX, 6596, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1453, 6597, UINT16_MAX, 6597, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1454, 6598, UINT16_MAX, 6598, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1455, 6599, UINT16_MAX, 6599, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1456, 6600, UINT16_MAX, 6600, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1457, 6601, UINT16_MAX, 6601, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1458, 6602, UINT16_MAX, 6602, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1459, 6603, UINT16_MAX, 6603, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1460, 6604, UINT16_MAX, 6604, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1462, 6605, UINT16_MAX, 6605, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 2809, 6606, UINT16_MAX, 6606, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1463, 6607, UINT16_MAX, 6607, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 3288, 6608, UINT16_MAX, 6608, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1464, 6609, UINT16_MAX, 6609, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1465, 6610, UINT16_MAX, 6610, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 2891, 6611, UINT16_MAX, 6611, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1466, 6612, UINT16_MAX, 6612, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 2908, 6613, UINT16_MAX, 6613, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 3295, 6614, UINT16_MAX, 6614, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 2817, 6615, UINT16_MAX, 6615, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6503, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6512, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6504, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6616, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PC, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6490, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 2704, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 0, UINT16_MAX, 8992, UINT16_MAX, 8992, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 1, UINT16_MAX, 8993, UINT16_MAX, 8993, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 2, UINT16_MAX, 8994, UINT16_MAX, 8994, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 3, UINT16_MAX, 8995, UINT16_MAX, 8995, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 4, UINT16_MAX, 8996, UINT16_MAX, 8996, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 5, UINT16_MAX, 8997, UINT16_MAX, 8997, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 6, UINT16_MAX, 8998, UINT16_MAX, 8998, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 7, UINT16_MAX, 8999, UINT16_MAX, 8999, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 8, UINT16_MAX, 9000, UINT16_MAX, 9000, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 9, UINT16_MAX, 9001, UINT16_MAX, 9001, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 10, UINT16_MAX, 9002, UINT16_MAX, 9002, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 11, UINT16_MAX, 9003, UINT16_MAX, 9003, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 12, UINT16_MAX, 9004, UINT16_MAX, 9004, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 13, UINT16_MAX, 9005, UINT16_MAX, 9005, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 14, UINT16_MAX, 9006, UINT16_MAX, 9006, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 15, UINT16_MAX, 9007, UINT16_MAX, 9007, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 16, UINT16_MAX, 9008, UINT16_MAX, 9008, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 17, UINT16_MAX, 9009, UINT16_MAX, 9009, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 18, UINT16_MAX, 9010, UINT16_MAX, 9010, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 19, UINT16_MAX, 9011, UINT16_MAX, 9011, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 20, UINT16_MAX, 9012, UINT16_MAX, 9012, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 21, UINT16_MAX, 9013, UINT16_MAX, 9013, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 22, UINT16_MAX, 9014, UINT16_MAX, 9014, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 23, UINT16_MAX, 9015, UINT16_MAX, 9015, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 24, UINT16_MAX, 9016, UINT16_MAX, 9016, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_WIDE, 25, UINT16_MAX, 9017, UINT16_MAX, 9017, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6491, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6617, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6492, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6618, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6619, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6620, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6480, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PS, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6499, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PE, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6500, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6479, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_PO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6621, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4314, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6622, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6623, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6624, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6625, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6626, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6627, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6628, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6629, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6630, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6631, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4268, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4269, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4270, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4271, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4272, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4273, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4274, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4275, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4276, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4277, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4278, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4279, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4280, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4281, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4282, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4283, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4284, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4285, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4286, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4287, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4288, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4289, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4290, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4291, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4292, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4293, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4294, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4295, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4296, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4297, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4298, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4299, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4300, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4301, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4302, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4303, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4304, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4305, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4306, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4307, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4308, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4309, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4310, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 4311, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6632, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6633, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_LM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6634, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6635, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, true, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6636, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6637, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6638, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6639, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6640, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6641, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6642, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6643, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6644, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6645, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6646, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6647, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6648, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6649, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6650, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6651, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6652, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6653, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6654, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6655, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6656, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6657, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6658, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6659, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6660, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6661, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6662, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6663, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6664, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6665, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6666, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6667, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6668, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6669, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6670, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6671, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6672, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6673, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6674, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6675, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6676, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6677, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6678, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6679, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6680, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6681, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6682, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6683, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6684, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6685, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_NARROW, 6686, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, 6687, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, 6688, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6689, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6690, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_WIDE, 6691, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, 6692, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SC, 0, UTF8PROC_BIDI_CLASS_ET, UTF8PROC_DECOMP_TYPE_WIDE, 6693, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6694, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6695, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6696, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6697, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6698, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6699, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_NARROW, 6700, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_CONTROL}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NL, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6701, UINT16_MAX, 6701, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6703, UINT16_MAX, 6703, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6705, UINT16_MAX, 6705, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6707, UINT16_MAX, 6707, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6709, UINT16_MAX, 6709, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6711, UINT16_MAX, 6711, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6713, UINT16_MAX, 6713, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6715, UINT16_MAX, 6715, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6717, UINT16_MAX, 6717, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6719, UINT16_MAX, 6719, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6721, UINT16_MAX, 6721, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6723, UINT16_MAX, 6723, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6725, UINT16_MAX, 6725, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6727, UINT16_MAX, 6727, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6729, UINT16_MAX, 6729, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6731, UINT16_MAX, 6731, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6733, UINT16_MAX, 6733, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6735, UINT16_MAX, 6735, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6737, UINT16_MAX, 6737, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6739, UINT16_MAX, 6739, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6741, UINT16_MAX, 6741, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6743, UINT16_MAX, 6743, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6745, UINT16_MAX, 6745, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6747, UINT16_MAX, 6747, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6749, UINT16_MAX, 6749, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6751, UINT16_MAX, 6751, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6753, UINT16_MAX, 6753, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6755, UINT16_MAX, 6755, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6757, UINT16_MAX, 6757, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6759, UINT16_MAX, 6759, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6761, UINT16_MAX, 6761, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6763, UINT16_MAX, 6763, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6765, UINT16_MAX, 6765, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6767, UINT16_MAX, 6767, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6769, UINT16_MAX, 6769, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6771, UINT16_MAX, 6771, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6773, UINT16_MAX, 6773, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6775, UINT16_MAX, 6775, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6777, UINT16_MAX, 6777, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6779, UINT16_MAX, 6779, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9018, UINT16_MAX, 9018, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9020, UINT16_MAX, 9020, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9022, UINT16_MAX, 9022, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9024, UINT16_MAX, 9024, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9026, UINT16_MAX, 9026, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9028, UINT16_MAX, 9028, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9030, UINT16_MAX, 9030, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9032, UINT16_MAX, 9032, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9034, UINT16_MAX, 9034, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9036, UINT16_MAX, 9036, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9038, UINT16_MAX, 9038, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9040, UINT16_MAX, 9040, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9042, UINT16_MAX, 9042, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9044, UINT16_MAX, 9044, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9046, UINT16_MAX, 9046, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9048, UINT16_MAX, 9048, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9050, UINT16_MAX, 9050, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9052, UINT16_MAX, 9052, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9054, UINT16_MAX, 9054, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9056, UINT16_MAX, 9056, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9058, UINT16_MAX, 9058, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9060, UINT16_MAX, 9060, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9062, UINT16_MAX, 9062, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9064, UINT16_MAX, 9064, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9066, UINT16_MAX, 9066, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9068, UINT16_MAX, 9068, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9070, UINT16_MAX, 9070, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9072, UINT16_MAX, 9072, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9074, UINT16_MAX, 9074, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9076, UINT16_MAX, 9076, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9078, UINT16_MAX, 9078, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9080, UINT16_MAX, 9080, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9082, UINT16_MAX, 9082, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9084, UINT16_MAX, 9084, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9086, UINT16_MAX, 9086, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9088, UINT16_MAX, 9088, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9090, UINT16_MAX, 9090, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9092, UINT16_MAX, 9092, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9094, UINT16_MAX, 9094, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9096, UINT16_MAX, 9096, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6781, UINT16_MAX, 6781, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6783, UINT16_MAX, 6783, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6785, UINT16_MAX, 6785, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6787, UINT16_MAX, 6787, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6789, UINT16_MAX, 6789, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6791, UINT16_MAX, 6791, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6793, UINT16_MAX, 6793, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6795, UINT16_MAX, 6795, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6797, UINT16_MAX, 6797, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6799, UINT16_MAX, 6799, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6801, UINT16_MAX, 6801, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6803, UINT16_MAX, 6803, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6805, UINT16_MAX, 6805, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6807, UINT16_MAX, 6807, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6809, UINT16_MAX, 6809, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6811, UINT16_MAX, 6811, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6813, UINT16_MAX, 6813, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6815, UINT16_MAX, 6815, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6817, UINT16_MAX, 6817, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6819, UINT16_MAX, 6819, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6821, UINT16_MAX, 6821, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6823, UINT16_MAX, 6823, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6825, UINT16_MAX, 6825, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6827, UINT16_MAX, 6827, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6829, UINT16_MAX, 6829, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6831, UINT16_MAX, 6831, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6833, UINT16_MAX, 6833, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6835, UINT16_MAX, 6835, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6837, UINT16_MAX, 6837, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6839, UINT16_MAX, 6839, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6841, UINT16_MAX, 6841, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6843, UINT16_MAX, 6843, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6845, UINT16_MAX, 6845, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6847, UINT16_MAX, 6847, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6849, UINT16_MAX, 6849, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 6851, UINT16_MAX, 6851, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9098, UINT16_MAX, 9098, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9100, UINT16_MAX, 9100, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9102, UINT16_MAX, 9102, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9104, UINT16_MAX, 9104, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9106, UINT16_MAX, 9106, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9108, UINT16_MAX, 9108, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9110, UINT16_MAX, 9110, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9112, UINT16_MAX, 9112, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9114, UINT16_MAX, 9114, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9116, UINT16_MAX, 9116, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9118, UINT16_MAX, 9118, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9120, UINT16_MAX, 9120, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9122, UINT16_MAX, 9122, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9124, UINT16_MAX, 9124, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9126, UINT16_MAX, 9126, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9128, UINT16_MAX, 9128, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9130, UINT16_MAX, 9130, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9132, UINT16_MAX, 9132, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9134, UINT16_MAX, 9134, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9136, UINT16_MAX, 9136, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9138, UINT16_MAX, 9138, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9140, UINT16_MAX, 9140, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9142, UINT16_MAX, 9142, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9144, UINT16_MAX, 9144, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9146, UINT16_MAX, 9146, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9148, UINT16_MAX, 9148, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9150, UINT16_MAX, 9150, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9152, UINT16_MAX, 9152, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9154, UINT16_MAX, 9154, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9156, UINT16_MAX, 9156, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9158, UINT16_MAX, 9158, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9160, UINT16_MAX, 9160, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9162, UINT16_MAX, 9162, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9164, UINT16_MAX, 9164, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9166, UINT16_MAX, 9166, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9168, UINT16_MAX, 9168, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6853, UINT16_MAX, 6853, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6855, UINT16_MAX, 6855, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6857, UINT16_MAX, 6857, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6859, UINT16_MAX, 6859, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6861, UINT16_MAX, 6861, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6863, UINT16_MAX, 6863, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6865, UINT16_MAX, 6865, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6867, UINT16_MAX, 6867, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6869, UINT16_MAX, 6869, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6871, UINT16_MAX, 6871, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6873, UINT16_MAX, 6873, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6875, UINT16_MAX, 6875, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6877, UINT16_MAX, 6877, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6879, UINT16_MAX, 6879, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6881, UINT16_MAX, 6881, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6883, UINT16_MAX, 6883, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6885, UINT16_MAX, 6885, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6887, UINT16_MAX, 6887, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6889, UINT16_MAX, 6889, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6891, UINT16_MAX, 6891, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6893, UINT16_MAX, 6893, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6895, UINT16_MAX, 6895, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6897, UINT16_MAX, 6897, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6899, UINT16_MAX, 6899, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6901, UINT16_MAX, 6901, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6903, UINT16_MAX, 6903, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6905, UINT16_MAX, 6905, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6907, UINT16_MAX, 6907, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6909, UINT16_MAX, 6909, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6911, UINT16_MAX, 6911, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6913, UINT16_MAX, 6913, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6915, UINT16_MAX, 6915, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6917, UINT16_MAX, 6917, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6919, UINT16_MAX, 6919, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6921, UINT16_MAX, 6921, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6923, UINT16_MAX, 6923, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6925, UINT16_MAX, 6925, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6927, UINT16_MAX, 6927, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6929, UINT16_MAX, 6929, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6931, UINT16_MAX, 6931, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6933, UINT16_MAX, 6933, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6935, UINT16_MAX, 6935, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6937, UINT16_MAX, 6937, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6939, UINT16_MAX, 6939, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6941, UINT16_MAX, 6941, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6943, UINT16_MAX, 6943, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6945, UINT16_MAX, 6945, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6947, UINT16_MAX, 6947, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6949, UINT16_MAX, 6949, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6951, UINT16_MAX, 6951, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 6953, UINT16_MAX, 6953, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9170, UINT16_MAX, 9170, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9172, UINT16_MAX, 9172, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9174, UINT16_MAX, 9174, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9176, UINT16_MAX, 9176, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9178, UINT16_MAX, 9178, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9180, UINT16_MAX, 9180, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9182, UINT16_MAX, 9182, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9184, UINT16_MAX, 9184, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9186, UINT16_MAX, 9186, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9188, UINT16_MAX, 9188, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9190, UINT16_MAX, 9190, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9192, UINT16_MAX, 9192, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9194, UINT16_MAX, 9194, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9196, UINT16_MAX, 9196, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9198, UINT16_MAX, 9198, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9200, UINT16_MAX, 9200, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9202, UINT16_MAX, 9202, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9204, UINT16_MAX, 9204, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9206, UINT16_MAX, 9206, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9208, UINT16_MAX, 9208, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9210, UINT16_MAX, 9210, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9212, UINT16_MAX, 9212, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9214, UINT16_MAX, 9214, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9216, UINT16_MAX, 9216, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9218, UINT16_MAX, 9218, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9220, UINT16_MAX, 9220, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9222, UINT16_MAX, 9222, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9224, UINT16_MAX, 9224, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9226, UINT16_MAX, 9226, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9228, UINT16_MAX, 9228, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9230, UINT16_MAX, 9230, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9232, UINT16_MAX, 9232, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9234, UINT16_MAX, 9234, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9236, UINT16_MAX, 9236, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9238, UINT16_MAX, 9238, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9240, UINT16_MAX, 9240, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9242, UINT16_MAX, 9242, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9244, UINT16_MAX, 9244, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9246, UINT16_MAX, 9246, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9248, UINT16_MAX, 9248, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9250, UINT16_MAX, 9250, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9252, UINT16_MAX, 9252, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9254, UINT16_MAX, 9254, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9256, UINT16_MAX, 9256, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9258, UINT16_MAX, 9258, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9260, UINT16_MAX, 9260, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9262, UINT16_MAX, 9262, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9264, UINT16_MAX, 9264, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9266, UINT16_MAX, 9266, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9268, UINT16_MAX, 9268, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9270, UINT16_MAX, 9270, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_AN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_AN, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5328, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15147, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5332, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15151, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5336, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15155, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_MN, 7, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49206, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_CF, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, true, 0, 0, UTF8PROC_BOUNDCLASS_PREPEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49208, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 15159, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, 15163, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5340, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5344, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49210, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5348, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 15167, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 15171, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49212, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49216, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5354, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MN, 0, UTF8PROC_BIDI_CLASS_NSM, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49214, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 15175, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 15179, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49218, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 15183, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49220, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5362, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5366, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 15187, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, 15191, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7003, UINT16_MAX, 7003, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7005, UINT16_MAX, 7005, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7007, UINT16_MAX, 7007, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7009, UINT16_MAX, 7009, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7011, UINT16_MAX, 7011, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7013, UINT16_MAX, 7013, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7015, UINT16_MAX, 7015, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7017, UINT16_MAX, 7017, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7019, UINT16_MAX, 7019, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7021, UINT16_MAX, 7021, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7023, UINT16_MAX, 7023, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7025, UINT16_MAX, 7025, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7027, UINT16_MAX, 7027, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7029, UINT16_MAX, 7029, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7031, UINT16_MAX, 7031, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7033, UINT16_MAX, 7033, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7035, UINT16_MAX, 7035, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7037, UINT16_MAX, 7037, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7039, UINT16_MAX, 7039, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7041, UINT16_MAX, 7041, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7043, UINT16_MAX, 7043, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7045, UINT16_MAX, 7045, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7047, UINT16_MAX, 7047, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7049, UINT16_MAX, 7049, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7051, UINT16_MAX, 7051, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7053, UINT16_MAX, 7053, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7055, UINT16_MAX, 7055, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7057, UINT16_MAX, 7057, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7059, UINT16_MAX, 7059, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7061, UINT16_MAX, 7061, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7063, UINT16_MAX, 7063, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, 7065, UINT16_MAX, 7065, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9272, UINT16_MAX, 9272, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9274, UINT16_MAX, 9274, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9276, UINT16_MAX, 9276, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9278, UINT16_MAX, 9278, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9280, UINT16_MAX, 9280, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9282, UINT16_MAX, 9282, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9284, UINT16_MAX, 9284, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9286, UINT16_MAX, 9286, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9288, UINT16_MAX, 9288, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9290, UINT16_MAX, 9290, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9292, UINT16_MAX, 9292, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9294, UINT16_MAX, 9294, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9296, UINT16_MAX, 9296, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9298, UINT16_MAX, 9298, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9300, UINT16_MAX, 9300, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9302, UINT16_MAX, 9302, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9304, UINT16_MAX, 9304, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9306, UINT16_MAX, 9306, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9308, UINT16_MAX, 9308, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9310, UINT16_MAX, 9310, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9312, UINT16_MAX, 9312, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9314, UINT16_MAX, 9314, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9316, UINT16_MAX, 9316, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9318, UINT16_MAX, 9318, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9320, UINT16_MAX, 9320, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9322, UINT16_MAX, 9322, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9324, UINT16_MAX, 9324, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9326, UINT16_MAX, 9326, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9328, UINT16_MAX, 9328, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9330, UINT16_MAX, 9330, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9332, UINT16_MAX, 9332, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, 9334, UINT16_MAX, 9334, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_MC, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MN, 9, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5370, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5374, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15259, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15263, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5378, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15267, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15271, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15275, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15279, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15283, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49222, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 226, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_SPACINGMARK}, + {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49224, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49226, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49228, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49230, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_MC, 216, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 49232, false, false, false, false, 0, 0, UTF8PROC_BOUNDCLASS_EXTEND}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5390, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5394, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15287, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5398, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15291, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, 5404, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15295, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15299, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15303, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, 15307, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, true, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1446, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1449, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1452, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1455, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1456, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1460, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3288, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1464, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1465, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2891, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1466, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2908, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3295, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 5, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 12, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 13, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 15, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 16, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 17, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 18, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 19, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 20, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 21, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 22, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 23, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 24, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 25, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1446, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1448, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2795, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1450, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2820, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1452, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1453, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1454, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1455, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1456, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1457, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1458, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1459, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1460, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1462, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2809, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1463, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3288, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1464, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1465, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2891, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1466, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2908, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 3295, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2817, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 1, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 4, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 5, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 6, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 8, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 9, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 10, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 11, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 12, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 13, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 14, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 15, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 16, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 17, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 18, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 19, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 20, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 21, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 22, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 23, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 24, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 25, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7119, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7120, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7121, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7122, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7123, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7124, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7125, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7126, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 915, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7127, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7128, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7129, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7130, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7131, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7132, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7133, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2830, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7134, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7135, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 917, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7136, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 897, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7137, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7138, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7139, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2818, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7140, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 845, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 846, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 847, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 848, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 849, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 850, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 851, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 852, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 807, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 853, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 854, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 35, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 855, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 856, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 857, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 858, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 859, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 914, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 860, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 861, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 862, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 863, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 864, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 865, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 866, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FONT, 7141, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7142, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7143, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7144, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7145, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7146, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7147, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7121, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7122, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2829, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7123, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7124, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7125, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7126, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 915, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7127, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7128, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7129, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7130, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7131, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7132, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7133, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7134, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7135, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 917, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7136, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 897, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7137, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7138, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7139, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 2818, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7140, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 845, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 846, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 848, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 849, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 850, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 851, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 852, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 807, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 853, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 854, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 35, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 855, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 856, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 857, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 859, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 914, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 860, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 861, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 862, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 863, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 864, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 865, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 866, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SM, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_FONT, 7141, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, true, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7142, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7144, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7145, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7146, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7147, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7143, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 7148, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_FONT, 904, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 2775, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 38, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 31, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 32, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 2776, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 2777, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 2778, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 2779, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 2780, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 2781, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 2775, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 38, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 31, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 32, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 2776, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 2777, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 2778, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 2779, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 2780, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_ND, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_FONT, 2781, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7149, UINT16_MAX, 7149, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7151, UINT16_MAX, 7151, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7153, UINT16_MAX, 7153, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7155, UINT16_MAX, 7155, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7157, UINT16_MAX, 7157, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7159, UINT16_MAX, 7159, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7161, UINT16_MAX, 7161, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7163, UINT16_MAX, 7163, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7165, UINT16_MAX, 7165, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7167, UINT16_MAX, 7167, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7169, UINT16_MAX, 7169, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7171, UINT16_MAX, 7171, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7173, UINT16_MAX, 7173, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7175, UINT16_MAX, 7175, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7177, UINT16_MAX, 7177, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7179, UINT16_MAX, 7179, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7181, UINT16_MAX, 7181, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7183, UINT16_MAX, 7183, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7185, UINT16_MAX, 7185, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7187, UINT16_MAX, 7187, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7189, UINT16_MAX, 7189, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7191, UINT16_MAX, 7191, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7193, UINT16_MAX, 7193, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7195, UINT16_MAX, 7195, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7197, UINT16_MAX, 7197, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7199, UINT16_MAX, 7199, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7201, UINT16_MAX, 7201, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7203, UINT16_MAX, 7203, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7205, UINT16_MAX, 7205, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7207, UINT16_MAX, 7207, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7209, UINT16_MAX, 7209, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7211, UINT16_MAX, 7211, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7213, UINT16_MAX, 7213, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LU, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, 7215, UINT16_MAX, 7215, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9336, UINT16_MAX, 9336, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9338, UINT16_MAX, 9338, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9340, UINT16_MAX, 9340, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9342, UINT16_MAX, 9342, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9344, UINT16_MAX, 9344, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9346, UINT16_MAX, 9346, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9348, UINT16_MAX, 9348, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9350, UINT16_MAX, 9350, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9352, UINT16_MAX, 9352, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9354, UINT16_MAX, 9354, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9356, UINT16_MAX, 9356, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9358, UINT16_MAX, 9358, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9360, UINT16_MAX, 9360, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9362, UINT16_MAX, 9362, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9364, UINT16_MAX, 9364, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9366, UINT16_MAX, 9366, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9368, UINT16_MAX, 9368, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9370, UINT16_MAX, 9370, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9372, UINT16_MAX, 9372, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9374, UINT16_MAX, 9374, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9376, UINT16_MAX, 9376, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9378, UINT16_MAX, 9378, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9380, UINT16_MAX, 9380, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9382, UINT16_MAX, 9382, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9384, UINT16_MAX, 9384, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9386, UINT16_MAX, 9386, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9388, UINT16_MAX, 9388, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9390, UINT16_MAX, 9390, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9392, UINT16_MAX, 9392, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9394, UINT16_MAX, 9394, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9396, UINT16_MAX, 9396, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9398, UINT16_MAX, 9398, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9400, UINT16_MAX, 9400, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LL, 0, UTF8PROC_BIDI_CLASS_R, 0, UINT16_MAX, UINT16_MAX, 9402, UINT16_MAX, 9402, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6550, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6551, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6555, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6558, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6577, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6561, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6556, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6566, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6578, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6572, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6573, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6574, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6575, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6562, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6568, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6570, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6564, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6571, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6560, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6563, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6553, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6554, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6557, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6559, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6565, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6567, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6569, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 7217, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 5760, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 7218, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 7219, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6576, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 1, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6576, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6551, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6555, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6558, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6577, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6561, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6556, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6566, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6578, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6573, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6574, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6575, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6562, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6568, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6570, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6564, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6571, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6560, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6563, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6553, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6554, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6557, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6559, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6565, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6567, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_AL, UTF8PROC_DECOMP_TYPE_FONT, 6569, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 15412, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 15414, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 15416, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 15418, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 15420, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 15422, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 15424, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 15426, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 15428, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 15430, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_NO, 0, UTF8PROC_BIDI_CLASS_EN, UTF8PROC_DECOMP_TYPE_COMPAT, 15432, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23626, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23629, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23632, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23635, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23638, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23641, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23644, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23647, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23650, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23653, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23656, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23659, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23662, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23665, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23668, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23671, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23674, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23677, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23680, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23683, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23686, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23689, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23692, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23695, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23698, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23701, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23704, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 2795, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 1463, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 15515, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 15517, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1446, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1448, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 2795, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1449, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1450, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 2820, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1452, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1453, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1454, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1455, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1456, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1457, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1458, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1459, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1460, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1462, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 2809, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1463, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3288, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1464, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1465, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 2891, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 1466, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 2908, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3295, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 2817, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 15519, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 15521, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 15523, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 23717, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 15528, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 15530, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, UTF8PROC_DECOMP_TYPE_SUPER, 15532, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 15534, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_REGIONAL_INDICATOR}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 15536, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 15538, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 4278, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3489, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7348, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7349, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7350, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3432, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7351, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7352, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3869, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7353, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7354, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7355, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 5399, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7356, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7357, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7358, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7359, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7360, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7361, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3525, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7362, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7363, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7364, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7365, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7366, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7367, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3426, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3861, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7368, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 4191, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3864, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 4192, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7369, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3581, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7370, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7371, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7372, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7373, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7374, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 4174, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 3499, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7375, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7376, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7377, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_SQUARE, 7378, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23763, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23766, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23769, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23772, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23775, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23778, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23781, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23784, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_COMPAT, 23787, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 7406, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_L, UTF8PROC_DECOMP_TYPE_CIRCLE, 7407, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_SK, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_E_MODIFIER}, + {UTF8PROC_CATEGORY_SO, 0, UTF8PROC_BIDI_CLASS_ON, 0, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_E_BASE_GAZ}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7408, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7409, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7410, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7411, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7413, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7414, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7415, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7416, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7417, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7418, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7419, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7420, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7422, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7423, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7424, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7425, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7427, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7428, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7358, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7429, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7431, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7432, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7433, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7434, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7435, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3442, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7437, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7438, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7439, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7440, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7376, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7441, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7442, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7443, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7444, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7445, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7446, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7447, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7448, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7449, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7450, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7452, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7453, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7454, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7455, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7457, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7458, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7459, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7460, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7461, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7462, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7463, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7464, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7465, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7466, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7467, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7468, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7469, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7470, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7471, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7472, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7473, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7474, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7475, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7476, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7477, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7478, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7479, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7480, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7481, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7482, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7483, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7484, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7485, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7487, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7488, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7489, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7351, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7490, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7491, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7492, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7494, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7496, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7497, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7498, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7499, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7500, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7501, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7502, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7503, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7504, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7505, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7507, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7508, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7509, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7510, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7512, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7513, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7514, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3468, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7515, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7516, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7517, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7518, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7519, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7521, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7522, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7524, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7525, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7526, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7527, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7528, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7529, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7530, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7531, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7532, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7533, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7534, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7535, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7537, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7538, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7539, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7540, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7541, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3480, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7543, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7545, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7546, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7547, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7548, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7550, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7552, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7553, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7554, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7555, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7556, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7557, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7558, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7559, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7560, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7561, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7562, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7564, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7565, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7566, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7567, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7568, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7569, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7570, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7571, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7572, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7573, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7574, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7575, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7576, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7577, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7578, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7580, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7581, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7582, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7583, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7584, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7585, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7587, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7588, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7589, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7590, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7591, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7592, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7593, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7594, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7595, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7596, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7597, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7599, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7600, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7601, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7602, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7603, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7604, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7605, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7606, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7607, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7608, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7609, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7610, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7611, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7612, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7613, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7614, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7616, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7617, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7618, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7619, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7620, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7622, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7623, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7624, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7625, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7626, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7627, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7628, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7629, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7631, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7632, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7633, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7634, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7636, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7637, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7638, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7639, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7640, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7641, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7643, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7645, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7647, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7648, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7650, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7651, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7652, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7653, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7654, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7655, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7656, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7657, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7658, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7660, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7661, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7662, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7663, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7664, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7665, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7667, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7668, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7669, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7671, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7673, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7674, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7675, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7676, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7677, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7678, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7679, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7680, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7681, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7683, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7684, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7686, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7687, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7689, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7690, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7691, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7693, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7694, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7695, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7697, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7699, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7700, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7701, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7702, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7703, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7704, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7705, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7706, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7707, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7708, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7709, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7710, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7712, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7713, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7715, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7717, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7718, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7720, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7722, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7724, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7725, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7726, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7728, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7730, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7732, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7734, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7735, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7736, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7737, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7738, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7739, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7741, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7742, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7743, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7745, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7747, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7749, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7750, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7751, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7752, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7753, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7755, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7757, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7758, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7759, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7761, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7762, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7763, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7764, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7766, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7767, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7768, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7769, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7770, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7771, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7773, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7774, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7775, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7776, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7777, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7778, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7779, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7781, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7783, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7784, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7786, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7787, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7789, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7790, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7791, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7793, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7795, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7796, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7798, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7799, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7801, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7802, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7803, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7804, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7805, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7806, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7807, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7809, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7811, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7813, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7815, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7816, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7817, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7818, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7819, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7820, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7821, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7822, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7823, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7824, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7825, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7826, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7828, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7829, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7830, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7831, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7832, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7833, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7834, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7835, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7836, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7837, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7838, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7840, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7842, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7844, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7845, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7846, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7847, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7848, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7850, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7851, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7853, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7854, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7855, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7857, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7859, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7860, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7861, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7862, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7863, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7864, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7865, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7866, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7867, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7868, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7869, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7870, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7871, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7872, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7873, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7874, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3570, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7875, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7877, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7878, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7879, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7880, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7881, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7882, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7884, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7886, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7887, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7888, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3577, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7889, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7891, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7892, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7893, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7894, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7895, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7897, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7899, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7900, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7901, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7902, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7904, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7905, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7907, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7909, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7910, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7911, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7912, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7914, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7915, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7916, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7917, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7918, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7919, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7920, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7921, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7923, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7924, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7925, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7926, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7928, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7929, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7930, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7931, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7932, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7934, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7936, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7937, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7938, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7939, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7941, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7942, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7944, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7945, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7947, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7948, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7949, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7950, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7951, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7952, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7953, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7954, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7956, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7957, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7958, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7959, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7960, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7961, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7963, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7964, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7966, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7968, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3625, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7970, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3629, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7971, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7972, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7973, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7974, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 3634, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, + {UTF8PROC_CATEGORY_LO, 0, UTF8PROC_BIDI_CLASS_L, 0, 7975, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, UINT16_MAX, false, false, false, false, 2, 0, UTF8PROC_BOUNDCLASS_OTHER}, }; UTF8PROC_DATA -const int32_t utf8proc_combinations[] = { - 192, 193, 194, 195, 196, 197, -1, - 256, 258, 260, 550, 461, -1, -1, 512, - 514, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 7680, 7840, -1, -1, -1, -1, -1, 7842, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 262, 264, - -1, -1, -1, 199, -1, -1, -1, 266, - 268, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 200, 201, 202, 7868, 203, -1, 552, - 274, 276, 280, 278, 282, -1, -1, 516, - 518, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7864, -1, 7704, 7706, -1, -1, 7866, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 204, 205, 206, - 296, 207, -1, -1, 298, 300, 302, 304, - 463, -1, -1, 520, 522, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7882, -1, -1, - 7724, -1, -1, 7880, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 504, 323, -1, 209, -1, -1, 325, - -1, -1, -1, 7748, 327, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7750, 7752, 7754, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 210, 211, 212, - 213, 214, -1, -1, 332, 334, 490, 558, - 465, 336, 416, 524, 526, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7884, -1, -1, - -1, -1, -1, 7886, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 217, 218, 219, 360, 220, 366, -1, - 362, 364, 370, -1, 467, 368, 431, 532, - 534, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7908, -1, 7798, 7796, -1, 7794, 7910, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7922, 221, 374, - 7928, 376, -1, -1, 562, -1, -1, 7822, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7924, -1, -1, - -1, -1, -1, 7926, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 224, 225, 226, 227, 228, 229, -1, - 257, 259, 261, 551, 462, -1, -1, 513, - 515, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 7681, 7841, -1, -1, -1, -1, -1, 7843, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 263, 265, - -1, -1, -1, 231, -1, -1, -1, 267, - 269, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 232, 233, 234, 7869, 235, -1, 553, - 275, 277, 281, 279, 283, -1, -1, 517, - 519, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7865, -1, 7705, 7707, -1, -1, 7867, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 236, 237, 238, - 297, 239, -1, -1, 299, 301, 303, -1, - 464, -1, -1, 521, 523, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7883, -1, -1, - 7725, -1, -1, 7881, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 505, 324, -1, 241, -1, -1, 326, - -1, -1, -1, 7749, 328, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7751, 7753, 7755, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 242, 243, 244, - 245, 246, -1, -1, 333, 335, 491, 559, - 466, 337, 417, 525, 527, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7885, -1, -1, - -1, -1, -1, 7887, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 249, 250, 251, 361, 252, 367, -1, - 363, 365, 371, -1, 468, 369, 432, 533, - 535, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7909, -1, 7799, 7797, -1, 7795, 7911, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7923, 253, 375, - 7929, 255, 7833, -1, 563, -1, -1, 7823, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7925, -1, -1, - -1, -1, -1, 7927, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 7696, - -1, -1, -1, 7690, 270, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7692, 7694, 7698, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 7697, -1, -1, -1, 7691, - 271, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7693, 7695, 7699, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 500, 284, -1, -1, -1, 290, - 7712, 286, -1, 288, 486, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 501, 285, - -1, -1, -1, 291, 7713, 287, -1, 289, - 487, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 292, -1, 7718, -1, 7720, - -1, -1, -1, 7714, 542, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7716, -1, -1, -1, 7722, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 293, - -1, 7719, -1, 7721, -1, -1, -1, 7715, - 543, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7717, 7830, -1, - -1, 7723, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 308, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 309, - -1, -1, -1, -1, -1, -1, -1, -1, - 496, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 7728, -1, -1, -1, -1, 310, - -1, -1, -1, -1, 488, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7730, 7732, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 7729, -1, - -1, -1, -1, 311, -1, -1, -1, -1, - 489, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7731, 7733, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 313, -1, -1, -1, -1, 315, - -1, -1, -1, -1, 317, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7734, 7738, 7740, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 314, -1, - -1, -1, -1, 316, -1, -1, -1, -1, - 318, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7735, 7739, 7741, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 340, -1, -1, -1, -1, 342, - -1, -1, -1, 7768, 344, -1, -1, 528, - 530, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7770, 7774, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 341, -1, - -1, -1, -1, 343, -1, -1, -1, 7769, - 345, -1, -1, 529, 531, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7771, 7775, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 346, 348, -1, -1, -1, 350, - -1, -1, -1, 7776, 352, -1, -1, -1, - -1, 536, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7778, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 347, 349, - -1, -1, -1, 351, -1, -1, -1, 7777, - 353, -1, -1, -1, -1, 537, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7779, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 354, - -1, -1, -1, 7786, 356, -1, -1, -1, - -1, 538, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7788, 7790, 7792, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7831, -1, 355, -1, -1, -1, 7787, - 357, -1, -1, -1, -1, 539, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7789, 7791, 7793, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7808, 7810, 372, -1, 7812, -1, -1, - -1, -1, -1, 7814, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7816, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7809, 7811, 373, - -1, 7813, 7832, -1, -1, -1, -1, 7815, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7817, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 377, 7824, -1, -1, -1, -1, - -1, -1, -1, 379, 381, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7826, 7828, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 378, 7825, - -1, -1, -1, -1, -1, -1, -1, 380, - 382, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7827, 7829, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 475, 471, -1, -1, -1, -1, -1, - 469, -1, -1, -1, 473, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 476, 472, -1, - -1, -1, -1, -1, 470, -1, -1, -1, - 474, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 478, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 479, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 480, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 481, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 508, -1, -1, -1, -1, -1, - 482, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 509, -1, - -1, -1, -1, -1, 483, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 492, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 493, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 494, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 495, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 506, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 507, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 510, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 511, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 554, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 555, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 7756, -1, -1, 7758, -1, -1, - 556, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 7757, -1, - -1, 7759, -1, -1, 557, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 560, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 561, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 8173, 901, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 8129, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 8122, 902, -1, - -1, -1, -1, -1, 8121, 8120, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 7944, 7945, -1, 8124, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 8136, 904, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 7960, 7961, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 8138, 905, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 7976, 7977, -1, 8140, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 8154, 906, -1, -1, 938, -1, -1, - 8153, 8152, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 7992, 7993, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 8184, 908, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8008, 8009, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 8170, 910, -1, -1, 939, -1, -1, - 8169, 8168, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 8025, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 8186, 911, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8040, 8041, -1, 8188, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 8146, 912, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 8151, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 8048, 940, -1, - -1, -1, -1, -1, 8113, 8112, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 7936, 7937, 8118, 8115, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 8050, 941, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 7952, 7953, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 8052, 942, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 7968, 7969, 8134, 8131, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 8054, 943, -1, -1, 970, -1, -1, - 8145, 8144, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 7984, 7985, 8150, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 8162, 944, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 8167, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 8058, 973, -1, -1, 971, -1, -1, - 8161, 8160, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 8016, 8017, 8166, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 8056, 972, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8000, 8001, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 8060, 974, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 8032, 8033, 8182, 8179, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 979, -1, - -1, 980, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 1024, -1, -1, -1, 1025, -1, -1, - -1, 1238, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 1027, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 1031, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 1036, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 1037, -1, -1, -1, 1252, -1, -1, - 1250, 1049, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 1264, -1, -1, 1262, 1038, -1, -1, - -1, 1266, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 1117, -1, -1, -1, 1253, -1, -1, - 1251, 1081, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 1104, -1, -1, - -1, 1105, -1, -1, -1, 1239, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 1107, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 1111, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 1116, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 1265, -1, -1, 1263, 1118, -1, -1, - -1, 1267, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 1142, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 1143, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 1244, -1, -1, - -1, 1217, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 1245, -1, -1, -1, 1218, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 1234, -1, -1, - -1, 1232, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 1235, -1, -1, -1, 1233, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 1242, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 1243, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 1246, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 1247, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 1254, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 1255, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 1258, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 1259, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 1260, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 1261, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 1268, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 1269, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 1272, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 1273, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 1570, 1571, 1573, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 1572, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 1574, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 1728, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 1730, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 1747, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 2345, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 2353, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 2356, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 2507, 2508, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 2888, 2891, 2892, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 2964, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 3020, 3018, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 3019, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 3144, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 3264, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 3271, 3272, - 3274, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 3275, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 3402, 3404, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 3403, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 3546, 3548, 3550, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 3549, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 4134, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 6918, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 6920, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 6922, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 6924, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 6926, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 6930, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 6971, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 6973, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 6976, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 6977, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 6979, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 7682, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7684, 7686, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 7683, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7685, 7687, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 7688, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 7689, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7700, 7702, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7701, 7703, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7708, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7709, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 7710, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 7711, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 7726, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 7727, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 7736, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 7737, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 7742, -1, -1, -1, -1, -1, - -1, -1, -1, 7744, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7746, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 7743, -1, - -1, -1, -1, -1, -1, -1, -1, 7745, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7747, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7760, 7762, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7761, 7763, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 7764, -1, -1, -1, -1, -1, - -1, -1, -1, 7766, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 7765, -1, - -1, -1, -1, -1, -1, -1, -1, 7767, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 7772, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 7773, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 7780, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 7781, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 7782, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 7783, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 7784, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 7785, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 7800, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 7801, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7802, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7803, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 7804, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7806, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 7805, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7807, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7820, -1, -1, - -1, -1, -1, 7818, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7821, -1, -1, -1, -1, -1, 7819, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 7835, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7846, 7844, -1, - 7850, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 7848, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7847, 7845, -1, 7851, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 7849, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 7852, - -1, -1, -1, -1, -1, 7862, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 7853, -1, -1, -1, -1, - -1, 7863, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7856, 7854, -1, - 7860, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 7858, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7857, 7855, -1, 7861, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 7859, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7872, 7870, -1, - 7876, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 7874, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7873, 7871, -1, 7877, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 7875, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 7878, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 7879, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7890, 7888, -1, - 7894, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 7892, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7891, 7889, -1, 7895, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 7893, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 7896, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 7897, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7900, 7898, -1, - 7904, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7906, -1, -1, - -1, -1, -1, 7902, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7901, 7899, -1, 7905, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7907, -1, -1, -1, -1, -1, 7903, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7914, 7912, -1, - 7918, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7920, -1, -1, - -1, -1, -1, 7916, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7915, 7913, -1, 7919, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7921, -1, -1, -1, -1, -1, 7917, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7938, 7940, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 7942, 8064, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7939, 7941, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 7943, 8065, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7946, 7948, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 7950, 8072, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7947, 7949, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 7951, 8073, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7954, 7956, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7955, 7957, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7962, 7964, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7963, 7965, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7970, 7972, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 7974, 8080, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7971, 7973, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 7975, 8081, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7978, 7980, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 7982, 8088, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7979, 7981, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 7983, 8089, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7986, 7988, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 7990, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7987, 7989, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 7991, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 7994, 7996, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 7998, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 7995, 7997, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 7999, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 8002, 8004, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 8003, 8005, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 8010, 8012, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 8011, 8013, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 8018, 8020, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 8022, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 8019, 8021, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 8023, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 8027, 8029, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 8031, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 8034, 8036, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 8038, 8096, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 8035, 8037, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 8039, 8097, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 8042, 8044, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 8046, 8104, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 8043, 8045, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 8047, 8105, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 8066, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 8067, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 8068, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 8069, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 8070, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 8071, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 8074, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 8075, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 8076, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 8077, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 8078, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 8079, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 8082, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 8083, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 8084, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 8085, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 8086, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 8087, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 8090, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 8091, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 8092, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 8093, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 8094, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 8095, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 8098, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 8099, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 8100, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 8101, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 8102, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 8103, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 8106, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 8107, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 8108, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 8109, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 8110, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 8111, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 8114, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 8116, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 8119, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 8130, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 8132, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 8135, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 8141, 8142, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 8143, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 8157, 8158, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 8159, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 8164, 8165, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 8172, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 8178, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 8180, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 8183, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 8602, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8603, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 8622, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8653, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 8654, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8655, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 8708, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8713, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 8716, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8740, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 8742, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8769, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 8772, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8775, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 8777, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8800, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 8802, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8813, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 8814, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8815, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 8816, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8817, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 8820, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8821, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 8824, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8825, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 8832, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8833, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 8836, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8837, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 8840, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8841, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 8876, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8877, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 8878, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8879, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 8928, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8929, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 8930, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8931, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 8938, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8939, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 8940, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 8941, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 10972, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 12364, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 12366, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 12368, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 12370, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 12372, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 12374, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 12376, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 12378, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 12380, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 12382, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 12384, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 12386, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 12389, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 12391, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 12393, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 12400, 12401, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 12403, 12404, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 12406, 12407, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 12409, 12410, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 12412, 12413, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 12436, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 12446, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 12460, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 12462, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 12464, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 12466, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 12468, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 12470, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 12472, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 12474, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 12476, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 12478, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 12480, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 12482, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 12485, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 12487, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 12489, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 12496, 12497, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 12499, 12500, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 12502, 12503, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 12505, 12506, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 12508, 12509, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 12532, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 12535, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 12536, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 12537, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 12538, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, 12542, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 119134, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 119135, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 119136, 119137, 119138, 119139, 119140, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 119227, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 119228, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 119229, 119231, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, - 119230, 119232, -1, -1, -1, }; +const utf8proc_uint16_t utf8proc_combinations[] = { + 0, 46, 192, 193, 194, 195, 196, 197, 0, + 256, 258, 260, 550, 461, 0, 0, 512, + 514, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7680, 7840, 0, 0, 0, 0, 0, 7842, +1, 11, + 262, 264, 0, 0, 0, 199, 0, 0, + 0, 266, 268, +0, 46, 200, 201, 202, 7868, 203, + 0, 552, 274, 276, 280, 278, 282, 0, + 0, 516, 518, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7864, 0, 7704, 7706, 0, + 0, 7866, +0, 46, 204, 205, 206, 296, 207, 0, + 0, 298, 300, 302, 304, 463, 0, 0, + 520, 522, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 7882, 0, 0, 7724, 0, 0, + 7880, +0, 42, 504, 323, 0, 209, 0, 0, 325, + 0, 0, 0, 7748, 327, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7750, 7752, 7754, +0, 46, 210, 211, 212, 213, + 214, 0, 0, 332, 334, 490, 558, 465, + 336, 416, 524, 526, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7884, 0, 0, 0, + 0, 0, 7886, +0, 46, 217, 218, 219, 360, 220, + 366, 0, 362, 364, 370, 0, 467, 368, + 431, 532, 534, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7908, 0, 7798, 7796, 0, + 7794, 7910, +0, 46, 7922, 221, 374, 7928, 376, 0, + 0, 562, 0, 0, 7822, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 7924, 0, 0, 0, 0, 0, + 7926, +0, 46, 224, 225, 226, 227, 228, 229, 0, + 257, 259, 261, 551, 462, 0, 0, 513, + 515, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7681, 7841, 0, 0, 0, 0, 0, 7843, +1, 11, + 263, 265, 0, 0, 0, 231, 0, 0, + 0, 267, 269, +0, 46, 232, 233, 234, 7869, 235, + 0, 553, 275, 277, 281, 279, 283, 0, + 0, 517, 519, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7865, 0, 7705, 7707, 0, + 0, 7867, +0, 46, 236, 237, 238, 297, 239, 0, + 0, 299, 301, 303, 0, 464, 0, 0, + 521, 523, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 7883, 0, 0, 7725, 0, 0, + 7881, +0, 42, 505, 324, 0, 241, 0, 0, 326, + 0, 0, 0, 7749, 328, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7751, 7753, 7755, +0, 46, 242, 243, 244, 245, + 246, 0, 0, 333, 335, 491, 559, 466, + 337, 417, 525, 527, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7885, 0, 0, 0, + 0, 0, 7887, +0, 46, 249, 250, 251, 361, 252, + 367, 0, 363, 365, 371, 0, 468, 369, + 432, 533, 535, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7909, 0, 7799, 7797, 0, + 7795, 7911, +0, 46, 7923, 253, 375, 7929, 255, 7833, + 0, 563, 0, 0, 7823, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 7925, 0, 0, 0, 0, 0, + 7927, +6, 42, 7696, 0, 0, 0, 7690, 270, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7692, 7694, 7698, +6, 42, 7697, 0, + 0, 0, 7691, 271, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7693, 7695, 7699, +1, 11, 500, 284, 0, 0, 0, + 290, 7712, 286, 0, 288, 486, +1, 11, 501, 285, + 0, 0, 0, 291, 7713, 287, 0, 289, + 487, +2, 44, 292, 0, 7718, 0, 7720, 0, 0, + 0, 7714, 542, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7716, + 0, 0, 0, 7722, +2, 44, 293, 0, 7719, 0, + 7721, 0, 0, 0, 7715, 543, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 7717, 7830, 0, 0, 7723, +2, 2, 308, +2, 11, + 309, 0, 0, 0, 0, 0, 0, 0, + 0, 496, +1, 41, 7728, 0, 0, 0, 0, 310, + 0, 0, 0, 0, 488, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7730, 7732, +1, 41, 7729, 0, 0, 0, 0, + 311, 0, 0, 0, 0, 489, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 7731, 7733, +1, 42, 313, 0, 0, 0, + 0, 315, 0, 0, 0, 0, 317, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7734, 7738, 7740, +1, 42, 314, 0, + 0, 0, 0, 316, 0, 0, 0, 0, + 318, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7735, 7739, 7741, +1, 41, + 340, 0, 0, 0, 0, 342, 0, 0, + 0, 7768, 344, 0, 0, 528, 530, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7770, + 7774, +1, 41, 341, 0, 0, 0, 0, 343, 0, + 0, 0, 7769, 345, 0, 0, 529, 531, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7771, 7775, +1, 40, 346, 348, 0, 0, 0, 350, + 0, 0, 0, 7776, 352, 0, 0, 0, + 0, 536, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7778, +1, 40, 347, 349, 0, 0, 0, 351, + 0, 0, 0, 7777, 353, 0, 0, 0, + 0, 537, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7779, +6, 42, 354, 0, 0, 0, 7786, 356, + 0, 0, 0, 0, 538, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7788, 7790, 7792, +4, 42, 7831, + 0, 355, 0, 0, 0, 7787, 357, 0, + 0, 0, 0, 539, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7789, 7791, 7793, +0, 40, 7808, 7810, + 372, 0, 7812, 0, 0, 0, 0, 0, + 7814, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7816, +0, 40, 7809, + 7811, 373, 0, 7813, 7832, 0, 0, 0, + 0, 7815, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7817, +1, 41, + 377, 7824, 0, 0, 0, 0, 0, 0, + 0, 379, 381, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7826, + 7828, +1, 41, 378, 7825, 0, 0, 0, 0, 0, + 0, 0, 380, 382, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7827, 7829, +0, 11, 475, 471, 0, 0, 0, 0, + 0, 469, 0, 0, 0, 473, +0, 11, 476, 472, + 0, 0, 0, 0, 0, 470, 0, 0, + 0, 474, +7, 7, 478, +7, 7, 479, +7, 7, 480, +7, 7, 481, +1, 7, 508, 0, + 0, 0, 0, 0, 482, +1, 7, 509, 0, 0, + 0, 0, 0, 483, +7, 7, 492, +7, 7, 493, +11, 11, 494, +11, 11, 495, +1, 1, + 506, +1, 1, 507, +1, 1, 510, +1, 1, 511, +7, 7, 554, +7, 7, 555, +1, 7, 7756, 0, + 0, 7758, 0, 0, 556, +1, 7, 7757, 0, 0, + 7759, 0, 0, 557, +7, 7, 560, +7, 7, 561, +0, 49, 8173, 901, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 8129, +0, 50, + 8122, 902, 0, 0, 0, 0, 0, 8121, + 8120, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7944, + 7945, 0, 8124, +0, 48, 8136, 904, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 7960, 7961, +0, 50, 8138, 905, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7976, 7977, 0, 8140, +0, 48, 8154, + 906, 0, 0, 938, 0, 0, 8153, 8152, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7992, 7993, +0, 48, + 8184, 908, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 8008, + 8009, +0, 48, 8170, 910, 0, 0, 939, 0, 0, + 8169, 8168, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8025, +0, 50, 8186, 911, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8040, 8041, 0, 8188, +0, 49, 8146, 912, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 8151, +0, 50, 8048, + 940, 0, 0, 0, 0, 0, 8113, 8112, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7936, 7937, + 8118, 8115, +0, 48, 8050, 941, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7952, 7953, +0, 50, 8052, 942, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 7968, 7969, 8134, 8131, +0, 49, 8054, 943, + 0, 0, 970, 0, 0, 8145, 8144, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7984, 7985, 8150, +0, 49, + 8162, 944, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8167, +0, 49, 8058, 973, 0, 0, 971, 0, + 0, 8161, 8160, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8016, 8017, 8166, +0, 48, 8056, 972, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8000, 8001, +0, 50, 8060, 974, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8032, 8033, 8182, 8179, +1, 4, + 979, 0, 0, 980, +0, 8, 1024, 0, 0, 0, + 1025, 0, 0, 0, 1238, +1, 1, 1027, +4, 4, 1031, +1, 1, 1036, +0, 8, + 1037, 0, 0, 0, 1252, 0, 0, 1250, + 1049, +4, 12, 1264, 0, 0, 1262, 1038, 0, 0, + 0, 1266, +0, 8, 1117, 0, 0, 0, 1253, 0, + 0, 1251, 1081, +0, 8, 1104, 0, 0, 0, 1105, + 0, 0, 0, 1239, +1, 1, 1107, +4, 4, 1111, +1, 1, 1116, +4, 12, 1265, + 0, 0, 1263, 1118, 0, 0, 0, 1267, +14, 14, + 1142, +14, 14, 1143, +4, 8, 1244, 0, 0, 0, 1217, +4, 8, 1245, + 0, 0, 0, 1218, +4, 8, 1234, 0, 0, 0, + 1232, +4, 8, 1235, 0, 0, 0, 1233, +4, 4, 1242, +4, 4, 1243, +4, 4, + 1246, +4, 4, 1247, +4, 4, 1254, +4, 4, 1255, +4, 4, 1258, +4, 4, 1259, +4, 4, 1260, +4, 4, 1261, +4, 4, + 1268, +4, 4, 1269, +4, 4, 1272, +4, 4, 1273, +17, 19, 1570, 1571, 1573, +18, 18, 1572, +18, 18, + 1574, +18, 18, 1728, +18, 18, 1730, +18, 18, 1747, +20, 20, 2345, +20, 20, 2353, +20, 20, 2356, +21, 22, 2507, + 2508, +23, 25, 2888, 2891, 2892, +26, 26, 2964, +26, 27, 3020, 3018, +27, 27, 3019, +28, 28, + 3144, +29, 29, 3264, +29, 31, 3271, 3272, 3274, +29, 29, 3275, +32, 33, 3402, 3404, +32, 32, + 3403, +34, 36, 3546, 3548, 3550, +34, 34, 3549, +37, 37, 4134, +38, 38, 6918, +38, 38, 6920, +38, 38, + 6922, +38, 38, 6924, +38, 38, 6926, +38, 38, 6930, +38, 38, 6971, +38, 38, 6973, +38, 38, 6976, +38, 38, 6977, +38, 38, + 6979, +10, 41, 7682, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7684, + 7686, +10, 41, 7683, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7685, + 7687, +1, 1, 7688, +1, 1, 7689, +0, 1, 7700, 7702, +0, 1, 7701, 7703, +8, 8, 7708, +8, 8, + 7709, +10, 10, 7710, +10, 10, 7711, +1, 1, 7726, +1, 1, 7727, +7, 7, 7736, +7, 7, 7737, +1, 40, 7742, + 0, 0, 0, 0, 0, 0, 0, 0, + 7744, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7746, +1, 40, 7743, + 0, 0, 0, 0, 0, 0, 0, 0, + 7745, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7747, +0, 1, 7760, + 7762, +0, 1, 7761, 7763, +1, 10, 7764, 0, 0, 0, 0, + 0, 0, 0, 0, 7766, +1, 10, 7765, 0, 0, + 0, 0, 0, 0, 0, 0, 7767, +7, 7, 7772, +7, 7, + 7773, +10, 10, 7780, +10, 10, 7781, +10, 10, 7782, +10, 10, 7783, +10, 10, 7784, +10, 10, 7785, +1, 1, 7800, +1, 1, + 7801, +4, 4, 7802, +4, 4, 7803, +3, 40, 7804, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7806, +3, 40, 7805, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7807, +4, 10, 7820, + 0, 0, 0, 0, 0, 7818, +4, 10, 7821, 0, + 0, 0, 0, 0, 7819, +10, 10, 7835, +0, 46, 7846, 7844, + 0, 7850, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7848, +0, 46, 7847, 7845, 0, + 7851, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7849, +2, 8, 7852, 0, 0, 0, + 0, 0, 7862, +2, 8, 7853, 0, 0, 0, 0, + 0, 7863, +0, 46, 7856, 7854, 0, 7860, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7858, +0, 46, 7857, 7855, 0, 7861, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7859, +0, 46, + 7872, 7870, 0, 7876, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7874, +0, 46, 7873, + 7871, 0, 7877, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7875, +2, 2, 7878, +2, 2, 7879, +0, 46, + 7890, 7888, 0, 7894, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7892, +0, 46, 7891, + 7889, 0, 7895, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7893, +2, 2, 7896, +2, 2, 7897, +0, 46, + 7900, 7898, 0, 7904, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7906, 0, 0, 0, 0, 0, 7902, +0, 46, 7901, + 7899, 0, 7905, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7907, + 0, 0, 0, 0, 0, 7903, +0, 46, 7914, 7912, + 0, 7918, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7920, 0, + 0, 0, 0, 0, 7916, +0, 46, 7915, 7913, 0, + 7919, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7921, 0, 0, + 0, 0, 0, 7917, +0, 50, 7938, 7940, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7942, 8064, +0, 50, 7939, + 7941, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 7943, 8065, +0, 50, 7946, 7948, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7950, 8072, +0, 50, 7947, 7949, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7951, 8073, +0, 1, + 7954, 7956, +0, 1, 7955, 7957, +0, 1, 7962, 7964, +0, 1, 7963, 7965, +0, 50, + 7970, 7972, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7974, 8080, +0, 50, 7971, 7973, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 7975, 8081, +0, 50, 7978, 7980, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7982, + 8088, +0, 50, 7979, 7981, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 7983, 8089, +0, 49, 7986, 7988, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7990, +0, 49, 7987, 7989, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7991, +0, 49, + 7994, 7996, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 7998, +0, 49, 7995, 7997, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7999, +0, 1, 8002, 8004, +0, 1, 8003, 8005, +0, 1, + 8010, 8012, +0, 1, 8011, 8013, +0, 49, 8018, 8020, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 8022, +0, 49, 8019, 8021, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 8023, +0, 49, + 8027, 8029, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8031, +0, 50, 8034, 8036, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8038, 8096, +0, 50, 8035, 8037, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 8039, 8097, +0, 50, + 8042, 8044, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8046, 8104, +0, 50, 8043, 8045, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 8047, 8105, +50, 50, 8066, +50, 50, 8067, +50, 50, + 8068, +50, 50, 8069, +50, 50, 8070, +50, 50, 8071, +50, 50, 8074, +50, 50, 8075, +50, 50, 8076, +50, 50, 8077, +50, 50, + 8078, +50, 50, 8079, +50, 50, 8082, +50, 50, 8083, +50, 50, 8084, +50, 50, 8085, +50, 50, 8086, +50, 50, 8087, +50, 50, + 8090, +50, 50, 8091, +50, 50, 8092, +50, 50, 8093, +50, 50, 8094, +50, 50, 8095, +50, 50, 8098, +50, 50, 8099, +50, 50, + 8100, +50, 50, 8101, +50, 50, 8102, +50, 50, 8103, +50, 50, 8106, +50, 50, 8107, +50, 50, 8108, +50, 50, 8109, +50, 50, + 8110, +50, 50, 8111, +50, 50, 8114, +50, 50, 8116, +50, 50, 8119, +50, 50, 8130, +50, 50, 8132, +50, 50, 8135, +0, 49, + 8141, 8142, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 8143, +0, 49, 8157, 8158, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8159, +47, 48, 8164, 8165, +48, 48, 8172, +50, 50, 8178, +50, 50, + 8180, +50, 50, 8183, +51, 51, 8602, +51, 51, 8603, +51, 51, 8622, +51, 51, 8653, +51, 51, 8654, +51, 51, 8655, +51, 51, + 8708, +51, 51, 8713, +51, 51, 8716, +51, 51, 8740, +51, 51, 8742, +51, 51, 8769, +51, 51, 8772, +51, 51, 8775, +51, 51, + 8777, +51, 51, 8800, +51, 51, 8802, +51, 51, 8813, +51, 51, 8814, +51, 51, 8815, +51, 51, 8816, +51, 51, 8817, +51, 51, + 8820, +51, 51, 8821, +51, 51, 8824, +51, 51, 8825, +51, 51, 8832, +51, 51, 8833, +51, 51, 8836, +51, 51, 8837, +51, 51, + 8840, +51, 51, 8841, +51, 51, 8876, +51, 51, 8877, +51, 51, 8878, +51, 51, 8879, +51, 51, 8928, +51, 51, 8929, +51, 51, + 8930, +51, 51, 8931, +51, 51, 8938, +51, 51, 8939, +51, 51, 8940, +51, 51, 8941, +51, 51, 10972, +52, 52, 12364, +52, 52, + 12366, +52, 52, 12368, +52, 52, 12370, +52, 52, 12372, +52, 52, 12374, +52, 52, 12376, +52, 52, 12378, +52, 52, 12380, +52, 52, + 12382, +52, 52, 12384, +52, 52, 12386, +52, 52, 12389, +52, 52, 12391, +52, 52, 12393, +52, 53, 12400, 12401, +52, 53, + 12403, 12404, +52, 53, 12406, 12407, +52, 53, 12409, 12410, +52, 53, 12412, 12413, +52, 52, + 12436, +52, 52, 12446, +52, 52, 12460, +52, 52, 12462, +52, 52, 12464, +52, 52, 12466, +52, 52, 12468, +52, 52, 12470, +52, 52, + 12472, +52, 52, 12474, +52, 52, 12476, +52, 52, 12478, +52, 52, 12480, +52, 52, 12482, +52, 52, 12485, +52, 52, 12487, +52, 52, + 12489, +52, 53, 12496, 12497, +52, 53, 12499, 12500, +52, 53, 12502, 12503, +52, 53, 12505, + 12506, +52, 53, 12508, 12509, +52, 52, 12532, +52, 52, 12535, +52, 52, 12536, +52, 52, 12537, +52, 52, 12538, +52, 52, + 12542, +54, 55, 1, 4250, +54, 55, 1, 4252, +54, 55, 1, 4267, +56, 57, 1, 4398, +56, 57, 1, 4399, +58, 61, 1, 4939, 1, 4940, +62, 67, + 1, 5307, 1, 5308, 1, 5310, +68, 69, 1, 5562, +68, 69, 1, 5563, +70, 71, 1, 53598, +70, 71, 1, 53599, +72, 81, 1, 53600, + 1, 53601, 1, 53602, 1, 53603, 1, 53604, +70, 71, 1, 53691, +70, 71, 1, 53692, +72, 75, 1, 53693, 1, 53695, +72, 75, + 1, 53694, 1, 53696, +}; diff --git a/subversion/libsvn_subr/utf8proc/utf8proc_internal.h b/subversion/libsvn_subr/utf8proc/utf8proc_internal.h new file mode 100644 index 000000000000..27ea66119969 --- /dev/null +++ b/subversion/libsvn_subr/utf8proc/utf8proc_internal.h @@ -0,0 +1,708 @@ +/* + * Copyright (c) 2015 Steven G. Johnson, Jiahao Chen, Peter Colberg, Tony Kelman, Scott P. Jones, and other contributors. + * Copyright (c) 2009 Public Software Group e. V., Berlin, Germany + * + * 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. + */ + + +/** + * @mainpage + * + * utf8proc is a free/open-source (MIT/expat licensed) C library + * providing Unicode normalization, case-folding, and other operations + * for strings in the UTF-8 encoding, supporting Unicode version + * 8.0.0. See the utf8proc home page (http://julialang.org/utf8proc/) + * for downloads and other information, or the source code on github + * (https://github.com/JuliaLang/utf8proc). + * + * For the utf8proc API documentation, see: @ref utf8proc.h + * + * The features of utf8proc include: + * + * - Transformation of strings (@ref utf8proc_map) to: + * - decompose (@ref UTF8PROC_DECOMPOSE) or compose (@ref UTF8PROC_COMPOSE) Unicode combining characters (http://en.wikipedia.org/wiki/Combining_character) + * - canonicalize Unicode compatibility characters (@ref UTF8PROC_COMPAT) + * - strip "ignorable" (@ref UTF8PROC_IGNORE) characters, control characters (@ref UTF8PROC_STRIPCC), or combining characters such as accents (@ref UTF8PROC_STRIPMARK) + * - case-folding (@ref UTF8PROC_CASEFOLD) + * - Unicode normalization: @ref utf8proc_NFD, @ref utf8proc_NFC, @ref utf8proc_NFKD, @ref utf8proc_NFKC + * - Detecting grapheme boundaries (@ref utf8proc_grapheme_break and @ref UTF8PROC_CHARBOUND) + * - Character-width computation: @ref utf8proc_charwidth + * - Classification of characters by Unicode category: @ref utf8proc_category and @ref utf8proc_category_string + * - Encode (@ref utf8proc_encode_char) and decode (@ref utf8proc_iterate) Unicode codepoints to/from UTF-8. + */ + +/** @file */ + +#ifndef UTF8PROC_H +#define UTF8PROC_H + +/** @name API version + * + * The utf8proc API version MAJOR.MINOR.PATCH, following + * semantic-versioning rules (http://semver.org) based on API + * compatibility. + * + * This is also returned at runtime by @ref utf8proc_version; however, the + * runtime version may append a string like "-dev" to the version number + * for prerelease versions. + * + * @note The shared-library version number in the Makefile + * (and CMakeLists.txt, and MANIFEST) may be different, + * being based on ABI compatibility rather than API compatibility. + */ +/** @{ */ +/** The MAJOR version number (increased when backwards API compatibility is broken). */ +#define UTF8PROC_VERSION_MAJOR 2 +/** The MINOR version number (increased when new functionality is added in a backwards-compatible manner). */ +#define UTF8PROC_VERSION_MINOR 1 +/** The PATCH version (increased for fixes that do not change the API). */ +#define UTF8PROC_VERSION_PATCH 0 +/** @} */ + +#include +#include +#include +typedef char utf8proc_int8_t; +typedef unsigned char utf8proc_uint8_t; +typedef apr_int16_t utf8proc_int16_t; +typedef apr_uint16_t utf8proc_uint16_t; +typedef apr_int32_t utf8proc_int32_t; +typedef apr_uint32_t utf8proc_uint32_t; +#ifdef _MSC_VER +# ifdef _WIN64 +typedef apr_int64_t utf8proc_ssize_t; +typedef apr_uint64_t utf8proc_size_t; +# else +typedef apr_int32_t utf8proc_ssize_t; +typedef apr_uint32_t utf8proc_size_t; +# endif +#else +typedef apr_size_t utf8proc_size_t; +typedef apr_ssize_t utf8proc_ssize_t; +#endif +#ifdef __cplusplus +typedef bool utf8proc_bool; +#elif defined HAVE_STDBOOL_H +# include +typedef bool utf8proc_bool; +#else +/* emulate C99 bool */ +# ifndef __bool_true_false_are_defined +# define false 0 +# define true 1 +# define __bool_true_false_are_defined 1 +# endif +typedef apr_byte_t utf8proc_bool; +#endif +#include + + +/* + * Define UTF8PROC_INLINE and include utf8proc.c to embed a static + * version of utf8proc in your program or library without exporting + * any of its symbols. + */ +#ifdef UTF8PROC_INLINE +# define UTF8PROC_DATA static +# undef UTF8PROC_DATA_EXPORT +# define UTF8PROC_DLLEXPORT static +#else +# define UTF8PROC_DATA +# define UTF8PROC_DATA_EXPORT +# ifdef _WIN32 +# ifdef UTF8PROC_EXPORTS +# define UTF8PROC_DLLEXPORT __declspec(dllexport) +# else +# define UTF8PROC_DLLEXPORT __declspec(dllimport) +# endif +# elif __GNUC__ >= 4 +# define UTF8PROC_DLLEXPORT __attribute__ ((visibility("default"))) +# else +# define UTF8PROC_DLLEXPORT +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef SSIZE_MAX +#define SSIZE_MAX ((size_t)SIZE_MAX/2) +#endif + +#ifndef UINT16_MAX +# define UINT16_MAX 65535U +#endif + +/** + * Option flags used by several functions in the library. + */ +typedef enum { + /** The given UTF-8 input is NULL terminated. */ + UTF8PROC_NULLTERM = (1<<0), + /** Unicode Versioning Stability has to be respected. */ + UTF8PROC_STABLE = (1<<1), + /** Compatibility decomposition (i.e. formatting information is lost). */ + UTF8PROC_COMPAT = (1<<2), + /** Return a result with decomposed characters. */ + UTF8PROC_COMPOSE = (1<<3), + /** Return a result with decomposed characters. */ + UTF8PROC_DECOMPOSE = (1<<4), + /** Strip "default ignorable characters" such as SOFT-HYPHEN or ZERO-WIDTH-SPACE. */ + UTF8PROC_IGNORE = (1<<5), + /** Return an error, if the input contains unassigned codepoints. */ + UTF8PROC_REJECTNA = (1<<6), + /** + * Indicating that NLF-sequences (LF, CRLF, CR, NEL) are representing a + * line break, and should be converted to the codepoint for line + * separation (LS). + */ + UTF8PROC_NLF2LS = (1<<7), + /** + * Indicating that NLF-sequences are representing a paragraph break, and + * should be converted to the codepoint for paragraph separation + * (PS). + */ + UTF8PROC_NLF2PS = (1<<8), + /** Indicating that the meaning of NLF-sequences is unknown. */ + UTF8PROC_NLF2LF = (UTF8PROC_NLF2LS | UTF8PROC_NLF2PS), + /** Strips and/or convers control characters. + * + * NLF-sequences are transformed into space, except if one of the + * NLF2LS/PS/LF options is given. HorizontalTab (HT) and FormFeed (FF) + * are treated as a NLF-sequence in this case. All other control + * characters are simply removed. + */ + UTF8PROC_STRIPCC = (1<<9), + /** + * Performs unicode case folding, to be able to do a case-insensitive + * string comparison. + */ + UTF8PROC_CASEFOLD = (1<<10), + /** + * Inserts 0xFF bytes at the beginning of each sequence which is + * representing a single grapheme cluster (see UAX#29). + */ + UTF8PROC_CHARBOUND = (1<<11), + /** Lumps certain characters together. + * + * E.g. HYPHEN U+2010 and MINUS U+2212 to ASCII "-". See lump.md for details. + * + * If NLF2LF is set, this includes a transformation of paragraph and + * line separators to ASCII line-feed (LF). + */ + UTF8PROC_LUMP = (1<<12), + /** Strips all character markings. + * + * This includes non-spacing, spacing and enclosing (i.e. accents). + * @note This option works only with @ref UTF8PROC_COMPOSE or + * @ref UTF8PROC_DECOMPOSE + */ + UTF8PROC_STRIPMARK = (1<<13), +} utf8proc_option_t; + +/** @name Error codes + * Error codes being returned by almost all functions. + */ +/** @{ */ +/** Memory could not be allocated. */ +#define UTF8PROC_ERROR_NOMEM -1 +/** The given string is too long to be processed. */ +#define UTF8PROC_ERROR_OVERFLOW -2 +/** The given string is not a legal UTF-8 string. */ +#define UTF8PROC_ERROR_INVALIDUTF8 -3 +/** The @ref UTF8PROC_REJECTNA flag was set and an unassigned codepoint was found. */ +#define UTF8PROC_ERROR_NOTASSIGNED -4 +/** Invalid options have been used. */ +#define UTF8PROC_ERROR_INVALIDOPTS -5 +/** @} */ + +/* @name Types */ + +/** Holds the value of a property. */ +typedef utf8proc_int16_t utf8proc_propval_t; + +/** Struct containing information about a codepoint. */ +typedef struct utf8proc_property_struct { + /** + * Unicode category. + * @see utf8proc_category_t. + */ + utf8proc_propval_t category; + utf8proc_propval_t combining_class; + /** + * Bidirectional class. + * @see utf8proc_bidi_class_t. + */ + utf8proc_propval_t bidi_class; + /** + * @anchor Decomposition type. + * @see utf8proc_decomp_type_t. + */ + utf8proc_propval_t decomp_type; + utf8proc_uint16_t decomp_seqindex; + utf8proc_uint16_t casefold_seqindex; + utf8proc_uint16_t uppercase_seqindex; + utf8proc_uint16_t lowercase_seqindex; + utf8proc_uint16_t titlecase_seqindex; + utf8proc_uint16_t comb_index; + unsigned bidi_mirrored:1; + unsigned comp_exclusion:1; + /** + * Can this codepoint be ignored? + * + * Used by @ref utf8proc_decompose_char when @ref UTF8PROC_IGNORE is + * passed as an option. + */ + unsigned ignorable:1; + unsigned control_boundary:1; + /** The width of the codepoint. */ + unsigned charwidth:2; + unsigned pad:2; + /** + * Boundclass. + * @see utf8proc_boundclass_t. + */ + unsigned boundclass:8; +} utf8proc_property_t; + +/** Unicode categories. */ +typedef enum { + UTF8PROC_CATEGORY_CN = 0, /**< Other, not assigned */ + UTF8PROC_CATEGORY_LU = 1, /**< Letter, uppercase */ + UTF8PROC_CATEGORY_LL = 2, /**< Letter, lowercase */ + UTF8PROC_CATEGORY_LT = 3, /**< Letter, titlecase */ + UTF8PROC_CATEGORY_LM = 4, /**< Letter, modifier */ + UTF8PROC_CATEGORY_LO = 5, /**< Letter, other */ + UTF8PROC_CATEGORY_MN = 6, /**< Mark, nonspacing */ + UTF8PROC_CATEGORY_MC = 7, /**< Mark, spacing combining */ + UTF8PROC_CATEGORY_ME = 8, /**< Mark, enclosing */ + UTF8PROC_CATEGORY_ND = 9, /**< Number, decimal digit */ + UTF8PROC_CATEGORY_NL = 10, /**< Number, letter */ + UTF8PROC_CATEGORY_NO = 11, /**< Number, other */ + UTF8PROC_CATEGORY_PC = 12, /**< Punctuation, connector */ + UTF8PROC_CATEGORY_PD = 13, /**< Punctuation, dash */ + UTF8PROC_CATEGORY_PS = 14, /**< Punctuation, open */ + UTF8PROC_CATEGORY_PE = 15, /**< Punctuation, close */ + UTF8PROC_CATEGORY_PI = 16, /**< Punctuation, initial quote */ + UTF8PROC_CATEGORY_PF = 17, /**< Punctuation, final quote */ + UTF8PROC_CATEGORY_PO = 18, /**< Punctuation, other */ + UTF8PROC_CATEGORY_SM = 19, /**< Symbol, math */ + UTF8PROC_CATEGORY_SC = 20, /**< Symbol, currency */ + UTF8PROC_CATEGORY_SK = 21, /**< Symbol, modifier */ + UTF8PROC_CATEGORY_SO = 22, /**< Symbol, other */ + UTF8PROC_CATEGORY_ZS = 23, /**< Separator, space */ + UTF8PROC_CATEGORY_ZL = 24, /**< Separator, line */ + UTF8PROC_CATEGORY_ZP = 25, /**< Separator, paragraph */ + UTF8PROC_CATEGORY_CC = 26, /**< Other, control */ + UTF8PROC_CATEGORY_CF = 27, /**< Other, format */ + UTF8PROC_CATEGORY_CS = 28, /**< Other, surrogate */ + UTF8PROC_CATEGORY_CO = 29, /**< Other, private use */ +} utf8proc_category_t; + +/** Bidirectional character classes. */ +typedef enum { + UTF8PROC_BIDI_CLASS_L = 1, /**< Left-to-Right */ + UTF8PROC_BIDI_CLASS_LRE = 2, /**< Left-to-Right Embedding */ + UTF8PROC_BIDI_CLASS_LRO = 3, /**< Left-to-Right Override */ + UTF8PROC_BIDI_CLASS_R = 4, /**< Right-to-Left */ + UTF8PROC_BIDI_CLASS_AL = 5, /**< Right-to-Left Arabic */ + UTF8PROC_BIDI_CLASS_RLE = 6, /**< Right-to-Left Embedding */ + UTF8PROC_BIDI_CLASS_RLO = 7, /**< Right-to-Left Override */ + UTF8PROC_BIDI_CLASS_PDF = 8, /**< Pop Directional Format */ + UTF8PROC_BIDI_CLASS_EN = 9, /**< European Number */ + UTF8PROC_BIDI_CLASS_ES = 10, /**< European Separator */ + UTF8PROC_BIDI_CLASS_ET = 11, /**< European Number Terminator */ + UTF8PROC_BIDI_CLASS_AN = 12, /**< Arabic Number */ + UTF8PROC_BIDI_CLASS_CS = 13, /**< Common Number Separator */ + UTF8PROC_BIDI_CLASS_NSM = 14, /**< Nonspacing Mark */ + UTF8PROC_BIDI_CLASS_BN = 15, /**< Boundary Neutral */ + UTF8PROC_BIDI_CLASS_B = 16, /**< Paragraph Separator */ + UTF8PROC_BIDI_CLASS_S = 17, /**< Segment Separator */ + UTF8PROC_BIDI_CLASS_WS = 18, /**< Whitespace */ + UTF8PROC_BIDI_CLASS_ON = 19, /**< Other Neutrals */ + UTF8PROC_BIDI_CLASS_LRI = 20, /**< Left-to-Right Isolate */ + UTF8PROC_BIDI_CLASS_RLI = 21, /**< Right-to-Left Isolate */ + UTF8PROC_BIDI_CLASS_FSI = 22, /**< First Strong Isolate */ + UTF8PROC_BIDI_CLASS_PDI = 23, /**< Pop Directional Isolate */ +} utf8proc_bidi_class_t; + +/** Decomposition type. */ +typedef enum { + UTF8PROC_DECOMP_TYPE_FONT = 1, /**< Font */ + UTF8PROC_DECOMP_TYPE_NOBREAK = 2, /**< Nobreak */ + UTF8PROC_DECOMP_TYPE_INITIAL = 3, /**< Initial */ + UTF8PROC_DECOMP_TYPE_MEDIAL = 4, /**< Medial */ + UTF8PROC_DECOMP_TYPE_FINAL = 5, /**< Final */ + UTF8PROC_DECOMP_TYPE_ISOLATED = 6, /**< Isolated */ + UTF8PROC_DECOMP_TYPE_CIRCLE = 7, /**< Circle */ + UTF8PROC_DECOMP_TYPE_SUPER = 8, /**< Super */ + UTF8PROC_DECOMP_TYPE_SUB = 9, /**< Sub */ + UTF8PROC_DECOMP_TYPE_VERTICAL = 10, /**< Vertical */ + UTF8PROC_DECOMP_TYPE_WIDE = 11, /**< Wide */ + UTF8PROC_DECOMP_TYPE_NARROW = 12, /**< Narrow */ + UTF8PROC_DECOMP_TYPE_SMALL = 13, /**< Small */ + UTF8PROC_DECOMP_TYPE_SQUARE = 14, /**< Square */ + UTF8PROC_DECOMP_TYPE_FRACTION = 15, /**< Fraction */ + UTF8PROC_DECOMP_TYPE_COMPAT = 16, /**< Compat */ +} utf8proc_decomp_type_t; + +/** Boundclass property. (TR29) */ +typedef enum { + UTF8PROC_BOUNDCLASS_START = 0, /**< Start */ + UTF8PROC_BOUNDCLASS_OTHER = 1, /**< Other */ + UTF8PROC_BOUNDCLASS_CR = 2, /**< Cr */ + UTF8PROC_BOUNDCLASS_LF = 3, /**< Lf */ + UTF8PROC_BOUNDCLASS_CONTROL = 4, /**< Control */ + UTF8PROC_BOUNDCLASS_EXTEND = 5, /**< Extend */ + UTF8PROC_BOUNDCLASS_L = 6, /**< L */ + UTF8PROC_BOUNDCLASS_V = 7, /**< V */ + UTF8PROC_BOUNDCLASS_T = 8, /**< T */ + UTF8PROC_BOUNDCLASS_LV = 9, /**< Lv */ + UTF8PROC_BOUNDCLASS_LVT = 10, /**< Lvt */ + UTF8PROC_BOUNDCLASS_REGIONAL_INDICATOR = 11, /**< Regional indicator */ + UTF8PROC_BOUNDCLASS_SPACINGMARK = 12, /**< Spacingmark */ + UTF8PROC_BOUNDCLASS_PREPEND = 13, /**< Prepend */ + UTF8PROC_BOUNDCLASS_ZWJ = 14, /**< Zero Width Joiner */ + UTF8PROC_BOUNDCLASS_E_BASE = 15, /**< Emoji Base */ + UTF8PROC_BOUNDCLASS_E_MODIFIER = 16, /**< Emoji Modifier */ + UTF8PROC_BOUNDCLASS_GLUE_AFTER_ZWJ = 17, /**< Glue_After_ZWJ */ + UTF8PROC_BOUNDCLASS_E_BASE_GAZ = 18, /**< E_BASE + GLUE_AFTER_ZJW */ +} utf8proc_boundclass_t; + +/** + * Function pointer type passed to @ref utf8proc_map_custom and + * @ref utf8proc_decompose_custom, which is used to specify a user-defined + * mapping of codepoints to be applied in conjunction with other mappings. + */ +typedef utf8proc_int32_t (*utf8proc_custom_func)(utf8proc_int32_t codepoint, void *data); + +#if defined(DOXYGEN) || defined(UTF8PROC_DATA_EXPORT) +/** + * Array containing the byte lengths of a UTF-8 encoded codepoint based + * on the first byte. + */ +UTF8PROC_DLLEXPORT extern const utf8proc_int8_t utf8proc_utf8class[256]; +#endif + +/** + * Returns the utf8proc API version as a string MAJOR.MINOR.PATCH + * (http://semver.org format), possibly with a "-dev" suffix for + * development versions. + */ +UTF8PROC_DLLEXPORT const char *utf8proc_version(void); + +/** + * Returns an informative error string for the given utf8proc error code + * (e.g. the error codes returned by @ref utf8proc_map). + */ +UTF8PROC_DLLEXPORT const char *utf8proc_errmsg(utf8proc_ssize_t errcode); + +/** + * Reads a single codepoint from the UTF-8 sequence being pointed to by `str`. + * The maximum number of bytes read is `strlen`, unless `strlen` is + * negative (in which case up to 4 bytes are read). + * + * If a valid codepoint could be read, it is stored in the variable + * pointed to by `codepoint_ref`, otherwise that variable will be set to -1. + * In case of success, the number of bytes read is returned; otherwise, a + * negative error code is returned. + */ +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_iterate(const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, utf8proc_int32_t *codepoint_ref); + +/** + * Check if a codepoint is valid (regardless of whether it has been + * assigned a value by the current Unicode standard). + * + * @return 1 if the given `codepoint` is valid and otherwise return 0. + */ +UTF8PROC_DLLEXPORT utf8proc_bool utf8proc_codepoint_valid(utf8proc_int32_t codepoint); + +/** + * Encodes the codepoint as an UTF-8 string in the byte array pointed + * to by `dst`. This array must be at least 4 bytes long. + * + * In case of success the number of bytes written is returned, and + * otherwise 0 is returned. + * + * This function does not check whether `codepoint` is valid Unicode. + */ +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_encode_char(utf8proc_int32_t codepoint, utf8proc_uint8_t *dst); + +/** + * Look up the properties for a given codepoint. + * + * @param codepoint The Unicode codepoint. + * + * @returns + * A pointer to a (constant) struct containing information about + * the codepoint. + * @par + * If the codepoint is unassigned or invalid, a pointer to a special struct is + * returned in which `category` is 0 (@ref UTF8PROC_CATEGORY_CN). + */ +UTF8PROC_DLLEXPORT const utf8proc_property_t *utf8proc_get_property(utf8proc_int32_t codepoint); + +/** Decompose a codepoint into an array of codepoints. + * + * @param codepoint the codepoint. + * @param dst the destination buffer. + * @param bufsize the size of the destination buffer. + * @param options one or more of the following flags: + * - @ref UTF8PROC_REJECTNA - return an error `codepoint` is unassigned + * - @ref UTF8PROC_IGNORE - strip "default ignorable" codepoints + * - @ref UTF8PROC_CASEFOLD - apply Unicode casefolding + * - @ref UTF8PROC_COMPAT - replace certain codepoints with their + * compatibility decomposition + * - @ref UTF8PROC_CHARBOUND - insert 0xFF bytes before each grapheme cluster + * - @ref UTF8PROC_LUMP - lump certain different codepoints together + * - @ref UTF8PROC_STRIPMARK - remove all character marks + * @param last_boundclass + * Pointer to an integer variable containing + * the previous codepoint's boundary class if the @ref UTF8PROC_CHARBOUND + * option is used. Otherwise, this parameter is ignored. + * + * @return + * In case of success, the number of codepoints written is returned; in case + * of an error, a negative error code is returned (@ref utf8proc_errmsg). + * @par + * If the number of written codepoints would be bigger than `bufsize`, the + * required buffer size is returned, while the buffer will be overwritten with + * undefined data. + */ +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_char( + utf8proc_int32_t codepoint, utf8proc_int32_t *dst, utf8proc_ssize_t bufsize, + utf8proc_option_t options, int *last_boundclass +); + +/** + * The same as @ref utf8proc_decompose_char, but acts on a whole UTF-8 + * string and orders the decomposed sequences correctly. + * + * If the @ref UTF8PROC_NULLTERM flag in `options` is set, processing + * will be stopped, when a NULL byte is encounted, otherwise `strlen` + * bytes are processed. The result (in the form of 32-bit unicode + * codepoints) is written into the buffer being pointed to by + * `buffer` (which must contain at least `bufsize` entries). In case of + * success, the number of codepoints written is returned; in case of an + * error, a negative error code is returned (@ref utf8proc_errmsg). + * See @ref utf8proc_decompose_custom to supply additional transformations. + * + * If the number of written codepoints would be bigger than `bufsize`, the + * required buffer size is returned, while the buffer will be overwritten with + * undefined data. + */ +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose( + const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, + utf8proc_int32_t *buffer, utf8proc_ssize_t bufsize, utf8proc_option_t options +); + +/** + * The same as @ref utf8proc_decompose, but also takes a `custom_func` mapping function + * that is called on each codepoint in `str` before any other transformations + * (along with a `custom_data` pointer that is passed through to `custom_func`). + * The `custom_func` argument is ignored if it is `NULL`. See also @ref utf8proc_map_custom. + */ +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_decompose_custom( + const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, + utf8proc_int32_t *buffer, utf8proc_ssize_t bufsize, utf8proc_option_t options, + utf8proc_custom_func custom_func, void *custom_data +); + +/** + * Normalizes the sequence of `length` codepoints pointed to by `buffer` + * in-place (i.e., the result is also stored in `buffer`). + * + * @param buffer the (native-endian UTF-32) unicode codepoints to re-encode. + * @param length the length (in codepoints) of the buffer. + * @param options a bitwise or (`|`) of one or more of the following flags: + * - @ref UTF8PROC_NLF2LS - convert LF, CRLF, CR and NEL into LS + * - @ref UTF8PROC_NLF2PS - convert LF, CRLF, CR and NEL into PS + * - @ref UTF8PROC_NLF2LF - convert LF, CRLF, CR and NEL into LF + * - @ref UTF8PROC_STRIPCC - strip or convert all non-affected control characters + * - @ref UTF8PROC_COMPOSE - try to combine decomposed codepoints into composite + * codepoints + * - @ref UTF8PROC_STABLE - prohibit combining characters that would violate + * the unicode versioning stability + * + * @return + * In case of success, the length (in codepoints) of the normalized UTF-32 string is + * returned; otherwise, a negative error code is returned (@ref utf8proc_errmsg). + * + * @warning The entries of the array pointed to by `str` have to be in the + * range `0x0000` to `0x10FFFF`. Otherwise, the program might crash! + */ +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_normalize_utf32(utf8proc_int32_t *buffer, utf8proc_ssize_t length, utf8proc_option_t options); + +/** + * Reencodes the sequence of `length` codepoints pointed to by `buffer` + * UTF-8 data in-place (i.e., the result is also stored in `buffer`). + * Can optionally normalize the UTF-32 sequence prior to UTF-8 conversion. + * + * @param buffer the (native-endian UTF-32) unicode codepoints to re-encode. + * @param length the length (in codepoints) of the buffer. + * @param options a bitwise or (`|`) of one or more of the following flags: + * - @ref UTF8PROC_NLF2LS - convert LF, CRLF, CR and NEL into LS + * - @ref UTF8PROC_NLF2PS - convert LF, CRLF, CR and NEL into PS + * - @ref UTF8PROC_NLF2LF - convert LF, CRLF, CR and NEL into LF + * - @ref UTF8PROC_STRIPCC - strip or convert all non-affected control characters + * - @ref UTF8PROC_COMPOSE - try to combine decomposed codepoints into composite + * codepoints + * - @ref UTF8PROC_STABLE - prohibit combining characters that would violate + * the unicode versioning stability + * - @ref UTF8PROC_CHARBOUND - insert 0xFF bytes before each grapheme cluster + * + * @return + * In case of success, the length (in bytes) of the resulting nul-terminated + * UTF-8 string is returned; otherwise, a negative error code is returned + * (@ref utf8proc_errmsg). + * + * @warning The amount of free space pointed to by `buffer` must + * exceed the amount of the input data by one byte, and the + * entries of the array pointed to by `str` have to be in the + * range `0x0000` to `0x10FFFF`. Otherwise, the program might crash! + */ +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_reencode(utf8proc_int32_t *buffer, utf8proc_ssize_t length, utf8proc_option_t options); + +/** + * Given a pair of consecutive codepoints, return whether a grapheme break is + * permitted between them (as defined by the extended grapheme clusters in UAX#29). + * + * @param state Beginning with Version 29 (Unicode 9.0.0), this algorithm requires + * state to break graphemes. This state can be passed in as a pointer + * in the `state` argument and should initially be set to 0. If the + * state is not passed in (i.e. a null pointer is passed), UAX#29 rules + * GB10/12/13 which require this state will not be applied, essentially + * matching the rules in Unicode 8.0.0. + * + * @warning If the state parameter is used, `utf8proc_grapheme_break_stateful` must + * be called IN ORDER on ALL potential breaks in a string. + */ +UTF8PROC_DLLEXPORT utf8proc_bool utf8proc_grapheme_break_stateful( + utf8proc_int32_t codepoint1, utf8proc_int32_t codepoint2, utf8proc_int32_t *state); + +/** + * Same as @ref utf8proc_grapheme_break_stateful, except without support for the + * Unicode 9 additions to the algorithm. Supported for legacy reasons. + */ +UTF8PROC_DLLEXPORT utf8proc_bool utf8proc_grapheme_break( + utf8proc_int32_t codepoint1, utf8proc_int32_t codepoint2); + + +/** + * Given a codepoint `c`, return the codepoint of the corresponding + * lower-case character, if any; otherwise (if there is no lower-case + * variant, or if `c` is not a valid codepoint) return `c`. + */ +UTF8PROC_DLLEXPORT utf8proc_int32_t utf8proc_tolower(utf8proc_int32_t c); + +/** + * Given a codepoint `c`, return the codepoint of the corresponding + * upper-case character, if any; otherwise (if there is no upper-case + * variant, or if `c` is not a valid codepoint) return `c`. + */ +UTF8PROC_DLLEXPORT utf8proc_int32_t utf8proc_toupper(utf8proc_int32_t c); + +/** + * Given a codepoint `c`, return the codepoint of the corresponding + * title-case character, if any; otherwise (if there is no title-case + * variant, or if `c` is not a valid codepoint) return `c`. + */ +UTF8PROC_DLLEXPORT utf8proc_int32_t utf8proc_totitle(utf8proc_int32_t c); + +/** + * Given a codepoint, return a character width analogous to `wcwidth(codepoint)`, + * except that a width of 0 is returned for non-printable codepoints + * instead of -1 as in `wcwidth`. + * + * @note + * If you want to check for particular types of non-printable characters, + * (analogous to `isprint` or `iscntrl`), use @ref utf8proc_category. */ +UTF8PROC_DLLEXPORT int utf8proc_charwidth(utf8proc_int32_t codepoint); + +/** + * Return the Unicode category for the codepoint (one of the + * @ref utf8proc_category_t constants.) + */ +UTF8PROC_DLLEXPORT utf8proc_category_t utf8proc_category(utf8proc_int32_t codepoint); + +/** + * Return the two-letter (nul-terminated) Unicode category string for + * the codepoint (e.g. `"Lu"` or `"Co"`). + */ +UTF8PROC_DLLEXPORT const char *utf8proc_category_string(utf8proc_int32_t codepoint); + +/** + * Maps the given UTF-8 string pointed to by `str` to a new UTF-8 + * string, allocated dynamically by `malloc` and returned via `dstptr`. + * + * If the @ref UTF8PROC_NULLTERM flag in the `options` field is set, + * the length is determined by a NULL terminator, otherwise the + * parameter `strlen` is evaluated to determine the string length, but + * in any case the result will be NULL terminated (though it might + * contain NULL characters with the string if `str` contained NULL + * characters). Other flags in the `options` field are passed to the + * functions defined above, and regarded as described. See also + * @ref utfproc_map_custom to supply a custom codepoint transformation. + * + * In case of success the length of the new string is returned, + * otherwise a negative error code is returned. + * + * @note The memory of the new UTF-8 string will have been allocated + * with `malloc`, and should therefore be deallocated with `free`. + */ +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_map( + const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, utf8proc_uint8_t **dstptr, utf8proc_option_t options +); + +/** + * Like @ref utf8proc_map, but also takes a `custom_func` mapping function + * that is called on each codepoint in `str` before any other transformations + * (along with a `custom_data` pointer that is passed through to `custom_func`). + * The `custom_func` argument is ignored if it is `NULL`. + */ +UTF8PROC_DLLEXPORT utf8proc_ssize_t utf8proc_map_custom( + const utf8proc_uint8_t *str, utf8proc_ssize_t strlen, utf8proc_uint8_t **dstptr, utf8proc_option_t options, + utf8proc_custom_func custom_func, void *custom_data +); + +/** @name Unicode normalization + * + * Returns a pointer to newly allocated memory of a NFD, NFC, NFKD or NFKC + * normalized version of the null-terminated string `str`. These + * are shortcuts to calling @ref utf8proc_map with @ref UTF8PROC_NULLTERM + * combined with @ref UTF8PROC_STABLE and flags indicating the normalization. + */ +/** @{ */ +/** NFD normalization (@ref UTF8PROC_DECOMPOSE). */ +UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFD(const utf8proc_uint8_t *str); +/** NFC normalization (@ref UTF8PROC_COMPOSE). */ +UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFC(const utf8proc_uint8_t *str); +/** NFKD normalization (@ref UTF8PROC_DECOMPOSE and @ref UTF8PROC_COMPAT). */ +UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKD(const utf8proc_uint8_t *str); +/** NFKC normalization (@ref UTF8PROC_COMPOSE and @ref UTF8PROC_COMPAT). */ +UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKC(const utf8proc_uint8_t *str); +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/subversion/libsvn_subr/version.c b/subversion/libsvn_subr/version.c index 0210fd8836e5..1aabb400800d 100644 --- a/subversion/libsvn_subr/version.c +++ b/subversion/libsvn_subr/version.c @@ -40,11 +40,13 @@ svn_subr_version(void) svn_boolean_t svn_ver_compatible(const svn_version_t *my_version, const svn_version_t *lib_version) { - /* With normal development builds the matching rules are strict, to - avoid inadvertantly using the wrong libraries. For backward - compatibility testing use --disable-full-version-match to - configure 1.7 and then the libraries that get built can be used - to replace those in 1.6 or earlier builds. */ + /* With normal development builds the matching rules are stricter + that for release builds, to avoid inadvertantly using the wrong + libraries. For backward compatibility testing of development + builds one can use --disable-full-version-match to cause a + development build to use the release build rules. This allows + the libraries from the newer development build to be used by an + older development build. */ #ifndef SVN_DISABLE_FULL_VERSION_MATCH if (lib_version->tag[0] != '\0') @@ -83,6 +85,11 @@ svn_ver_check_list2(const svn_version_t *my_version, svn_error_t *err = SVN_NO_ERROR; int i; +#ifdef SVN_DISABLE_FULL_VERSION_MATCH + /* Force more relaxed check for --disable-full-version-match. */ + comparator = svn_ver_compatible; +#endif + for (i = 0; checklist[i].label != NULL; ++i) { const svn_version_t *lib_version = checklist[i].version_query(); @@ -136,7 +143,7 @@ svn_version_extended(svn_boolean_t verbose, info->build_time = __TIME__; info->build_host = SVN_BUILD_HOST; info->copyright = apr_pstrdup - (pool, _("Copyright (C) 2017 The Apache Software Foundation.\n" + (pool, _("Copyright (C) 2018 The Apache Software Foundation.\n" "This software consists of contributions made by many people;\n" "see the NOTICE file for more information.\n" "Subversion is open source software, see " @@ -264,7 +271,7 @@ svn_version__parse_version_string(svn_version_t **version_p, svn_boolean_t -svn_version__at_least(svn_version_t *version, +svn_version__at_least(const svn_version_t *version, int major, int minor, int patch) diff --git a/subversion/libsvn_subr/win32_crashrpt.c b/subversion/libsvn_subr/win32_crashrpt.c index 1349d84c9fe2..bed2d6eaa466 100644 --- a/subversion/libsvn_subr/win32_crashrpt.c +++ b/subversion/libsvn_subr/win32_crashrpt.c @@ -43,7 +43,7 @@ typedef int win32_crashrpt__dummy; #include "win32_crashrpt_dll.h" /*** Global variables ***/ -HANDLE dbghelp_dll = INVALID_HANDLE_VALUE; +static HANDLE dbghelp_dll = INVALID_HANDLE_VALUE; /* Email address where the crash reports should be sent too. */ #define CRASHREPORT_EMAIL "users@subversion.apache.org" @@ -84,32 +84,33 @@ convert_wbcs_to_ansi(const wchar_t *str) static const char * exception_string(int exception) { -#define EXCEPTION(x) case EXCEPTION_##x: return (#x); +#define EXCEPTION(x) case x: return (#x); switch (exception) { - EXCEPTION(ACCESS_VIOLATION) - EXCEPTION(DATATYPE_MISALIGNMENT) - EXCEPTION(BREAKPOINT) - EXCEPTION(SINGLE_STEP) - EXCEPTION(ARRAY_BOUNDS_EXCEEDED) - EXCEPTION(FLT_DENORMAL_OPERAND) - EXCEPTION(FLT_DIVIDE_BY_ZERO) - EXCEPTION(FLT_INEXACT_RESULT) - EXCEPTION(FLT_INVALID_OPERATION) - EXCEPTION(FLT_OVERFLOW) - EXCEPTION(FLT_STACK_CHECK) - EXCEPTION(FLT_UNDERFLOW) - EXCEPTION(INT_DIVIDE_BY_ZERO) - EXCEPTION(INT_OVERFLOW) - EXCEPTION(PRIV_INSTRUCTION) - EXCEPTION(IN_PAGE_ERROR) - EXCEPTION(ILLEGAL_INSTRUCTION) - EXCEPTION(NONCONTINUABLE_EXCEPTION) - EXCEPTION(STACK_OVERFLOW) - EXCEPTION(INVALID_DISPOSITION) - EXCEPTION(GUARD_PAGE) - EXCEPTION(INVALID_HANDLE) + EXCEPTION(EXCEPTION_ACCESS_VIOLATION) + EXCEPTION(EXCEPTION_DATATYPE_MISALIGNMENT) + EXCEPTION(EXCEPTION_BREAKPOINT) + EXCEPTION(EXCEPTION_SINGLE_STEP) + EXCEPTION(EXCEPTION_ARRAY_BOUNDS_EXCEEDED) + EXCEPTION(EXCEPTION_FLT_DENORMAL_OPERAND) + EXCEPTION(EXCEPTION_FLT_DIVIDE_BY_ZERO) + EXCEPTION(EXCEPTION_FLT_INEXACT_RESULT) + EXCEPTION(EXCEPTION_FLT_INVALID_OPERATION) + EXCEPTION(EXCEPTION_FLT_OVERFLOW) + EXCEPTION(EXCEPTION_FLT_STACK_CHECK) + EXCEPTION(EXCEPTION_FLT_UNDERFLOW) + EXCEPTION(EXCEPTION_INT_DIVIDE_BY_ZERO) + EXCEPTION(EXCEPTION_INT_OVERFLOW) + EXCEPTION(EXCEPTION_PRIV_INSTRUCTION) + EXCEPTION(EXCEPTION_IN_PAGE_ERROR) + EXCEPTION(EXCEPTION_ILLEGAL_INSTRUCTION) + EXCEPTION(EXCEPTION_NONCONTINUABLE_EXCEPTION) + EXCEPTION(EXCEPTION_STACK_OVERFLOW) + EXCEPTION(EXCEPTION_INVALID_DISPOSITION) + EXCEPTION(EXCEPTION_GUARD_PAGE) + EXCEPTION(EXCEPTION_INVALID_HANDLE) + EXCEPTION(STATUS_NO_MEMORY) default: return "UNKNOWN_ERROR"; @@ -379,7 +380,7 @@ write_value(FILE *log_file, DWORD64 mod_base, DWORD type, void *value_addr) } break; case 12: /* SymTagEnum */ - fprintf(log_file, "%d", *(DWORD_PTR *)value_addr); + fprintf(log_file, "%Id", *(DWORD_PTR *)value_addr); break; case 13: /* SymTagFunctionType */ fprintf(log_file, FORMAT_PTR, *(DWORD_PTR *)value_addr); @@ -598,20 +599,7 @@ write_stacktrace(CONTEXT *context, FILE *log_file) static BOOL is_debugger_present() { - HANDLE kernel32_dll = LoadLibrary("kernel32.dll"); - BOOL result; - - ISDEBUGGERPRESENT IsDebuggerPresent_ = - (ISDEBUGGERPRESENT)GetProcAddress(kernel32_dll, "IsDebuggerPresent"); - - if (IsDebuggerPresent_ && IsDebuggerPresent_()) - result = TRUE; - else - result = FALSE; - - FreeLibrary(kernel32_dll); - - return result; + return IsDebuggerPresent(); } /* Load the dbghelp.dll file, try to find a version that matches our @@ -620,7 +608,7 @@ static BOOL load_dbghelp_dll() { dbghelp_dll = LoadLibrary(DBGHELP_DLL); - if (dbghelp_dll != INVALID_HANDLE_VALUE) + if (dbghelp_dll != NULL) { DWORD opts; @@ -807,4 +795,11 @@ svn__unhandled_exception_filter(PEXCEPTION_POINTERS ptrs) return EXCEPTION_EXECUTE_HANDLER; } #endif /* SVN_USE_WIN32_CRASHHANDLER */ +#else /* !WIN32 */ + +/* Silence OSX ranlib warnings about object files with no symbols. */ +#include +extern const apr_uint32_t svn__fake__win32_crashrpt; +const apr_uint32_t svn__fake__win32_crashrpt = 0xdeadbeef; + #endif /* WIN32 */ diff --git a/subversion/libsvn_subr/win32_crashrpt_dll.h b/subversion/libsvn_subr/win32_crashrpt_dll.h index 18a4fc978823..ff6e26cda9b0 100644 --- a/subversion/libsvn_subr/win32_crashrpt_dll.h +++ b/subversion/libsvn_subr/win32_crashrpt_dll.h @@ -69,9 +69,6 @@ typedef PVOID (WINAPI * SYMFUNCTIONTABLEACCESS64)(HANDLE hProcess, DWORD64 AddrB typedef DWORD64 (WINAPI * SYMGETMODULEBASE64)(HANDLE hProcess, DWORD64 dwAddr); -/* public functions in kernel32.dll */ -typedef BOOL (WINAPI * ISDEBUGGERPRESENT)(VOID); - /* function pointers */ MINIDUMPWRITEDUMP MiniDumpWriteDump_; SYMINITIALIZE SymInitialize_; diff --git a/subversion/libsvn_subr/win32_crypto.c b/subversion/libsvn_subr/win32_crypto.c index 74bda1c68fb5..0986e5a5076b 100644 --- a/subversion/libsvn_subr/win32_crypto.c +++ b/subversion/libsvn_subr/win32_crypto.c @@ -512,4 +512,11 @@ svn_auth__get_windows_ssl_server_authority_provider( } +#else /* !WIN32 */ + +/* Silence OSX ranlib warnings about object files with no symbols. */ +#include +extern const apr_uint32_t svn__fake__win32_crypto; +const apr_uint32_t svn__fake__win32_crypto = 0xdeadbeef; + #endif /* WIN32 */ diff --git a/subversion/libsvn_subr/win32_xlate.c b/subversion/libsvn_subr/win32_xlate.c index d95d62ea07ca..2f508c930af6 100644 --- a/subversion/libsvn_subr/win32_xlate.c +++ b/subversion/libsvn_subr/win32_xlate.c @@ -248,4 +248,11 @@ svn_subr__win32_xlate_to_stringbuf(svn_subr__win32_xlate_t *handle, return APR_SUCCESS; } +#else /* !WIN32 */ + +/* Silence OSX ranlib warnings about object files with no symbols. */ +#include +extern const apr_uint32_t svn__fake__win32_xlate; +const apr_uint32_t svn__fake__win32_xlate = 0xdeadbeef; + #endif /* WIN32 */ diff --git a/subversion/libsvn_subr/x509info.c b/subversion/libsvn_subr/x509info.c index 351459629324..9cd437249118 100644 --- a/subversion/libsvn_subr/x509info.c +++ b/subversion/libsvn_subr/x509info.c @@ -41,8 +41,7 @@ svn_x509_name_attr_dup(const svn_x509_name_attr_t *attr, { svn_x509_name_attr_t *result = apr_palloc(result_pool, sizeof(*result)); result->oid_len = attr->oid_len; - result->oid = apr_palloc(result_pool, result->oid_len); - memcpy(result->oid, attr->oid, result->oid_len); + result->oid = apr_pmemdup(result_pool, attr->oid, attr->oid_len); result->utf8_value = apr_pstrdup(result_pool, attr->utf8_value); return result; @@ -124,7 +123,7 @@ svn_x509_certinfo_dup(const svn_x509_certinfo_t *certinfo, typedef struct asn1_oid { const unsigned char *oid; - const ptrdiff_t oid_len; + const apr_size_t oid_len; const char *short_label; const char *long_label; } asn1_oid; @@ -312,7 +311,7 @@ svn_x509_certinfo_get_valid_from(const svn_x509_certinfo_t *certinfo) return certinfo->valid_from; } -const apr_time_t +apr_time_t svn_x509_certinfo_get_valid_to(const svn_x509_certinfo_t *certinfo) { return certinfo->valid_to; diff --git a/subversion/libsvn_subr/x509parse.c b/subversion/libsvn_subr/x509parse.c index 32af4a7bf302..a121575c4378 100644 --- a/subversion/libsvn_subr/x509parse.c +++ b/subversion/libsvn_subr/x509parse.c @@ -262,13 +262,34 @@ x509_get_alg(const unsigned char **p, const unsigned char *end, x509_buf * alg) if (*p == end) return SVN_NO_ERROR; + + /* The OID encoding of 1.2.840.113549.1.1.10 (id-RSASSA-PSS) */ +#define OID_RSASSA_PSS "\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0a" - /* - * assume the algorithm parameters must be NULL - */ - err = asn1_get_tag(p, end, &len, ASN1_NULL); - if (err) - return svn_error_create(SVN_ERR_X509_CERT_INVALID_ALG, err, NULL); + if (equal(alg->p, alg->len, OID_RSASSA_PSS, sizeof(OID_RSASSA_PSS) - 1)) + { + /* Skip over algorithm parameters for id-RSASSA-PSS (RFC 8017) + * + * RSASSA-PSS-params ::= SEQUENCE { + * hashAlgorithm [0] HashAlgorithm DEFAULT sha1, + * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1, + * saltLength [2] INTEGER DEFAULT 20, + * trailerField [3] TrailerField DEFAULT trailerFieldBC + * } + */ + err = asn1_get_tag(p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE); + if (err) + return svn_error_create(SVN_ERR_X509_CERT_INVALID_ALG, err, NULL); + + *p += len; + } + else + { + /* Algorithm parameters must be NULL for other algorithms */ + err = asn1_get_tag(p, end, &len, ASN1_NULL); + if (err) + return svn_error_create(SVN_ERR_X509_CERT_INVALID_ALG, err, NULL); + } if (*p != end) { @@ -362,7 +383,7 @@ x509_get_name(const unsigned char **p, const unsigned char *name_end, x509_name *cur = NULL; err = asn1_get_tag(p, name_end, &len, ASN1_CONSTRUCTED | ASN1_SET); - if (err) + if (err || len < 1) return svn_error_create(SVN_ERR_X509_CERT_INVALID_NAME, err, NULL); set_end = *p + len; @@ -472,6 +493,18 @@ x509_get_date(apr_time_t *when, /* apr_time_exp_t expects months to be zero indexed, 0=Jan, 11=Dec. */ xt.tm_mon -= 1; + /* range checks (as per definition of apr_time_exp_t in apr_time.h) */ + if (xt.tm_usec < 0 || + xt.tm_sec < 0 || xt.tm_sec > 61 || + xt.tm_min < 0 || xt.tm_min > 59 || + xt.tm_hour < 0 || xt.tm_hour > 23 || + xt.tm_mday < 1 || xt.tm_mday > 31 || + xt.tm_mon < 0 || xt.tm_mon > 11 || + xt.tm_year < 0 || + xt.tm_wday < 0 || xt.tm_wday > 6 || + xt.tm_yday < 0 || xt.tm_yday > 365) + return svn_error_create(SVN_ERR_X509_CERT_INVALID_DATE, NULL, NULL); + ret = apr_time_exp_gmt_get(when, &xt); if (ret) return svn_error_wrap_apr(ret, NULL); @@ -691,8 +724,7 @@ x509_get_ext(apr_array_header_t *dnsnames, else { /* We found a dNSName entry */ - x509_buf *dnsname = apr_palloc(dnsnames->pool, - sizeof(x509_buf)); + x509_buf *dnsname = apr_palloc(dnsnames->pool, sizeof(*dnsname)); dnsname->tag = ASN1_IA5_STRING; /* implicit based on dNSName */ dnsname->len = len; dnsname->p = *p; @@ -919,8 +951,7 @@ x509_name_to_certinfo(apr_array_header_t **result, svn_x509_name_attr_t *attr = apr_palloc(result_pool, sizeof(svn_x509_name_attr_t)); attr->oid_len = name->oid.len; - attr->oid = apr_palloc(result_pool, attr->oid_len); - memcpy(attr->oid, name->oid.p, attr->oid_len); + attr->oid = apr_pmemdup(result_pool, name->oid.p, attr->oid_len); attr->utf8_value = x509name_to_utf8_string(name, result_pool); if (!attr->utf8_value) /* this should never happen */ diff --git a/subversion/libsvn_subr/xml.c b/subversion/libsvn_subr/xml.c index edf21aae6d30..b63658fe5835 100644 --- a/subversion/libsvn_subr/xml.c +++ b/subversion/libsvn_subr/xml.c @@ -42,10 +42,6 @@ #include #endif -#ifdef XML_UNICODE -#error Expat is unusable -- it has been compiled for wide characters -#endif - #ifndef XML_VERSION_AT_LEAST #define XML_VERSION_AT_LEAST(major,minor,patch) \ (((major) < XML_MAJOR_VERSION) \ @@ -54,6 +50,10 @@ (patch) <= XML_MICRO_VERSION)) #endif /* XML_VERSION_AT_LEAST */ +#ifdef XML_UNICODE +#error Expat is unusable -- it has been compiled for wide characters +#endif + const char * svn_xml__compiled_version(void) { @@ -353,6 +353,15 @@ static void expat_start_handler(void *userData, svn_xml_parser_t *svn_parser = userData; (*svn_parser->start_handler)(svn_parser->baton, name, atts); + +#if XML_VERSION_AT_LEAST(1, 95, 8) + /* Stop XML parsing if svn_xml_signal_bailout() was called. + We cannot do this in svn_xml_signal_bailout() because Expat + documentation states that XML_StopParser() must be called only from + callbacks. */ + if (svn_parser->error) + (void) XML_StopParser(svn_parser->parser, 0 /* resumable */); +#endif } static void expat_end_handler(void *userData, const XML_Char *name) @@ -360,6 +369,15 @@ static void expat_end_handler(void *userData, const XML_Char *name) svn_xml_parser_t *svn_parser = userData; (*svn_parser->end_handler)(svn_parser->baton, name); + +#if XML_VERSION_AT_LEAST(1, 95, 8) + /* Stop XML parsing if svn_xml_signal_bailout() was called. + We cannot do this in svn_xml_signal_bailout() because Expat + documentation states that XML_StopParser() must be called only from + callbacks. */ + if (svn_parser->error) + (void) XML_StopParser(svn_parser->parser, 0 /* resumable */); +#endif } static void expat_data_handler(void *userData, const XML_Char *s, int len) @@ -367,6 +385,15 @@ static void expat_data_handler(void *userData, const XML_Char *s, int len) svn_xml_parser_t *svn_parser = userData; (*svn_parser->data_handler)(svn_parser->baton, s, (apr_size_t)len); + +#if XML_VERSION_AT_LEAST(1, 95, 8) + /* Stop XML parsing if svn_xml_signal_bailout() was called. + We cannot do this in svn_xml_signal_bailout() because Expat + documentation states that XML_StopParser() must be called only from + callbacks. */ + if (svn_parser->error) + (void) XML_StopParser(svn_parser->parser, 0 /* resumable */); +#endif } #if XML_VERSION_AT_LEAST(1, 95, 8) @@ -394,6 +421,19 @@ static void expat_default_handler(void *userData, const XML_Char *s, int len) /*** Making a parser. ***/ +static apr_status_t parser_cleanup(void *data) +{ + svn_xml_parser_t *svn_parser = data; + + /* Free Expat parser. */ + if (svn_parser->parser) + { + XML_ParserFree(svn_parser->parser); + svn_parser->parser = NULL; + } + return APR_SUCCESS; +} + svn_xml_parser_t * svn_xml_make_parser(void *baton, svn_xml_start_elem start_handler, @@ -402,8 +442,6 @@ svn_xml_make_parser(void *baton, apr_pool_t *pool) { svn_xml_parser_t *svn_parser; - apr_pool_t *subpool; - XML_Parser parser = XML_ParserCreate(NULL); XML_SetElementHandler(parser, @@ -418,22 +456,23 @@ svn_xml_make_parser(void *baton, XML_SetDefaultHandler(parser, expat_default_handler); #endif - /* ### we probably don't want this pool; or at least we should pass it - ### to the callbacks and clear it periodically. */ - subpool = svn_pool_create(pool); - - svn_parser = apr_pcalloc(subpool, sizeof(*svn_parser)); + svn_parser = apr_pcalloc(pool, sizeof(*svn_parser)); svn_parser->parser = parser; svn_parser->start_handler = start_handler; svn_parser->end_handler = end_handler; svn_parser->data_handler = data_handler; svn_parser->baton = baton; - svn_parser->pool = subpool; + svn_parser->pool = pool; /* store our parser info as the UserData in the Expat parser */ XML_SetUserData(parser, svn_parser); + /* Register pool cleanup handler to free Expat XML parser on cleanup, + if svn_xml_free_parser() was not called explicitly. */ + apr_pool_cleanup_register(svn_parser->pool, svn_parser, + parser_cleanup, apr_pool_cleanup_null); + return svn_parser; } @@ -442,11 +481,7 @@ svn_xml_make_parser(void *baton, void svn_xml_free_parser(svn_xml_parser_t *svn_parser) { - /* Free the expat parser */ - XML_ParserFree(svn_parser->parser); - - /* Free the subversion parser */ - svn_pool_destroy(svn_parser->pool); + apr_pool_cleanup_run(svn_parser->pool, svn_parser, parser_cleanup); } @@ -464,6 +499,14 @@ svn_xml_parse(svn_xml_parser_t *svn_parser, /* Parse some xml data */ success = XML_Parse(svn_parser->parser, buf, (int) len, is_final); + /* Did an error occur somewhere *inside* the expat callbacks? */ + if (svn_parser->error) + { + /* Kill all parsers and return the error */ + svn_xml_free_parser(svn_parser); + return svn_parser->error; + } + /* If expat choked internally, return its error. */ if (! success) { @@ -480,14 +523,6 @@ svn_xml_parse(svn_xml_parser_t *svn_parser, return err; } - /* Did an error occur somewhere *inside* the expat callbacks? */ - if (svn_parser->error) - { - err = svn_parser->error; - svn_xml_free_parser(svn_parser); - return err; - } - return SVN_NO_ERROR; } @@ -502,7 +537,6 @@ void svn_xml_signal_bailout(svn_error_t *error, #if XML_VERSION_AT_LEAST(1, 95, 8) XML_SetEntityDeclHandler(svn_parser->parser, NULL); #endif - /* Once outside of XML_Parse(), the existence of this field will cause svn_delta_parse()'s main read-loop to return error. */ svn_parser->error = error; diff --git a/subversion/libsvn_wc/adm_crawler.c b/subversion/libsvn_wc/adm_crawler.c index ebdc75e105f4..864535f6a70b 100644 --- a/subversion/libsvn_wc/adm_crawler.c +++ b/subversion/libsvn_wc/adm_crawler.c @@ -906,6 +906,27 @@ close_handler_copy(void *baton) return svn_stream_close(btn->source); } +/* Implements svn_stream_seek_fn_t */ +static svn_error_t * +seek_handler_copy(void *baton, const svn_stream_mark_t *mark) +{ + struct copying_stream_baton *btn = baton; + + /* Only reset support. */ + if (mark) + { + return svn_error_create(SVN_ERR_STREAM_SEEK_NOT_SUPPORTED, + NULL, NULL); + } + else + { + SVN_ERR(svn_stream_reset(btn->source)); + SVN_ERR(svn_stream_reset(btn->target)); + } + + return SVN_NO_ERROR; +} + /* Return a stream - allocated in POOL - which reads its input * from SOURCE and, while returning that to the caller, at the @@ -928,6 +949,11 @@ copying_stream(svn_stream_t *source, read_handler_copy); svn_stream_set_close(stream, close_handler_copy); + if (svn_stream_supports_reset(source) && svn_stream_supports_reset(target)) + { + svn_stream_set_seek(stream, seek_handler_copy); + } + return stream; } @@ -995,9 +1021,38 @@ read_and_checksum_pristine_text(svn_stream_t **stream, return SVN_NO_ERROR; } +typedef struct open_txdelta_stream_baton_t +{ + svn_boolean_t need_reset; + svn_stream_t *base_stream; + svn_stream_t *local_stream; +} open_txdelta_stream_baton_t; + +/* Implements svn_txdelta_stream_open_func_t */ +static svn_error_t * +open_txdelta_stream(svn_txdelta_stream_t **txdelta_stream_p, + void *baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + open_txdelta_stream_baton_t *b = baton; + + if (b->need_reset) + { + /* Under rare circumstances, we can be restarted and would need to + * supply the delta stream again. In this case, reset both streams. */ + SVN_ERR(svn_stream_reset(b->base_stream)); + SVN_ERR(svn_stream_reset(b->local_stream)); + } + + svn_txdelta2(txdelta_stream_p, b->base_stream, b->local_stream, + FALSE, result_pool); + b->need_reset = TRUE; + return SVN_NO_ERROR; +} svn_error_t * -svn_wc__internal_transmit_text_deltas(const char **tempfile, +svn_wc__internal_transmit_text_deltas(svn_stream_t *tempstream, const svn_checksum_t **new_text_base_md5_checksum, const svn_checksum_t **new_text_base_sha1_checksum, svn_wc__db_t *db, @@ -1008,8 +1063,6 @@ svn_wc__internal_transmit_text_deltas(const char **tempfile, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - svn_txdelta_window_handler_t handler; - void *wh_baton; const svn_checksum_t *expected_md5_checksum; /* recorded MD5 of BASE_S. */ svn_checksum_t *verify_checksum; /* calc'd MD5 of BASE_STREAM */ svn_checksum_t *local_md5_checksum; /* calc'd MD5 of LOCAL_STREAM */ @@ -1027,22 +1080,13 @@ svn_wc__internal_transmit_text_deltas(const char **tempfile, scratch_pool, scratch_pool)); /* If the caller wants a copy of the working file translated to - * repository-normal form, make the copy by tee-ing the stream and set - * *TEMPFILE to the path to it. This is only needed for the 1.6 API, - * 1.7 doesn't set TEMPFILE. Even when using the 1.6 API this file - * is not used by the functions that would have used it when using - * the 1.6 code. It's possible that 3rd party users (if there are any) - * might expect this file to be a text-base. */ - if (tempfile) + * repository-normal form, make the copy by tee-ing the TEMPSTREAM. + * This is only needed for the 1.6 API. Even when using the 1.6 API + * this temporary file is not used by the functions that would have used + * it when using the 1.6 code. It's possible that 3rd party users (if + * there are any) might expect this file to be a text-base. */ + if (tempstream) { - svn_stream_t *tempstream; - - /* It can't be the same location as in 1.6 because the admin directory - no longer exists. */ - SVN_ERR(svn_stream_open_unique(&tempstream, tempfile, - NULL, svn_io_file_del_none, - result_pool, scratch_pool)); - /* Wrap the translated stream with a new stream that writes the translated contents into the new text base file as we read from it. Note that the new text base file will be closed when the new stream @@ -1088,30 +1132,33 @@ svn_wc__internal_transmit_text_deltas(const char **tempfile, verify_checksum = NULL; } - /* Tell the editor that we're about to apply a textdelta to the - file baton; the editor returns to us a window consumer and baton. */ + /* Arrange the stream to calculate the resulting MD5. */ + local_stream = svn_stream_checksummed2(local_stream, &local_md5_checksum, + NULL, svn_checksum_md5, TRUE, + scratch_pool); + + /* Tell the editor to apply a textdelta stream to the file baton. */ { - /* apply_textdelta() is working against a base with this checksum */ + open_txdelta_stream_baton_t baton = { 0 }; + + /* apply_textdelta_stream() is working against a base with this checksum */ const char *base_digest_hex = NULL; if (expected_md5_checksum) /* ### Why '..._display()'? expected_md5_checksum should never be all- * zero, but if it is, we would want to pass NULL not an all-zero - * digest to apply_textdelta(), wouldn't we? */ + * digest to apply_textdelta_stream(), wouldn't we? */ base_digest_hex = svn_checksum_to_cstring_display(expected_md5_checksum, scratch_pool); - SVN_ERR(editor->apply_textdelta(file_baton, base_digest_hex, scratch_pool, - &handler, &wh_baton)); + baton.need_reset = FALSE; + baton.base_stream = svn_stream_disown(base_stream, scratch_pool); + baton.local_stream = svn_stream_disown(local_stream, scratch_pool); + err = editor->apply_textdelta_stream(editor, file_baton, base_digest_hex, + open_txdelta_stream, &baton, + scratch_pool); } - /* Run diff processing, throwing windows at the handler. */ - err = svn_txdelta_run(base_stream, local_stream, - handler, wh_baton, - svn_checksum_md5, &local_md5_checksum, - NULL, NULL, - scratch_pool, scratch_pool); - /* Close the two streams to force writing the digest */ err2 = svn_stream_close(base_stream); if (err2) @@ -1141,11 +1188,6 @@ svn_wc__internal_transmit_text_deltas(const char **tempfile, investigate. Other commands could be affected, too, such as `svn diff'. */ - if (tempfile) - err = svn_error_compose_create( - err, - svn_io_remove_file2(*tempfile, TRUE, scratch_pool)); - err = svn_error_compose_create( svn_checksum_mismatch_err(expected_md5_checksum, verify_checksum, scratch_pool, diff --git a/subversion/libsvn_wc/conflicts.c b/subversion/libsvn_wc/conflicts.c index f04c6de59481..606710c69f00 100644 --- a/subversion/libsvn_wc/conflicts.c +++ b/subversion/libsvn_wc/conflicts.c @@ -50,6 +50,7 @@ #include "private/svn_wc_private.h" #include "private/svn_skel.h" +#include "private/svn_sorts_private.h" #include "private/svn_string_private.h" #include "svn_private_config.h" @@ -1351,8 +1352,6 @@ generate_propconflict(svn_boolean_t *conflict_remains, } case svn_wc_conflict_choose_merged: { - svn_stringbuf_t *merged_stringbuf; - if (!cdesc->merged_file && (!result->merged_file && !result->merged_value)) return svn_error_create @@ -1364,6 +1363,8 @@ generate_propconflict(svn_boolean_t *conflict_remains, new_value = result->merged_value; else { + svn_stringbuf_t *merged_stringbuf; + SVN_ERR(svn_stringbuf_from_file2(&merged_stringbuf, result->merged_file ? result->merged_file : @@ -2339,6 +2340,17 @@ svn_wc__read_conflicts(const apr_array_header_t **conflicts, return SVN_NO_ERROR; } +svn_error_t * +svn_wc__read_conflict_descriptions2_t(const apr_array_header_t **conflicts, + svn_wc_context_t *wc_ctx, + const char *local_abspath, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + return svn_wc__read_conflicts(conflicts, NULL, wc_ctx->db, local_abspath, + FALSE, FALSE, result_pool, scratch_pool); +} + /*** Resolving a conflict automatically ***/ @@ -2477,15 +2489,12 @@ resolve_prop_conflict_on_node(svn_boolean_t *did_resolve, if (!merged_value) { - svn_stream_t *stream; - svn_string_t *merged_propval; + svn_stringbuf_t *merged_propval; - SVN_ERR(svn_stream_open_readonly(&stream, merged_file, - scratch_pool, scratch_pool)); - SVN_ERR(svn_string_from_stream(&merged_propval, stream, - scratch_pool, scratch_pool)); + SVN_ERR(svn_stringbuf_from_file2(&merged_propval, merged_file, + scratch_pool)); - merged_value = merged_propval; + merged_value = svn_stringbuf__morph_into_string(merged_propval); } svn_hash_sets(resolve_from, conflicted_propname, merged_value); } @@ -2594,6 +2603,35 @@ resolve_prop_conflict_on_node(svn_boolean_t *did_resolve, return SVN_NO_ERROR; } +/* + * Record a tree conflict resolution failure due to error condition ERR + * in the RESOLVE_LATER hash table. If the hash table is not available + * (meaning the caller does not wish to retry resolution later), or if + * the error condition does not indicate circumstances where another + * existing tree conflict is blocking the resolution attempt, then + * return the error ERR itself. + */ +static svn_error_t * +handle_tree_conflict_resolution_failure(const char *local_abspath, + svn_error_t *err, + apr_hash_t *resolve_later) +{ + const char *dup_abspath; + + if (!resolve_later + || (err->apr_err != SVN_ERR_WC_OBSTRUCTED_UPDATE + && err->apr_err != SVN_ERR_WC_FOUND_CONFLICT)) + return svn_error_trace(err); /* Give up. Do not retry resolution later. */ + + svn_error_clear(err); + dup_abspath = apr_pstrdup(apr_hash_pool_get(resolve_later), + local_abspath); + + svn_hash_sets(resolve_later, dup_abspath, dup_abspath); + + return SVN_NO_ERROR; /* Caller may retry after resolving other conflicts. */ +} + /* * Resolve the tree conflict found in DB/LOCAL_ABSPATH according to * CONFLICT_CHOICE. @@ -2603,9 +2641,11 @@ resolve_prop_conflict_on_node(svn_boolean_t *did_resolve, * * It is not an error if there is no tree conflict. * - * If the conflict can't be resolved yet because another tree conflict is - * blocking a storage location, store the tree conflict in the RESOLVE_LATER - * hash. + * If the conflict can't be resolved yet (e.g. because another tree conflict + * is blocking a storage location), and RESOLVE_LATER is not NULL, store the + * tree conflict in RESOLVE_LATER and do not mark the conflict resolved. + * Else if RESOLVE_LATER is NULL, do not mark the conflict resolved and + * return the error which prevented the conflict from being marked resolved. */ static svn_error_t * resolve_tree_conflict_on_node(svn_boolean_t *did_resolve, @@ -2670,8 +2710,9 @@ resolve_tree_conflict_on_node(svn_boolean_t *did_resolve, { svn_skel_t *new_conflicts; - /* Raise moved-away conflicts on any children moved out of - * this directory, and leave this directory as-is. + /* Raise local moved-away vs. incoming edit conflicts on + * any children moved out of this directory, and leave + * this directory as-is. * * The newly conflicted moved-away children will be updated * if they are resolved with 'mine_conflict' as well. */ @@ -2680,21 +2721,8 @@ resolve_tree_conflict_on_node(svn_boolean_t *did_resolve, scratch_pool); if (err) - { - const char *dup_abspath; - - if (!resolve_later - || err->apr_err != SVN_ERR_WC_OBSTRUCTED_UPDATE) - return svn_error_trace(err); - - svn_error_clear(err); - dup_abspath = apr_pstrdup(apr_hash_pool_get(resolve_later), - local_abspath); - - svn_hash_sets(resolve_later, dup_abspath, dup_abspath); - - return SVN_NO_ERROR; /* Retry after other conflicts */ - } + SVN_ERR(handle_tree_conflict_resolution_failure( + local_abspath, err, resolve_later)); /* We might now have a moved-away on *this* path, let's try to resolve that directly if that is the case */ @@ -2713,7 +2741,7 @@ resolve_tree_conflict_on_node(svn_boolean_t *did_resolve, if (!new_conflicts || !tree_conflicted) { /* TC is marked resolved by calling - svn_wc__db_resolve_delete_raise_moved_away */ + svn_wc__db_op_raise_moved_away */ *did_resolve = TRUE; return SVN_NO_ERROR; } @@ -2761,21 +2789,8 @@ resolve_tree_conflict_on_node(svn_boolean_t *did_resolve, scratch_pool); if (err) - { - const char *dup_abspath; - - if (!resolve_later - || err->apr_err != SVN_ERR_WC_OBSTRUCTED_UPDATE) - return svn_error_trace(err); - - svn_error_clear(err); - dup_abspath = apr_pstrdup(apr_hash_pool_get(resolve_later), - local_abspath); - - svn_hash_sets(resolve_later, dup_abspath, dup_abspath); - - return SVN_NO_ERROR; /* Retry after other conflicts */ - } + SVN_ERR(handle_tree_conflict_resolution_failure( + local_abspath, err, resolve_later)); else *did_resolve = TRUE; } @@ -2973,12 +2988,13 @@ conflict_status_walker(void *baton, { struct conflict_status_walker_baton *cswb = baton; svn_wc__db_t *db = cswb->db; - + svn_wc_notify_action_t notify_action = svn_wc_notify_resolved; const apr_array_header_t *conflicts; apr_pool_t *iterpool; int i; svn_boolean_t resolved = FALSE; svn_skel_t *conflict; + const svn_wc_conflict_description2_t *cd; if (!status->conflicted) return SVN_NO_ERROR; @@ -2993,7 +3009,6 @@ conflict_status_walker(void *baton, for (i = 0; i < conflicts->nelts; i++) { - const svn_wc_conflict_description2_t *cd; svn_boolean_t did_resolve; svn_wc_conflict_choice_t my_choice = cswb->conflict_choice; svn_wc_conflict_result_t *result = NULL; @@ -3045,7 +3060,10 @@ conflict_status_walker(void *baton, iterpool)); if (did_resolve) - resolved = TRUE; + { + resolved = TRUE; + notify_action = svn_wc_notify_resolved_tree; + } break; case svn_wc_conflict_kind_text: @@ -3069,6 +3087,8 @@ conflict_status_walker(void *baton, SVN_ERR(svn_wc__wq_run(db, local_abspath, cswb->cancel_func, cswb->cancel_baton, iterpool)); + if (resolved) + notify_action = svn_wc_notify_resolved_text; break; case svn_wc_conflict_kind_property: @@ -3089,7 +3109,10 @@ conflict_status_walker(void *baton, iterpool)); if (did_resolve) - resolved = TRUE; + { + resolved = TRUE; + notify_action = svn_wc_notify_resolved_prop; + } break; default: @@ -3100,12 +3123,33 @@ conflict_status_walker(void *baton, /* Notify */ if (cswb->notify_func && resolved) - cswb->notify_func(cswb->notify_baton, - svn_wc_create_notify(local_abspath, - svn_wc_notify_resolved, - iterpool), - iterpool); + { + svn_wc_notify_t *notify; + /* If our caller asked for all conflicts to be resolved, + * send a general 'resolved' notification. */ + if (cswb->resolve_text && cswb->resolve_tree && + (cswb->resolve_prop == NULL || cswb->resolve_prop[0] == '\0')) + notify_action = svn_wc_notify_resolved; + + /* If we resolved a property conflict, but no specific property was + * requested by the caller, send a general 'resolved' notification. */ + if (notify_action == svn_wc_notify_resolved_prop && + (cswb->resolve_prop == NULL || cswb->resolve_prop[0] == '\0')) + notify_action = svn_wc_notify_resolved; + + notify = svn_wc_create_notify(local_abspath, notify_action, iterpool); + + /* Add the property name for property-specific notifications. */ + if (notify_action == svn_wc_notify_resolved_prop) + { + notify->prop_name = cd->property_name; + SVN_ERR_ASSERT(strlen(notify->prop_name) > 0); + } + + cswb->notify_func(cswb->notify_baton, notify, iterpool); + + } if (resolved) cswb->resolved_one = TRUE; @@ -3130,26 +3174,11 @@ svn_wc__resolve_conflicts(svn_wc_context_t *wc_ctx, void *notify_baton, apr_pool_t *scratch_pool) { - svn_node_kind_t kind; - svn_boolean_t conflicted; struct conflict_status_walker_baton cswb; apr_pool_t *iterpool = NULL; svn_error_t *err; - /* ### Just a versioned check? */ - /* Conflicted is set to allow invoking on actual only nodes */ - SVN_ERR(svn_wc__db_read_info(NULL, &kind, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, &conflicted, - NULL, NULL, NULL, NULL, NULL, NULL, - wc_ctx->db, local_abspath, - scratch_pool, scratch_pool)); - - /* When the implementation still used the entry walker, depth - unknown was translated to infinity. */ - if (kind != svn_node_dir) - depth = svn_depth_empty; - else if (depth == svn_depth_unknown) + if (depth == svn_depth_unknown) depth = svn_depth_infinity; cswb.db = wc_ctx->db; @@ -3321,8 +3350,591 @@ svn_wc_create_conflict_result(svn_wc_conflict_choice_t choice, result->choice = choice; result->merged_file = apr_pstrdup(pool, merged_file); result->save_merged = FALSE; + result->merged_value = NULL; /* If we add more fields to svn_wc_conflict_result_t, add them here. */ return result; } + +svn_error_t * +svn_wc__conflict_text_mark_resolved(svn_wc_context_t *wc_ctx, + const char *local_abspath, + svn_wc_conflict_choice_t choice, + svn_cancel_func_t cancel_func, + void *cancel_baton, + svn_wc_notify_func2_t notify_func, + void *notify_baton, + apr_pool_t *scratch_pool) +{ + svn_skel_t *work_items; + svn_skel_t *conflict; + svn_boolean_t did_resolve; + + SVN_ERR(svn_wc__db_read_conflict(&conflict, NULL, NULL, + wc_ctx->db, local_abspath, + scratch_pool, scratch_pool)); + + if (!conflict) + return SVN_NO_ERROR; + + SVN_ERR(build_text_conflict_resolve_items(&work_items, &did_resolve, + wc_ctx->db, local_abspath, + conflict, choice, + NULL, FALSE, NULL, + cancel_func, cancel_baton, + scratch_pool, scratch_pool)); + + SVN_ERR(svn_wc__db_op_mark_resolved(wc_ctx->db, local_abspath, + TRUE, FALSE, FALSE, + work_items, scratch_pool)); + + SVN_ERR(svn_wc__wq_run(wc_ctx->db, local_abspath, + cancel_func, cancel_baton, + scratch_pool)); + + if (did_resolve && notify_func) + notify_func(notify_baton, + svn_wc_create_notify(local_abspath, + svn_wc_notify_resolved_text, + scratch_pool), + scratch_pool); + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_wc__conflict_prop_mark_resolved(svn_wc_context_t *wc_ctx, + const char *local_abspath, + const char *propname, + svn_wc_conflict_choice_t choice, + const svn_string_t *merged_value, + svn_wc_notify_func2_t notify_func, + void *notify_baton, + apr_pool_t *scratch_pool) +{ + svn_boolean_t did_resolve; + svn_skel_t *conflicts; + + SVN_ERR(svn_wc__db_read_conflict(&conflicts, NULL, NULL, + wc_ctx->db, local_abspath, + scratch_pool, scratch_pool)); + + if (!conflicts) + return SVN_NO_ERROR; + + SVN_ERR(resolve_prop_conflict_on_node(&did_resolve, wc_ctx->db, + local_abspath, conflicts, + propname, choice, NULL, merged_value, + NULL, NULL, scratch_pool)); + + if (did_resolve && notify_func) + { + svn_wc_notify_t *notify; + + /* Send a general notification if no specific property was requested. */ + if (propname == NULL || propname[0] == '\0') + { + notify = svn_wc_create_notify(local_abspath, + svn_wc_notify_resolved, + scratch_pool); + } + else + { + notify = svn_wc_create_notify(local_abspath, + svn_wc_notify_resolved_prop, + scratch_pool); + notify->prop_name = propname; + } + + notify_func(notify_baton, notify, scratch_pool); + } + return SVN_NO_ERROR; +} + +svn_error_t * +svn_wc__conflict_tree_update_break_moved_away(svn_wc_context_t *wc_ctx, + const char *local_abspath, + svn_cancel_func_t cancel_func, + void *cancel_baton, + svn_wc_notify_func2_t notify_func, + void *notify_baton, + apr_pool_t *scratch_pool) +{ + svn_wc_conflict_reason_t reason; + svn_wc_conflict_action_t action; + svn_wc_operation_t operation; + svn_boolean_t tree_conflicted; + const char *src_op_root_abspath; + const apr_array_header_t *conflicts; + svn_skel_t *conflict_skel; + + SVN_ERR(svn_wc__read_conflicts(&conflicts, &conflict_skel, + wc_ctx->db, local_abspath, + FALSE, /* no tempfiles */ + FALSE, /* only tree conflicts */ + scratch_pool, scratch_pool)); + + SVN_ERR(svn_wc__conflict_read_info(&operation, NULL, NULL, NULL, + &tree_conflicted, wc_ctx->db, + local_abspath, conflict_skel, + scratch_pool, scratch_pool)); + if (!tree_conflicted) + return SVN_NO_ERROR; + + SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, &action, + &src_op_root_abspath, + wc_ctx->db, local_abspath, + conflict_skel, + scratch_pool, scratch_pool)); + + /* Make sure the expected conflict is recorded. */ + if (operation != svn_wc_operation_update && + operation != svn_wc_operation_switch) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Unexpected conflict operation '%s' on '%s'"), + svn_token__to_word(operation_map, operation), + svn_dirent_local_style(local_abspath, + scratch_pool)); + if (reason != svn_wc_conflict_reason_deleted && + reason != svn_wc_conflict_reason_replaced && + reason != svn_wc_conflict_reason_moved_away) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Unexpected conflict reason '%s' on '%s'"), + svn_token__to_word(reason_map, reason), + svn_dirent_local_style(local_abspath, + scratch_pool)); + + /* Break moves for any children moved out of this directory, + * and leave this directory deleted. */ + if (action != svn_wc_conflict_action_delete) + { + SVN_ERR(svn_wc__db_op_break_moved_away( + wc_ctx->db, local_abspath, src_op_root_abspath, TRUE, + notify_func, notify_baton, scratch_pool)); + /* Conflict was marked resolved by db_op_break_moved_away() call .*/ + + if (notify_func) + notify_func(notify_baton, + svn_wc_create_notify(local_abspath, + svn_wc_notify_resolved_tree, + scratch_pool), + scratch_pool); + return SVN_NO_ERROR; + } + /* else # The move is/moves are already broken */ + + SVN_ERR(svn_wc__db_op_mark_resolved(wc_ctx->db, local_abspath, + FALSE, FALSE, TRUE, + NULL, scratch_pool)); + SVN_ERR(svn_wc__wq_run(wc_ctx->db, local_abspath, cancel_func, cancel_baton, + scratch_pool)); + + if (notify_func) + notify_func(notify_baton, + svn_wc_create_notify(local_abspath, + svn_wc_notify_resolved_tree, + scratch_pool), + scratch_pool); + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_wc__conflict_tree_update_raise_moved_away(svn_wc_context_t *wc_ctx, + const char *local_abspath, + svn_cancel_func_t cancel_func, + void *cancel_baton, + svn_wc_notify_func2_t notify_func, + void *notify_baton, + apr_pool_t *scratch_pool) +{ + svn_wc_conflict_reason_t reason; + svn_wc_conflict_action_t action; + svn_wc_operation_t operation; + svn_boolean_t tree_conflicted; + const apr_array_header_t *conflicts; + svn_skel_t *conflict_skel; + + SVN_ERR(svn_wc__read_conflicts(&conflicts, &conflict_skel, + wc_ctx->db, local_abspath, + FALSE, /* no tempfiles */ + FALSE, /* only tree conflicts */ + scratch_pool, scratch_pool)); + + SVN_ERR(svn_wc__conflict_read_info(&operation, NULL, NULL, NULL, + &tree_conflicted, wc_ctx->db, + local_abspath, conflict_skel, + scratch_pool, scratch_pool)); + if (!tree_conflicted) + return SVN_NO_ERROR; + + SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, &action, NULL, + wc_ctx->db, local_abspath, + conflict_skel, + scratch_pool, scratch_pool)); + + /* Make sure the expected conflict is recorded. */ + if (operation != svn_wc_operation_update && + operation != svn_wc_operation_switch) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Unexpected conflict operation '%s' on '%s'"), + svn_token__to_word(operation_map, operation), + svn_dirent_local_style(local_abspath, + scratch_pool)); + if (reason != svn_wc_conflict_reason_deleted && + reason != svn_wc_conflict_reason_replaced) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Unexpected conflict reason '%s' on '%s'"), + svn_token__to_word(reason_map, reason), + svn_dirent_local_style(local_abspath, + scratch_pool)); + if (action != svn_wc_conflict_action_edit) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Unexpected conflict action '%s' on '%s'"), + svn_token__to_word(action_map, action), + svn_dirent_local_style(local_abspath, + scratch_pool)); + + /* Raise local moved-away vs. incoming edit conflicts on any children + * moved out of this directory, and leave this directory as-is. + * The user may choose to update newly conflicted moved-away children + * when resolving them. If this function raises an error, the conflict + * cannot be resolved yet because other conflicts or obstructions + * prevent us from propagating the conflict to moved-away children. */ + SVN_ERR(svn_wc__db_op_raise_moved_away(wc_ctx->db, local_abspath, + notify_func, notify_baton, + scratch_pool)); + + /* The conflict was marked resolved by svn_wc__db_op_raise_moved_away(). */ + if (notify_func) + notify_func(notify_baton, + svn_wc_create_notify(local_abspath, + svn_wc_notify_resolved_tree, + scratch_pool), + scratch_pool); + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_wc__conflict_tree_update_moved_away_node(svn_wc_context_t *wc_ctx, + const char *local_abspath, + svn_cancel_func_t cancel_func, + void *cancel_baton, + svn_wc_notify_func2_t notify_func, + void *notify_baton, + apr_pool_t *scratch_pool) +{ + svn_wc_conflict_reason_t reason; + svn_wc_conflict_action_t action; + svn_wc_operation_t operation; + svn_boolean_t tree_conflicted; + const char *src_op_root_abspath; + const apr_array_header_t *conflicts; + svn_skel_t *conflict_skel; + + SVN_ERR(svn_wc__read_conflicts(&conflicts, &conflict_skel, + wc_ctx->db, local_abspath, + FALSE, /* no tempfiles */ + FALSE, /* only tree conflicts */ + scratch_pool, scratch_pool)); + + SVN_ERR(svn_wc__conflict_read_info(&operation, NULL, NULL, NULL, + &tree_conflicted, wc_ctx->db, + local_abspath, conflict_skel, + scratch_pool, scratch_pool)); + if (!tree_conflicted) + return SVN_NO_ERROR; + + SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, &action, + &src_op_root_abspath, + wc_ctx->db, local_abspath, + conflict_skel, + scratch_pool, scratch_pool)); + + /* Make sure the expected conflict is recorded. */ + if (operation != svn_wc_operation_update && + operation != svn_wc_operation_switch) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Unexpected conflict operation '%s' on '%s'"), + svn_token__to_word(operation_map, operation), + svn_dirent_local_style(local_abspath, + scratch_pool)); + if (reason != svn_wc_conflict_reason_moved_away) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Unexpected conflict reason '%s' on '%s'"), + svn_token__to_word(reason_map, reason), + svn_dirent_local_style(local_abspath, + scratch_pool)); + if (action != svn_wc_conflict_action_edit) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Unexpected conflict action '%s' on '%s'"), + svn_token__to_word(action_map, action), + svn_dirent_local_style(local_abspath, + scratch_pool)); + + /* Update the moved-away conflict victim. */ + SVN_ERR(svn_wc__db_update_moved_away_conflict_victim(wc_ctx->db, + local_abspath, + src_op_root_abspath, + operation, + action, + reason, + cancel_func, + cancel_baton, + notify_func, + notify_baton, + scratch_pool)); + + SVN_ERR(svn_wc__db_op_mark_resolved(wc_ctx->db, local_abspath, + FALSE, FALSE, TRUE, + NULL, scratch_pool)); + SVN_ERR(svn_wc__wq_run(wc_ctx->db, local_abspath, cancel_func, cancel_baton, + scratch_pool)); + + if (notify_func) + notify_func(notify_baton, + svn_wc_create_notify(local_abspath, + svn_wc_notify_resolved_tree, + scratch_pool), + scratch_pool); + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_wc__conflict_tree_update_incoming_move(svn_wc_context_t *wc_ctx, + const char *local_abspath, + const char *dest_abspath, + svn_cancel_func_t cancel_func, + void *cancel_baton, + svn_wc_notify_func2_t notify_func, + void *notify_baton, + apr_pool_t *scratch_pool) +{ + svn_wc_conflict_reason_t local_change; + svn_wc_conflict_action_t incoming_change; + svn_wc_operation_t operation; + svn_boolean_t tree_conflicted; + const apr_array_header_t *conflicts; + svn_skel_t *conflict_skel; + + SVN_ERR(svn_wc__read_conflicts(&conflicts, &conflict_skel, + wc_ctx->db, local_abspath, + FALSE, /* no tempfiles */ + FALSE, /* only tree conflicts */ + scratch_pool, scratch_pool)); + + SVN_ERR(svn_wc__conflict_read_info(&operation, NULL, NULL, NULL, + &tree_conflicted, wc_ctx->db, + local_abspath, conflict_skel, + scratch_pool, scratch_pool)); + if (!tree_conflicted) + return SVN_NO_ERROR; + + SVN_ERR(svn_wc__conflict_read_tree_conflict(&local_change, &incoming_change, + NULL, wc_ctx->db, local_abspath, + conflict_skel, + scratch_pool, scratch_pool)); + + /* Make sure the expected conflict is recorded. */ + if (operation != svn_wc_operation_update && + operation != svn_wc_operation_switch && + operation != svn_wc_operation_merge) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Unexpected conflict operation '%s' on '%s'"), + svn_token__to_word(operation_map, operation), + svn_dirent_local_style(local_abspath, + scratch_pool)); + if (local_change != svn_wc_conflict_reason_edited) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Unexpected conflict reason '%s' on '%s'"), + svn_token__to_word(reason_map, local_change), + svn_dirent_local_style(local_abspath, + scratch_pool)); + if (incoming_change != svn_wc_conflict_action_delete) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Unexpected conflict action '%s' on '%s'"), + svn_token__to_word(action_map, incoming_change), + svn_dirent_local_style(local_abspath, + scratch_pool)); + + SVN_ERR(svn_wc__db_update_incoming_move(wc_ctx->db, local_abspath, + dest_abspath, operation, + incoming_change, local_change, + cancel_func, cancel_baton, + notify_func, notify_baton, + scratch_pool)); + + SVN_ERR(svn_wc__wq_run(wc_ctx->db, local_abspath, cancel_func, cancel_baton, + scratch_pool)); + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_wc__conflict_tree_update_local_add(svn_wc_context_t *wc_ctx, + const char *local_abspath, + svn_cancel_func_t cancel_func, + void *cancel_baton, + svn_wc_notify_func2_t notify_func, + void *notify_baton, + apr_pool_t *scratch_pool) +{ + svn_wc_conflict_reason_t local_change; + svn_wc_conflict_action_t incoming_change; + svn_wc_operation_t operation; + svn_boolean_t tree_conflicted; + const apr_array_header_t *conflicts; + svn_skel_t *conflict_skel; + + SVN_ERR(svn_wc__read_conflicts(&conflicts, &conflict_skel, + wc_ctx->db, local_abspath, + FALSE, /* no tempfiles */ + FALSE, /* only tree conflicts */ + scratch_pool, scratch_pool)); + + SVN_ERR(svn_wc__conflict_read_info(&operation, NULL, NULL, NULL, + &tree_conflicted, wc_ctx->db, + local_abspath, conflict_skel, + scratch_pool, scratch_pool)); + if (!tree_conflicted) + return SVN_NO_ERROR; + + SVN_ERR(svn_wc__conflict_read_tree_conflict(&local_change, &incoming_change, + NULL, wc_ctx->db, local_abspath, + conflict_skel, + scratch_pool, scratch_pool)); + + /* Make sure the expected conflict is recorded. */ + if (operation != svn_wc_operation_update) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Unexpected conflict operation '%s' on '%s'"), + svn_token__to_word(operation_map, operation), + svn_dirent_local_style(local_abspath, + scratch_pool)); + if (local_change != svn_wc_conflict_reason_added) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Unexpected conflict reason '%s' on '%s'"), + svn_token__to_word(reason_map, local_change), + svn_dirent_local_style(local_abspath, + scratch_pool)); + if (incoming_change != svn_wc_conflict_action_add) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Unexpected conflict action '%s' on '%s'"), + svn_token__to_word(action_map, incoming_change), + svn_dirent_local_style(local_abspath, + scratch_pool)); + + SVN_ERR(svn_wc__db_update_local_add(wc_ctx->db, local_abspath, + cancel_func, cancel_baton, + notify_func, notify_baton, + scratch_pool)); + + SVN_ERR(svn_wc__wq_run(wc_ctx->db, local_abspath, cancel_func, cancel_baton, + scratch_pool)); + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_wc__guess_incoming_move_target_nodes(apr_array_header_t **possible_targets, + svn_wc_context_t *wc_ctx, + const char *victim_abspath, + svn_node_kind_t victim_node_kind, + const char *moved_to_repos_relpath, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + apr_array_header_t *candidates; + apr_pool_t *iterpool; + int i; + apr_size_t longest_ancestor_len = 0; + + *possible_targets = apr_array_make(result_pool, 1, sizeof(const char *)); + SVN_ERR(svn_wc__find_repos_node_in_wc(&candidates, wc_ctx->db, victim_abspath, + moved_to_repos_relpath, + scratch_pool, scratch_pool)); + + /* Find a "useful move target" node in our set of candidates. + * Since there is no way to be certain, filter out nodes which seem + * unlikely candidates, and return the first node which is "good enough". + * Nodes which are tree conflict victims don't count, and nodes which + * cannot be modified (e.g. replaced or deleted nodes) don't count. + * Nodes which are of a different node kind don't count either. + * Ignore switched nodes as well, since that is an unlikely case during + * update/swtich/merge conflict resolution. And externals shouldn't even + * be on our candidate list in the first place. + * If multiple candidates match these criteria, choose the one which + * shares the longest common ancestor with the victim. */ + iterpool = svn_pool_create(scratch_pool); + for (i = 0; i < candidates->nelts; i++) + { + const char *local_abspath; + const char *ancestor_abspath; + apr_size_t ancestor_len; + svn_boolean_t tree_conflicted; + svn_wc__db_status_t status; + svn_boolean_t is_wcroot; + svn_boolean_t is_switched; + svn_node_kind_t node_kind; + const char *moved_to_abspath; + int insert_index; + + svn_pool_clear(iterpool); + + local_abspath = APR_ARRAY_IDX(candidates, i, const char *); + + SVN_ERR(svn_wc__internal_conflicted_p(NULL, NULL, &tree_conflicted, + wc_ctx->db, local_abspath, + iterpool)); + if (tree_conflicted) + continue; + + SVN_ERR(svn_wc__db_read_info(&status, &node_kind, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + wc_ctx->db, local_abspath, iterpool, + iterpool)); + if (status != svn_wc__db_status_normal && + status != svn_wc__db_status_added) + continue; + + if (node_kind != victim_node_kind) + continue; + + SVN_ERR(svn_wc__db_is_switched(&is_wcroot, &is_switched, NULL, + wc_ctx->db, local_abspath, iterpool)); + if (is_wcroot || is_switched) + continue; + + /* This might be a move target. Fingers crossed ;-) */ + moved_to_abspath = apr_pstrdup(result_pool, local_abspath); + + /* Insert the move target into the list. Targets which are closer + * (path-wise) to the conflict victim are more likely to be a good + * match, so put them at the front of the list. */ + ancestor_abspath = svn_dirent_get_longest_ancestor(local_abspath, + victim_abspath, + iterpool); + ancestor_len = strlen(ancestor_abspath); + if (ancestor_len >= longest_ancestor_len) + { + longest_ancestor_len = ancestor_len; + insert_index = 0; /* prepend */ + } + else + { + insert_index = (*possible_targets)->nelts; /* append */ + } + svn_sort__array_insert(*possible_targets, &moved_to_abspath, + insert_index); + } + + svn_pool_destroy(iterpool); + + return SVN_NO_ERROR; +} diff --git a/subversion/libsvn_wc/copy.c b/subversion/libsvn_wc/copy.c index 30a0db58cc6a..7d4256feabad 100644 --- a/subversion/libsvn_wc/copy.c +++ b/subversion/libsvn_wc/copy.c @@ -791,10 +791,11 @@ copy_or_move(svn_boolean_t *record_move_on_delete, break; /* OK to add */ default: - return svn_error_createf(SVN_ERR_ENTRY_EXISTS, NULL, - _("There is already a versioned item '%s'"), - svn_dirent_local_style(dst_abspath, - scratch_pool)); + if (!metadata_only) + return svn_error_createf(SVN_ERR_ENTRY_EXISTS, NULL, + _("There is already a versioned item '%s'"), + svn_dirent_local_style(dst_abspath, + scratch_pool)); } } @@ -1104,8 +1105,8 @@ svn_wc__move2(svn_wc_context_t *wc_ctx, { svn_error_t *err; - err = svn_error_trace(svn_io_file_rename(src_abspath, dst_abspath, - scratch_pool)); + err = svn_error_trace(svn_io_file_rename2(src_abspath, dst_abspath, + FALSE, scratch_pool)); /* Let's try if we can keep wc.db consistent even when the move fails. Deleting the target is a wc.db only operation, while diff --git a/subversion/libsvn_wc/crop.c b/subversion/libsvn_wc/crop.c index 3a46b42d4be2..51f130aa2620 100644 --- a/subversion/libsvn_wc/crop.c +++ b/subversion/libsvn_wc/crop.c @@ -106,7 +106,12 @@ crop_children(svn_wc__db_t *db, svn_boolean_t modified, all_deletes; if (child_status != svn_wc__db_status_deleted) - continue; /* Leave local additions alone */ + { + /* ### TODO: Check for issue #4636 constraints, but not only on + this node, but also at all its descendants: We don't want + to remove moved_from information here! */ + continue; /* Leave local additions alone */ + } SVN_ERR(svn_wc__node_has_local_mods(&modified, &all_deletes, db, child_abspath, FALSE, diff --git a/subversion/libsvn_wc/deprecated.c b/subversion/libsvn_wc/deprecated.c index dcb5e42f749b..e54a86df903b 100644 --- a/subversion/libsvn_wc/deprecated.c +++ b/subversion/libsvn_wc/deprecated.c @@ -39,6 +39,7 @@ #include "private/svn_subr_private.h" #include "private/svn_wc_private.h" +#include "private/svn_io_private.h" #include "wc.h" #include "entries.h" @@ -478,20 +479,49 @@ svn_wc_transmit_text_deltas2(const char **tempfile, const char *local_abspath; svn_wc_context_t *wc_ctx; const svn_checksum_t *new_text_base_md5_checksum; + svn_stream_t *tempstream; + svn_error_t *err; SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool)); SVN_ERR(svn_wc__context_create_with_db(&wc_ctx, NULL /* config */, svn_wc__adm_get_db(adm_access), pool)); + if (tempfile) + { + apr_file_t *f; - SVN_ERR(svn_wc__internal_transmit_text_deltas(tempfile, - (digest - ? &new_text_base_md5_checksum - : NULL), - NULL, wc_ctx->db, - local_abspath, fulltext, - editor, file_baton, - pool, pool)); + /* The temporary file can't be the same location as in 1.6 because the + * admin directory no longer exists. */ + SVN_ERR(svn_io_open_unique_file3(&f, tempfile, NULL, + svn_io_file_del_none, + pool, pool)); + tempstream = svn_stream__from_aprfile(f, FALSE, TRUE, pool); + } + else + { + tempstream = NULL; + } + + err = svn_wc__internal_transmit_text_deltas(svn_stream_disown(tempstream, pool), + (digest + ? &new_text_base_md5_checksum + : NULL), + NULL, wc_ctx->db, + local_abspath, fulltext, + editor, file_baton, + pool, pool); + if (tempfile) + { + err = svn_error_compose_create(err, svn_stream_close(tempstream)); + + if (err) + { + err = svn_error_compose_create( + err, svn_io_remove_file2(*tempfile, TRUE, pool)); + } + } + + SVN_ERR(err); if (digest) memcpy(digest, new_text_base_md5_checksum->digest, APR_MD5_DIGESTSIZE); diff --git a/subversion/libsvn_wc/diff.h b/subversion/libsvn_wc/diff.h index 2df88e16a3e3..c91c5ffc3748 100644 --- a/subversion/libsvn_wc/diff.h +++ b/subversion/libsvn_wc/diff.h @@ -52,6 +52,7 @@ svn_error_t * svn_wc__diff_local_only_file(svn_wc__db_t *db, const char *local_abspath, const char *relpath, + const char *moved_from_relpath, const svn_diff_tree_processor_t *processor, void *processor_parent_baton, svn_boolean_t diff_pristine, @@ -75,6 +76,7 @@ svn_wc__diff_local_only_dir(svn_wc__db_t *db, const char *local_abspath, const char *relpath, svn_depth_t depth, + const char *moved_from_relpath, const svn_diff_tree_processor_t *processor, void *processor_parent_baton, svn_boolean_t diff_pristine, diff --git a/subversion/libsvn_wc/diff_editor.c b/subversion/libsvn_wc/diff_editor.c index fc059a5d4dea..9b1b0d50baa0 100644 --- a/subversion/libsvn_wc/diff_editor.c +++ b/subversion/libsvn_wc/diff_editor.c @@ -145,6 +145,9 @@ struct dir_baton_t /* TRUE if the node is to be compared with an unrelated node*/ svn_boolean_t ignoring_ancestry; + /* TRUE if the directory was reported incomplete to the repository */ + svn_boolean_t is_incomplete; + /* Processor state */ void *pdb; svn_boolean_t skip; @@ -741,9 +744,29 @@ walk_local_nodes_diff(struct edit_baton_t *eb, if (eb->local_before_remote && local_only) { + const char *moved_from_relpath; + + if (info->moved_here) + { + const char *moved_from_abspath; + + SVN_ERR(svn_wc__db_scan_moved(&moved_from_abspath, + NULL, NULL, NULL, + db, child_abspath, + iterpool, iterpool)); + SVN_ERR_ASSERT(moved_from_abspath != NULL); + + moved_from_relpath = svn_dirent_skip_ancestor( + eb->anchor_abspath, + moved_from_abspath); + } + else + moved_from_relpath = NULL; + if (info->kind == svn_node_file && diff_files) SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath, child_relpath, + moved_from_relpath, eb->processor, dir_baton, eb->diff_pristine, eb->cancel_func, @@ -753,6 +776,7 @@ walk_local_nodes_diff(struct edit_baton_t *eb, SVN_ERR(svn_wc__diff_local_only_dir(db, child_abspath, child_relpath, depth_below_here, + moved_from_relpath, eb->processor, dir_baton, eb->diff_pristine, eb->cancel_func, @@ -807,9 +831,29 @@ walk_local_nodes_diff(struct edit_baton_t *eb, if (!eb->local_before_remote && local_only) { + const char *moved_from_relpath; + + if (info->moved_here) + { + const char *moved_from_abspath; + + SVN_ERR(svn_wc__db_scan_moved(&moved_from_abspath, + NULL, NULL, NULL, + db, child_abspath, + iterpool, iterpool)); + SVN_ERR_ASSERT(moved_from_abspath != NULL); + + moved_from_relpath = svn_dirent_skip_ancestor( + eb->anchor_abspath, + moved_from_abspath); + } + else + moved_from_relpath = NULL; + if (info->kind == svn_node_file && diff_files) SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath, child_relpath, + moved_from_relpath, eb->processor, dir_baton, eb->diff_pristine, eb->cancel_func, @@ -817,12 +861,13 @@ walk_local_nodes_diff(struct edit_baton_t *eb, iterpool)); else if (info->kind == svn_node_dir && diff_dirs) SVN_ERR(svn_wc__diff_local_only_dir(db, child_abspath, - child_relpath, depth_below_here, - eb->processor, dir_baton, - eb->diff_pristine, - eb->cancel_func, - eb->cancel_baton, - iterpool)); + child_relpath, depth_below_here, + moved_from_relpath, + eb->processor, dir_baton, + eb->diff_pristine, + eb->cancel_func, + eb->cancel_baton, + iterpool)); } } } @@ -873,6 +918,7 @@ svn_error_t * svn_wc__diff_local_only_file(svn_wc__db_t *db, const char *local_abspath, const char *relpath, + const char *moved_from_relpath, const svn_diff_tree_processor_t *processor, void *processor_parent_baton, svn_boolean_t diff_pristine, @@ -935,6 +981,7 @@ svn_wc__diff_local_only_file(svn_wc__db_t *db, { copyfrom_src = svn_diff__source_create(original_revision, scratch_pool); copyfrom_src->repos_relpath = original_repos_relpath; + copyfrom_src->moved_from_relpath = moved_from_relpath; } if (props_mod || !SVN_IS_VALID_REVNUM(revision)) @@ -1013,6 +1060,7 @@ svn_wc__diff_local_only_dir(svn_wc__db_t *db, const char *local_abspath, const char *relpath, svn_depth_t depth, + const char *moved_from_relpath, const svn_diff_tree_processor_t *processor, void *processor_parent_baton, svn_boolean_t diff_pristine, @@ -1049,6 +1097,7 @@ svn_wc__diff_local_only_dir(svn_wc__db_t *db, { copyfrom_src = svn_diff__source_create(original_revision, scratch_pool); copyfrom_src->repos_relpath = original_repos_relpath; + copyfrom_src->moved_from_relpath = moved_from_relpath; } /* svn_wc__db_status_incomplete should never happen, as the result won't be @@ -1136,12 +1185,40 @@ svn_wc__diff_local_only_dir(svn_wc__db_t *db, child_relpath = svn_relpath_join(relpath, name, iterpool); + if (info->moved_here) + { + const char *moved_from_abspath; + const char *a_abspath; + const char *a_relpath; + + a_relpath = relpath; + a_abspath = local_abspath; + while (*a_relpath) + { + a_relpath = svn_relpath_dirname(a_relpath, iterpool); + a_abspath = svn_dirent_dirname(a_abspath, iterpool); + } + + SVN_ERR(svn_wc__db_scan_moved(&moved_from_abspath, + NULL, NULL, NULL, + db, child_abspath, + iterpool, iterpool)); + SVN_ERR_ASSERT(moved_from_abspath != NULL); + + moved_from_relpath = svn_dirent_skip_ancestor( + a_abspath, + moved_from_abspath); + } + else + moved_from_relpath = NULL; + switch (info->kind) { case svn_node_file: case svn_node_symlink: SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath, child_relpath, + moved_from_relpath, processor, pdb, diff_pristine, cancel_func, cancel_baton, @@ -1154,6 +1231,7 @@ svn_wc__diff_local_only_dir(svn_wc__db_t *db, SVN_ERR(svn_wc__diff_local_only_dir(db, child_abspath, child_relpath, depth_below_here, + moved_from_relpath, processor, pdb, diff_pristine, cancel_func, @@ -1202,6 +1280,8 @@ handle_local_only(struct dir_baton_t *pb, { struct edit_baton_t *eb = pb->eb; const struct svn_wc__db_info_t *info; + const char *child_abspath; + const char *moved_from_relpath; svn_boolean_t repos_delete = (pb->deletes && svn_hash_gets(pb->deletes, name)); @@ -1220,10 +1300,8 @@ handle_local_only(struct dir_baton_t *pb, switch (info->status) { - case svn_wc__db_status_incomplete: - return SVN_NO_ERROR; /* Not local only */ - case svn_wc__db_status_normal: + case svn_wc__db_status_incomplete: if (!repos_delete) return SVN_NO_ERROR; /* Local and remote */ svn_hash_sets(pb->deletes, name, NULL); @@ -1239,6 +1317,25 @@ handle_local_only(struct dir_baton_t *pb, break; } + child_abspath = svn_dirent_join(pb->local_abspath, name, scratch_pool); + + if (info->moved_here) + { + const char *moved_from_abspath; + + SVN_ERR(svn_wc__db_scan_moved(&moved_from_abspath, + NULL, NULL, NULL, + eb->db, child_abspath, + scratch_pool, scratch_pool)); + SVN_ERR_ASSERT(moved_from_abspath != NULL); + + moved_from_relpath = svn_dirent_skip_ancestor( + eb->anchor_abspath, + moved_from_abspath); + } + else + moved_from_relpath = NULL; + if (info->kind == svn_node_dir) { svn_depth_t depth ; @@ -1250,9 +1347,10 @@ handle_local_only(struct dir_baton_t *pb, SVN_ERR(svn_wc__diff_local_only_dir( eb->db, - svn_dirent_join(pb->local_abspath, name, scratch_pool), + child_abspath, svn_relpath_join(pb->relpath, name, scratch_pool), repos_delete ? svn_depth_infinity : depth, + moved_from_relpath, eb->processor, pb->pdb, eb->diff_pristine, eb->cancel_func, eb->cancel_baton, @@ -1261,8 +1359,9 @@ handle_local_only(struct dir_baton_t *pb, else SVN_ERR(svn_wc__diff_local_only_file( eb->db, - svn_dirent_join(pb->local_abspath, name, scratch_pool), + child_abspath, svn_relpath_join(pb->relpath, name, scratch_pool), + moved_from_relpath, eb->processor, pb->pdb, eb->diff_pristine, eb->cancel_func, eb->cancel_baton, @@ -1608,25 +1707,47 @@ open_directory(const char *path, db->repos_only = TRUE; if (!db->repos_only) - switch (info->status) - { - case svn_wc__db_status_normal: - break; - case svn_wc__db_status_deleted: - db->repos_only = TRUE; - - if (!info->have_more_work) - svn_hash_sets(pb->compared, - apr_pstrdup(pb->pool, db->name), ""); - break; - case svn_wc__db_status_added: - if (eb->ignore_ancestry) - db->ignoring_ancestry = TRUE; - else + { + switch (info->status) + { + case svn_wc__db_status_normal: + case svn_wc__db_status_incomplete: + db->is_incomplete = (info->status == + svn_wc__db_status_incomplete); + break; + case svn_wc__db_status_deleted: db->repos_only = TRUE; - break; - default: - SVN_ERR_MALFUNCTION(); + + if (!info->have_more_work) + svn_hash_sets(pb->compared, + apr_pstrdup(pb->pool, db->name), ""); + break; + case svn_wc__db_status_added: + if (eb->ignore_ancestry) + db->ignoring_ancestry = TRUE; + else + db->repos_only = TRUE; + break; + default: + SVN_ERR_MALFUNCTION(); + } + + if (info->status == svn_wc__db_status_added + || info->status == svn_wc__db_status_deleted) + { + svn_wc__db_status_t base_status; + + /* Node is shadowed; check BASE */ + SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + eb->db, db->local_abspath, + dir_pool, dir_pool)); + + if (base_status == svn_wc__db_status_incomplete) + db->is_incomplete = TRUE; + } } if (!db->repos_only) @@ -1714,7 +1835,7 @@ close_directory(void *dir_baton, { apr_hash_t *repos_props; - if (db->added) + if (db->added || db->is_incomplete) { repos_props = apr_hash_make(scratch_pool); } @@ -1891,6 +2012,7 @@ open_file(const char *path, switch (info->status) { case svn_wc__db_status_normal: + case svn_wc__db_status_incomplete: break; case svn_wc__db_status_deleted: fb->repos_only = TRUE; diff --git a/subversion/libsvn_wc/diff_local.c b/subversion/libsvn_wc/diff_local.c index e1cb3294b4ba..61ec06767e3a 100644 --- a/subversion/libsvn_wc/diff_local.c +++ b/subversion/libsvn_wc/diff_local.c @@ -281,7 +281,8 @@ diff_status_callback(void *baton, { local_only = TRUE; /* Only report additions */ } - else if (db_status == svn_wc__db_status_normal) + else if (db_status == svn_wc__db_status_normal + || db_status == svn_wc__db_status_incomplete) { /* Simple diff */ base_kind = db_kind; @@ -297,7 +298,8 @@ diff_status_callback(void *baton, eb->db, local_abspath, scratch_pool, scratch_pool)); - if (base_status != svn_wc__db_status_normal) + if (base_status != svn_wc__db_status_normal + && base_status != svn_wc__db_status_incomplete) return SVN_NO_ERROR; } else @@ -312,7 +314,8 @@ diff_status_callback(void *baton, eb->db, local_abspath, scratch_pool, scratch_pool)); - if (base_status != svn_wc__db_status_normal) + if (base_status != svn_wc__db_status_normal + && base_status != svn_wc__db_status_incomplete) local_only = TRUE; else if (base_kind != db_kind || !eb->ignore_ancestry) { @@ -388,9 +391,20 @@ diff_status_callback(void *baton, if (local_only && (db_status != svn_wc__db_status_deleted)) { + /* Moved from. Relative from diff anchor*/ + const char *moved_from_relpath = NULL; + + if (status->moved_from_abspath) + { + moved_from_relpath = svn_dirent_skip_ancestor( + eb->anchor_abspath, + status->moved_from_abspath); + } + if (db_kind == svn_node_file) SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath, child_relpath, + moved_from_relpath, eb->processor, eb->cur ? eb->cur->baton : NULL, FALSE, @@ -400,6 +414,7 @@ diff_status_callback(void *baton, else if (db_kind == svn_node_dir) SVN_ERR(svn_wc__diff_local_only_dir(db, child_abspath, child_relpath, depth_below_here, + moved_from_relpath, eb->processor, eb->cur ? eb->cur->baton : NULL, FALSE, diff --git a/subversion/libsvn_wc/entries.c b/subversion/libsvn_wc/entries.c index 1be6a8bec870..5748aa3cb857 100644 --- a/subversion/libsvn_wc/entries.c +++ b/subversion/libsvn_wc/entries.c @@ -1800,7 +1800,7 @@ write_entry(struct write_baton **entry_node, normal replace+copied base base+work add+copied replace+copied work work+work - although obviously the node is a directory rather then a file. + although obviously the node is a directory rather than a file. There are then more conversion states where the parent is replaced. @@ -2004,7 +2004,7 @@ write_entry(struct write_baton **entry_node, if (entry_node && entry->tree_conflict_data) { /* Issues #3840/#3916: 1.6 stores multiple tree conflicts on the - parent node, 1.7 stores them directly on the conflited nodes. + parent node, 1.7 stores them directly on the conflicted nodes. So "((skel1) (skel2))" becomes "(skel1)" and "(skel2)" */ svn_skel_t *skel; diff --git a/subversion/libsvn_wc/externals.c b/subversion/libsvn_wc/externals.c index 4cbd4f0e4b26..be42cdf4fb58 100644 --- a/subversion/libsvn_wc/externals.c +++ b/subversion/libsvn_wc/externals.c @@ -475,6 +475,8 @@ struct edit_baton /* Introducing a new file external */ svn_boolean_t added; + svn_wc_conflict_resolver_func2_t conflict_func; + void *conflict_baton; svn_cancel_func_t cancel_func; void *cancel_baton; svn_wc_notify_func2_t notify_func; @@ -963,6 +965,18 @@ close_file(void *file_baton, /* Run the work queue to complete the installation */ SVN_ERR(svn_wc__wq_run(eb->db, eb->wri_abspath, eb->cancel_func, eb->cancel_baton, pool)); + + if (conflict_skel && eb->conflict_func) + SVN_ERR(svn_wc__conflict_invoke_resolver(eb->db, + eb->local_abspath, + svn_node_file, + conflict_skel, + NULL /* merge_options */, + eb->conflict_func, + eb->conflict_baton, + eb->cancel_func, + eb->cancel_baton, + pool)); } /* Notify */ @@ -1053,6 +1067,8 @@ svn_wc__get_file_external_editor(const svn_delta_editor_t **editor, const char *recorded_url, const svn_opt_revision_t *recorded_peg_rev, const svn_opt_revision_t *recorded_rev, + svn_wc_conflict_resolver_func2_t conflict_func, + void *conflict_baton, svn_cancel_func_t cancel_func, void *cancel_baton, svn_wc_notify_func2_t notify_func, @@ -1104,6 +1120,8 @@ svn_wc__get_file_external_editor(const svn_delta_editor_t **editor, else eb->recorded_revision = SVN_INVALID_REVNUM; /* Not fixed/HEAD */ + eb->conflict_func = conflict_func; + eb->conflict_baton = conflict_baton; eb->cancel_func = cancel_func; eb->cancel_baton = cancel_baton; eb->notify_func = notify_func; diff --git a/subversion/libsvn_wc/node.c b/subversion/libsvn_wc/node.c index 560a899ea043..586477637274 100644 --- a/subversion/libsvn_wc/node.c +++ b/subversion/libsvn_wc/node.c @@ -906,7 +906,8 @@ svn_wc__rename_wc(svn_wc_context_t *wc_ctx, { SVN_ERR(svn_wc__db_drop_root(wc_ctx->db, wcroot_abspath, scratch_pool)); - SVN_ERR(svn_io_file_rename(from_abspath, dst_abspath, scratch_pool)); + SVN_ERR(svn_io_file_rename2(from_abspath, dst_abspath, FALSE, + scratch_pool)); } else return svn_error_createf( diff --git a/subversion/libsvn_wc/old-and-busted.c b/subversion/libsvn_wc/old-and-busted.c index 8cd94af2733b..b2e8d240f15e 100644 --- a/subversion/libsvn_wc/old-and-busted.c +++ b/subversion/libsvn_wc/old-and-busted.c @@ -1203,7 +1203,8 @@ svn_wc__read_entries_old(apr_hash_t **entries, /* Open the entries file. */ SVN_ERR(svn_wc__open_adm_stream(&stream, dir_abspath, SVN_WC__ADM_ENTRIES, scratch_pool, scratch_pool)); - SVN_ERR(svn_string_from_stream(&buf, stream, scratch_pool, scratch_pool)); + SVN_ERR(svn_string_from_stream2(&buf, stream, SVN__STREAM_CHUNK_SIZE, + scratch_pool)); /* We own the returned data; it is modifiable, so cast away... */ curp = (char *)buf->data; diff --git a/subversion/libsvn_wc/props.c b/subversion/libsvn_wc/props.c index 664bcf170664..f56899d86002 100644 --- a/subversion/libsvn_wc/props.c +++ b/subversion/libsvn_wc/props.c @@ -2170,11 +2170,8 @@ svn_wc_canonicalize_svn_prop(const svn_string_t **propval_p, /* Keep this static, it may get stored (for read-only purposes) in a hash that outlives this function. */ - static const svn_string_t boolean_value = - { - SVN_PROP_BOOLEAN_TRUE, - sizeof(SVN_PROP_BOOLEAN_TRUE) - 1 - }; + static const svn_string_t boolean_value + = SVN__STATIC_STRING(SVN_PROP_BOOLEAN_TRUE); SVN_ERR(validate_prop_against_node_kind(propname, path, kind, pool)); diff --git a/subversion/libsvn_wc/status.c b/subversion/libsvn_wc/status.c index 83fd3d4a377b..b8cbc0ed30d9 100644 --- a/subversion/libsvn_wc/status.c +++ b/subversion/libsvn_wc/status.c @@ -69,6 +69,7 @@ typedef struct svn_wc__internal_status_t svn_wc_status3_t s; /* First member; same pointer*/ svn_boolean_t has_descendants; + svn_boolean_t op_root; /* Make sure to update hash_stash() when adding values here */ } svn_wc__internal_status_t; @@ -587,7 +588,8 @@ assemble_status(svn_wc__internal_status_t **status, This filter should match the filter in is_sendable_status() */ if (! get_all) if (((node_status == svn_wc_status_none) - || (node_status == svn_wc_status_normal)) + || (node_status == svn_wc_status_normal) + || (node_status == svn_wc_status_deleted && !info->op_root)) && (! switched_p) && (! info->locked) @@ -606,6 +608,7 @@ assemble_status(svn_wc__internal_status_t **status, inner_stat = apr_pcalloc(result_pool, sizeof(*inner_stat)); stat = &inner_stat->s; inner_stat->has_descendants = info->has_descendants; + inner_stat->op_root = info->op_root; switch (info->kind) { @@ -1484,6 +1487,7 @@ hash_stash(void *baton, /* Copy the internal/private data. */ svn_wc__internal_status_t *is = new_status; is->has_descendants = old_status->has_descendants; + is->op_root = old_status->op_root; assert(! svn_hash_gets(stat_hash, path)); svn_hash_sets(stat_hash, apr_pstrdup(hash_pool, path), new_status); @@ -1865,7 +1869,9 @@ is_sendable_status(const svn_wc__internal_status_t *i_status, /* If the text, property or tree state is interesting, send it. */ if ((status->node_status != svn_wc_status_none) - && (status->node_status != svn_wc_status_normal)) + && (status->node_status != svn_wc_status_normal) + && !(status->node_status == svn_wc_status_deleted + && !i_status->op_root)) return TRUE; /* If it's switched, send it. */ diff --git a/subversion/libsvn_wc/translate.c b/subversion/libsvn_wc/translate.c index 0e16235d7827..bc5db887e24d 100644 --- a/subversion/libsvn_wc/translate.c +++ b/subversion/libsvn_wc/translate.c @@ -440,3 +440,20 @@ svn_wc__sync_flags_with_props(svn_boolean_t *did_set, return SVN_NO_ERROR; } + +svn_error_t * +svn_wc__translated_stream(svn_stream_t **stream, + svn_wc_context_t *wc_ctx, + const char *local_abspath, + const char *versioned_abspath, + apr_uint32_t flags, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + return svn_error_trace( + svn_wc__internal_translated_stream(stream, wc_ctx->db, + local_abspath, + versioned_abspath, + flags, result_pool, + scratch_pool)); +} diff --git a/subversion/libsvn_wc/upgrade.c b/subversion/libsvn_wc/upgrade.c index aebf4eb1eb88..3b9ab3a35319 100644 --- a/subversion/libsvn_wc/upgrade.c +++ b/subversion/libsvn_wc/upgrade.c @@ -535,7 +535,7 @@ svn_wc__wipe_postupgrade(const char *dir_abspath, int i; if (cancel_func) - SVN_ERR((*cancel_func)(cancel_baton)); + SVN_ERR(cancel_func(cancel_baton)); err = get_versioned_subdirs(&subdirs, &delete_dir, dir_abspath, TRUE, scratch_pool, iterpool); @@ -653,178 +653,6 @@ ensure_repos_info(svn_wc_entry_t *entry, } -/* - * Read tree conflict descriptions from @a conflict_data. Set @a *conflicts - * to a hash of pointers to svn_wc_conflict_description2_t objects indexed by - * svn_wc_conflict_description2_t.local_abspath, all newly allocated in @a - * pool. @a dir_path is the path to the working copy directory whose conflicts - * are being read. The conflicts read are the tree conflicts on the immediate - * child nodes of @a dir_path. Do all allocations in @a pool. - * - * Note: There were some concerns about this function: - * - * ### this is BAD. the CONFLICTS structure should not be dependent upon - * ### DIR_PATH. each conflict should be labeled with an entry name, not - * ### a whole path. (and a path which happens to vary based upon invocation - * ### of the user client and these APIs) - * - * those assumptions were baked into former versions of the data model, so - * they have to stick around here. But they have been removed from the - * New Way. */ -static svn_error_t * -read_tree_conflicts(apr_hash_t **conflicts, - const char *conflict_data, - const char *dir_path, - apr_pool_t *pool) -{ - const svn_skel_t *skel; - apr_pool_t *iterpool; - - *conflicts = apr_hash_make(pool); - - if (conflict_data == NULL) - return SVN_NO_ERROR; - - skel = svn_skel__parse(conflict_data, strlen(conflict_data), pool); - if (skel == NULL) - return svn_error_create(SVN_ERR_WC_CORRUPT, NULL, - _("Error parsing tree conflict skel")); - - iterpool = svn_pool_create(pool); - for (skel = skel->children; skel != NULL; skel = skel->next) - { - const svn_wc_conflict_description2_t *conflict; - - svn_pool_clear(iterpool); - SVN_ERR(svn_wc__deserialize_conflict(&conflict, skel, dir_path, - pool, iterpool)); - if (conflict != NULL) - svn_hash_sets(*conflicts, - svn_dirent_basename(conflict->local_abspath, pool), - conflict); - } - svn_pool_destroy(iterpool); - - return SVN_NO_ERROR; -} - -/* */ -static svn_error_t * -migrate_single_tree_conflict_data(svn_sqlite__db_t *sdb, - const char *tree_conflict_data, - apr_int64_t wc_id, - const char *local_relpath, - apr_pool_t *scratch_pool) -{ - apr_hash_t *conflicts; - apr_hash_index_t *hi; - apr_pool_t *iterpool; - - SVN_ERR(read_tree_conflicts(&conflicts, tree_conflict_data, local_relpath, - scratch_pool)); - - iterpool = svn_pool_create(scratch_pool); - for (hi = apr_hash_first(scratch_pool, conflicts); - hi; - hi = apr_hash_next(hi)) - { - const svn_wc_conflict_description2_t *conflict = apr_hash_this_val(hi); - const char *conflict_relpath; - const char *conflict_data; - svn_sqlite__stmt_t *stmt; - svn_boolean_t have_row; - svn_skel_t *skel; - - svn_pool_clear(iterpool); - - conflict_relpath = svn_dirent_join(local_relpath, - svn_dirent_basename( - conflict->local_abspath, iterpool), - iterpool); - - SVN_ERR(svn_wc__serialize_conflict(&skel, conflict, iterpool, iterpool)); - conflict_data = svn_skel__unparse(skel, iterpool)->data; - - /* See if we need to update or insert an ACTUAL node. */ - SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_SELECT_ACTUAL_NODE)); - SVN_ERR(svn_sqlite__bindf(stmt, "is", wc_id, conflict_relpath)); - SVN_ERR(svn_sqlite__step(&have_row, stmt)); - SVN_ERR(svn_sqlite__reset(stmt)); - - if (have_row) - { - /* There is an existing ACTUAL row, so just update it. */ - SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, - STMT_UPDATE_ACTUAL_CONFLICT)); - } - else - { - /* We need to insert an ACTUAL row with the tree conflict data. */ - SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, - STMT_INSERT_ACTUAL_CONFLICT)); - } - - SVN_ERR(svn_sqlite__bindf(stmt, "iss", wc_id, conflict_relpath, - conflict_data)); - if (!have_row) - SVN_ERR(svn_sqlite__bind_text(stmt, 4, local_relpath)); - - SVN_ERR(svn_sqlite__step_done(stmt)); - } - - svn_pool_destroy(iterpool); - - return SVN_NO_ERROR; -} - - -/* */ -static svn_error_t * -migrate_tree_conflict_data(svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool) -{ - svn_sqlite__stmt_t *stmt; - svn_boolean_t have_row; - apr_pool_t *iterpool = svn_pool_create(scratch_pool); - - /* Iterate over each node which has a set of tree conflicts, then insert - all of them into the new schema. */ - - SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, - STMT_UPGRADE_21_SELECT_OLD_TREE_CONFLICT)); - - /* Get all the existing tree conflict data. */ - SVN_ERR(svn_sqlite__step(&have_row, stmt)); - while (have_row) - { - apr_int64_t wc_id; - const char *local_relpath; - const char *tree_conflict_data; - - svn_pool_clear(iterpool); - - wc_id = svn_sqlite__column_int64(stmt, 0); - local_relpath = svn_sqlite__column_text(stmt, 1, iterpool); - tree_conflict_data = svn_sqlite__column_text(stmt, 2, iterpool); - - SVN_ERR(migrate_single_tree_conflict_data(sdb, tree_conflict_data, - wc_id, local_relpath, - iterpool)); - - /* We don't need to do anything but step over the previously - prepared statement. */ - SVN_ERR(svn_sqlite__step(&have_row, stmt)); - } - SVN_ERR(svn_sqlite__reset(stmt)); - - /* Erase all the old tree conflict data. */ - SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, - STMT_UPGRADE_21_ERASE_OLD_CONFLICTS)); - SVN_ERR(svn_sqlite__step_done(stmt)); - - svn_pool_destroy(iterpool); - return SVN_NO_ERROR; -} - /* ### need much more docco ### this function should be called within a sqlite transaction. it makes @@ -1318,234 +1146,6 @@ migrate_text_bases(apr_hash_t **text_bases_info, return SVN_NO_ERROR; } -static svn_error_t * -bump_to_20(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool) -{ - SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_CREATE_NODES)); - SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_20)); - return SVN_NO_ERROR; -} - -static svn_error_t * -bump_to_21(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool) -{ - SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_21)); - SVN_ERR(migrate_tree_conflict_data(sdb, scratch_pool)); - return SVN_NO_ERROR; -} - -static svn_error_t * -bump_to_22(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool) -{ - SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_22)); - return SVN_NO_ERROR; -} - -static svn_error_t * -bump_to_23(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool) -{ - const char *wcroot_abspath = ((struct bump_baton *)baton)->wcroot_abspath; - svn_sqlite__stmt_t *stmt; - svn_boolean_t have_row; - - SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, - STMT_UPGRADE_23_HAS_WORKING_NODES)); - SVN_ERR(svn_sqlite__step(&have_row, stmt)); - SVN_ERR(svn_sqlite__reset(stmt)); - if (have_row) - return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL, - _("The working copy at '%s' is format 22 with " - "WORKING nodes; use a format 22 client to " - "diff/revert before using this client"), - wcroot_abspath); - - SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_23)); - return SVN_NO_ERROR; -} - -static svn_error_t * -bump_to_24(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool) -{ - SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_24)); - SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_CREATE_NODES_TRIGGERS)); - return SVN_NO_ERROR; -} - -static svn_error_t * -bump_to_25(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool) -{ - SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_25)); - return SVN_NO_ERROR; -} - -static svn_error_t * -bump_to_26(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool) -{ - SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_26)); - return SVN_NO_ERROR; -} - -static svn_error_t * -bump_to_27(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool) -{ - const char *wcroot_abspath = ((struct bump_baton *)baton)->wcroot_abspath; - svn_sqlite__stmt_t *stmt; - svn_boolean_t have_row; - - SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, - STMT_UPGRADE_27_HAS_ACTUAL_NODES_CONFLICTS)); - SVN_ERR(svn_sqlite__step(&have_row, stmt)); - SVN_ERR(svn_sqlite__reset(stmt)); - if (have_row) - return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL, - _("The working copy at '%s' is format 26 with " - "conflicts; use a format 26 client to resolve " - "before using this client"), - wcroot_abspath); - SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_27)); - return SVN_NO_ERROR; -} - -static svn_error_t * -bump_to_28(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool) -{ - SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_28)); - return SVN_NO_ERROR; -} - -/* If FINFO indicates that ABSPATH names a file, rename it to - * '.svn-base'. - * - * Ignore any file whose name is not the expected length, in order to make - * life easier for any developer who runs this code twice or has some - * non-standard files in the pristine directory. - * - * A callback for bump_to_29(), implementing #svn_io_walk_func_t. */ -static svn_error_t * -rename_pristine_file(void *baton, - const char *abspath, - const apr_finfo_t *finfo, - apr_pool_t *pool) -{ - if (finfo->filetype == APR_REG - && (strlen(svn_dirent_basename(abspath, pool)) - == PRISTINE_BASENAME_OLD_LEN)) - { - const char *new_abspath - = apr_pstrcat(pool, abspath, PRISTINE_STORAGE_EXT, SVN_VA_NULL); - - SVN_ERR(svn_io_file_rename(abspath, new_abspath, pool)); - } - return SVN_NO_ERROR; -} - -static svn_error_t * -upgrade_externals(struct bump_baton *bb, - svn_sqlite__db_t *sdb, - apr_pool_t *scratch_pool) -{ - svn_sqlite__stmt_t *stmt; - svn_sqlite__stmt_t *stmt_add; - svn_boolean_t have_row; - apr_pool_t *iterpool; - - SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, - STMT_SELECT_EXTERNAL_PROPERTIES)); - - SVN_ERR(svn_sqlite__get_statement(&stmt_add, sdb, - STMT_INSERT_EXTERNAL)); - - /* ### For this intermediate upgrade we just assume WC_ID = 1. - ### Before this bump we lost track of externals all the time, - ### so lets keep this easy. */ - SVN_ERR(svn_sqlite__bindf(stmt, "is", (apr_int64_t)1, "")); - - SVN_ERR(svn_sqlite__step(&have_row, stmt)); - - iterpool = svn_pool_create(scratch_pool); - while (have_row) - { - apr_hash_t *props; - const char *externals; - - svn_pool_clear(iterpool); - - SVN_ERR(svn_sqlite__column_properties(&props, stmt, 0, - iterpool, iterpool)); - - externals = svn_prop_get_value(props, SVN_PROP_EXTERNALS); - - if (externals) - { - apr_array_header_t *ext; - const char *local_relpath; - const char *local_abspath; - int i; - - local_relpath = svn_sqlite__column_text(stmt, 1, NULL); - local_abspath = svn_dirent_join(bb->wcroot_abspath, local_relpath, - iterpool); - - SVN_ERR(svn_wc_parse_externals_description3(&ext, local_abspath, - externals, FALSE, - iterpool)); - - for (i = 0; i < ext->nelts; i++) - { - const svn_wc_external_item2_t *item; - const char *item_relpath; - - item = APR_ARRAY_IDX(ext, i, const svn_wc_external_item2_t *); - item_relpath = svn_relpath_join(local_relpath, item->target_dir, - iterpool); - - /* Insert dummy externals definitions: Insert an unknown - external, to make sure it will be cleaned up when it is not - updated on the next update. */ - SVN_ERR(svn_sqlite__bindf(stmt_add, "isssssis", - (apr_int64_t)1, /* wc_id */ - item_relpath, - svn_relpath_dirname(item_relpath, - iterpool), - "normal", - "unknown", - local_relpath, - (apr_int64_t)1, /* repos_id */ - "" /* repos_relpath */)); - SVN_ERR(svn_sqlite__insert(NULL, stmt_add)); - } - } - - SVN_ERR(svn_sqlite__step(&have_row, stmt)); - } - - svn_pool_destroy(iterpool); - return svn_error_trace(svn_sqlite__reset(stmt)); -} - -static svn_error_t * -bump_to_29(void *baton, svn_sqlite__db_t *sdb, apr_pool_t *scratch_pool) -{ - struct bump_baton *bb = baton; - const char *wcroot_abspath = bb->wcroot_abspath; - const char *pristine_dir_abspath; - - /* Rename all pristine files, adding a ".svn-base" suffix. */ - pristine_dir_abspath = svn_dirent_join_many(scratch_pool, wcroot_abspath, - svn_wc_get_adm_dir(scratch_pool), - PRISTINE_STORAGE_RELPATH, - SVN_VA_NULL); - SVN_ERR(svn_io_dir_walk2(pristine_dir_abspath, APR_FINFO_MIN, - rename_pristine_file, NULL, scratch_pool)); - - /* Externals */ - SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_CREATE_EXTERNALS)); - - SVN_ERR(upgrade_externals(bb, sdb, scratch_pool)); - SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_29)); - return SVN_NO_ERROR; -} - svn_error_t * svn_wc__upgrade_conflict_skel_from_raw(svn_skel_t **conflicts, svn_wc__db_t *db, @@ -1774,41 +1374,10 @@ bump_to_31(void *baton, apr_pool_t *iterpool = svn_pool_create(scratch_pool); apr_array_header_t *empty_iprops = apr_array_make( scratch_pool, 0, sizeof(svn_prop_inherited_item_t *)); - svn_boolean_t iprops_column_exists = FALSE; svn_error_t *err; - /* Add the inherited_props column to NODES if it does not yet exist. - * - * When using a format >= 31 client to upgrade from old formats which - * did not yet have a NODES table, the inherited_props column has - * already been created as part of the NODES table. Attemping to add - * the inherited_props column will raise an error in this case, so check - * if the column exists first. - * - * Checking for the existence of a column before ALTER TABLE is not - * possible within SQLite. We need to run a separate query and evaluate - * its result in C first. - */ - SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_PRAGMA_TABLE_INFO_NODES)); - SVN_ERR(svn_sqlite__step(&have_row, stmt)); - while (have_row) - { - const char *column_name = svn_sqlite__column_text(stmt, 1, NULL); - - if (strcmp(column_name, "inherited_props") == 0) - { - iprops_column_exists = TRUE; - break; - } - - SVN_ERR(svn_sqlite__step(&have_row, stmt)); - } - SVN_ERR(svn_sqlite__reset(stmt)); - if (!iprops_column_exists) - SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_31_ALTER_TABLE)); - /* Run additional statements to finalize the upgrade to format 31. */ - SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_31_FINALIZE)); + SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_UPGRADE_TO_31)); /* Set inherited_props to an empty array for the roots of all switched subtrees in the WC. This allows subsequent updates @@ -2090,6 +1659,15 @@ svn_wc__upgrade_sdb(int *result_format, svn_dirent_local_style(wcroot_abspath, scratch_pool), start_format); + else if (start_format < 29) + return svn_error_createf(SVN_ERR_WC_UPGRADE_REQUIRED, NULL, + _("Working copy '%s' is an old development " + "version (format %d); to upgrade it, " + "use a Subversion 1.7-1.9 client, then " + "use the current client"), + svn_dirent_local_style(wcroot_abspath, + scratch_pool), + start_format); /* ### need lock-out. only one upgrade at a time. note that other code ### cannot use this un-upgraded database until we finish the upgrade. */ @@ -2098,66 +1676,6 @@ svn_wc__upgrade_sdb(int *result_format, intentional. */ switch (start_format) { - case 19: - SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_20, &bb, - scratch_pool)); - *result_format = 20; - /* FALLTHROUGH */ - - case 20: - SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_21, &bb, - scratch_pool)); - *result_format = 21; - /* FALLTHROUGH */ - - case 21: - SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_22, &bb, - scratch_pool)); - *result_format = 22; - /* FALLTHROUGH */ - - case 22: - SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_23, &bb, - scratch_pool)); - *result_format = 23; - /* FALLTHROUGH */ - - case 23: - SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_24, &bb, - scratch_pool)); - *result_format = 24; - /* FALLTHROUGH */ - - case 24: - SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_25, &bb, - scratch_pool)); - *result_format = 25; - /* FALLTHROUGH */ - - case 25: - SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_26, &bb, - scratch_pool)); - *result_format = 26; - /* FALLTHROUGH */ - - case 26: - SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_27, &bb, - scratch_pool)); - *result_format = 27; - /* FALLTHROUGH */ - - case 27: - SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_28, &bb, - scratch_pool)); - *result_format = 28; - /* FALLTHROUGH */ - - case 28: - SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_29, &bb, - scratch_pool)); - *result_format = 29; - /* FALLTHROUGH */ - case 29: SVN_ERR(svn_sqlite__with_transaction(sdb, bump_to_30, &bb, scratch_pool)); @@ -2513,7 +2031,7 @@ svn_wc_upgrade(svn_wc_context_t *wc_ctx, /* Renaming the db file is what makes the pre-wcng into a wcng */ db_from = svn_wc__adm_child(data.root_abspath, SDB_FILE, scratch_pool); db_to = svn_wc__adm_child(local_abspath, SDB_FILE, scratch_pool); - SVN_ERR(svn_io_file_rename(db_from, db_to, scratch_pool)); + SVN_ERR(svn_io_file_rename2(db_from, db_to, FALSE, scratch_pool)); /* Now we have a working wcng, tidy up the droppings */ SVN_ERR(svn_wc__db_open(&db, NULL /* ### config */, FALSE, FALSE, diff --git a/subversion/libsvn_wc/wc-checks.h b/subversion/libsvn_wc/wc-checks.h index e867506d4e9b..c1d356ced965 100644 --- a/subversion/libsvn_wc/wc-checks.h +++ b/subversion/libsvn_wc/wc-checks.h @@ -1,4 +1,4 @@ -/* This file is automatically generated from wc-checks.sql and .dist_sandbox/subversion-1.9.7/subversion/libsvn_wc/token-map.h. +/* This file is automatically generated from wc-checks.sql and /opt/svnrm/tempdir/subversion-1.10.0/subversion/libsvn_wc/token-map.h. * Do not edit this file -- edit the source and rerun gen-make.py */ #define STMT_VERIFICATION_TRIGGERS 0 diff --git a/subversion/libsvn_wc/wc-metadata.h b/subversion/libsvn_wc/wc-metadata.h index f548d9174d3a..98064242d706 100644 --- a/subversion/libsvn_wc/wc-metadata.h +++ b/subversion/libsvn_wc/wc-metadata.h @@ -1,4 +1,4 @@ -/* This file is automatically generated from wc-metadata.sql and .dist_sandbox/subversion-1.9.7/subversion/libsvn_wc/token-map.h. +/* This file is automatically generated from wc-metadata.sql and /opt/svnrm/tempdir/subversion-1.10.0/subversion/libsvn_wc/token-map.h. * Do not edit this file -- edit the source and rerun gen-make.py */ #define STMT_CREATE_SCHEMA 0 @@ -63,14 +63,6 @@ " locked_levels INTEGER NOT NULL DEFAULT -1, " \ " PRIMARY KEY (wc_id, local_dir_relpath) " \ " ); " \ - "PRAGMA user_version = " \ - APR_STRINGIFY(SVN_WC__VERSION) \ - "; " \ - "" - -#define STMT_CREATE_NODES 1 -#define STMT_1_INFO {"STMT_CREATE_NODES", NULL} -#define STMT_1 \ "CREATE TABLE NODES ( " \ " wc_id INTEGER NOT NULL REFERENCES WCROOT (id), " \ " local_relpath TEXT NOT NULL, " \ @@ -108,11 +100,6 @@ "CREATE VIEW NODES_BASE AS " \ " SELECT * FROM nodes " \ " WHERE op_depth = 0; " \ - "" - -#define STMT_CREATE_NODES_TRIGGERS 2 -#define STMT_2_INFO {"STMT_CREATE_NODES_TRIGGERS", NULL} -#define STMT_2 \ "CREATE TRIGGER nodes_insert_trigger " \ "AFTER INSERT ON nodes " \ "WHEN NEW.checksum IS NOT NULL " \ @@ -136,11 +123,6 @@ " UPDATE pristine SET refcount = refcount - 1 " \ " WHERE checksum = OLD.checksum; " \ "END; " \ - "" - -#define STMT_CREATE_EXTERNALS 3 -#define STMT_3_INFO {"STMT_CREATE_EXTERNALS", NULL} -#define STMT_3 \ "CREATE TABLE EXTERNALS ( " \ " wc_id INTEGER NOT NULL REFERENCES WCROOT (id), " \ " local_relpath TEXT NOT NULL, " \ @@ -157,11 +139,14 @@ "CREATE UNIQUE INDEX I_EXTERNALS_DEFINED ON EXTERNALS (wc_id, " \ " def_local_relpath, " \ " local_relpath); " \ + "PRAGMA user_version = " \ + APR_STRINGIFY(SVN_WC__VERSION) \ + "; " \ "" -#define STMT_INSTALL_SCHEMA_STATISTICS 4 -#define STMT_4_INFO {"STMT_INSTALL_SCHEMA_STATISTICS", NULL} -#define STMT_4 \ +#define STMT_INSTALL_SCHEMA_STATISTICS 1 +#define STMT_1_INFO {"STMT_INSTALL_SCHEMA_STATISTICS", NULL} +#define STMT_1 \ "ANALYZE sqlite_master; " \ "DELETE FROM sqlite_stat1 " \ "WHERE tbl in ('NODES', 'ACTUAL_NODE', 'LOCK', 'WC_LOCK', 'EXTERNALS'); " \ @@ -186,183 +171,9 @@ "ANALYZE sqlite_master; " \ "" -#define STMT_UPGRADE_TO_20 5 -#define STMT_5_INFO {"STMT_UPGRADE_TO_20", NULL} -#define STMT_5 \ - "UPDATE BASE_NODE SET checksum = (SELECT checksum FROM pristine " \ - " WHERE md5_checksum = BASE_NODE.checksum) " \ - "WHERE EXISTS (SELECT 1 FROM pristine WHERE md5_checksum = BASE_NODE.checksum); " \ - "UPDATE WORKING_NODE SET checksum = (SELECT checksum FROM pristine " \ - " WHERE md5_checksum = WORKING_NODE.checksum) " \ - "WHERE EXISTS (SELECT 1 FROM pristine " \ - " WHERE md5_checksum = WORKING_NODE.checksum); " \ - "INSERT INTO NODES ( " \ - " wc_id, local_relpath, op_depth, parent_relpath, " \ - " repos_id, repos_path, revision, " \ - " presence, depth, moved_here, moved_to, kind, " \ - " changed_revision, changed_date, changed_author, " \ - " checksum, properties, translated_size, last_mod_time, " \ - " dav_cache, symlink_target, file_external ) " \ - "SELECT wc_id, local_relpath, 0 , parent_relpath, " \ - " repos_id, repos_relpath, revnum, " \ - " presence, depth, NULL , NULL , kind, " \ - " changed_rev, changed_date, changed_author, " \ - " checksum, properties, translated_size, last_mod_time, " \ - " dav_cache, symlink_target, file_external " \ - "FROM BASE_NODE; " \ - "INSERT INTO NODES ( " \ - " wc_id, local_relpath, op_depth, parent_relpath, " \ - " repos_id, repos_path, revision, " \ - " presence, depth, moved_here, moved_to, kind, " \ - " changed_revision, changed_date, changed_author, " \ - " checksum, properties, translated_size, last_mod_time, " \ - " dav_cache, symlink_target, file_external ) " \ - "SELECT wc_id, local_relpath, 2 , parent_relpath, " \ - " copyfrom_repos_id, copyfrom_repos_path, copyfrom_revnum, " \ - " presence, depth, NULL , NULL , kind, " \ - " changed_rev, changed_date, changed_author, " \ - " checksum, properties, translated_size, last_mod_time, " \ - " NULL , symlink_target, NULL " \ - "FROM WORKING_NODE; " \ - "DROP TABLE BASE_NODE; " \ - "DROP TABLE WORKING_NODE; " \ - "PRAGMA user_version = 20; " \ - "" - -#define STMT_UPGRADE_TO_21 6 -#define STMT_6_INFO {"STMT_UPGRADE_TO_21", NULL} -#define STMT_6 \ - "PRAGMA user_version = 21; " \ - "" - -#define STMT_UPGRADE_21_SELECT_OLD_TREE_CONFLICT 7 -#define STMT_7_INFO {"STMT_UPGRADE_21_SELECT_OLD_TREE_CONFLICT", NULL} -#define STMT_7 \ - "SELECT wc_id, local_relpath, tree_conflict_data " \ - "FROM actual_node " \ - "WHERE tree_conflict_data IS NOT NULL " \ - "" - -#define STMT_UPGRADE_21_ERASE_OLD_CONFLICTS 8 -#define STMT_8_INFO {"STMT_UPGRADE_21_ERASE_OLD_CONFLICTS", NULL} -#define STMT_8 \ - "UPDATE actual_node SET tree_conflict_data = NULL " \ - "" - -#define STMT_UPGRADE_TO_22 9 -#define STMT_9_INFO {"STMT_UPGRADE_TO_22", NULL} -#define STMT_9 \ - "UPDATE actual_node SET tree_conflict_data = conflict_data; " \ - "UPDATE actual_node SET conflict_data = NULL; " \ - "PRAGMA user_version = 22; " \ - "" - -#define STMT_UPGRADE_TO_23 10 -#define STMT_10_INFO {"STMT_UPGRADE_TO_23", NULL} -#define STMT_10 \ - "PRAGMA user_version = 23; " \ - "" - -#define STMT_UPGRADE_23_HAS_WORKING_NODES 11 -#define STMT_11_INFO {"STMT_UPGRADE_23_HAS_WORKING_NODES", NULL} -#define STMT_11 \ - "SELECT 1 FROM nodes WHERE op_depth > 0 " \ - "LIMIT 1 " \ - "" - -#define STMT_UPGRADE_TO_24 12 -#define STMT_12_INFO {"STMT_UPGRADE_TO_24", NULL} -#define STMT_12 \ - "UPDATE pristine SET refcount = " \ - " (SELECT COUNT(*) FROM nodes " \ - " WHERE checksum = pristine.checksum ); " \ - "PRAGMA user_version = 24; " \ - "" - -#define STMT_UPGRADE_TO_25 13 -#define STMT_13_INFO {"STMT_UPGRADE_TO_25", NULL} -#define STMT_13 \ - "DROP VIEW IF EXISTS NODES_CURRENT; " \ - "CREATE VIEW NODES_CURRENT AS " \ - " SELECT * FROM nodes " \ - " JOIN (SELECT wc_id, local_relpath, MAX(op_depth) AS op_depth FROM nodes " \ - " GROUP BY wc_id, local_relpath) AS filter " \ - " ON nodes.wc_id = filter.wc_id " \ - " AND nodes.local_relpath = filter.local_relpath " \ - " AND nodes.op_depth = filter.op_depth; " \ - "PRAGMA user_version = 25; " \ - "" - -#define STMT_UPGRADE_TO_26 14 -#define STMT_14_INFO {"STMT_UPGRADE_TO_26", NULL} -#define STMT_14 \ - "DROP VIEW IF EXISTS NODES_BASE; " \ - "CREATE VIEW NODES_BASE AS " \ - " SELECT * FROM nodes " \ - " WHERE op_depth = 0; " \ - "PRAGMA user_version = 26; " \ - "" - -#define STMT_UPGRADE_TO_27 15 -#define STMT_15_INFO {"STMT_UPGRADE_TO_27", NULL} -#define STMT_15 \ - "PRAGMA user_version = 27; " \ - "" - -#define STMT_UPGRADE_27_HAS_ACTUAL_NODES_CONFLICTS 16 -#define STMT_16_INFO {"STMT_UPGRADE_27_HAS_ACTUAL_NODES_CONFLICTS", NULL} -#define STMT_16 \ - "SELECT 1 FROM actual_node " \ - "WHERE NOT ((prop_reject IS NULL) AND (conflict_old IS NULL) " \ - " AND (conflict_new IS NULL) AND (conflict_working IS NULL) " \ - " AND (tree_conflict_data IS NULL)) " \ - "LIMIT 1 " \ - "" - -#define STMT_UPGRADE_TO_28 17 -#define STMT_17_INFO {"STMT_UPGRADE_TO_28", NULL} -#define STMT_17 \ - "UPDATE NODES SET checksum = (SELECT checksum FROM pristine " \ - " WHERE md5_checksum = nodes.checksum) " \ - "WHERE EXISTS (SELECT 1 FROM pristine WHERE md5_checksum = nodes.checksum); " \ - "PRAGMA user_version = 28; " \ - "" - -#define STMT_UPGRADE_TO_29 18 -#define STMT_18_INFO {"STMT_UPGRADE_TO_29", NULL} -#define STMT_18 \ - "DROP TRIGGER IF EXISTS nodes_update_checksum_trigger; " \ - "DROP TRIGGER IF EXISTS nodes_insert_trigger; " \ - "DROP TRIGGER IF EXISTS nodes_delete_trigger; " \ - "CREATE TRIGGER nodes_update_checksum_trigger " \ - "AFTER UPDATE OF checksum ON nodes " \ - "WHEN NEW.checksum IS NOT OLD.checksum " \ - "BEGIN " \ - " UPDATE pristine SET refcount = refcount + 1 " \ - " WHERE checksum = NEW.checksum; " \ - " UPDATE pristine SET refcount = refcount - 1 " \ - " WHERE checksum = OLD.checksum; " \ - "END; " \ - "CREATE TRIGGER nodes_insert_trigger " \ - "AFTER INSERT ON nodes " \ - "WHEN NEW.checksum IS NOT NULL " \ - "BEGIN " \ - " UPDATE pristine SET refcount = refcount + 1 " \ - " WHERE checksum = NEW.checksum; " \ - "END; " \ - "CREATE TRIGGER nodes_delete_trigger " \ - "AFTER DELETE ON nodes " \ - "WHEN OLD.checksum IS NOT NULL " \ - "BEGIN " \ - " UPDATE pristine SET refcount = refcount - 1 " \ - " WHERE checksum = OLD.checksum; " \ - "END; " \ - "PRAGMA user_version = 29; " \ - "" - -#define STMT_UPGRADE_TO_30 19 -#define STMT_19_INFO {"STMT_UPGRADE_TO_30", NULL} -#define STMT_19 \ +#define STMT_UPGRADE_TO_30 2 +#define STMT_2_INFO {"STMT_UPGRADE_TO_30", NULL} +#define STMT_2 \ "CREATE UNIQUE INDEX IF NOT EXISTS I_NODES_MOVED " \ "ON NODES (wc_id, moved_to, op_depth); " \ "CREATE INDEX IF NOT EXISTS I_PRISTINE_MD5 ON PRISTINE (md5_checksum); " \ @@ -370,9 +181,9 @@ "UPDATE nodes SET file_external=1 WHERE file_external IS NOT NULL; " \ "" -#define STMT_UPGRADE_30_SELECT_CONFLICT_SEPARATE 20 -#define STMT_20_INFO {"STMT_UPGRADE_30_SELECT_CONFLICT_SEPARATE", NULL} -#define STMT_20 \ +#define STMT_UPGRADE_30_SELECT_CONFLICT_SEPARATE 3 +#define STMT_3_INFO {"STMT_UPGRADE_30_SELECT_CONFLICT_SEPARATE", NULL} +#define STMT_3 \ "SELECT wc_id, local_relpath, " \ " conflict_old, conflict_working, conflict_new, prop_reject, tree_conflict_data " \ "FROM actual_node " \ @@ -384,24 +195,19 @@ "ORDER by wc_id, local_relpath " \ "" -#define STMT_UPGRADE_30_SET_CONFLICT 21 -#define STMT_21_INFO {"STMT_UPGRADE_30_SET_CONFLICT", NULL} -#define STMT_21 \ +#define STMT_UPGRADE_30_SET_CONFLICT 4 +#define STMT_4_INFO {"STMT_UPGRADE_30_SET_CONFLICT", NULL} +#define STMT_4 \ "UPDATE actual_node SET conflict_data = ?3, conflict_old = NULL, " \ " conflict_working = NULL, conflict_new = NULL, prop_reject = NULL, " \ " tree_conflict_data = NULL " \ "WHERE wc_id = ?1 and local_relpath = ?2 " \ "" -#define STMT_UPGRADE_TO_31_ALTER_TABLE 22 -#define STMT_22_INFO {"STMT_UPGRADE_TO_31_ALTER_TABLE", NULL} -#define STMT_22 \ +#define STMT_UPGRADE_TO_31 5 +#define STMT_5_INFO {"STMT_UPGRADE_TO_31", NULL} +#define STMT_5 \ "ALTER TABLE NODES ADD COLUMN inherited_props BLOB; " \ - "" - -#define STMT_UPGRADE_TO_31_FINALIZE 23 -#define STMT_23_INFO {"STMT_UPGRADE_TO_31_FINALIZE", NULL} -#define STMT_23 \ "DROP INDEX IF EXISTS I_ACTUAL_CHANGELIST; " \ "DROP INDEX IF EXISTS I_EXTERNALS_PARENT; " \ "DROP INDEX I_NODES_PARENT; " \ @@ -413,9 +219,9 @@ "PRAGMA user_version = 31; " \ "" -#define STMT_UPGRADE_31_SELECT_WCROOT_NODES 24 -#define STMT_24_INFO {"STMT_UPGRADE_31_SELECT_WCROOT_NODES", NULL} -#define STMT_24 \ +#define STMT_UPGRADE_31_SELECT_WCROOT_NODES 6 +#define STMT_6_INFO {"STMT_UPGRADE_31_SELECT_WCROOT_NODES", NULL} +#define STMT_6 \ "SELECT l.wc_id, l.local_relpath FROM nodes as l " \ "LEFT OUTER JOIN nodes as r " \ "ON l.wc_id = r.wc_id " \ @@ -427,21 +233,6 @@ " OR (l.repos_path IS NOT (CASE WHEN (r.local_relpath) = '' THEN (CASE WHEN (r.repos_path) = '' THEN (l.local_relpath) WHEN (l.local_relpath) = '' THEN (r.repos_path) ELSE (r.repos_path) || '/' || (l.local_relpath) END) WHEN (r.repos_path) = '' THEN (CASE WHEN (r.local_relpath) = '' THEN (l.local_relpath) WHEN SUBSTR((l.local_relpath), 1, LENGTH(r.local_relpath)) = (r.local_relpath) THEN CASE WHEN LENGTH(r.local_relpath) = LENGTH(l.local_relpath) THEN '' WHEN SUBSTR((l.local_relpath), LENGTH(r.local_relpath)+1, 1) = '/' THEN SUBSTR((l.local_relpath), LENGTH(r.local_relpath)+2) END END) WHEN SUBSTR((l.local_relpath), 1, LENGTH(r.local_relpath)) = (r.local_relpath) THEN CASE WHEN LENGTH(r.local_relpath) = LENGTH(l.local_relpath) THEN (r.repos_path) WHEN SUBSTR((l.local_relpath), LENGTH(r.local_relpath)+1, 1) = '/' THEN (r.repos_path) || SUBSTR((l.local_relpath), LENGTH(r.local_relpath)+1) END END))) " \ "" -#define STMT_UPGRADE_TO_32 25 -#define STMT_25_INFO {"STMT_UPGRADE_TO_32", NULL} -#define STMT_25 \ - "DROP INDEX IF EXISTS I_ACTUAL_CHANGELIST; " \ - "DROP INDEX IF EXISTS I_EXTERNALS_PARENT; " \ - "CREATE INDEX I_EXTERNALS_PARENT ON EXTERNALS (wc_id, parent_relpath); " \ - "DROP INDEX I_NODES_PARENT; " \ - "CREATE UNIQUE INDEX I_NODES_PARENT ON NODES (wc_id, parent_relpath, " \ - " local_relpath, op_depth); " \ - "DROP INDEX I_ACTUAL_PARENT; " \ - "CREATE UNIQUE INDEX I_ACTUAL_PARENT ON ACTUAL_NODE (wc_id, parent_relpath, " \ - " local_relpath); " \ - "-- format: YYY " \ - "" - #define WC_METADATA_SQL_99 \ "CREATE TABLE ACTUAL_NODE_BACKUP ( " \ " wc_id INTEGER NOT NULL, " \ @@ -491,25 +282,6 @@ STMT_4, \ STMT_5, \ STMT_6, \ - STMT_7, \ - STMT_8, \ - STMT_9, \ - STMT_10, \ - STMT_11, \ - STMT_12, \ - STMT_13, \ - STMT_14, \ - STMT_15, \ - STMT_16, \ - STMT_17, \ - STMT_18, \ - STMT_19, \ - STMT_20, \ - STMT_21, \ - STMT_22, \ - STMT_23, \ - STMT_24, \ - STMT_25, \ NULL \ } @@ -522,24 +294,5 @@ STMT_4_INFO, \ STMT_5_INFO, \ STMT_6_INFO, \ - STMT_7_INFO, \ - STMT_8_INFO, \ - STMT_9_INFO, \ - STMT_10_INFO, \ - STMT_11_INFO, \ - STMT_12_INFO, \ - STMT_13_INFO, \ - STMT_14_INFO, \ - STMT_15_INFO, \ - STMT_16_INFO, \ - STMT_17_INFO, \ - STMT_18_INFO, \ - STMT_19_INFO, \ - STMT_20_INFO, \ - STMT_21_INFO, \ - STMT_22_INFO, \ - STMT_23_INFO, \ - STMT_24_INFO, \ - STMT_25_INFO, \ {NULL, NULL} \ } diff --git a/subversion/libsvn_wc/wc-metadata.sql b/subversion/libsvn_wc/wc-metadata.sql index f52df93f462a..e34cf1422e60 100644 --- a/subversion/libsvn_wc/wc-metadata.sql +++ b/subversion/libsvn_wc/wc-metadata.sql @@ -229,11 +229,6 @@ CREATE TABLE WC_LOCK ( ); -PRAGMA user_version = --- define: SVN_WC__VERSION -; - - /* ------------------------------------------------------------------------- */ /* The NODES table describes the way WORKING nodes are layered on top of @@ -279,7 +274,6 @@ PRAGMA user_version = An 'svn revert foo/bar' would remove the NODES of (2). */ --- STMT_CREATE_NODES CREATE TABLE NODES ( /* Working copy location related fields */ @@ -503,8 +497,6 @@ CREATE VIEW NODES_BASE AS SELECT * FROM nodes WHERE op_depth = 0; --- STMT_CREATE_NODES_TRIGGERS - CREATE TRIGGER nodes_insert_trigger AFTER INSERT ON nodes WHEN NEW.checksum IS NOT NULL @@ -532,8 +524,6 @@ BEGIN WHERE checksum = OLD.checksum; END; --- STMT_CREATE_EXTERNALS - CREATE TABLE EXTERNALS ( /* Working copy location related fields (like NODES)*/ @@ -572,6 +562,12 @@ CREATE UNIQUE INDEX I_EXTERNALS_DEFINED ON EXTERNALS (wc_id, def_local_relpath, local_relpath); + +PRAGMA user_version = +-- define: SVN_WC__VERSION +; + + /* ------------------------------------------------------------------------- */ /* This statement provides SQLite with the necessary information about our indexes to make better decisions in the query planner. @@ -630,208 +626,6 @@ INSERT INTO sqlite_stat1(tbl, idx, stat) VALUES ANALYZE sqlite_master; /* Loads sqlite_stat1 data for query optimizer */ /* ------------------------------------------------------------------------- */ -/* Format 20 introduces NODES and removes BASE_NODE and WORKING_NODE */ - --- STMT_UPGRADE_TO_20 - -UPDATE BASE_NODE SET checksum = (SELECT checksum FROM pristine - WHERE md5_checksum = BASE_NODE.checksum) -WHERE EXISTS (SELECT 1 FROM pristine WHERE md5_checksum = BASE_NODE.checksum); - -UPDATE WORKING_NODE SET checksum = (SELECT checksum FROM pristine - WHERE md5_checksum = WORKING_NODE.checksum) -WHERE EXISTS (SELECT 1 FROM pristine - WHERE md5_checksum = WORKING_NODE.checksum); - -INSERT INTO NODES ( - wc_id, local_relpath, op_depth, parent_relpath, - repos_id, repos_path, revision, - presence, depth, moved_here, moved_to, kind, - changed_revision, changed_date, changed_author, - checksum, properties, translated_size, last_mod_time, - dav_cache, symlink_target, file_external ) -SELECT wc_id, local_relpath, 0 /*op_depth*/, parent_relpath, - repos_id, repos_relpath, revnum, - presence, depth, NULL /*moved_here*/, NULL /*moved_to*/, kind, - changed_rev, changed_date, changed_author, - checksum, properties, translated_size, last_mod_time, - dav_cache, symlink_target, file_external -FROM BASE_NODE; -INSERT INTO NODES ( - wc_id, local_relpath, op_depth, parent_relpath, - repos_id, repos_path, revision, - presence, depth, moved_here, moved_to, kind, - changed_revision, changed_date, changed_author, - checksum, properties, translated_size, last_mod_time, - dav_cache, symlink_target, file_external ) -SELECT wc_id, local_relpath, 2 /*op_depth*/, parent_relpath, - copyfrom_repos_id, copyfrom_repos_path, copyfrom_revnum, - presence, depth, NULL /*moved_here*/, NULL /*moved_to*/, kind, - changed_rev, changed_date, changed_author, - checksum, properties, translated_size, last_mod_time, - NULL /*dav_cache*/, symlink_target, NULL /*file_external*/ -FROM WORKING_NODE; - -DROP TABLE BASE_NODE; -DROP TABLE WORKING_NODE; - -PRAGMA user_version = 20; - - -/* ------------------------------------------------------------------------- */ - -/* Format 21 involves no schema changes, it moves the tree conflict victim - information to victime nodes, rather than parents. */ - --- STMT_UPGRADE_TO_21 -PRAGMA user_version = 21; - -/* For format 21 bump code */ --- STMT_UPGRADE_21_SELECT_OLD_TREE_CONFLICT -SELECT wc_id, local_relpath, tree_conflict_data -FROM actual_node -WHERE tree_conflict_data IS NOT NULL - -/* For format 21 bump code */ --- STMT_UPGRADE_21_ERASE_OLD_CONFLICTS -UPDATE actual_node SET tree_conflict_data = NULL - -/* ------------------------------------------------------------------------- */ - -/* Format 22 simply moves the tree conflict information from the conflict_data - column to the tree_conflict_data column. */ - --- STMT_UPGRADE_TO_22 -UPDATE actual_node SET tree_conflict_data = conflict_data; -UPDATE actual_node SET conflict_data = NULL; - -PRAGMA user_version = 22; - - -/* ------------------------------------------------------------------------- */ - -/* Format 23 involves no schema changes, it introduces multi-layer - op-depth processing for NODES. */ - --- STMT_UPGRADE_TO_23 -PRAGMA user_version = 23; - --- STMT_UPGRADE_23_HAS_WORKING_NODES -SELECT 1 FROM nodes WHERE op_depth > 0 -LIMIT 1 - -/* ------------------------------------------------------------------------- */ - -/* Format 24 involves no schema changes; it starts using the pristine - table's refcount column correctly. */ - --- STMT_UPGRADE_TO_24 -UPDATE pristine SET refcount = - (SELECT COUNT(*) FROM nodes - WHERE checksum = pristine.checksum /*OR checksum = pristine.md5_checksum*/); - -PRAGMA user_version = 24; - -/* ------------------------------------------------------------------------- */ - -/* Format 25 introduces the NODES_CURRENT view. */ - --- STMT_UPGRADE_TO_25 -DROP VIEW IF EXISTS NODES_CURRENT; -CREATE VIEW NODES_CURRENT AS - SELECT * FROM nodes - JOIN (SELECT wc_id, local_relpath, MAX(op_depth) AS op_depth FROM nodes - GROUP BY wc_id, local_relpath) AS filter - ON nodes.wc_id = filter.wc_id - AND nodes.local_relpath = filter.local_relpath - AND nodes.op_depth = filter.op_depth; - -PRAGMA user_version = 25; - -/* ------------------------------------------------------------------------- */ - -/* Format 26 introduces the NODES_BASE view. */ - --- STMT_UPGRADE_TO_26 -DROP VIEW IF EXISTS NODES_BASE; -CREATE VIEW NODES_BASE AS - SELECT * FROM nodes - WHERE op_depth = 0; - -PRAGMA user_version = 26; - -/* ------------------------------------------------------------------------- */ - -/* Format 27 involves no schema changes, it introduces stores - conflict files as relpaths rather than names in ACTUAL_NODE. */ - --- STMT_UPGRADE_TO_27 -PRAGMA user_version = 27; - -/* For format 27 bump code */ --- STMT_UPGRADE_27_HAS_ACTUAL_NODES_CONFLICTS -SELECT 1 FROM actual_node -WHERE NOT ((prop_reject IS NULL) AND (conflict_old IS NULL) - AND (conflict_new IS NULL) AND (conflict_working IS NULL) - AND (tree_conflict_data IS NULL)) -LIMIT 1 - - -/* ------------------------------------------------------------------------- */ - -/* Format 28 involves no schema changes, it only converts MD5 pristine - references to SHA1. */ - --- STMT_UPGRADE_TO_28 - -UPDATE NODES SET checksum = (SELECT checksum FROM pristine - WHERE md5_checksum = nodes.checksum) -WHERE EXISTS (SELECT 1 FROM pristine WHERE md5_checksum = nodes.checksum); - -PRAGMA user_version = 28; - -/* ------------------------------------------------------------------------- */ - -/* Format 29 introduces the EXTERNALS table (See STMT_CREATE_TRIGGERS) and - optimizes a few trigger definitions. ... */ - --- STMT_UPGRADE_TO_29 - -DROP TRIGGER IF EXISTS nodes_update_checksum_trigger; -DROP TRIGGER IF EXISTS nodes_insert_trigger; -DROP TRIGGER IF EXISTS nodes_delete_trigger; - -CREATE TRIGGER nodes_update_checksum_trigger -AFTER UPDATE OF checksum ON nodes -WHEN NEW.checksum IS NOT OLD.checksum - /* AND (NEW.checksum IS NOT NULL OR OLD.checksum IS NOT NULL) */ -BEGIN - UPDATE pristine SET refcount = refcount + 1 - WHERE checksum = NEW.checksum; - UPDATE pristine SET refcount = refcount - 1 - WHERE checksum = OLD.checksum; -END; - -CREATE TRIGGER nodes_insert_trigger -AFTER INSERT ON nodes -WHEN NEW.checksum IS NOT NULL -BEGIN - UPDATE pristine SET refcount = refcount + 1 - WHERE checksum = NEW.checksum; -END; - -CREATE TRIGGER nodes_delete_trigger -AFTER DELETE ON nodes -WHEN OLD.checksum IS NOT NULL -BEGIN - UPDATE pristine SET refcount = refcount - 1 - WHERE checksum = OLD.checksum; -END; - -PRAGMA user_version = 29; - -/* ------------------------------------------------------------------------- */ - /* Format 30 creates a new NODES index for move information, and a new PRISTINE index for the md5_checksum column. It also activates use of skel-based conflict storage -- see notes/wc-ng/conflict-storage-2.0. @@ -870,9 +664,9 @@ WHERE wc_id = ?1 and local_relpath = ?2 /* Format 31 adds the inherited_props column to the NODES table. C code then initializes the update/switch roots to make sure future updates fetch the inherited properties */ --- STMT_UPGRADE_TO_31_ALTER_TABLE +-- STMT_UPGRADE_TO_31 ALTER TABLE NODES ADD COLUMN inherited_props BLOB; --- STMT_UPGRADE_TO_31_FINALIZE + DROP INDEX IF EXISTS I_ACTUAL_CHANGELIST; DROP INDEX IF EXISTS I_EXTERNALS_PARENT; @@ -906,25 +700,8 @@ WHERE l.op_depth = 0 /* ------------------------------------------------------------------------- */ /* Format 32 .... */ --- STMT_UPGRADE_TO_32 - -/* Drop old index. ### Remove this part from the upgrade to 31 once bumped */ -DROP INDEX IF EXISTS I_ACTUAL_CHANGELIST; -DROP INDEX IF EXISTS I_EXTERNALS_PARENT; -CREATE INDEX I_EXTERNALS_PARENT ON EXTERNALS (wc_id, parent_relpath); - -DROP INDEX I_NODES_PARENT; -CREATE UNIQUE INDEX I_NODES_PARENT ON NODES (wc_id, parent_relpath, - local_relpath, op_depth); - -DROP INDEX I_ACTUAL_PARENT; -CREATE UNIQUE INDEX I_ACTUAL_PARENT ON ACTUAL_NODE (wc_id, parent_relpath, - local_relpath); - -/* ------------------------------------------------------------------------- */ - -/* Format YYY introduces new handling for conflict information. */ --- format: YYY +/* -- STMT_UPGRADE_TO_32 +PRAGMA user_version = 32; */ /* ------------------------------------------------------------------------- */ diff --git a/subversion/libsvn_wc/wc-queries.h b/subversion/libsvn_wc/wc-queries.h index 2a7594067ed6..b333e95ffdbe 100644 --- a/subversion/libsvn_wc/wc-queries.h +++ b/subversion/libsvn_wc/wc-queries.h @@ -1,4 +1,4 @@ -/* This file is automatically generated from wc-queries.sql and .dist_sandbox/subversion-1.9.7/subversion/libsvn_wc/token-map.h. +/* This file is automatically generated from wc-queries.sql and subversion/libsvn_wc/token-map.h. * Do not edit this file -- edit the source and rerun gen-make.py */ #define STMT_SELECT_NODE_INFO 0 @@ -23,7 +23,7 @@ " lock_token, lock_owner, lock_comment, lock_date " \ "FROM nodes " \ "LEFT OUTER JOIN lock ON nodes.repos_id = lock.repos_id " \ - " AND nodes.repos_path = lock.repos_relpath " \ + " AND nodes.repos_path = lock.repos_relpath AND nodes.op_depth=0 " \ "WHERE wc_id = ?1 AND local_relpath = ?2 " \ "ORDER BY op_depth DESC " \ "" @@ -132,7 +132,7 @@ " lock_comment, lock_date, local_relpath, moved_here, moved_to, file_external " \ "FROM nodes " \ "LEFT OUTER JOIN lock ON nodes.repos_id = lock.repos_id " \ - " AND nodes.repos_path = lock.repos_relpath AND op_depth = 0 " \ + " AND nodes.repos_path = lock.repos_relpath AND nodes.op_depth = 0 " \ "WHERE wc_id = ?1 AND parent_relpath = ?2 " \ "ORDER BY local_relpath DESC, op_depth DESC " \ "" @@ -146,7 +146,7 @@ " lock_comment, lock_date, local_relpath, moved_here, moved_to, file_external " \ "FROM nodes " \ "LEFT OUTER JOIN lock ON nodes.repos_id = lock.repos_id " \ - " AND nodes.repos_path = lock.repos_relpath AND op_depth = 0 " \ + " AND nodes.repos_path = lock.repos_relpath " \ "WHERE wc_id = ?1 AND parent_relpath = ?2 AND op_depth = 0 " \ "ORDER BY local_relpath DESC " \ "" @@ -1627,37 +1627,44 @@ "PRAGMA journal_mode = DELETE " \ "" -#define STMT_INSERT_ACTUAL_NODE 152 -#define STMT_152_INFO {"STMT_INSERT_ACTUAL_NODE", NULL} +#define STMT_FIND_REPOS_PATH_IN_WC 152 +#define STMT_152_INFO {"STMT_FIND_REPOS_PATH_IN_WC", NULL} #define STMT_152 \ + "SELECT local_relpath FROM nodes_current " \ + " WHERE wc_id = ?1 AND repos_path = ?2 " \ + "" + +#define STMT_INSERT_ACTUAL_NODE 153 +#define STMT_153_INFO {"STMT_INSERT_ACTUAL_NODE", NULL} +#define STMT_153 \ "INSERT OR REPLACE INTO actual_node ( " \ " wc_id, local_relpath, parent_relpath, properties, changelist, conflict_data) " \ "VALUES (?1, ?2, ?3, ?4, ?5, ?6) " \ "" -#define STMT_SELECT_ALL_FILES 153 -#define STMT_153_INFO {"STMT_SELECT_ALL_FILES", NULL} -#define STMT_153 \ +#define STMT_SELECT_ALL_FILES 154 +#define STMT_154_INFO {"STMT_SELECT_ALL_FILES", NULL} +#define STMT_154 \ "SELECT local_relpath FROM nodes_current " \ "WHERE wc_id = ?1 AND parent_relpath = ?2 AND kind = 'file' " \ "" -#define STMT_UPDATE_NODE_PROPS 154 -#define STMT_154_INFO {"STMT_UPDATE_NODE_PROPS", NULL} -#define STMT_154 \ +#define STMT_UPDATE_NODE_PROPS 155 +#define STMT_155_INFO {"STMT_UPDATE_NODE_PROPS", NULL} +#define STMT_155 \ "UPDATE nodes SET properties = ?4 " \ "WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = ?3 " \ "" -#define STMT_PRAGMA_TABLE_INFO_NODES 155 -#define STMT_155_INFO {"STMT_PRAGMA_TABLE_INFO_NODES", NULL} -#define STMT_155 \ +#define STMT_PRAGMA_TABLE_INFO_NODES 156 +#define STMT_156_INFO {"STMT_PRAGMA_TABLE_INFO_NODES", NULL} +#define STMT_156 \ "PRAGMA table_info(\"NODES\") " \ "" -#define STMT_CREATE_TARGET_PROP_CACHE 156 -#define STMT_156_INFO {"STMT_CREATE_TARGET_PROP_CACHE", NULL} -#define STMT_156 \ +#define STMT_CREATE_TARGET_PROP_CACHE 157 +#define STMT_157_INFO {"STMT_CREATE_TARGET_PROP_CACHE", NULL} +#define STMT_157 \ "DROP TABLE IF EXISTS target_prop_cache; " \ "CREATE TEMPORARY TABLE target_prop_cache ( " \ " local_relpath TEXT NOT NULL PRIMARY KEY, " \ @@ -1666,9 +1673,9 @@ "); " \ "" -#define STMT_CACHE_TARGET_PROPS 157 -#define STMT_157_INFO {"STMT_CACHE_TARGET_PROPS", NULL} -#define STMT_157 \ +#define STMT_CACHE_TARGET_PROPS 158 +#define STMT_158_INFO {"STMT_CACHE_TARGET_PROPS", NULL} +#define STMT_158 \ "INSERT INTO target_prop_cache(local_relpath, kind, properties) " \ " SELECT n.local_relpath, n.kind, " \ " IFNULL((SELECT properties FROM actual_node AS a " \ @@ -1687,9 +1694,9 @@ " ORDER BY t.local_relpath " \ "" -#define STMT_CACHE_TARGET_PRISTINE_PROPS 158 -#define STMT_158_INFO {"STMT_CACHE_TARGET_PRISTINE_PROPS", NULL} -#define STMT_158 \ +#define STMT_CACHE_TARGET_PRISTINE_PROPS 159 +#define STMT_159_INFO {"STMT_CACHE_TARGET_PRISTINE_PROPS", NULL} +#define STMT_159 \ "INSERT INTO target_prop_cache(local_relpath, kind, properties) " \ " SELECT n.local_relpath, n.kind, " \ " CASE n.presence " \ @@ -1714,22 +1721,22 @@ " ORDER BY t.local_relpath " \ "" -#define STMT_SELECT_ALL_TARGET_PROP_CACHE 159 -#define STMT_159_INFO {"STMT_SELECT_ALL_TARGET_PROP_CACHE", NULL} -#define STMT_159 \ +#define STMT_SELECT_ALL_TARGET_PROP_CACHE 160 +#define STMT_160_INFO {"STMT_SELECT_ALL_TARGET_PROP_CACHE", NULL} +#define STMT_160 \ "SELECT local_relpath, properties FROM target_prop_cache " \ "ORDER BY local_relpath " \ "" -#define STMT_DROP_TARGET_PROP_CACHE 160 -#define STMT_160_INFO {"STMT_DROP_TARGET_PROP_CACHE", NULL} -#define STMT_160 \ +#define STMT_DROP_TARGET_PROP_CACHE 161 +#define STMT_161_INFO {"STMT_DROP_TARGET_PROP_CACHE", NULL} +#define STMT_161 \ "DROP TABLE target_prop_cache; " \ "" -#define STMT_CREATE_REVERT_LIST 161 -#define STMT_161_INFO {"STMT_CREATE_REVERT_LIST", NULL} -#define STMT_161 \ +#define STMT_CREATE_REVERT_LIST 162 +#define STMT_162_INFO {"STMT_CREATE_REVERT_LIST", NULL} +#define STMT_162 \ "DROP TABLE IF EXISTS revert_list; " \ "CREATE TEMPORARY TABLE revert_list ( " \ " local_relpath TEXT NOT NULL, " \ @@ -1787,26 +1794,26 @@ "END " \ "" -#define STMT_DROP_REVERT_LIST_TRIGGERS 162 -#define STMT_162_INFO {"STMT_DROP_REVERT_LIST_TRIGGERS", NULL} -#define STMT_162 \ +#define STMT_DROP_REVERT_LIST_TRIGGERS 163 +#define STMT_163_INFO {"STMT_DROP_REVERT_LIST_TRIGGERS", NULL} +#define STMT_163 \ "DROP TRIGGER trigger_revert_list_nodes; " \ "DROP TRIGGER trigger_revert_list_actual_delete; " \ "DROP TRIGGER trigger_revert_list_actual_update " \ "" -#define STMT_SELECT_REVERT_LIST 163 -#define STMT_163_INFO {"STMT_SELECT_REVERT_LIST", NULL} -#define STMT_163 \ +#define STMT_SELECT_REVERT_LIST 164 +#define STMT_164_INFO {"STMT_SELECT_REVERT_LIST", NULL} +#define STMT_164 \ "SELECT actual, notify, kind, op_depth, repos_id, conflict_data " \ "FROM revert_list " \ "WHERE local_relpath = ?1 " \ "ORDER BY actual DESC " \ "" -#define STMT_SELECT_REVERT_LIST_COPIED_CHILDREN 164 -#define STMT_164_INFO {"STMT_SELECT_REVERT_LIST_COPIED_CHILDREN", NULL} -#define STMT_164 \ +#define STMT_SELECT_REVERT_LIST_COPIED_CHILDREN 165 +#define STMT_165_INFO {"STMT_SELECT_REVERT_LIST_COPIED_CHILDREN", NULL} +#define STMT_165 \ "SELECT local_relpath, kind " \ "FROM revert_list " \ "WHERE (((local_relpath) > (CASE (?1) WHEN '' THEN '' ELSE (?1) || '/' END)) AND ((local_relpath) < CASE (?1) WHEN '' THEN X'FFFF' ELSE (?1) || '0' END)) " \ @@ -1815,15 +1822,15 @@ "ORDER BY local_relpath " \ "" -#define STMT_DELETE_REVERT_LIST 165 -#define STMT_165_INFO {"STMT_DELETE_REVERT_LIST", NULL} -#define STMT_165 \ +#define STMT_DELETE_REVERT_LIST 166 +#define STMT_166_INFO {"STMT_DELETE_REVERT_LIST", NULL} +#define STMT_166 \ "DELETE FROM revert_list WHERE local_relpath = ?1 " \ "" -#define STMT_SELECT_REVERT_LIST_RECURSIVE 166 -#define STMT_166_INFO {"STMT_SELECT_REVERT_LIST_RECURSIVE", NULL} -#define STMT_166 \ +#define STMT_SELECT_REVERT_LIST_RECURSIVE 167 +#define STMT_167_INFO {"STMT_SELECT_REVERT_LIST_RECURSIVE", NULL} +#define STMT_167 \ "SELECT p.local_relpath, n.kind, a.notify, a.kind " \ "FROM (SELECT DISTINCT local_relpath " \ " FROM revert_list " \ @@ -1834,32 +1841,32 @@ "ORDER BY p.local_relpath " \ "" -#define STMT_DELETE_REVERT_LIST_RECURSIVE 167 -#define STMT_167_INFO {"STMT_DELETE_REVERT_LIST_RECURSIVE", NULL} -#define STMT_167 \ +#define STMT_DELETE_REVERT_LIST_RECURSIVE 168 +#define STMT_168_INFO {"STMT_DELETE_REVERT_LIST_RECURSIVE", NULL} +#define STMT_168 \ "DELETE FROM revert_list " \ "WHERE (local_relpath = ?1 " \ " OR (((local_relpath) > (CASE (?1) WHEN '' THEN '' ELSE (?1) || '/' END)) AND ((local_relpath) < CASE (?1) WHEN '' THEN X'FFFF' ELSE (?1) || '0' END))) " \ "" -#define STMT_DROP_REVERT_LIST 168 -#define STMT_168_INFO {"STMT_DROP_REVERT_LIST", NULL} -#define STMT_168 \ +#define STMT_DROP_REVERT_LIST 169 +#define STMT_169_INFO {"STMT_DROP_REVERT_LIST", NULL} +#define STMT_169 \ "DROP TABLE IF EXISTS revert_list " \ "" -#define STMT_CREATE_DELETE_LIST 169 -#define STMT_169_INFO {"STMT_CREATE_DELETE_LIST", NULL} -#define STMT_169 \ +#define STMT_CREATE_DELETE_LIST 170 +#define STMT_170_INFO {"STMT_CREATE_DELETE_LIST", NULL} +#define STMT_170 \ "DROP TABLE IF EXISTS delete_list; " \ "CREATE TEMPORARY TABLE delete_list ( " \ " local_relpath TEXT PRIMARY KEY NOT NULL UNIQUE " \ " ) " \ "" -#define STMT_INSERT_DELETE_LIST 170 -#define STMT_170_INFO {"STMT_INSERT_DELETE_LIST", NULL} -#define STMT_170 \ +#define STMT_INSERT_DELETE_LIST 171 +#define STMT_171_INFO {"STMT_INSERT_DELETE_LIST", NULL} +#define STMT_171 \ "INSERT INTO delete_list(local_relpath) " \ "SELECT ?2 " \ "UNION ALL " \ @@ -1875,22 +1882,22 @@ "ORDER by local_relpath " \ "" -#define STMT_SELECT_DELETE_LIST 171 -#define STMT_171_INFO {"STMT_SELECT_DELETE_LIST", NULL} -#define STMT_171 \ +#define STMT_SELECT_DELETE_LIST 172 +#define STMT_172_INFO {"STMT_SELECT_DELETE_LIST", NULL} +#define STMT_172 \ "SELECT local_relpath FROM delete_list " \ "ORDER BY local_relpath " \ "" -#define STMT_FINALIZE_DELETE 172 -#define STMT_172_INFO {"STMT_FINALIZE_DELETE", NULL} -#define STMT_172 \ +#define STMT_FINALIZE_DELETE 173 +#define STMT_173_INFO {"STMT_FINALIZE_DELETE", NULL} +#define STMT_173 \ "DROP TABLE IF EXISTS delete_list " \ "" -#define STMT_CREATE_UPDATE_MOVE_LIST 173 -#define STMT_173_INFO {"STMT_CREATE_UPDATE_MOVE_LIST", NULL} -#define STMT_173 \ +#define STMT_CREATE_UPDATE_MOVE_LIST 174 +#define STMT_174_INFO {"STMT_CREATE_UPDATE_MOVE_LIST", NULL} +#define STMT_174 \ "DROP TABLE IF EXISTS update_move_list; " \ "CREATE TEMPORARY TABLE update_move_list ( " \ " local_relpath TEXT PRIMARY KEY NOT NULL UNIQUE, " \ @@ -1901,39 +1908,39 @@ " ) " \ "" -#define STMT_INSERT_UPDATE_MOVE_LIST 174 -#define STMT_174_INFO {"STMT_INSERT_UPDATE_MOVE_LIST", NULL} -#define STMT_174 \ +#define STMT_INSERT_UPDATE_MOVE_LIST 175 +#define STMT_175_INFO {"STMT_INSERT_UPDATE_MOVE_LIST", NULL} +#define STMT_175 \ "INSERT INTO update_move_list(local_relpath, action, kind, content_state, " \ " prop_state) " \ "VALUES (?1, ?2, ?3, ?4, ?5) " \ "" -#define STMT_SELECT_UPDATE_MOVE_LIST 175 -#define STMT_175_INFO {"STMT_SELECT_UPDATE_MOVE_LIST", NULL} -#define STMT_175 \ +#define STMT_SELECT_UPDATE_MOVE_LIST 176 +#define STMT_176_INFO {"STMT_SELECT_UPDATE_MOVE_LIST", NULL} +#define STMT_176 \ "SELECT local_relpath, action, kind, content_state, prop_state " \ "FROM update_move_list " \ "ORDER BY local_relpath " \ "" -#define STMT_FINALIZE_UPDATE_MOVE 176 -#define STMT_176_INFO {"STMT_FINALIZE_UPDATE_MOVE", NULL} -#define STMT_176 \ +#define STMT_FINALIZE_UPDATE_MOVE 177 +#define STMT_177_INFO {"STMT_FINALIZE_UPDATE_MOVE", NULL} +#define STMT_177 \ "DROP TABLE IF EXISTS update_move_list " \ "" -#define STMT_MOVE_NOTIFY_TO_REVERT 177 -#define STMT_177_INFO {"STMT_MOVE_NOTIFY_TO_REVERT", NULL} -#define STMT_177 \ +#define STMT_MOVE_NOTIFY_TO_REVERT 178 +#define STMT_178_INFO {"STMT_MOVE_NOTIFY_TO_REVERT", NULL} +#define STMT_178 \ "INSERT INTO revert_list (local_relpath, notify, kind, actual) " \ " SELECT local_relpath, 2, kind, 1 FROM update_move_list; " \ "DROP TABLE update_move_list " \ "" -#define STMT_SELECT_MIN_MAX_REVISIONS 178 -#define STMT_178_INFO {"STMT_SELECT_MIN_MAX_REVISIONS", NULL} -#define STMT_178 \ +#define STMT_SELECT_MIN_MAX_REVISIONS 179 +#define STMT_179_INFO {"STMT_SELECT_MIN_MAX_REVISIONS", NULL} +#define STMT_179 \ "SELECT MIN(revision), MAX(revision), " \ " MIN(changed_revision), MAX(changed_revision) FROM nodes " \ " WHERE wc_id = ?1 " \ @@ -1944,9 +1951,9 @@ " AND op_depth = 0 " \ "" -#define STMT_HAS_SPARSE_NODES 179 -#define STMT_179_INFO {"STMT_HAS_SPARSE_NODES", NULL} -#define STMT_179 \ +#define STMT_HAS_SPARSE_NODES 180 +#define STMT_180_INFO {"STMT_HAS_SPARSE_NODES", NULL} +#define STMT_180 \ "SELECT 1 FROM nodes " \ "WHERE wc_id = ?1 " \ " AND (local_relpath = ?2 " \ @@ -1958,9 +1965,9 @@ "LIMIT 1 " \ "" -#define STMT_SUBTREE_HAS_TREE_MODIFICATIONS 180 -#define STMT_180_INFO {"STMT_SUBTREE_HAS_TREE_MODIFICATIONS", NULL} -#define STMT_180 \ +#define STMT_SUBTREE_HAS_TREE_MODIFICATIONS 181 +#define STMT_181_INFO {"STMT_SUBTREE_HAS_TREE_MODIFICATIONS", NULL} +#define STMT_181 \ "SELECT 1 FROM nodes " \ "WHERE wc_id = ?1 " \ " AND (local_relpath = ?2 " \ @@ -1969,9 +1976,9 @@ "LIMIT 1 " \ "" -#define STMT_SUBTREE_HAS_PROP_MODIFICATIONS 181 -#define STMT_181_INFO {"STMT_SUBTREE_HAS_PROP_MODIFICATIONS", NULL} -#define STMT_181 \ +#define STMT_SUBTREE_HAS_PROP_MODIFICATIONS 182 +#define STMT_182_INFO {"STMT_SUBTREE_HAS_PROP_MODIFICATIONS", NULL} +#define STMT_182 \ "SELECT 1 FROM actual_node " \ "WHERE wc_id = ?1 " \ " AND (local_relpath = ?2 " \ @@ -1980,9 +1987,9 @@ "LIMIT 1 " \ "" -#define STMT_HAS_SWITCHED 182 -#define STMT_182_INFO {"STMT_HAS_SWITCHED", NULL} -#define STMT_182 \ +#define STMT_HAS_SWITCHED 183 +#define STMT_183_INFO {"STMT_HAS_SWITCHED", NULL} +#define STMT_183 \ "SELECT 1 " \ "FROM nodes " \ "WHERE wc_id = ?1 " \ @@ -1994,47 +2001,47 @@ "LIMIT 1 " \ "" -#define STMT_SELECT_MOVED_FROM_RELPATH 183 -#define STMT_183_INFO {"STMT_SELECT_MOVED_FROM_RELPATH", NULL} -#define STMT_183 \ +#define STMT_SELECT_MOVED_FROM_RELPATH 184 +#define STMT_184_INFO {"STMT_SELECT_MOVED_FROM_RELPATH", NULL} +#define STMT_184 \ "SELECT local_relpath, op_depth FROM nodes " \ "WHERE wc_id = ?1 AND moved_to = ?2 AND op_depth > 0 " \ "" -#define STMT_UPDATE_MOVED_TO_RELPATH 184 -#define STMT_184_INFO {"STMT_UPDATE_MOVED_TO_RELPATH", NULL} -#define STMT_184 \ +#define STMT_UPDATE_MOVED_TO_RELPATH 185 +#define STMT_185_INFO {"STMT_UPDATE_MOVED_TO_RELPATH", NULL} +#define STMT_185 \ "UPDATE nodes SET moved_to = ?4 " \ "WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = ?3 " \ "" -#define STMT_CLEAR_MOVED_TO_RELPATH 185 -#define STMT_185_INFO {"STMT_CLEAR_MOVED_TO_RELPATH", NULL} -#define STMT_185 \ +#define STMT_CLEAR_MOVED_TO_RELPATH 186 +#define STMT_186_INFO {"STMT_CLEAR_MOVED_TO_RELPATH", NULL} +#define STMT_186 \ "UPDATE nodes SET moved_to = NULL " \ "WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth = ?3 " \ "" -#define STMT_CLEAR_MOVED_HERE_RECURSIVE 186 -#define STMT_186_INFO {"STMT_CLEAR_MOVED_HERE_RECURSIVE", NULL} -#define STMT_186 \ +#define STMT_CLEAR_MOVED_HERE_RECURSIVE 187 +#define STMT_187_INFO {"STMT_CLEAR_MOVED_HERE_RECURSIVE", NULL} +#define STMT_187 \ "UPDATE nodes SET moved_here = NULL " \ "WHERE wc_id = ?1 " \ " AND (local_relpath = ?2 OR (((local_relpath) > (CASE (?2) WHEN '' THEN '' ELSE (?2) || '/' END)) AND ((local_relpath) < CASE (?2) WHEN '' THEN X'FFFF' ELSE (?2) || '0' END))) " \ " AND op_depth = ?3 " \ "" -#define STMT_SELECT_MOVED_HERE_CHILDREN 187 -#define STMT_187_INFO {"STMT_SELECT_MOVED_HERE_CHILDREN", NULL} -#define STMT_187 \ +#define STMT_SELECT_MOVED_HERE_CHILDREN 188 +#define STMT_188_INFO {"STMT_SELECT_MOVED_HERE_CHILDREN", NULL} +#define STMT_188 \ "SELECT moved_to, local_relpath FROM nodes " \ "WHERE wc_id = ?1 AND op_depth > 0 " \ " AND (((moved_to) > (CASE (?2) WHEN '' THEN '' ELSE (?2) || '/' END)) AND ((moved_to) < CASE (?2) WHEN '' THEN X'FFFF' ELSE (?2) || '0' END)) " \ "" -#define STMT_SELECT_MOVED_FOR_DELETE 188 -#define STMT_188_INFO {"STMT_SELECT_MOVED_FOR_DELETE", NULL} -#define STMT_188 \ +#define STMT_SELECT_MOVED_FOR_DELETE 189 +#define STMT_189_INFO {"STMT_SELECT_MOVED_FOR_DELETE", NULL} +#define STMT_189 \ "SELECT local_relpath, moved_to, op_depth, " \ " (SELECT CASE WHEN r.moved_here THEN r.op_depth END FROM nodes r " \ " WHERE r.wc_id = ?1 " \ @@ -2048,9 +2055,9 @@ " AND op_depth >= ?3 " \ "" -#define STMT_SELECT_MOVED_FROM_FOR_DELETE 189 -#define STMT_189_INFO {"STMT_SELECT_MOVED_FROM_FOR_DELETE", NULL} -#define STMT_189 \ +#define STMT_SELECT_MOVED_FROM_FOR_DELETE 190 +#define STMT_190_INFO {"STMT_SELECT_MOVED_FROM_FOR_DELETE", NULL} +#define STMT_190 \ "SELECT local_relpath, op_depth, " \ " (SELECT CASE WHEN r.moved_here THEN r.op_depth END FROM nodes r " \ " WHERE r.wc_id = ?1 " \ @@ -2061,25 +2068,25 @@ "WHERE wc_id = ?1 AND moved_to = ?2 AND op_depth > 0 " \ "" -#define STMT_UPDATE_MOVED_TO_DESCENDANTS 190 -#define STMT_190_INFO {"STMT_UPDATE_MOVED_TO_DESCENDANTS", NULL} -#define STMT_190 \ +#define STMT_UPDATE_MOVED_TO_DESCENDANTS 191 +#define STMT_191_INFO {"STMT_UPDATE_MOVED_TO_DESCENDANTS", NULL} +#define STMT_191 \ "UPDATE nodes SET moved_to = (CASE WHEN (?2) = '' THEN (CASE WHEN (?3) = '' THEN (moved_to) WHEN (moved_to) = '' THEN (?3) ELSE (?3) || '/' || (moved_to) END) WHEN (?3) = '' THEN (CASE WHEN (?2) = '' THEN (moved_to) WHEN SUBSTR((moved_to), 1, LENGTH(?2)) = (?2) THEN CASE WHEN LENGTH(?2) = LENGTH(moved_to) THEN '' WHEN SUBSTR((moved_to), LENGTH(?2)+1, 1) = '/' THEN SUBSTR((moved_to), LENGTH(?2)+2) END END) WHEN SUBSTR((moved_to), 1, LENGTH(?2)) = (?2) THEN CASE WHEN LENGTH(?2) = LENGTH(moved_to) THEN (?3) WHEN SUBSTR((moved_to), LENGTH(?2)+1, 1) = '/' THEN (?3) || SUBSTR((moved_to), LENGTH(?2)+1) END END) " \ " WHERE wc_id = ?1 " \ " AND (((moved_to) > (CASE (?2) WHEN '' THEN '' ELSE (?2) || '/' END)) AND ((moved_to) < CASE (?2) WHEN '' THEN X'FFFF' ELSE (?2) || '0' END)) " \ "" -#define STMT_CLEAR_MOVED_TO_DESCENDANTS 191 -#define STMT_191_INFO {"STMT_CLEAR_MOVED_TO_DESCENDANTS", NULL} -#define STMT_191 \ +#define STMT_CLEAR_MOVED_TO_DESCENDANTS 192 +#define STMT_192_INFO {"STMT_CLEAR_MOVED_TO_DESCENDANTS", NULL} +#define STMT_192 \ "UPDATE nodes SET moved_to = NULL " \ " WHERE wc_id = ?1 " \ " AND (((moved_to) > (CASE (?2) WHEN '' THEN '' ELSE (?2) || '/' END)) AND ((moved_to) < CASE (?2) WHEN '' THEN X'FFFF' ELSE (?2) || '0' END)) " \ "" -#define STMT_SELECT_MOVED_PAIR3 192 -#define STMT_192_INFO {"STMT_SELECT_MOVED_PAIR3", NULL} -#define STMT_192 \ +#define STMT_SELECT_MOVED_PAIR3 193 +#define STMT_193_INFO {"STMT_SELECT_MOVED_PAIR3", NULL} +#define STMT_193 \ "SELECT n.local_relpath, d.moved_to, d.op_depth, n.kind " \ "FROM nodes n " \ "JOIN nodes d ON d.wc_id = ?1 AND d.local_relpath = n.local_relpath " \ @@ -2105,9 +2112,9 @@ "ORDER BY n.local_relpath " \ "" -#define STMT_SELECT_MOVED_OUTSIDE 193 -#define STMT_193_INFO {"STMT_SELECT_MOVED_OUTSIDE", NULL} -#define STMT_193 \ +#define STMT_SELECT_MOVED_OUTSIDE 194 +#define STMT_194_INFO {"STMT_SELECT_MOVED_OUTSIDE", NULL} +#define STMT_194 \ "SELECT local_relpath, moved_to, op_depth FROM nodes " \ "WHERE wc_id = ?1 " \ " AND (local_relpath = ?2 OR (((local_relpath) > (CASE (?2) WHEN '' THEN '' ELSE (?2) || '/' END)) AND ((local_relpath) < CASE (?2) WHEN '' THEN X'FFFF' ELSE (?2) || '0' END))) " \ @@ -2116,9 +2123,9 @@ " AND NOT (((moved_to) > (CASE (?2) WHEN '' THEN '' ELSE (?2) || '/' END)) AND ((moved_to) < CASE (?2) WHEN '' THEN X'FFFF' ELSE (?2) || '0' END)) " \ "" -#define STMT_SELECT_MOVED_DESCENDANTS_SRC 194 -#define STMT_194_INFO {"STMT_SELECT_MOVED_DESCENDANTS_SRC", NULL} -#define STMT_194 \ +#define STMT_SELECT_MOVED_DESCENDANTS_SRC 195 +#define STMT_195_INFO {"STMT_SELECT_MOVED_DESCENDANTS_SRC", NULL} +#define STMT_195 \ "SELECT s.op_depth, n.local_relpath, n.kind, n.repos_path, s.moved_to " \ "FROM nodes n " \ "JOIN nodes s ON s.wc_id = n.wc_id AND s.local_relpath = n.local_relpath " \ @@ -2132,9 +2139,9 @@ " AND s.moved_to IS NOT NULL " \ "" -#define STMT_COMMIT_UPDATE_ORIGIN 195 -#define STMT_195_INFO {"STMT_COMMIT_UPDATE_ORIGIN", NULL} -#define STMT_195 \ +#define STMT_COMMIT_UPDATE_ORIGIN 196 +#define STMT_196_INFO {"STMT_COMMIT_UPDATE_ORIGIN", NULL} +#define STMT_196 \ "UPDATE nodes SET repos_id = ?4, " \ " repos_path = (CASE WHEN (?2) = '' THEN (CASE WHEN (?5) = '' THEN (local_relpath) WHEN (local_relpath) = '' THEN (?5) ELSE (?5) || '/' || (local_relpath) END) WHEN (?5) = '' THEN (CASE WHEN (?2) = '' THEN (local_relpath) WHEN SUBSTR((local_relpath), 1, LENGTH(?2)) = (?2) THEN CASE WHEN LENGTH(?2) = LENGTH(local_relpath) THEN '' WHEN SUBSTR((local_relpath), LENGTH(?2)+1, 1) = '/' THEN SUBSTR((local_relpath), LENGTH(?2)+2) END END) WHEN SUBSTR((local_relpath), 1, LENGTH(?2)) = (?2) THEN CASE WHEN LENGTH(?2) = LENGTH(local_relpath) THEN (?5) WHEN SUBSTR((local_relpath), LENGTH(?2)+1, 1) = '/' THEN (?5) || SUBSTR((local_relpath), LENGTH(?2)+1) END END), " \ " revision = ?6 " \ @@ -2144,16 +2151,16 @@ " AND op_depth = ?3 " \ "" -#define STMT_HAS_LAYER_BETWEEN 196 -#define STMT_196_INFO {"STMT_HAS_LAYER_BETWEEN", NULL} -#define STMT_196 \ +#define STMT_HAS_LAYER_BETWEEN 197 +#define STMT_197_INFO {"STMT_HAS_LAYER_BETWEEN", NULL} +#define STMT_197 \ "SELECT 1 FROM NODES " \ "WHERE wc_id = ?1 AND local_relpath = ?2 AND op_depth > ?3 AND op_depth < ?4 " \ "" -#define STMT_SELECT_REPOS_PATH_REVISION 197 -#define STMT_197_INFO {"STMT_SELECT_REPOS_PATH_REVISION", NULL} -#define STMT_197 \ +#define STMT_SELECT_REPOS_PATH_REVISION 198 +#define STMT_198_INFO {"STMT_SELECT_REPOS_PATH_REVISION", NULL} +#define STMT_198 \ "SELECT local_relpath, repos_path, revision FROM nodes " \ "WHERE wc_id = ?1 " \ " AND (((local_relpath) > (CASE (?2) WHEN '' THEN '' ELSE (?2) || '/' END)) AND ((local_relpath) < CASE (?2) WHEN '' THEN X'FFFF' ELSE (?2) || '0' END)) " \ @@ -2161,17 +2168,17 @@ "ORDER BY local_relpath " \ "" -#define STMT_SELECT_HAS_NON_FILE_CHILDREN 198 -#define STMT_198_INFO {"STMT_SELECT_HAS_NON_FILE_CHILDREN", NULL} -#define STMT_198 \ +#define STMT_SELECT_HAS_NON_FILE_CHILDREN 199 +#define STMT_199_INFO {"STMT_SELECT_HAS_NON_FILE_CHILDREN", NULL} +#define STMT_199 \ "SELECT 1 FROM nodes " \ "WHERE wc_id = ?1 AND parent_relpath = ?2 AND op_depth = ?3 AND kind != 'file' " \ "LIMIT 1 " \ "" -#define STMT_SELECT_HAS_GRANDCHILDREN 199 -#define STMT_199_INFO {"STMT_SELECT_HAS_GRANDCHILDREN", NULL} -#define STMT_199 \ +#define STMT_SELECT_HAS_GRANDCHILDREN 200 +#define STMT_200_INFO {"STMT_SELECT_HAS_GRANDCHILDREN", NULL} +#define STMT_200 \ "SELECT 1 FROM nodes " \ "WHERE wc_id = ?1 " \ " AND (((parent_relpath) > (CASE (?2) WHEN '' THEN '' ELSE (?2) || '/' END)) AND ((parent_relpath) < CASE (?2) WHEN '' THEN X'FFFF' ELSE (?2) || '0' END)) " \ @@ -2180,22 +2187,13 @@ "LIMIT 1 " \ "" -#define STMT_SELECT_ALL_NODES 200 -#define STMT_200_INFO {"STMT_SELECT_ALL_NODES", NULL} -#define STMT_200 \ +#define STMT_SELECT_ALL_NODES 201 +#define STMT_201_INFO {"STMT_SELECT_ALL_NODES", NULL} +#define STMT_201 \ "SELECT op_depth, local_relpath, parent_relpath, file_external FROM nodes " \ "WHERE wc_id = ?1 " \ "" -#define STMT_SELECT_IPROPS 201 -#define STMT_201_INFO {"STMT_SELECT_IPROPS", NULL} -#define STMT_201 \ - "SELECT inherited_props FROM nodes " \ - "WHERE wc_id = ?1 " \ - " AND local_relpath = ?2 " \ - " AND op_depth = 0 " \ - "" - #define STMT_UPDATE_IPROP 202 #define STMT_202_INFO {"STMT_UPDATE_IPROP", NULL} #define STMT_202 \ @@ -2303,14 +2301,6 @@ " locked_levels INTEGER NOT NULL DEFAULT -1, " \ " PRIMARY KEY (wc_id, local_dir_relpath) " \ " ); " \ - "PRAGMA user_version = " \ - APR_STRINGIFY(SVN_WC__VERSION) \ - "; " \ - "" - -#define STMT_CREATE_NODES 208 -#define STMT_208_INFO {"STMT_CREATE_NODES", NULL} -#define STMT_208 \ "CREATE TABLE NODES ( " \ " wc_id INTEGER NOT NULL REFERENCES WCROOT (id), " \ " local_relpath TEXT NOT NULL, " \ @@ -2348,11 +2338,6 @@ "CREATE VIEW NODES_BASE AS " \ " SELECT * FROM nodes " \ " WHERE op_depth = 0; " \ - "" - -#define STMT_CREATE_NODES_TRIGGERS 209 -#define STMT_209_INFO {"STMT_CREATE_NODES_TRIGGERS", NULL} -#define STMT_209 \ "CREATE TRIGGER nodes_insert_trigger " \ "AFTER INSERT ON nodes " \ "WHEN NEW.checksum IS NOT NULL " \ @@ -2376,11 +2361,6 @@ " UPDATE pristine SET refcount = refcount - 1 " \ " WHERE checksum = OLD.checksum; " \ "END; " \ - "" - -#define STMT_CREATE_EXTERNALS 210 -#define STMT_210_INFO {"STMT_CREATE_EXTERNALS", NULL} -#define STMT_210 \ "CREATE TABLE EXTERNALS ( " \ " wc_id INTEGER NOT NULL REFERENCES WCROOT (id), " \ " local_relpath TEXT NOT NULL, " \ @@ -2397,11 +2377,14 @@ "CREATE UNIQUE INDEX I_EXTERNALS_DEFINED ON EXTERNALS (wc_id, " \ " def_local_relpath, " \ " local_relpath); " \ + "PRAGMA user_version = " \ + APR_STRINGIFY(SVN_WC__VERSION) \ + "; " \ "" -#define STMT_INSTALL_SCHEMA_STATISTICS 211 -#define STMT_211_INFO {"STMT_INSTALL_SCHEMA_STATISTICS", NULL} -#define STMT_211 \ +#define STMT_INSTALL_SCHEMA_STATISTICS 208 +#define STMT_208_INFO {"STMT_INSTALL_SCHEMA_STATISTICS", NULL} +#define STMT_208 \ "ANALYZE sqlite_master; " \ "DELETE FROM sqlite_stat1 " \ "WHERE tbl in ('NODES', 'ACTUAL_NODE', 'LOCK', 'WC_LOCK', 'EXTERNALS'); " \ @@ -2426,183 +2409,9 @@ "ANALYZE sqlite_master; " \ "" -#define STMT_UPGRADE_TO_20 212 -#define STMT_212_INFO {"STMT_UPGRADE_TO_20", NULL} -#define STMT_212 \ - "UPDATE BASE_NODE SET checksum = (SELECT checksum FROM pristine " \ - " WHERE md5_checksum = BASE_NODE.checksum) " \ - "WHERE EXISTS (SELECT 1 FROM pristine WHERE md5_checksum = BASE_NODE.checksum); " \ - "UPDATE WORKING_NODE SET checksum = (SELECT checksum FROM pristine " \ - " WHERE md5_checksum = WORKING_NODE.checksum) " \ - "WHERE EXISTS (SELECT 1 FROM pristine " \ - " WHERE md5_checksum = WORKING_NODE.checksum); " \ - "INSERT INTO NODES ( " \ - " wc_id, local_relpath, op_depth, parent_relpath, " \ - " repos_id, repos_path, revision, " \ - " presence, depth, moved_here, moved_to, kind, " \ - " changed_revision, changed_date, changed_author, " \ - " checksum, properties, translated_size, last_mod_time, " \ - " dav_cache, symlink_target, file_external ) " \ - "SELECT wc_id, local_relpath, 0 , parent_relpath, " \ - " repos_id, repos_relpath, revnum, " \ - " presence, depth, NULL , NULL , kind, " \ - " changed_rev, changed_date, changed_author, " \ - " checksum, properties, translated_size, last_mod_time, " \ - " dav_cache, symlink_target, file_external " \ - "FROM BASE_NODE; " \ - "INSERT INTO NODES ( " \ - " wc_id, local_relpath, op_depth, parent_relpath, " \ - " repos_id, repos_path, revision, " \ - " presence, depth, moved_here, moved_to, kind, " \ - " changed_revision, changed_date, changed_author, " \ - " checksum, properties, translated_size, last_mod_time, " \ - " dav_cache, symlink_target, file_external ) " \ - "SELECT wc_id, local_relpath, 2 , parent_relpath, " \ - " copyfrom_repos_id, copyfrom_repos_path, copyfrom_revnum, " \ - " presence, depth, NULL , NULL , kind, " \ - " changed_rev, changed_date, changed_author, " \ - " checksum, properties, translated_size, last_mod_time, " \ - " NULL , symlink_target, NULL " \ - "FROM WORKING_NODE; " \ - "DROP TABLE BASE_NODE; " \ - "DROP TABLE WORKING_NODE; " \ - "PRAGMA user_version = 20; " \ - "" - -#define STMT_UPGRADE_TO_21 213 -#define STMT_213_INFO {"STMT_UPGRADE_TO_21", NULL} -#define STMT_213 \ - "PRAGMA user_version = 21; " \ - "" - -#define STMT_UPGRADE_21_SELECT_OLD_TREE_CONFLICT 214 -#define STMT_214_INFO {"STMT_UPGRADE_21_SELECT_OLD_TREE_CONFLICT", NULL} -#define STMT_214 \ - "SELECT wc_id, local_relpath, tree_conflict_data " \ - "FROM actual_node " \ - "WHERE tree_conflict_data IS NOT NULL " \ - "" - -#define STMT_UPGRADE_21_ERASE_OLD_CONFLICTS 215 -#define STMT_215_INFO {"STMT_UPGRADE_21_ERASE_OLD_CONFLICTS", NULL} -#define STMT_215 \ - "UPDATE actual_node SET tree_conflict_data = NULL " \ - "" - -#define STMT_UPGRADE_TO_22 216 -#define STMT_216_INFO {"STMT_UPGRADE_TO_22", NULL} -#define STMT_216 \ - "UPDATE actual_node SET tree_conflict_data = conflict_data; " \ - "UPDATE actual_node SET conflict_data = NULL; " \ - "PRAGMA user_version = 22; " \ - "" - -#define STMT_UPGRADE_TO_23 217 -#define STMT_217_INFO {"STMT_UPGRADE_TO_23", NULL} -#define STMT_217 \ - "PRAGMA user_version = 23; " \ - "" - -#define STMT_UPGRADE_23_HAS_WORKING_NODES 218 -#define STMT_218_INFO {"STMT_UPGRADE_23_HAS_WORKING_NODES", NULL} -#define STMT_218 \ - "SELECT 1 FROM nodes WHERE op_depth > 0 " \ - "LIMIT 1 " \ - "" - -#define STMT_UPGRADE_TO_24 219 -#define STMT_219_INFO {"STMT_UPGRADE_TO_24", NULL} -#define STMT_219 \ - "UPDATE pristine SET refcount = " \ - " (SELECT COUNT(*) FROM nodes " \ - " WHERE checksum = pristine.checksum ); " \ - "PRAGMA user_version = 24; " \ - "" - -#define STMT_UPGRADE_TO_25 220 -#define STMT_220_INFO {"STMT_UPGRADE_TO_25", NULL} -#define STMT_220 \ - "DROP VIEW IF EXISTS NODES_CURRENT; " \ - "CREATE VIEW NODES_CURRENT AS " \ - " SELECT * FROM nodes " \ - " JOIN (SELECT wc_id, local_relpath, MAX(op_depth) AS op_depth FROM nodes " \ - " GROUP BY wc_id, local_relpath) AS filter " \ - " ON nodes.wc_id = filter.wc_id " \ - " AND nodes.local_relpath = filter.local_relpath " \ - " AND nodes.op_depth = filter.op_depth; " \ - "PRAGMA user_version = 25; " \ - "" - -#define STMT_UPGRADE_TO_26 221 -#define STMT_221_INFO {"STMT_UPGRADE_TO_26", NULL} -#define STMT_221 \ - "DROP VIEW IF EXISTS NODES_BASE; " \ - "CREATE VIEW NODES_BASE AS " \ - " SELECT * FROM nodes " \ - " WHERE op_depth = 0; " \ - "PRAGMA user_version = 26; " \ - "" - -#define STMT_UPGRADE_TO_27 222 -#define STMT_222_INFO {"STMT_UPGRADE_TO_27", NULL} -#define STMT_222 \ - "PRAGMA user_version = 27; " \ - "" - -#define STMT_UPGRADE_27_HAS_ACTUAL_NODES_CONFLICTS 223 -#define STMT_223_INFO {"STMT_UPGRADE_27_HAS_ACTUAL_NODES_CONFLICTS", NULL} -#define STMT_223 \ - "SELECT 1 FROM actual_node " \ - "WHERE NOT ((prop_reject IS NULL) AND (conflict_old IS NULL) " \ - " AND (conflict_new IS NULL) AND (conflict_working IS NULL) " \ - " AND (tree_conflict_data IS NULL)) " \ - "LIMIT 1 " \ - "" - -#define STMT_UPGRADE_TO_28 224 -#define STMT_224_INFO {"STMT_UPGRADE_TO_28", NULL} -#define STMT_224 \ - "UPDATE NODES SET checksum = (SELECT checksum FROM pristine " \ - " WHERE md5_checksum = nodes.checksum) " \ - "WHERE EXISTS (SELECT 1 FROM pristine WHERE md5_checksum = nodes.checksum); " \ - "PRAGMA user_version = 28; " \ - "" - -#define STMT_UPGRADE_TO_29 225 -#define STMT_225_INFO {"STMT_UPGRADE_TO_29", NULL} -#define STMT_225 \ - "DROP TRIGGER IF EXISTS nodes_update_checksum_trigger; " \ - "DROP TRIGGER IF EXISTS nodes_insert_trigger; " \ - "DROP TRIGGER IF EXISTS nodes_delete_trigger; " \ - "CREATE TRIGGER nodes_update_checksum_trigger " \ - "AFTER UPDATE OF checksum ON nodes " \ - "WHEN NEW.checksum IS NOT OLD.checksum " \ - "BEGIN " \ - " UPDATE pristine SET refcount = refcount + 1 " \ - " WHERE checksum = NEW.checksum; " \ - " UPDATE pristine SET refcount = refcount - 1 " \ - " WHERE checksum = OLD.checksum; " \ - "END; " \ - "CREATE TRIGGER nodes_insert_trigger " \ - "AFTER INSERT ON nodes " \ - "WHEN NEW.checksum IS NOT NULL " \ - "BEGIN " \ - " UPDATE pristine SET refcount = refcount + 1 " \ - " WHERE checksum = NEW.checksum; " \ - "END; " \ - "CREATE TRIGGER nodes_delete_trigger " \ - "AFTER DELETE ON nodes " \ - "WHEN OLD.checksum IS NOT NULL " \ - "BEGIN " \ - " UPDATE pristine SET refcount = refcount - 1 " \ - " WHERE checksum = OLD.checksum; " \ - "END; " \ - "PRAGMA user_version = 29; " \ - "" - -#define STMT_UPGRADE_TO_30 226 -#define STMT_226_INFO {"STMT_UPGRADE_TO_30", NULL} -#define STMT_226 \ +#define STMT_UPGRADE_TO_30 209 +#define STMT_209_INFO {"STMT_UPGRADE_TO_30", NULL} +#define STMT_209 \ "CREATE UNIQUE INDEX IF NOT EXISTS I_NODES_MOVED " \ "ON NODES (wc_id, moved_to, op_depth); " \ "CREATE INDEX IF NOT EXISTS I_PRISTINE_MD5 ON PRISTINE (md5_checksum); " \ @@ -2610,9 +2419,9 @@ "UPDATE nodes SET file_external=1 WHERE file_external IS NOT NULL; " \ "" -#define STMT_UPGRADE_30_SELECT_CONFLICT_SEPARATE 227 -#define STMT_227_INFO {"STMT_UPGRADE_30_SELECT_CONFLICT_SEPARATE", NULL} -#define STMT_227 \ +#define STMT_UPGRADE_30_SELECT_CONFLICT_SEPARATE 210 +#define STMT_210_INFO {"STMT_UPGRADE_30_SELECT_CONFLICT_SEPARATE", NULL} +#define STMT_210 \ "SELECT wc_id, local_relpath, " \ " conflict_old, conflict_working, conflict_new, prop_reject, tree_conflict_data " \ "FROM actual_node " \ @@ -2624,24 +2433,19 @@ "ORDER by wc_id, local_relpath " \ "" -#define STMT_UPGRADE_30_SET_CONFLICT 228 -#define STMT_228_INFO {"STMT_UPGRADE_30_SET_CONFLICT", NULL} -#define STMT_228 \ +#define STMT_UPGRADE_30_SET_CONFLICT 211 +#define STMT_211_INFO {"STMT_UPGRADE_30_SET_CONFLICT", NULL} +#define STMT_211 \ "UPDATE actual_node SET conflict_data = ?3, conflict_old = NULL, " \ " conflict_working = NULL, conflict_new = NULL, prop_reject = NULL, " \ " tree_conflict_data = NULL " \ "WHERE wc_id = ?1 and local_relpath = ?2 " \ "" -#define STMT_UPGRADE_TO_31_ALTER_TABLE 229 -#define STMT_229_INFO {"STMT_UPGRADE_TO_31_ALTER_TABLE", NULL} -#define STMT_229 \ +#define STMT_UPGRADE_TO_31 212 +#define STMT_212_INFO {"STMT_UPGRADE_TO_31", NULL} +#define STMT_212 \ "ALTER TABLE NODES ADD COLUMN inherited_props BLOB; " \ - "" - -#define STMT_UPGRADE_TO_31_FINALIZE 230 -#define STMT_230_INFO {"STMT_UPGRADE_TO_31_FINALIZE", NULL} -#define STMT_230 \ "DROP INDEX IF EXISTS I_ACTUAL_CHANGELIST; " \ "DROP INDEX IF EXISTS I_EXTERNALS_PARENT; " \ "DROP INDEX I_NODES_PARENT; " \ @@ -2653,9 +2457,9 @@ "PRAGMA user_version = 31; " \ "" -#define STMT_UPGRADE_31_SELECT_WCROOT_NODES 231 -#define STMT_231_INFO {"STMT_UPGRADE_31_SELECT_WCROOT_NODES", NULL} -#define STMT_231 \ +#define STMT_UPGRADE_31_SELECT_WCROOT_NODES 213 +#define STMT_213_INFO {"STMT_UPGRADE_31_SELECT_WCROOT_NODES", NULL} +#define STMT_213 \ "SELECT l.wc_id, l.local_relpath FROM nodes as l " \ "LEFT OUTER JOIN nodes as r " \ "ON l.wc_id = r.wc_id " \ @@ -2667,21 +2471,6 @@ " OR (l.repos_path IS NOT (CASE WHEN (r.local_relpath) = '' THEN (CASE WHEN (r.repos_path) = '' THEN (l.local_relpath) WHEN (l.local_relpath) = '' THEN (r.repos_path) ELSE (r.repos_path) || '/' || (l.local_relpath) END) WHEN (r.repos_path) = '' THEN (CASE WHEN (r.local_relpath) = '' THEN (l.local_relpath) WHEN SUBSTR((l.local_relpath), 1, LENGTH(r.local_relpath)) = (r.local_relpath) THEN CASE WHEN LENGTH(r.local_relpath) = LENGTH(l.local_relpath) THEN '' WHEN SUBSTR((l.local_relpath), LENGTH(r.local_relpath)+1, 1) = '/' THEN SUBSTR((l.local_relpath), LENGTH(r.local_relpath)+2) END END) WHEN SUBSTR((l.local_relpath), 1, LENGTH(r.local_relpath)) = (r.local_relpath) THEN CASE WHEN LENGTH(r.local_relpath) = LENGTH(l.local_relpath) THEN (r.repos_path) WHEN SUBSTR((l.local_relpath), LENGTH(r.local_relpath)+1, 1) = '/' THEN (r.repos_path) || SUBSTR((l.local_relpath), LENGTH(r.local_relpath)+1) END END))) " \ "" -#define STMT_UPGRADE_TO_32 232 -#define STMT_232_INFO {"STMT_UPGRADE_TO_32", NULL} -#define STMT_232 \ - "DROP INDEX IF EXISTS I_ACTUAL_CHANGELIST; " \ - "DROP INDEX IF EXISTS I_EXTERNALS_PARENT; " \ - "CREATE INDEX I_EXTERNALS_PARENT ON EXTERNALS (wc_id, parent_relpath); " \ - "DROP INDEX I_NODES_PARENT; " \ - "CREATE UNIQUE INDEX I_NODES_PARENT ON NODES (wc_id, parent_relpath, " \ - " local_relpath, op_depth); " \ - "DROP INDEX I_ACTUAL_PARENT; " \ - "CREATE UNIQUE INDEX I_ACTUAL_PARENT ON ACTUAL_NODE (wc_id, parent_relpath, " \ - " local_relpath); " \ - "-- format: YYY " \ - "" - #define WC_QUERIES_SQL_99 \ "CREATE TABLE ACTUAL_NODE_BACKUP ( " \ " wc_id INTEGER NOT NULL, " \ @@ -2722,9 +2511,9 @@ "DROP TABLE ACTUAL_NODE_BACKUP; " \ "" -#define STMT_VERIFICATION_TRIGGERS 233 -#define STMT_233_INFO {"STMT_VERIFICATION_TRIGGERS", NULL} -#define STMT_233 \ +#define STMT_VERIFICATION_TRIGGERS 214 +#define STMT_214_INFO {"STMT_VERIFICATION_TRIGGERS", NULL} +#define STMT_214 \ "CREATE TEMPORARY TRIGGER no_repository_updates BEFORE UPDATE ON repository " \ "BEGIN " \ " SELECT RAISE(FAIL, 'Updates to REPOSITORY are not allowed.'); " \ @@ -2763,9 +2552,9 @@ "END; " \ "" -#define STMT_STATIC_VERIFY 234 -#define STMT_234_INFO {"STMT_STATIC_VERIFY", NULL} -#define STMT_234 \ +#define STMT_STATIC_VERIFY 215 +#define STMT_215_INFO {"STMT_STATIC_VERIFY", NULL} +#define STMT_215 \ "SELECT local_relpath, op_depth, 1, 'Invalid parent relpath set in NODES' " \ "FROM nodes n WHERE local_relpath != '' " \ " AND (parent_relpath IS NULL " \ @@ -3154,25 +2943,6 @@ STMT_213, \ STMT_214, \ STMT_215, \ - STMT_216, \ - STMT_217, \ - STMT_218, \ - STMT_219, \ - STMT_220, \ - STMT_221, \ - STMT_222, \ - STMT_223, \ - STMT_224, \ - STMT_225, \ - STMT_226, \ - STMT_227, \ - STMT_228, \ - STMT_229, \ - STMT_230, \ - STMT_231, \ - STMT_232, \ - STMT_233, \ - STMT_234, \ NULL \ } @@ -3394,24 +3164,5 @@ STMT_213_INFO, \ STMT_214_INFO, \ STMT_215_INFO, \ - STMT_216_INFO, \ - STMT_217_INFO, \ - STMT_218_INFO, \ - STMT_219_INFO, \ - STMT_220_INFO, \ - STMT_221_INFO, \ - STMT_222_INFO, \ - STMT_223_INFO, \ - STMT_224_INFO, \ - STMT_225_INFO, \ - STMT_226_INFO, \ - STMT_227_INFO, \ - STMT_228_INFO, \ - STMT_229_INFO, \ - STMT_230_INFO, \ - STMT_231_INFO, \ - STMT_232_INFO, \ - STMT_233_INFO, \ - STMT_234_INFO, \ {NULL, NULL} \ } diff --git a/subversion/libsvn_wc/wc-queries.sql b/subversion/libsvn_wc/wc-queries.sql index 3a8bf92a2776..86cf9216a058 100644 --- a/subversion/libsvn_wc/wc-queries.sql +++ b/subversion/libsvn_wc/wc-queries.sql @@ -46,7 +46,7 @@ SELECT op_depth, nodes.repos_id, nodes.repos_path, presence, kind, revision, lock_token, lock_owner, lock_comment, lock_date FROM nodes LEFT OUTER JOIN lock ON nodes.repos_id = lock.repos_id - AND nodes.repos_path = lock.repos_relpath + AND nodes.repos_path = lock.repos_relpath AND nodes.op_depth=0 WHERE wc_id = ?1 AND local_relpath = ?2 ORDER BY op_depth DESC @@ -134,7 +134,7 @@ SELECT op_depth, nodes.repos_id, nodes.repos_path, presence, kind, revision, lock_comment, lock_date, local_relpath, moved_here, moved_to, file_external FROM nodes LEFT OUTER JOIN lock ON nodes.repos_id = lock.repos_id - AND nodes.repos_path = lock.repos_relpath AND op_depth = 0 + AND nodes.repos_path = lock.repos_relpath AND nodes.op_depth = 0 WHERE wc_id = ?1 AND parent_relpath = ?2 ORDER BY local_relpath DESC, op_depth DESC @@ -148,7 +148,7 @@ SELECT op_depth, nodes.repos_id, nodes.repos_path, presence, kind, revision, lock_comment, lock_date, local_relpath, moved_here, moved_to, file_external FROM nodes LEFT OUTER JOIN lock ON nodes.repos_id = lock.repos_id - AND nodes.repos_path = lock.repos_relpath AND op_depth = 0 + AND nodes.repos_path = lock.repos_relpath WHERE wc_id = ?1 AND parent_relpath = ?2 AND op_depth = 0 ORDER BY local_relpath DESC @@ -1291,6 +1291,10 @@ PRAGMA locking_mode = exclusive; exclusive-locking is mostly used on remote file systems. */ PRAGMA journal_mode = DELETE +-- STMT_FIND_REPOS_PATH_IN_WC +SELECT local_relpath FROM nodes_current + WHERE wc_id = ?1 AND repos_path = ?2 + /* ------------------------------------------------------------------------- */ /* these are used in entries.c */ @@ -1747,13 +1751,6 @@ WHERE wc_id = ?1 /* Queries for cached inherited properties. */ -/* Select the inherited properties of a single base node. */ --- STMT_SELECT_IPROPS -SELECT inherited_props FROM nodes -WHERE wc_id = ?1 - AND local_relpath = ?2 - AND op_depth = 0 - /* Update the inherited properties of a single base node. */ -- STMT_UPDATE_IPROP UPDATE nodes diff --git a/subversion/libsvn_wc/wc.h b/subversion/libsvn_wc/wc.h index ab6870d1a74f..f8bbebd93ade 100644 --- a/subversion/libsvn_wc/wc.h +++ b/subversion/libsvn_wc/wc.h @@ -158,6 +158,8 @@ extern "C" { * Bumped in r1395109. * * == 1.8.x shipped with format 31 + * == 1.9.x shipped with format 31 + * == 1.10.x shipped with format 31 * * Please document any further format changes here. */ @@ -479,7 +481,7 @@ svn_wc__conflicted_for_update_p(svn_boolean_t *conflicted_p, /* Internal version of svn_wc_transmit_text_deltas3(). */ svn_error_t * -svn_wc__internal_transmit_text_deltas(const char **tempfile, +svn_wc__internal_transmit_text_deltas(svn_stream_t *tempstream, const svn_checksum_t **new_text_base_md5_checksum, const svn_checksum_t **new_text_base_sha1_checksum, svn_wc__db_t *db, diff --git a/subversion/libsvn_wc/wc_db.c b/subversion/libsvn_wc/wc_db.c index ee17b85e3a58..bc87b2f9d8d9 100644 --- a/subversion/libsvn_wc/wc_db.c +++ b/subversion/libsvn_wc/wc_db.c @@ -1371,9 +1371,6 @@ init_db(/* output values */ /* Create the database's schema. */ SVN_ERR(svn_sqlite__exec_statements(db, STMT_CREATE_SCHEMA)); - SVN_ERR(svn_sqlite__exec_statements(db, STMT_CREATE_NODES)); - SVN_ERR(svn_sqlite__exec_statements(db, STMT_CREATE_NODES_TRIGGERS)); - SVN_ERR(svn_sqlite__exec_statements(db, STMT_CREATE_EXTERNALS)); SVN_ERR(svn_wc__db_install_schema_statistics(db, scratch_pool)); @@ -6698,8 +6695,14 @@ svn_wc__db_op_mark_resolved_internal(svn_wc__db_wcroot_t *wcroot, conflict_data = svn_sqlite__column_blob(stmt, 2, &conflict_len, scratch_pool); - conflicts = svn_skel__parse(conflict_data, conflict_len, scratch_pool); SVN_ERR(svn_sqlite__reset(stmt)); + SVN_ERR(add_work_items(wcroot->sdb, work_items, scratch_pool)); + + if (!conflict_data) + return SVN_NO_ERROR; + + conflicts = svn_skel__parse(conflict_data, conflict_len, scratch_pool); + SVN_ERR(svn_wc__conflict_skel_resolve(&resolved_all, conflicts, db, wcroot->abspath, @@ -6731,8 +6734,6 @@ svn_wc__db_op_mark_resolved_internal(svn_wc__db_wcroot_t *wcroot, SVN_ERR(svn_sqlite__step_done(stmt)); } - SVN_ERR(add_work_items(wcroot->sdb, work_items, scratch_pool)); - return SVN_NO_ERROR; } @@ -10164,7 +10165,7 @@ db_read_repos_info(svn_revnum_t *revision, local_relpath), result_pool); } - else + else if (base_del_relpath) { SVN_ERR(svn_wc__db_base_get_info_internal(NULL, NULL, revision, repos_relpath, @@ -10184,6 +10185,8 @@ db_read_repos_info(svn_revnum_t *revision, local_relpath), result_pool); } + else + SVN_ERR_MALFUNCTION(); } else if (status == svn_wc__db_status_excluded) { @@ -10614,68 +10617,6 @@ svn_wc__db_prop_retrieve_recursive(apr_hash_t **values, return svn_error_trace(svn_sqlite__reset(stmt)); } -/* The body of svn_wc__db_read_cached_iprops(). */ -static svn_error_t * -db_read_cached_iprops(apr_array_header_t **iprops, - svn_wc__db_wcroot_t *wcroot, - const char *local_relpath, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) -{ - svn_sqlite__stmt_t *stmt; - svn_boolean_t have_row; - - SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_SELECT_IPROPS)); - SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath)); - SVN_ERR(svn_sqlite__step(&have_row, stmt)); - - if (!have_row) - { - return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, - svn_sqlite__reset(stmt), - _("The node '%s' was not found."), - path_for_error_message(wcroot, local_relpath, - scratch_pool)); - } - - SVN_ERR(svn_sqlite__column_iprops(iprops, stmt, 0, - result_pool, scratch_pool)); - - SVN_ERR(svn_sqlite__reset(stmt)); - - return SVN_NO_ERROR; -} - -svn_error_t * -svn_wc__db_read_cached_iprops(apr_array_header_t **iprops, - svn_wc__db_t *db, - const char *local_abspath, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) -{ - svn_wc__db_wcroot_t *wcroot; - const char *local_relpath; - - SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath)); - - SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, - db, local_abspath, - scratch_pool, scratch_pool)); - VERIFY_USABLE_WCROOT(wcroot); - - /* Don't use with_txn yet, as we perform just a single transaction */ - SVN_ERR(db_read_cached_iprops(iprops, wcroot, local_relpath, - result_pool, scratch_pool)); - - if (!*iprops) - { - *iprops = apr_array_make(result_pool, 0, - sizeof(svn_prop_inherited_item_t *)); - } - - return SVN_NO_ERROR; -} - /* Remove all prop name value pairs from PROP_HASH where the property name is not PROPNAME. */ static void @@ -11398,7 +11339,9 @@ relocate_txn(svn_wc__db_wcroot_t *wcroot, SVN_ERR(svn_wc__db_fetch_repos_info(NULL, &repos_uuid, wcroot, old_repos_id, scratch_pool)); - SVN_ERR_ASSERT(repos_uuid); /* This function affects all the children of the given local_relpath, + SVN_ERR_ASSERT(repos_uuid); + + /* This function affects all the children of the given local_relpath, but the way that it does this is through the repos inheritance mechanism. So, we only need to rewrite the repos_id of the given local_relpath, as well as any children with a non-null repos_id, as well as various @@ -11425,6 +11368,11 @@ relocate_txn(svn_wc__db_wcroot_t *wcroot, SVN_ERR(svn_sqlite__step_done(stmt)); } + /* ### TODO: Update urls stored in inherited properties... + What about urls in conflicts? + # We can probably keep these as they are only used + for showing full urls to the user */ + return SVN_NO_ERROR; } @@ -16628,3 +16576,47 @@ svn_wc__db_process_commit_queue(svn_wc__db_t *db, return SVN_NO_ERROR; } + +svn_error_t * +svn_wc__find_repos_node_in_wc(apr_array_header_t **local_abspath_list, + svn_wc__db_t *db, + const char *wri_abspath, + const char *repos_relpath, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_wc__db_wcroot_t *wcroot; + const char *wri_relpath; + svn_sqlite__stmt_t *stmt; + svn_boolean_t have_row; + + SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath)); + + SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &wri_relpath, db, + wri_abspath, scratch_pool, + scratch_pool)); + VERIFY_USABLE_WCROOT(wcroot); + + SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, + STMT_FIND_REPOS_PATH_IN_WC)); + SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, repos_relpath)); + SVN_ERR(svn_sqlite__step(&have_row, stmt)); + + *local_abspath_list = apr_array_make(result_pool, have_row ? 1 : 0, + sizeof(const char*)); + while (have_row) + { + const char *local_relpath; + const char *local_abspath; + + local_relpath = svn_sqlite__column_text(stmt, 0, NULL); + local_abspath = svn_dirent_join(wcroot->abspath, local_relpath, + result_pool); + APR_ARRAY_PUSH(*local_abspath_list, const char *) = local_abspath; + + SVN_ERR(svn_sqlite__step(&have_row, stmt)); + } + + return svn_error_trace(svn_sqlite__reset(stmt)); +} + diff --git a/subversion/libsvn_wc/wc_db.h b/subversion/libsvn_wc/wc_db.h index a947be04ee76..0bf6432100fb 100644 --- a/subversion/libsvn_wc/wc_db.h +++ b/subversion/libsvn_wc/wc_db.h @@ -1644,7 +1644,12 @@ svn_wc__db_op_mark_conflict(svn_wc__db_t *db, apr_pool_t *scratch_pool); -/* ### caller maintains ACTUAL, and how the resolution occurred. we're just +/* Clear all or some of the conflicts stored on LOCAL_ABSPATH, if any. + + Any work items that are necessary as part of resolving this node + can be passed in WORK_ITEMS. + +### caller maintains ACTUAL, and how the resolution occurred. we're just ### recording state. ### ### I'm not sure that these three values are the best way to do this, @@ -3043,7 +3048,7 @@ svn_wc__db_wclock_obtain(svn_wc__db_t *db, svn_boolean_t steal_lock, apr_pool_t *scratch_pool); -/* Set LOCK_ABSPATH to the path of the the directory that owns the +/* Set LOCK_ABSPATH to the path of the directory that owns the lock on LOCAL_ABSPATH, or NULL, if LOCAL_ABSPATH is not locked. */ svn_error_t* svn_wc__db_wclock_find_root(const char **lock_abspath, @@ -3399,6 +3404,33 @@ svn_wc__db_update_moved_away_conflict_victim(svn_wc__db_t *db, void *notify_baton, apr_pool_t *scratch_pool); +/* Merge local changes from tree conflict victim at LOCAL_ABSPATH into the + directory at DEST_ABSPATH. This function requires that LOCAL_ABSPATH is + a directory and a tree-conflict victim. DST_ABSPATH must be a directory. */ +svn_error_t * +svn_wc__db_update_incoming_move(svn_wc__db_t *db, + const char *local_abspath, + const char *dest_abspath, + svn_wc_operation_t operation, + svn_wc_conflict_action_t action, + svn_wc_conflict_reason_t reason, + svn_cancel_func_t cancel_func, + void *cancel_baton, + svn_wc_notify_func2_t notify_func, + void *notify_baton, + apr_pool_t *scratch_pool); + +/* Merge locally added dir tree conflict victim at LOCAL_ABSPATH with the + * directory since added to the BASE layer by an update operation. */ +svn_error_t * +svn_wc__db_update_local_add(svn_wc__db_t *db, + const char *local_abspath, + svn_cancel_func_t cancel_func, + void *cancel_baton, + svn_wc_notify_func2_t notify_func, + void *notify_baton, + apr_pool_t *scratch_pool); + /* LOCAL_ABSPATH is moved to MOVE_DST_ABSPATH. MOVE_SRC_ROOT_ABSPATH * is the root of the move to MOVE_DST_OP_ROOT_ABSPATH. * DELETE_ABSPATH is the op-root of the move; it's the same @@ -3433,7 +3465,7 @@ svn_wc__db_op_raise_moved_away(svn_wc__db_t *db, apr_pool_t *scratch_pool); /* Breaks all moves of nodes that exist at or below LOCAL_ABSPATH as - shadowed (read: deleted) by the opration rooted at + shadowed (read: deleted) by the operation rooted at delete_op_root_abspath. */ svn_error_t * @@ -3454,6 +3486,22 @@ svn_wc__required_lock_for_resolve(const char **required_abspath, const char *local_abspath, apr_pool_t *result_pool, apr_pool_t *scratch_pool); + +/* Return an array of const char * elements, which represent local absolute + * paths for nodes, within the working copy indicated by WRI_ABSPATH, which + * correspond to REPOS_RELPATH. If no such nodes exist, return an empty array. + * + * Note that this function returns each and every such node that is known + * in the WC, including, for example, nodes that were children of a directory + * which has been replaced. + */ +svn_error_t * +svn_wc__find_repos_node_in_wc(apr_array_header_t **local_abspath_list, + svn_wc__db_t *db, + const char *wri_abspath, + const char *repos_relpath, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); /* @} */ typedef svn_error_t * (*svn_wc__db_verify_cb_t)(void *baton, diff --git a/subversion/libsvn_wc/wc_db_pristine.c b/subversion/libsvn_wc/wc_db_pristine.c index 9118d7068810..90b35774df48 100644 --- a/subversion/libsvn_wc/wc_db_pristine.c +++ b/subversion/libsvn_wc/wc_db_pristine.c @@ -227,7 +227,6 @@ svn_wc__db_pristine_read(svn_stream_t **contents, const char *local_relpath; const char *pristine_abspath; - SVN_ERR_ASSERT(contents != NULL); SVN_ERR_ASSERT(svn_dirent_is_absolute(wri_abspath)); /* Some 1.6-to-1.7 wc upgrades created rows without checksums and @@ -317,9 +316,10 @@ pristine_install_txn(svn_sqlite__db_t *sdb, { return svn_error_createf( SVN_ERR_WC_CORRUPT_TEXT_BASE, NULL, - _("New pristine text '%s' has different size: %ld versus %ld"), + _("New pristine text '%s' has different size: %s versus %s"), svn_checksum_to_cstring_display(sha1_checksum, scratch_pool), - (long int)finfo1.size, (long int)finfo2.size); + apr_off_t_toa(scratch_pool, finfo1.size), + apr_off_t_toa(scratch_pool, finfo2.size)); } } #endif @@ -333,13 +333,12 @@ pristine_install_txn(svn_sqlite__db_t *sdb, * an orphan file and it doesn't matter if we overwrite it.) */ { apr_finfo_t finfo; - SVN_ERR(svn_stream__install_get_info(&finfo, install_stream, APR_FINFO_SIZE, - scratch_pool)); + SVN_ERR(svn_stream__install_get_info(&finfo, install_stream, + APR_FINFO_SIZE, scratch_pool)); SVN_ERR(svn_stream__install_stream(install_stream, pristine_abspath, - TRUE, scratch_pool)); + TRUE, scratch_pool)); - SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, - STMT_INSERT_PRISTINE)); + SVN_ERR(svn_sqlite__get_statement(&stmt, sdb, STMT_INSERT_PRISTINE)); SVN_ERR(svn_sqlite__bind_checksum(stmt, 1, sha1_checksum, scratch_pool)); SVN_ERR(svn_sqlite__bind_checksum(stmt, 2, md5_checksum, scratch_pool)); SVN_ERR(svn_sqlite__bind_int64(stmt, 3, finfo.size)); @@ -569,7 +568,8 @@ maybe_transfer_one_pristine(svn_wc__db_wcroot_t *src_wcroot, /* Move the file to its target location. (If it is already there, it is * an orphan file and it doesn't matter if we overwrite it.) */ - err = svn_io_file_rename(tmp_abspath, pristine_abspath, scratch_pool); + err = svn_io_file_rename2(tmp_abspath, pristine_abspath, FALSE, + scratch_pool); /* Maybe the directory doesn't exist yet? */ if (err && APR_STATUS_IS_ENOENT(err->apr_err)) @@ -587,7 +587,8 @@ maybe_transfer_one_pristine(svn_wc__db_wcroot_t *src_wcroot, /* We could create a directory: retry install */ svn_error_clear(err); - SVN_ERR(svn_io_file_rename(tmp_abspath, pristine_abspath, scratch_pool)); + SVN_ERR(svn_io_file_rename2(tmp_abspath, pristine_abspath, FALSE, + scratch_pool)); } else SVN_ERR(err); @@ -686,42 +687,6 @@ svn_wc__db_pristine_transfer(svn_wc__db_t *db, -/* Remove the file at FILE_ABSPATH in such a way that we could re-create a - * new file of the same name at any time thereafter. - * - * On Windows, the file will not disappear immediately from the directory if - * it is still being read so the best thing to do is first rename it to a - * unique name. */ -static svn_error_t * -remove_file(const char *file_abspath, - svn_wc__db_wcroot_t *wcroot, - svn_boolean_t ignore_enoent, - apr_pool_t *scratch_pool) -{ -#ifdef WIN32 - svn_error_t *err; - const char *temp_abspath; - const char *temp_dir_abspath - = pristine_get_tempdir(wcroot, scratch_pool, scratch_pool); - - /* To rename the file to a unique name in the temp dir, first create a - * uniquely named file in the temp dir and then overwrite it. */ - SVN_ERR(svn_io_open_unique_file3(NULL, &temp_abspath, temp_dir_abspath, - svn_io_file_del_none, - scratch_pool, scratch_pool)); - err = svn_io_file_rename(file_abspath, temp_abspath, scratch_pool); - if (err && ignore_enoent && APR_STATUS_IS_ENOENT(err->apr_err)) - svn_error_clear(err); - else - SVN_ERR(err); - file_abspath = temp_abspath; -#endif - - SVN_ERR(svn_io_remove_file2(file_abspath, ignore_enoent, scratch_pool)); - - return SVN_NO_ERROR; -} - /* If the pristine text referenced by SHA1_CHECKSUM in WCROOT/SDB, whose path * within the pristine store is PRISTINE_ABSPATH, has a reference count of * zero, delete it (both the database row and the disk file). @@ -757,8 +722,8 @@ pristine_remove_if_unreferenced_txn(svn_sqlite__db_t *sdb, svn_boolean_t ignore_enoent = TRUE; #endif - SVN_ERR(remove_file(pristine_abspath, wcroot, ignore_enoent, - scratch_pool)); + SVN_ERR(svn_io_remove_file2(pristine_abspath, ignore_enoent, + scratch_pool)); } return SVN_NO_ERROR; @@ -949,11 +914,28 @@ svn_wc__db_pristine_check(svn_boolean_t *present, { const char *pristine_abspath; svn_node_kind_t kind_on_disk; + svn_error_t *err; SVN_ERR(get_pristine_fname(&pristine_abspath, wcroot->abspath, sha1_checksum, scratch_pool, scratch_pool)); - SVN_ERR(svn_io_check_path(pristine_abspath, &kind_on_disk, scratch_pool)); - if (kind_on_disk != svn_node_file) + err = svn_io_check_path(pristine_abspath, &kind_on_disk, scratch_pool); +#ifdef WIN32 + if (err && err->apr_err == APR_FROM_OS_ERROR(ERROR_ACCESS_DENIED)) + { + svn_error_clear(err); + /* Possible race condition: The filename is locked, but there is no + file or dir with this name. Let's fall back on checking the DB. + + This case is triggered by the pristine store tests on deleting + a file that is still open via another handle, where this other + handle has a FILE_SHARE_DELETE share mode. + */ + } + else +#endif + if (err) + return svn_error_trace(err); + else if (kind_on_disk != svn_node_file) { *present = FALSE; return SVN_NO_ERROR; diff --git a/subversion/libsvn_wc/wc_db_update_move.c b/subversion/libsvn_wc/wc_db_update_move.c index 46cbeae361c8..ba7117581ec1 100644 --- a/subversion/libsvn_wc/wc_db_update_move.c +++ b/subversion/libsvn_wc/wc_db_update_move.c @@ -21,13 +21,16 @@ * ==================================================================== */ -/* This file implements an editor and an edit driver which are used - * to resolve an "incoming edit, local move-away" tree conflict resulting - * from an update (or switch). +/* This implements editors and edit drivers which are used to resolve + * "incoming edit, local move-away", "incoming move, local edit", and + * "incoming add, local add" tree conflicts resulting from an update + * (or switch). * - * Our goal is to be able to resolve this conflict such that the end - * result is just the same as if the user had run the update *before* - * the local move. + * Our goal is to be able to resolve conflicts such that the end result + * is just the same as if the user had run the update *before* the local + * (or incoming) move or local add. + * + * -- Updating local moves -- * * When an update (or switch) produces incoming changes for a locally * moved-away subtree, it updates the base nodes of the moved-away tree @@ -72,6 +75,58 @@ * representing a replacement, but this editor only reads from the * single-op-depth layer of it, and makes no changes of any kind * within the source tree. + * + * -- Updating incoming moves -- + * + * When an update (or switch) produces an incoming move, it deletes the + * moved node at the old location from the BASE tree and adds a node at + * the new location to the BASE tree. If the old location contains local + * changes, a tree conflict is raised, and the former BASE tree which + * the local changes were based on (the tree conflict victim) is re-added + * as a copy which contains these local changes. + * + * The driver sees two NODES trees: The op-root of the copy, and the + * WORKING layer on top of this copy which represents the local changes. + * The driver will compare the two NODES trees and drive an editor to + * change the move destination's WORKING tree so that it now contains + * the local changes seen in the copy of the victim's tree. + * + * We require that no local changes exist at the destination, in order + * to avoid tree conflicts where the "incoming" and "local" change both + * originated in the working copy, because the resolver code cannot handle + * such tree conflicts at present. + * + * The whole drive occurs as one single wc.db transaction. At the end + * of the transaction the destination NODES table should have a WORKING + * layer that is equivalent to the WORKING layer found in the copied victim + * tree, and there should be workqueue items to make any required changes + * to working files/directories in the move destination, and there should be + * tree-conflicts in the move destination where it was not possible to + * update the working files/directories. + * + * -- Updating local adds -- + * + * When an update (or switch) adds a directory tree it creates corresponding + * nodes in the BASE tree. Any existing locally added nodes are bumped to a + * higher layer with the top-most locally added directory as op-root. + * In-between, the update inserts a base-deleted layer, i.e. it schedules the + * directory in the BASE tree for removal upon the next commit, to be replaced + * by the locally added directory. + * + * The driver sees two NODES trees: The BASE layer, and the WORKING layer + * which represents the locally added tree. + * The driver will compare the two NODES trees and drive an editor to + * merge WORKING tree nodes with the nodes in the BASE tree. + * + * The whole drive occurs as one single wc.db transaction. + * Directories which exist in both trees become part of the BASE tree, with + * properties merged. + * Files which exist in both trees are merged (there is no common ancestor, + * so the common ancestor in this merge is the empty file). + * Files and directories which exist only in the WORKING layer become + * local-add op-roots of their own. + * Mismatching node kinds produce new 'incoming add vs local add upon update' + * tree conflicts which must be resolved individually later on. */ #define SVN_WC__I_AM_WC_DB @@ -357,7 +412,7 @@ create_tree_conflict(svn_skel_t **conflict_p, move_src_op_root_relpath, scratch_pool) : NULL; const char *old_repos_relpath_part - = old_repos_relpath + = old_repos_relpath && old_version ? svn_relpath_skip_ancestor(old_version->path_in_repos, old_repos_relpath) : NULL; @@ -400,7 +455,7 @@ create_tree_conflict(svn_skel_t **conflict_p, if (conflict_operation != svn_wc_operation_update && conflict_operation != svn_wc_operation_switch) - return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + return svn_error_createf(SVN_ERR_WC_FOUND_CONFLICT, NULL, _("'%s' already in conflict"), path_for_error_message(wcroot, local_relpath, scratch_pool)); @@ -424,7 +479,7 @@ create_tree_conflict(svn_skel_t **conflict_p, && strcmp(move_src_op_root_relpath, svn_dirent_skip_ancestor(wcroot->abspath, existing_abspath)))) - return svn_error_createf(SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL, + return svn_error_createf(SVN_ERR_WC_FOUND_CONFLICT, NULL, _("'%s' already in conflict"), path_for_error_message(wcroot, local_relpath, @@ -448,10 +503,14 @@ create_tree_conflict(svn_skel_t **conflict_p, result_pool, scratch_pool)); - conflict_old_version = svn_wc_conflict_version_create2( - old_version->repos_url, old_version->repos_uuid, - old_repos_relpath, old_version->peg_rev, - old_kind, scratch_pool); + if (old_version) + conflict_old_version = svn_wc_conflict_version_create2( + old_version->repos_url, + old_version->repos_uuid, + old_repos_relpath, old_version->peg_rev, + old_kind, scratch_pool); + else + conflict_old_version = NULL; conflict_new_version = svn_wc_conflict_version_create2( new_version->repos_url, new_version->repos_uuid, @@ -491,7 +550,7 @@ create_node_tree_conflict(svn_skel_t **conflict_p, update_move_baton_t *umb = nmb->umb; const char *dst_repos_relpath; const char *dst_root_relpath = svn_relpath_prefix(nmb->dst_relpath, - nmb->umb->dst_op_depth, + umb->dst_op_depth, scratch_pool); dst_repos_relpath = @@ -500,8 +559,6 @@ create_node_tree_conflict(svn_skel_t **conflict_p, nmb->dst_relpath), scratch_pool); - - return svn_error_trace( create_tree_conflict(conflict_p, umb->wcroot, dst_local_relpath, svn_relpath_prefix(dst_local_relpath, @@ -736,6 +793,111 @@ tc_editor_add_directory(node_move_baton_t *nmb, return SVN_NO_ERROR; } +static svn_error_t * +copy_working_node(const char *src_relpath, + const char *dst_relpath, + svn_wc__db_wcroot_t *wcroot, + apr_pool_t *scratch_pool) +{ + svn_sqlite__stmt_t *stmt; + svn_boolean_t have_row; + const char *dst_parent_relpath = svn_relpath_dirname(dst_relpath, + scratch_pool); + + /* Add a WORKING row for the new node, based on the source. */ + SVN_ERR(svn_sqlite__get_statement(&stmt,wcroot->sdb, + STMT_INSERT_WORKING_NODE_COPY_FROM)); + SVN_ERR(svn_sqlite__bindf(stmt, "issdst", wcroot->wc_id, src_relpath, + dst_relpath, relpath_depth(dst_relpath), + dst_parent_relpath, presence_map, + svn_wc__db_status_normal)); + SVN_ERR(svn_sqlite__step_done(stmt)); + + /* Copy properties over. ### This loses changelist association. */ + SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, + STMT_SELECT_ACTUAL_NODE)); + SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, src_relpath)); + SVN_ERR(svn_sqlite__step(&have_row, stmt)); + if (have_row) + { + apr_size_t props_size; + const char *properties; + + properties = svn_sqlite__column_blob(stmt, 1, &props_size, + scratch_pool); + SVN_ERR(svn_sqlite__reset(stmt)); + SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, + STMT_INSERT_ACTUAL_NODE)); + SVN_ERR(svn_sqlite__bindf(stmt, "issbs", + wcroot->wc_id, dst_relpath, + svn_relpath_dirname(dst_relpath, + scratch_pool), + properties, props_size, NULL)); + SVN_ERR(svn_sqlite__step(&have_row, stmt)); + } + SVN_ERR(svn_sqlite__reset(stmt)); + + return SVN_NO_ERROR; +} + +static svn_error_t * +tc_editor_incoming_add_directory(node_move_baton_t *nmb, + const char *dst_relpath, + svn_node_kind_t old_kind, + apr_hash_t *props, + const char *src_relpath, + apr_pool_t *scratch_pool) +{ + update_move_baton_t *b = nmb->umb; + const char *dst_abspath; + svn_node_kind_t wc_kind; + svn_skel_t *work_item = NULL; + svn_skel_t *conflict = NULL; + svn_wc_conflict_reason_t reason = svn_wc_conflict_reason_unversioned; + + SVN_ERR(mark_parent_edited(nmb, scratch_pool)); + if (nmb->skip) + return SVN_NO_ERROR; + + dst_abspath = svn_dirent_join(b->wcroot->abspath, dst_relpath, scratch_pool); + + /* Check for unversioned tree-conflict */ + SVN_ERR(svn_io_check_path(dst_abspath, &wc_kind, scratch_pool)); + + if (wc_kind == old_kind) + wc_kind = svn_node_none; /* Node will be gone once we install */ + + if (wc_kind != svn_node_none && wc_kind != old_kind) /* replace */ + { + SVN_ERR(create_node_tree_conflict(&conflict, nmb, dst_relpath, + old_kind, svn_node_dir, + reason, + (old_kind == svn_node_none) + ? svn_wc_conflict_action_add + : svn_wc_conflict_action_replace, + NULL, + scratch_pool, scratch_pool)); + nmb->skip = TRUE; + } + else + { + SVN_ERR(copy_working_node(src_relpath, dst_relpath, b->wcroot, + scratch_pool)); + SVN_ERR(svn_wc__wq_build_dir_install(&work_item, b->db, dst_abspath, + scratch_pool, scratch_pool)); + } + + SVN_ERR(update_move_list_add(b->wcroot, dst_relpath, b->db, + (old_kind == svn_node_none) + ? svn_wc_notify_update_add + : svn_wc_notify_update_replace, + svn_node_dir, + svn_wc_notify_state_inapplicable, + svn_wc_notify_state_inapplicable, + conflict, work_item, scratch_pool)); + return SVN_NO_ERROR; +} + static svn_error_t * tc_editor_add_file(node_move_baton_t *nmb, const char *relpath, @@ -824,6 +986,85 @@ tc_editor_add_file(node_move_baton_t *nmb, return SVN_NO_ERROR; } +static svn_error_t * +tc_editor_incoming_add_file(node_move_baton_t *nmb, + const char *dst_relpath, + svn_node_kind_t old_kind, + const svn_checksum_t *checksum, + apr_hash_t *props, + const char *src_relpath, + const char *content_abspath, + apr_pool_t *scratch_pool) +{ + update_move_baton_t *b = nmb->umb; + svn_wc_conflict_reason_t reason = svn_wc_conflict_reason_unversioned; + svn_node_kind_t wc_kind; + const char *dst_abspath; + svn_skel_t *work_items = NULL; + svn_skel_t *work_item = NULL; + svn_skel_t *conflict = NULL; + + SVN_ERR(mark_parent_edited(nmb, scratch_pool)); + if (nmb->skip) + { + SVN_ERR(svn_io_remove_file2(content_abspath, TRUE, scratch_pool)); + return SVN_NO_ERROR; + } + + dst_abspath = svn_dirent_join(b->wcroot->abspath, dst_relpath, scratch_pool); + + /* Check for unversioned tree-conflict */ + SVN_ERR(svn_io_check_path(dst_abspath, &wc_kind, scratch_pool)); + + if (wc_kind != svn_node_none && wc_kind != old_kind) /* replace */ + { + SVN_ERR(create_node_tree_conflict(&conflict, nmb, dst_relpath, + old_kind, svn_node_file, + reason, + (old_kind == svn_node_none) + ? svn_wc_conflict_action_add + : svn_wc_conflict_action_replace, + NULL, + scratch_pool, scratch_pool)); + nmb->skip = TRUE; + SVN_ERR(svn_io_remove_file2(content_abspath, TRUE, scratch_pool)); + } + else + { + const char *src_abspath; + + SVN_ERR(copy_working_node(src_relpath, dst_relpath, b->wcroot, + scratch_pool)); + + /* Update working file. */ + src_abspath = svn_dirent_join(b->wcroot->abspath, src_relpath, + scratch_pool); + SVN_ERR(svn_wc__wq_build_file_install(&work_item, b->db, dst_abspath, + src_abspath, + FALSE /* FIXME: use_commit_times?*/, + TRUE /* record_file_info */, + scratch_pool, scratch_pool)); + work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool); + + /* Queue removal of temporary content copy. */ + SVN_ERR(svn_wc__wq_build_file_remove(&work_item, b->db, + b->wcroot->abspath, src_abspath, + scratch_pool, scratch_pool)); + + work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool); + } + + SVN_ERR(update_move_list_add(b->wcroot, dst_relpath, b->db, + (old_kind == svn_node_none) + ? svn_wc_notify_update_add + : svn_wc_notify_update_replace, + svn_node_file, + svn_wc_notify_state_inapplicable, + svn_wc_notify_state_inapplicable, + conflict, work_items, scratch_pool)); + return SVN_NO_ERROR; +} + /* All the info we need about one version of a working node. */ typedef struct working_node_version_t { @@ -860,6 +1101,11 @@ create_conflict_markers(svn_skel_t **work_items, part = svn_relpath_skip_ancestor(original_version->path_in_repos, repos_relpath); + if (part == NULL) + part = svn_relpath_skip_ancestor(conflicted_version->path_in_repos, + repos_relpath); + SVN_ERR_ASSERT(part != NULL); + conflicted_version->path_in_repos = svn_relpath_join(conflicted_version->path_in_repos, part, scratch_pool); original_version->path_in_repos = repos_relpath; @@ -873,6 +1119,13 @@ create_conflict_markers(svn_skel_t **work_items, conflicted_version, scratch_pool, scratch_pool)); } + else if (operation == svn_wc_operation_merge) + { + SVN_ERR(svn_wc__conflict_skel_set_op_merge( + conflict_skel, original_version, + conflicted_version, + scratch_pool, scratch_pool)); + } else { SVN_ERR(svn_wc__conflict_skel_set_op_switch( @@ -1196,6 +1449,217 @@ tc_editor_alter_file(node_move_baton_t *nmb, return SVN_NO_ERROR; } +static svn_error_t * +tc_editor_update_incoming_moved_file(node_move_baton_t *nmb, + const char *dst_relpath, + const char *src_relpath, + const svn_checksum_t *src_checksum, + const svn_checksum_t *dst_checksum, + apr_hash_t *dst_props, + apr_hash_t *src_props, + svn_boolean_t do_text_merge, + apr_pool_t *scratch_pool) +{ + update_move_baton_t *b = nmb->umb; + working_node_version_t old_version, new_version; + const char *dst_abspath = svn_dirent_join(b->wcroot->abspath, + dst_relpath, + scratch_pool); + svn_skel_t *conflict_skel = NULL; + enum svn_wc_merge_outcome_t merge_outcome; + svn_wc_notify_state_t prop_state = svn_wc_notify_state_unchanged; + svn_wc_notify_state_t content_state = svn_wc_notify_state_unchanged; + svn_skel_t *work_item, *work_items = NULL; + svn_node_kind_t dst_kind_on_disk; + const char *dst_repos_relpath; + svn_boolean_t tree_conflict = FALSE; + svn_node_kind_t dst_db_kind; + svn_error_t *err; + + SVN_ERR(mark_node_edited(nmb, scratch_pool)); + if (nmb->skip) + return SVN_NO_ERROR; + + err = svn_wc__db_base_get_info_internal(NULL, &dst_db_kind, NULL, + &dst_repos_relpath, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + b->wcroot, dst_relpath, + scratch_pool, scratch_pool); + if (err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND) + { + const char *dst_parent_relpath; + const char *dst_parent_repos_relpath; + const char *src_abspath; + + /* If the file cannot be found, it was either deleted at the + * move destination, or it was moved after its parent was moved. + * We cannot deal with this problem right now. Instead, we will + * raise a new tree conflict at the location where this file should + * have been, and let another run of the resolver deal with the + * new conflict later on. */ + + svn_error_clear(err); + + /* Create a WORKING node for this file at the move destination. */ + SVN_ERR(copy_working_node(src_relpath, dst_relpath, b->wcroot, + scratch_pool)); + + /* Raise a tree conflict at the new WORKING node. */ + dst_db_kind = svn_node_none; + SVN_ERR(create_node_tree_conflict(&conflict_skel, nmb, dst_relpath, + svn_node_file, dst_db_kind, + svn_wc_conflict_reason_edited, + svn_wc_conflict_action_delete, + NULL, scratch_pool, scratch_pool)); + dst_parent_relpath = svn_relpath_dirname(dst_relpath, scratch_pool); + SVN_ERR(svn_wc__db_base_get_info_internal(NULL, NULL, NULL, + &dst_parent_repos_relpath, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, b->wcroot, + dst_parent_relpath, + scratch_pool, scratch_pool)); + dst_repos_relpath = svn_relpath_join(dst_parent_repos_relpath, + svn_relpath_basename(dst_relpath, + scratch_pool), + scratch_pool); + tree_conflict = TRUE; + + /* Schedule a copy of the victim's file content to the new node's path. */ + src_abspath = svn_dirent_join(b->wcroot->abspath, src_relpath, + scratch_pool); + SVN_ERR(svn_wc__wq_build_file_install(&work_item, b->db, + dst_abspath, + src_abspath, + FALSE /*FIXME: use_commit_times?*/, + TRUE /* record_file_info */, + scratch_pool, scratch_pool)); + work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool); + } + else + SVN_ERR(err); + + if ((dst_db_kind == svn_node_none || dst_db_kind != svn_node_file) && + conflict_skel == NULL) + { + SVN_ERR(create_node_tree_conflict(&conflict_skel, nmb, dst_relpath, + svn_node_file, dst_db_kind, + dst_db_kind == svn_node_none + ? svn_wc_conflict_reason_missing + : svn_wc_conflict_reason_obstructed, + svn_wc_conflict_action_edit, + NULL, + scratch_pool, scratch_pool)); + tree_conflict = TRUE; + } + + SVN_ERR(svn_io_check_path(dst_abspath, &dst_kind_on_disk, scratch_pool)); + if ((dst_kind_on_disk == svn_node_none || dst_kind_on_disk != svn_node_file) + && conflict_skel == NULL) + { + SVN_ERR(create_node_tree_conflict(&conflict_skel, nmb, dst_relpath, + svn_node_file, dst_kind_on_disk, + dst_kind_on_disk == svn_node_none + ? svn_wc_conflict_reason_missing + : svn_wc_conflict_reason_obstructed, + svn_wc_conflict_action_edit, + NULL, + scratch_pool, scratch_pool)); + tree_conflict = TRUE; + } + + old_version.location_and_kind = b->old_version; + new_version.location_and_kind = b->new_version; + + old_version.checksum = src_checksum; + old_version.props = src_props; + new_version.checksum = dst_checksum; + new_version.props = dst_props; + + /* Merge properties and text content if there is no tree conflict. */ + if (conflict_skel == NULL) + { + apr_hash_t *actual_props; + apr_array_header_t *propchanges; + + SVN_ERR(update_working_props(&prop_state, &conflict_skel, &propchanges, + &actual_props, b, dst_relpath, + &old_version, &new_version, + scratch_pool, scratch_pool)); + if (do_text_merge) + { + const char *old_pristine_abspath; + const char *src_abspath; + const char *label_left; + const char *label_target; + + /* + * Run a 3-way merge to update the file at its post-move location, + * using the pre-move file's pristine text as the merge base, the + * post-move content as the merge-right version, and the current + * content of the working file at the pre-move location as the + * merge-left version. + */ + SVN_ERR(svn_wc__db_pristine_get_path(&old_pristine_abspath, + b->db, b->wcroot->abspath, + src_checksum, + scratch_pool, scratch_pool)); + src_abspath = svn_dirent_join(b->wcroot->abspath, src_relpath, + scratch_pool); + label_left = apr_psprintf(scratch_pool, ".r%ld", + b->old_version->peg_rev); + label_target = apr_psprintf(scratch_pool, ".r%ld", + b->new_version->peg_rev); + SVN_ERR(svn_wc__internal_merge(&work_item, &conflict_skel, + &merge_outcome, b->db, + old_pristine_abspath, + src_abspath, + dst_abspath, + dst_abspath, + label_left, + _(".working"), + label_target, + actual_props, + FALSE, /* dry-run */ + NULL, /* diff3-cmd */ + NULL, /* merge options */ + propchanges, + b->cancel_func, b->cancel_baton, + scratch_pool, scratch_pool)); + + work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool); + + if (merge_outcome == svn_wc_merge_conflict) + content_state = svn_wc_notify_state_conflicted; + else + content_state = svn_wc_notify_state_merged; + } + } + + /* If there are any conflicts to be stored, convert them into work items + * too. */ + if (conflict_skel) + { + SVN_ERR(create_conflict_markers(&work_item, dst_abspath, b->db, + dst_repos_relpath, conflict_skel, + b->operation, &old_version, &new_version, + svn_node_file, !tree_conflict, + scratch_pool, scratch_pool)); + + work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool); + } + + SVN_ERR(update_move_list_add(b->wcroot, dst_relpath, b->db, + svn_wc_notify_update_update, + svn_node_file, + content_state, + prop_state, + conflict_skel, work_items, scratch_pool)); + + return SVN_NO_ERROR; +} + static svn_error_t * tc_editor_delete(node_move_baton_t *nmb, const char *relpath, @@ -1327,6 +1791,93 @@ tc_editor_delete(node_move_baton_t *nmb, return SVN_NO_ERROR; } +/* Handle node deletion for an incoming move. */ +static svn_error_t * +tc_incoming_editor_delete(node_move_baton_t *nmb, + const char *relpath, + svn_node_kind_t old_kind, + svn_node_kind_t new_kind, + apr_pool_t *scratch_pool) +{ + update_move_baton_t *b = nmb->umb; + svn_sqlite__stmt_t *stmt; + const char *local_abspath; + svn_boolean_t is_modified, is_all_deletes; + svn_skel_t *work_items = NULL; + svn_skel_t *conflict = NULL; + + SVN_ERR(mark_parent_edited(nmb, scratch_pool)); + if (nmb->skip) + return SVN_NO_ERROR; + + /* Check before retracting delete to catch delete-delete + conflicts. This catches conflicts on the node itself; deleted + children are caught as local modifications below.*/ + if (nmb->shadowed) + { + SVN_ERR(mark_tc_on_op_root(nmb, + old_kind, new_kind, + svn_wc_conflict_action_delete, + scratch_pool)); + return SVN_NO_ERROR; + } + + local_abspath = svn_dirent_join(b->wcroot->abspath, relpath, scratch_pool); + SVN_ERR(svn_wc__node_has_local_mods(&is_modified, &is_all_deletes, + nmb->umb->db, local_abspath, FALSE, + NULL, NULL, scratch_pool)); + if (is_modified) + { + svn_wc_conflict_reason_t reason; + + /* No conflict means no NODES rows at the relpath op-depth + so it's easy to convert the modified tree into a copy. + + Note the following assumptions for relpath: + * it is not shadowed + * it is not the/an op-root. (or we can't make us a copy) + */ + + SVN_ERR(svn_wc__db_op_make_copy_internal(b->wcroot, relpath, FALSE, + NULL, NULL, scratch_pool)); + + reason = svn_wc_conflict_reason_edited; + + SVN_ERR(create_node_tree_conflict(&conflict, nmb, relpath, + old_kind, new_kind, reason, + (new_kind == svn_node_none) + ? svn_wc_conflict_action_delete + : svn_wc_conflict_action_replace, + NULL, + scratch_pool, scratch_pool)); + nmb->skip = TRUE; + } + else + { + /* Delete the WORKING node at DST_RELPATH. */ + SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb, + STMT_INSERT_DELETE_FROM_NODE_RECURSIVE)); + SVN_ERR(svn_sqlite__bindf(stmt, "isdd", + b->wcroot->wc_id, relpath, + 0, relpath_depth(relpath))); + SVN_ERR(svn_sqlite__step_done(stmt)); + } + + /* Only notify if add_file/add_dir is not going to notify */ + if (conflict || (new_kind == svn_node_none)) + SVN_ERR(update_move_list_add(b->wcroot, relpath, b->db, + svn_wc_notify_update_delete, + new_kind, + svn_wc_notify_state_inapplicable, + svn_wc_notify_state_inapplicable, + conflict, work_items, scratch_pool)); + else if (work_items) + SVN_ERR(svn_wc__db_wq_add_internal(b->wcroot, work_items, + scratch_pool)); + + return SVN_NO_ERROR; +} + /* * Driver code. * @@ -1618,28 +2169,30 @@ suitable_for_move(svn_wc__db_wcroot_t *wcroot, while (have_row) { svn_revnum_t node_revision = svn_sqlite__column_revnum(stmt, 2); - const char *relpath = svn_sqlite__column_text(stmt, 0, NULL); + const char *child_relpath = svn_sqlite__column_text(stmt, 0, NULL); + const char *relpath; svn_pool_clear(iterpool); - relpath = svn_relpath_skip_ancestor(local_relpath, relpath); + relpath = svn_relpath_skip_ancestor(local_relpath, child_relpath); relpath = svn_relpath_join(repos_relpath, relpath, iterpool); - if (revision != node_revision) - return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, - svn_sqlite__reset(stmt), - _("Cannot apply update because move source " - "%s' is a mixed-revision working copy"), - path_for_error_message(wcroot, local_relpath, - scratch_pool)); - if (strcmp(relpath, svn_sqlite__column_text(stmt, 1, NULL))) return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, svn_sqlite__reset(stmt), - _("Cannot apply update because move source " - "'%s' is a switched subtree"), - path_for_error_message(wcroot, - local_relpath, + _("Cannot apply update because '%s' is a " + "switched path (please switch it back to " + "its original URL and try again)"), + path_for_error_message(wcroot, child_relpath, + scratch_pool)); + + if (revision != node_revision) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, + svn_sqlite__reset(stmt), + _("Cannot apply update because '%s' is a " + "mixed-revision working copy (please " + "update and try again)"), + path_for_error_message(wcroot, local_relpath, scratch_pool)); SVN_ERR(svn_sqlite__step(&have_row, stmt)); @@ -1827,6 +2380,1236 @@ svn_wc__db_update_moved_away_conflict_victim(svn_wc__db_t *db, return SVN_NO_ERROR; } +static svn_error_t * +get_working_info(apr_hash_t **props, + const svn_checksum_t **checksum, + apr_array_header_t **children, + svn_node_kind_t *kind, + const char *local_relpath, + svn_wc__db_wcroot_t *wcroot, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_wc__db_status_t status; + const char *repos_relpath; + svn_node_kind_t db_kind; + svn_error_t *err; + + err = svn_wc__db_read_info_internal(&status, &db_kind, NULL, &repos_relpath, + NULL, NULL, NULL, NULL, NULL, + checksum, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + wcroot, local_relpath, + result_pool, scratch_pool); + + /* If there is no node, or only a node that describes a delete + of a lower layer we report this node as not existing. */ + if ((err && err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND) + || (!err && status != svn_wc__db_status_added + && status != svn_wc__db_status_normal)) + { + svn_error_clear(err); + + if (kind) + *kind = svn_node_none; + if (checksum) + *checksum = NULL; + if (props) + *props = NULL; + if (children) + *children = apr_array_make(result_pool, 0, sizeof(const char *)); + + return SVN_NO_ERROR; + } + else + SVN_ERR(err); + + SVN_ERR(svn_wc__db_read_props_internal(props, wcroot, local_relpath, + result_pool, scratch_pool)); + + if (kind) + *kind = db_kind; + + if (children && db_kind == svn_node_dir) + { + svn_sqlite__stmt_t *stmt; + svn_boolean_t have_row; + + *children = apr_array_make(result_pool, 16, sizeof(const char *)); + SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, + STMT_SELECT_WORKING_CHILDREN)); + SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath)); + SVN_ERR(svn_sqlite__step(&have_row, stmt)); + while (have_row) + { + const char *child_relpath = svn_sqlite__column_text(stmt, 0, NULL); + + APR_ARRAY_PUSH(*children, const char *) + = svn_relpath_basename(child_relpath, result_pool); + + SVN_ERR(svn_sqlite__step(&have_row, stmt)); + } + SVN_ERR(svn_sqlite__reset(stmt)); + } + else if (children) + *children = apr_array_make(result_pool, 0, sizeof(const char *)); + + return SVN_NO_ERROR; +} + +/* Apply changes found in the victim node at SRC_RELPATH to the incoming + * move at DST_RELPATH. */ +static svn_error_t * +update_incoming_moved_node(node_move_baton_t *nmb, + svn_wc__db_wcroot_t *wcroot, + const char *src_relpath, + const char *dst_relpath, + apr_pool_t *scratch_pool) +{ + update_move_baton_t *b = nmb->umb; + svn_node_kind_t orig_kind, working_kind; + const char *victim_relpath = src_relpath; + const svn_checksum_t *orig_checksum, *working_checksum; + apr_hash_t *orig_props, *working_props; + apr_array_header_t *orig_children, *working_children; + + if (b->cancel_func) + SVN_ERR(b->cancel_func(b->cancel_baton)); + + /* Compare the tree conflict victim's copied layer (the "original") with + * the working layer, i.e. look for changes layered on top of the copy. */ + SVN_ERR(get_info(&orig_props, &orig_checksum, &orig_children, &orig_kind, + victim_relpath, b->src_op_depth, wcroot, scratch_pool, + scratch_pool)); + SVN_ERR(get_working_info(&working_props, &working_checksum, + &working_children, &working_kind, victim_relpath, + wcroot, scratch_pool, scratch_pool)); + + if (working_kind == svn_node_none + || (orig_kind != svn_node_none && orig_kind != working_kind)) + { + SVN_ERR(tc_incoming_editor_delete(nmb, dst_relpath, orig_kind, + working_kind, scratch_pool)); + } + + if (nmb->skip) + return SVN_NO_ERROR; + + if (working_kind != svn_node_none && orig_kind != working_kind) + { + if (working_kind == svn_node_file || working_kind == svn_node_symlink) + { + const char *victim_abspath; + const char *wctemp_abspath; + svn_stream_t *working_stream; + svn_stream_t *temp_stream; + const char *temp_abspath; + svn_error_t *err; + + /* Copy the victim's content to a safe place and add it from there. */ + SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&wctemp_abspath, b->db, + b->wcroot->abspath, + scratch_pool, + scratch_pool)); + victim_abspath = svn_dirent_join(b->wcroot->abspath, + victim_relpath, scratch_pool); + SVN_ERR(svn_stream_open_readonly(&working_stream, victim_abspath, + scratch_pool, scratch_pool)); + SVN_ERR(svn_stream_open_unique(&temp_stream, &temp_abspath, + wctemp_abspath, svn_io_file_del_none, + scratch_pool, scratch_pool)); + err = svn_stream_copy3(working_stream, temp_stream, + b->cancel_func, b->cancel_baton, + scratch_pool); + if (err && err->apr_err == SVN_ERR_CANCELLED) + { + svn_error_t *err2; + + err2 = svn_io_remove_file2(temp_abspath, TRUE, scratch_pool); + return svn_error_compose_create(err, err2); + } + else + SVN_ERR(err); + + SVN_ERR(tc_editor_incoming_add_file(nmb, dst_relpath, orig_kind, + working_checksum, working_props, + victim_relpath, temp_abspath, + scratch_pool)); + } + else if (working_kind == svn_node_dir) + { + SVN_ERR(tc_editor_incoming_add_directory(nmb, dst_relpath, + orig_kind, working_props, + victim_relpath, + scratch_pool)); + } + } + else if (working_kind != svn_node_none) + { + svn_boolean_t props_equal; + + SVN_ERR(props_match(&props_equal, orig_props, working_props, + scratch_pool)); + + if (working_kind == svn_node_file || working_kind == svn_node_symlink) + { + svn_boolean_t is_modified; + + SVN_ERR(svn_wc__internal_file_modified_p(&is_modified, b->db, + svn_dirent_join( + b->wcroot->abspath, + victim_relpath, + scratch_pool), + FALSE /* exact_comparison */, + scratch_pool)); + if (!props_equal || is_modified) + SVN_ERR(tc_editor_update_incoming_moved_file(nmb, dst_relpath, + victim_relpath, + working_checksum, + orig_checksum, + orig_props, + working_props, + is_modified, + scratch_pool)); + } + else if (working_kind == svn_node_dir) + { + if (!props_equal) + SVN_ERR(tc_editor_alter_directory(nmb, dst_relpath, + orig_props, working_props, + scratch_pool)); + } + } + + if (nmb->skip) + return SVN_NO_ERROR; + + if (working_kind == svn_node_dir) + { + apr_pool_t *iterpool = svn_pool_create(scratch_pool); + int i = 0, j = 0; + + while (i < orig_children->nelts || j < working_children->nelts) + { + const char *child_name; + svn_boolean_t orig_only = FALSE, working_only = FALSE; + node_move_baton_t cnmb = { 0 }; + + cnmb.pb = nmb; + cnmb.umb = nmb->umb; + cnmb.shadowed = nmb->shadowed; + + svn_pool_clear(iterpool); + if (i >= orig_children->nelts) + { + working_only = TRUE; + child_name = APR_ARRAY_IDX(working_children, j, const char *); + } + else if (j >= working_children->nelts) + { + orig_only = TRUE; + child_name = APR_ARRAY_IDX(orig_children, i, const char *); + } + else + { + const char *orig_name = APR_ARRAY_IDX(orig_children, i, + const char *); + const char *working_name = APR_ARRAY_IDX(working_children, j, + const char *); + int cmp = strcmp(orig_name, working_name); + + if (cmp > 0) + working_only = TRUE; + else if (cmp < 0) + orig_only = TRUE; + + child_name = working_only ? working_name : orig_name; + } + + cnmb.src_relpath = svn_relpath_join(src_relpath, child_name, + iterpool); + cnmb.dst_relpath = svn_relpath_join(dst_relpath, child_name, + iterpool); + + SVN_ERR(update_incoming_moved_node(&cnmb, wcroot, cnmb.src_relpath, + cnmb.dst_relpath, iterpool)); + + if (!working_only) + ++i; + if (!orig_only) + ++j; + + if (nmb->skip) /* Does parent now want a skip? */ + break; + } + } + + return SVN_NO_ERROR; +} + +/* The body of svn_wc__db_update_incoming_move(). */ +static svn_error_t * +update_incoming_move(svn_revnum_t *old_rev, + svn_revnum_t *new_rev, + svn_wc__db_t *db, + svn_wc__db_wcroot_t *wcroot, + const char *local_relpath, + const char *dst_relpath, + svn_wc_operation_t operation, + svn_wc_conflict_action_t action, + svn_wc_conflict_reason_t reason, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *scratch_pool) +{ + update_move_baton_t umb = { NULL }; + svn_wc_conflict_version_t old_version; + svn_wc_conflict_version_t new_version; + apr_int64_t repos_id; + node_move_baton_t nmb = { 0 }; + svn_boolean_t is_modified; + + SVN_ERR_ASSERT(svn_relpath_skip_ancestor(dst_relpath, local_relpath) == NULL); + + /* For incoming moves during update/switch, the move source is a copied + * tree which was copied from the pre-update BASE revision while raising + * the tree conflict, when the update attempted to delete the move source. + * This copy is our "original" state (SRC of the diff) and the local changes + * on top of this copy at the top-most WORKING layer are used to drive the + * editor (DST of the diff). + * + * The move destination, where changes are applied to, is now in the BASE + * tree at DST_RELPATH. This repository-side move is the "incoming change" + * recorded for any tree conflicts created during the editor drive. + * We assume this path contains no local changes, and create local changes + * in DST_RELPATH corresponding to changes contained in the conflict victim. + * + * DST_OP_DEPTH is used to infer the "op-root" of the incoming move. This + * "op-root" is virtual because all nodes belonging to the incoming move + * live in the BASE tree. It is used for constructing repository paths + * when new tree conflicts need to be raised. + */ + umb.src_op_depth = relpath_depth(local_relpath); /* SRC of diff */ + umb.dst_op_depth = relpath_depth(dst_relpath); /* virtual DST op-root */ + + SVN_ERR(verify_write_lock(wcroot, local_relpath, scratch_pool)); + SVN_ERR(verify_write_lock(wcroot, dst_relpath, scratch_pool)); + + /* Make sure there are no local modifications in the move destination. */ + SVN_ERR(svn_wc__node_has_local_mods(&is_modified, NULL, db, + svn_dirent_join(wcroot->abspath, + dst_relpath, + scratch_pool), + TRUE, cancel_func, cancel_baton, + scratch_pool)); + if (is_modified) + return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Cannot merge local changes from '%s' because " + "'%s' already contains other local changes " + "(please commit or revert these other changes " + "and try again)"), + svn_dirent_local_style( + svn_dirent_join(wcroot->abspath, local_relpath, + scratch_pool), + scratch_pool), + svn_dirent_local_style( + svn_dirent_join(wcroot->abspath, dst_relpath, + scratch_pool), + scratch_pool)); + + /* Check for switched subtrees and mixed-revision working copy. */ + SVN_ERR(suitable_for_move(wcroot, dst_relpath, scratch_pool)); + + /* Read version info from the updated incoming post-move location. */ + SVN_ERR(svn_wc__db_base_get_info_internal(NULL, &new_version.node_kind, + &new_version.peg_rev, + &new_version.path_in_repos, + &repos_id, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + wcroot, dst_relpath, + scratch_pool, scratch_pool)); + + SVN_ERR(svn_wc__db_fetch_repos_info(&new_version.repos_url, + &new_version.repos_uuid, + wcroot, repos_id, + scratch_pool)); + + /* Read version info from the victim's location. */ + SVN_ERR(svn_wc__db_depth_get_info(NULL, &old_version.node_kind, + &old_version.peg_rev, + &old_version.path_in_repos, &repos_id, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, wcroot, + local_relpath, umb.src_op_depth, + scratch_pool, scratch_pool)); + + SVN_ERR(svn_wc__db_fetch_repos_info(&old_version.repos_url, + &old_version.repos_uuid, + wcroot, repos_id, + scratch_pool)); + *old_rev = old_version.peg_rev; + *new_rev = new_version.peg_rev; + + umb.operation = operation; + umb.old_version= &old_version; + umb.new_version= &new_version; + umb.db = db; + umb.wcroot = wcroot; + umb.cancel_func = cancel_func; + umb.cancel_baton = cancel_baton; + + /* Create a new, and empty, list for notification information. */ + SVN_ERR(svn_sqlite__exec_statements(wcroot->sdb, + STMT_CREATE_UPDATE_MOVE_LIST)); + + /* Drive the editor... */ + + nmb.umb = &umb; + nmb.src_relpath = local_relpath; + nmb.dst_relpath = dst_relpath; + /* nmb.shadowed = FALSE; */ + /* nmb.edited = FALSE; */ + /* nmb.skip_children = FALSE; */ + + /* We walk the conflict victim, comparing each node with the equivalent node + * at the WORKING layer, applying any local changes to nodes at the move + * destination. */ + SVN_ERR(update_incoming_moved_node(&nmb, wcroot, local_relpath, dst_relpath, + scratch_pool)); + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_wc__db_update_incoming_move(svn_wc__db_t *db, + const char *local_abspath, + const char *dest_abspath, + svn_wc_operation_t operation, + svn_wc_conflict_action_t action, + svn_wc_conflict_reason_t reason, + svn_cancel_func_t cancel_func, + void *cancel_baton, + svn_wc_notify_func2_t notify_func, + void *notify_baton, + apr_pool_t *scratch_pool) +{ + svn_wc__db_wcroot_t *wcroot; + svn_revnum_t old_rev, new_rev; + const char *local_relpath; + const char *dest_relpath; + + /* ### Check for mixed-rev src or dst? */ + + SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, + db, local_abspath, + scratch_pool, scratch_pool)); + VERIFY_USABLE_WCROOT(wcroot); + + dest_relpath + = svn_dirent_skip_ancestor(wcroot->abspath, dest_abspath); + + SVN_WC__DB_WITH_TXN(update_incoming_move(&old_rev, &new_rev, db, wcroot, + local_relpath, dest_relpath, + operation, action, reason, + cancel_func, cancel_baton, + scratch_pool), + wcroot); + + /* Send all queued up notifications. */ + SVN_ERR(svn_wc__db_update_move_list_notify(wcroot, old_rev, new_rev, + notify_func, notify_baton, + scratch_pool)); + if (notify_func) + { + svn_wc_notify_t *notify; + + notify = svn_wc_create_notify(svn_dirent_join(wcroot->abspath, + local_relpath, + scratch_pool), + svn_wc_notify_update_completed, + scratch_pool); + notify->kind = svn_node_none; + notify->content_state = svn_wc_notify_state_inapplicable; + notify->prop_state = svn_wc_notify_state_inapplicable; + notify->revision = new_rev; + notify_func(notify_baton, notify, scratch_pool); + } + + + return SVN_NO_ERROR; +} + +typedef struct update_local_add_baton_t { + int add_op_depth; + svn_wc__db_t *db; + svn_wc__db_wcroot_t *wcroot; + svn_cancel_func_t cancel_func; + void *cancel_baton; + + /* We refer to these if raising new tree conflicts. */ + const svn_wc_conflict_version_t *new_version; +} update_local_add_baton_t; + +typedef struct added_node_baton_t { + struct update_local_add_baton_t *b; + struct added_node_baton_t *pb; + const char *local_relpath; + svn_boolean_t skip; + svn_boolean_t edited; +} added_node_baton_t; + + +static svn_error_t * +update_local_add_mark_node_edited(added_node_baton_t *nb, + apr_pool_t *scratch_pool) +{ + if (nb->edited) + return SVN_NO_ERROR; + + if (nb->pb) + { + SVN_ERR(update_local_add_mark_node_edited(nb->pb, scratch_pool)); + + if (nb->pb->skip) + nb->skip = TRUE; + } + + nb->edited = TRUE; + + return SVN_NO_ERROR; +} + +static svn_error_t * +update_local_add_mark_parent_edited(added_node_baton_t *nb, + apr_pool_t *scratch_pool) +{ + SVN_ERR_ASSERT(nb && nb->pb); + + SVN_ERR(update_local_add_mark_node_edited(nb->pb, scratch_pool)); + + if (nb->pb->skip) + nb->skip = TRUE; + + return SVN_NO_ERROR; +} + +static svn_error_t * +mark_update_add_add_tree_conflict(added_node_baton_t *nb, + svn_node_kind_t base_kind, + svn_node_kind_t working_kind, + svn_wc_conflict_reason_t local_change, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) + +{ + svn_wc__db_t *db = nb->b->db; + svn_wc__db_wcroot_t *wcroot = nb->b->wcroot; + svn_wc_conflict_version_t *new_version; + svn_skel_t *conflict; + + new_version = svn_wc_conflict_version_dup(nb->b->new_version, result_pool); + + /* Fill in conflict info templates with info for this node. */ + SVN_ERR(svn_wc__db_base_get_info_internal(NULL, NULL, &new_version->peg_rev, + &new_version->path_in_repos, + NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + wcroot, nb->local_relpath, + scratch_pool, scratch_pool)); + new_version->node_kind = base_kind; + + SVN_ERR(create_tree_conflict(&conflict, wcroot, nb->local_relpath, + nb->local_relpath, db, NULL, new_version, + svn_wc_operation_update, + svn_node_none, base_kind, NULL, + local_change, svn_wc_conflict_action_add, + NULL, scratch_pool, scratch_pool)); + + SVN_ERR(update_move_list_add(wcroot, nb->local_relpath, db, + svn_wc_notify_tree_conflict, working_kind, + svn_wc_notify_state_inapplicable, + svn_wc_notify_state_inapplicable, + conflict, NULL, scratch_pool)); + return SVN_NO_ERROR; +} + +static svn_error_t * +update_local_add_notify_obstructed_or_missing(added_node_baton_t *nb, + svn_node_kind_t working_kind, + svn_node_kind_t kind_on_disk, + apr_pool_t *scratch_pool) +{ + svn_wc_notify_state_t content_state; + + if (kind_on_disk == svn_node_none) + content_state = svn_wc_notify_state_missing; + else + content_state = svn_wc_notify_state_obstructed; + + SVN_ERR(update_move_list_add(nb->b->wcroot, nb->local_relpath, nb->b->db, + svn_wc_notify_skip, working_kind, + content_state, svn_wc_notify_state_inapplicable, + NULL, NULL, scratch_pool)); + return SVN_NO_ERROR; +} + +static svn_error_t * +tc_editor_update_add_new_file(added_node_baton_t *nb, + svn_node_kind_t base_kind, + const svn_checksum_t *base_checksum, + apr_hash_t *base_props, + svn_node_kind_t working_kind, + const svn_checksum_t *working_checksum, + apr_hash_t *working_props, + apr_pool_t *scratch_pool) +{ + const char *local_abspath; + svn_node_kind_t kind_on_disk; + + SVN_ERR(update_local_add_mark_parent_edited(nb, scratch_pool)); + if (nb->skip) + return SVN_NO_ERROR; + + if (base_kind != svn_node_none) + { + SVN_ERR(mark_update_add_add_tree_conflict(nb, base_kind, svn_node_file, + svn_wc_conflict_reason_added, + scratch_pool, scratch_pool)); + nb->skip = TRUE; + return SVN_NO_ERROR; + } + + /* Check for obstructions. */ + local_abspath = svn_dirent_join(nb->b->wcroot->abspath, nb->local_relpath, + scratch_pool); + SVN_ERR(svn_io_check_path(local_abspath, &kind_on_disk, scratch_pool)); + if (kind_on_disk != svn_node_file) + { + SVN_ERR(update_local_add_notify_obstructed_or_missing(nb, working_kind, + kind_on_disk, + scratch_pool)); + nb->skip = TRUE; + return SVN_NO_ERROR; + } + + /* Nothing else to do. Locally added files are an op-root in NODES. */ + + SVN_ERR(update_move_list_add(nb->b->wcroot, nb->local_relpath, nb->b->db, + svn_wc_notify_update_add, svn_node_file, + svn_wc_notify_state_inapplicable, + svn_wc_notify_state_inapplicable, + NULL, NULL, scratch_pool)); + return SVN_NO_ERROR; +} + +static svn_error_t * +tc_editor_update_add_new_directory(added_node_baton_t *nb, + svn_node_kind_t base_kind, + apr_hash_t *base_props, + apr_hash_t *working_props, + apr_pool_t *scratch_pool) +{ + const char *local_abspath; + svn_node_kind_t kind_on_disk; + + SVN_ERR(update_local_add_mark_parent_edited(nb, scratch_pool)); + if (nb->skip) + return SVN_NO_ERROR; + + if (base_kind != svn_node_none) + { + SVN_ERR(mark_update_add_add_tree_conflict(nb, base_kind, svn_node_dir, + svn_wc_conflict_reason_added, + scratch_pool, scratch_pool)); + nb->skip = TRUE; + return SVN_NO_ERROR; + } + + /* Check for obstructions. */ + local_abspath = svn_dirent_join(nb->b->wcroot->abspath, nb->local_relpath, + scratch_pool); + SVN_ERR(svn_io_check_path(local_abspath, &kind_on_disk, scratch_pool)); + if (kind_on_disk != svn_node_dir) + { + SVN_ERR(update_local_add_notify_obstructed_or_missing(nb, svn_node_dir, + kind_on_disk, + scratch_pool)); + nb->skip = TRUE; + return SVN_NO_ERROR; + } + + /* Nothing else to do. Locally added directories are an op-root in NODES. */ + + SVN_ERR(update_move_list_add(nb->b->wcroot, nb->local_relpath, nb->b->db, + svn_wc_notify_update_add, svn_node_dir, + svn_wc_notify_state_inapplicable, + svn_wc_notify_state_inapplicable, + NULL, NULL, scratch_pool)); + return SVN_NO_ERROR; +} + +static svn_error_t * +update_incoming_add_merge_props(svn_wc_notify_state_t *prop_state, + svn_skel_t **conflict_skel, + const char *local_relpath, + apr_hash_t *base_props, + apr_hash_t *working_props, + svn_wc__db_t *db, + svn_wc__db_wcroot_t *wcroot, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + apr_hash_t *new_actual_props; + apr_array_header_t *propchanges; + const char *local_abspath = svn_dirent_join(wcroot->abspath, + local_relpath, + scratch_pool); + + /* + * Run a 3-way prop merge to update the props, using the empty props + * as the merge base, the post-update props as the merge-left version, and + * the current props of the added working file as the merge-right version. + */ + SVN_ERR(svn_prop_diffs(&propchanges, working_props, + apr_hash_make(scratch_pool), scratch_pool)); + SVN_ERR(svn_wc__merge_props(conflict_skel, prop_state, &new_actual_props, + db, local_abspath, + apr_hash_make(scratch_pool), + base_props, working_props, propchanges, + result_pool, scratch_pool)); + + /* Install the new actual props. */ + if (apr_hash_count(new_actual_props) > 0) + SVN_ERR(svn_wc__db_op_set_props_internal(wcroot, local_relpath, + new_actual_props, + svn_wc__has_magic_property( + propchanges), + scratch_pool)); + + return SVN_NO_ERROR; +} + +static svn_error_t * +tc_editor_update_add_merge_files(added_node_baton_t *nb, + const svn_checksum_t *working_checksum, + const svn_checksum_t *base_checksum, + apr_hash_t *working_props, + apr_hash_t *base_props, + apr_pool_t *scratch_pool) +{ + update_local_add_baton_t *b = nb->b; + apr_array_header_t *propchanges; + svn_boolean_t is_modified; + enum svn_wc_merge_outcome_t merge_outcome; + svn_skel_t *conflict_skel = NULL; + svn_wc_notify_state_t prop_state, content_state; + svn_skel_t *work_items = NULL; + svn_node_kind_t kind_on_disk; + const char *local_abspath = svn_dirent_join(b->wcroot->abspath, + nb->local_relpath, + scratch_pool); + + SVN_ERR(update_local_add_mark_node_edited(nb, scratch_pool)); + if (nb->skip) + return SVN_NO_ERROR; + + /* Check for on-disk obstructions or missing files. */ + SVN_ERR(svn_io_check_path(local_abspath, &kind_on_disk, scratch_pool)); + if (kind_on_disk != svn_node_file) + { + SVN_ERR(update_local_add_notify_obstructed_or_missing(nb, svn_node_file, + kind_on_disk, + scratch_pool)); + nb->skip = TRUE; + return SVN_NO_ERROR; + } + + SVN_ERR(update_incoming_add_merge_props(&prop_state, &conflict_skel, + nb->local_relpath, + base_props, working_props, + b->db, b->wcroot, + scratch_pool, scratch_pool)); + + SVN_ERR(svn_wc__internal_file_modified_p(&is_modified, + b->db, local_abspath, + FALSE /* exact_comparison */, + scratch_pool)); + if (!is_modified) + { + svn_skel_t *work_item = NULL; + + SVN_ERR(svn_wc__wq_build_file_install(&work_item, b->db, + local_abspath, NULL, + /* FIXME: use_commit_times? */ + FALSE, + TRUE, /* record_file_info */ + scratch_pool, scratch_pool)); + work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool); + content_state = svn_wc_notify_state_changed; + } + else + { + const char *empty_file_abspath; + const char *pristine_abspath; + svn_skel_t *work_item = NULL; + + /* + * Run a 3-way merge to update the file, using the empty file + * merge base, the post-update pristine text as the merge-left version, + * and the locally added content of the working file as the merge-right + * version. + */ + SVN_ERR(svn_io_open_unique_file3(NULL, &empty_file_abspath, NULL, + svn_io_file_del_on_pool_cleanup, + scratch_pool, scratch_pool)); + SVN_ERR(svn_wc__db_pristine_get_path(&pristine_abspath, b->db, + b->wcroot->abspath, base_checksum, + scratch_pool, scratch_pool)); + + /* Create a property diff which shows all props as added. */ + SVN_ERR(svn_prop_diffs(&propchanges, working_props, + apr_hash_make(scratch_pool), scratch_pool)); + + SVN_ERR(svn_wc__internal_merge(&work_item, &conflict_skel, + &merge_outcome, b->db, + empty_file_abspath, + pristine_abspath, + local_abspath, + local_abspath, + NULL, NULL, NULL, /* diff labels */ + apr_hash_make(scratch_pool), + FALSE, /* dry-run */ + NULL, /* diff3-cmd */ + NULL, /* merge options */ + propchanges, + b->cancel_func, b->cancel_baton, + scratch_pool, scratch_pool)); + + work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool); + + if (merge_outcome == svn_wc_merge_conflict) + content_state = svn_wc_notify_state_conflicted; + else + content_state = svn_wc_notify_state_merged; + } + + /* If there are any conflicts to be stored, convert them into work items + * too. */ + if (conflict_skel) + { + svn_wc_conflict_version_t *new_version; + svn_node_kind_t new_kind; + svn_revnum_t new_rev; + const char *repos_relpath; + + new_version = svn_wc_conflict_version_dup(nb->b->new_version, + scratch_pool); + SVN_ERR(svn_wc__db_base_get_info_internal(NULL, &new_kind, &new_rev, + &repos_relpath, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + b->wcroot, nb->local_relpath, + scratch_pool, scratch_pool)); + /* Fill in conflict info templates with info for this node. */ + new_version->path_in_repos = repos_relpath; + new_version->node_kind = new_kind; + new_version->peg_rev = new_rev; + + /* Create conflict markers. */ + SVN_ERR(svn_wc__conflict_skel_set_op_update(conflict_skel, NULL, + new_version, scratch_pool, + scratch_pool)); + if (prop_state == svn_wc_notify_state_conflicted) + SVN_ERR(svn_wc__conflict_create_markers(&work_items, b->db, + local_abspath, + conflict_skel, + scratch_pool, + scratch_pool)); + } + + SVN_ERR(update_move_list_add(b->wcroot, nb->local_relpath, b->db, + svn_wc_notify_update_update, + svn_node_file, content_state, prop_state, + conflict_skel, work_items, scratch_pool)); + + return SVN_NO_ERROR; +} + +static svn_error_t * +tc_editor_update_add_merge_dirprops(added_node_baton_t *nb, + apr_hash_t *working_props, + apr_hash_t *base_props, + apr_pool_t *scratch_pool) +{ + update_local_add_baton_t *b = nb->b; + svn_skel_t *conflict_skel = NULL; + svn_wc_notify_state_t prop_state; + svn_skel_t *work_items = NULL; + svn_node_kind_t kind_on_disk; + const char *local_abspath = svn_dirent_join(b->wcroot->abspath, + nb->local_relpath, + scratch_pool); + + SVN_ERR(update_local_add_mark_node_edited(nb, scratch_pool)); + if (nb->skip) + return SVN_NO_ERROR; + + /* Check for on-disk obstructions or missing files. */ + SVN_ERR(svn_io_check_path(local_abspath, &kind_on_disk, scratch_pool)); + if (kind_on_disk != svn_node_dir) + { + SVN_ERR(update_local_add_notify_obstructed_or_missing(nb, svn_node_dir, + kind_on_disk, + scratch_pool)); + nb->skip = TRUE; + return SVN_NO_ERROR; + } + + SVN_ERR(update_incoming_add_merge_props(&prop_state, &conflict_skel, + nb->local_relpath, + base_props, working_props, + b->db, b->wcroot, + scratch_pool, scratch_pool)); + + /* If there are any conflicts to be stored, convert them into work items. */ + if (conflict_skel && prop_state == svn_wc_notify_state_conflicted) + { + svn_wc_conflict_version_t *new_version; + svn_node_kind_t new_kind; + svn_revnum_t new_rev; + const char *repos_relpath; + + new_version = svn_wc_conflict_version_dup(nb->b->new_version, + scratch_pool); + SVN_ERR(svn_wc__db_base_get_info_internal(NULL, &new_kind, &new_rev, + &repos_relpath, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + b->wcroot, nb->local_relpath, + scratch_pool, scratch_pool)); + /* Fill in conflict info templates with info for this node. */ + new_version->path_in_repos = repos_relpath; + new_version->node_kind = new_kind; + new_version->peg_rev = new_rev; + + /* Create conflict markers. */ + SVN_ERR(svn_wc__conflict_skel_set_op_update(conflict_skel, NULL, + new_version, scratch_pool, + scratch_pool)); + SVN_ERR(svn_wc__conflict_create_markers(&work_items, b->db, + local_abspath, + conflict_skel, + scratch_pool, + scratch_pool)); + } + + SVN_ERR(update_move_list_add(b->wcroot, nb->local_relpath, b->db, + svn_wc_notify_update_update, svn_node_dir, + svn_wc_notify_state_inapplicable, prop_state, + conflict_skel, work_items, scratch_pool)); + + return SVN_NO_ERROR; +} + +static svn_error_t * +update_locally_added_node(added_node_baton_t *nb, + apr_pool_t *scratch_pool) +{ + update_local_add_baton_t *b = nb->b; + svn_wc__db_wcroot_t *wcroot = b->wcroot; + svn_wc__db_t *db = b->db; + svn_node_kind_t base_kind, working_kind; + const svn_checksum_t *base_checksum; + apr_hash_t *base_props, *working_props; + apr_array_header_t *base_children, *working_children; + const char *local_abspath = svn_dirent_join(wcroot->abspath, + nb->local_relpath, + scratch_pool); + + if (b->cancel_func) + SVN_ERR(b->cancel_func(b->cancel_baton)); + + if (nb->skip) + return SVN_NO_ERROR; + + /* Compare the tree conflict victim's BASE layer to the working layer. */ + SVN_ERR(get_info(&base_props, &base_checksum, &base_children, &base_kind, + nb->local_relpath, 0, wcroot, scratch_pool, scratch_pool)); + SVN_ERR(get_working_info(&working_props, NULL, &working_children, + &working_kind, nb->local_relpath, wcroot, + scratch_pool, scratch_pool)); + if (working_kind == svn_node_none) + { + svn_node_kind_t kind_on_disk; + svn_skel_t *work_item = NULL; + + /* Skip obstructed nodes. */ + SVN_ERR(svn_io_check_path(local_abspath, &kind_on_disk, + scratch_pool)); + if (kind_on_disk != base_kind && kind_on_disk != svn_node_none) + { + SVN_ERR(update_move_list_add(nb->b->wcroot, nb->local_relpath, + nb->b->db, + svn_wc_notify_skip, + base_kind, + svn_wc_notify_state_obstructed, + svn_wc_notify_state_inapplicable, + NULL, NULL, scratch_pool)); + nb->skip = TRUE; + return SVN_NO_ERROR; + } + + /* The working tree has no node here. The working copy of this node + * is currently not installed because the base tree is shadowed. + * Queue an installation of this node into the working copy. */ + if (base_kind == svn_node_file || base_kind == svn_node_symlink) + SVN_ERR(svn_wc__wq_build_file_install(&work_item, db, local_abspath, + NULL, + /* FIXME: use_commit_times? */ + FALSE, + TRUE, /* record_file_info */ + scratch_pool, scratch_pool)); + else if (base_kind == svn_node_dir) + SVN_ERR(svn_wc__wq_build_dir_install(&work_item, db, local_abspath, + scratch_pool, scratch_pool)); + + if (work_item) + SVN_ERR(update_move_list_add(wcroot, nb->local_relpath, db, + svn_wc_notify_update_add, + base_kind, + svn_wc_notify_state_inapplicable, + svn_wc_notify_state_inapplicable, + NULL, work_item, scratch_pool)); + return SVN_NO_ERROR; + } + + if (base_kind != working_kind) + { + if (working_kind == svn_node_file || working_kind == svn_node_symlink) + { + svn_checksum_t *working_checksum = NULL; + + if (base_checksum) + SVN_ERR(svn_io_file_checksum2(&working_checksum, local_abspath, + base_checksum->kind, scratch_pool)); + SVN_ERR(tc_editor_update_add_new_file(nb, base_kind, base_checksum, + base_props, working_kind, + working_checksum, working_props, + scratch_pool)); + } + else if (working_kind == svn_node_dir) + SVN_ERR(tc_editor_update_add_new_directory(nb, base_kind, base_props, + working_props, + scratch_pool)); + } + else + { + svn_boolean_t props_equal; + + SVN_ERR(props_match(&props_equal, base_props, working_props, + scratch_pool)); + + if (working_kind == svn_node_file || working_kind == svn_node_symlink) + { + svn_checksum_t *working_checksum; + + SVN_ERR_ASSERT(base_checksum); + SVN_ERR(svn_io_file_checksum2(&working_checksum, local_abspath, + base_checksum->kind, scratch_pool)); + if (!props_equal || !svn_checksum_match(base_checksum, + working_checksum)) + SVN_ERR(tc_editor_update_add_merge_files(nb, working_checksum, + base_checksum, + working_props, base_props, + scratch_pool)); + } + else if (working_kind == svn_node_dir && !props_equal) + SVN_ERR(tc_editor_update_add_merge_dirprops(nb, working_props, + base_props, + scratch_pool)); + } + + if (nb->skip) + return SVN_NO_ERROR; + + if (working_kind == svn_node_dir) + { + apr_pool_t *iterpool = svn_pool_create(scratch_pool); + int i = 0, j = 0; + + while (i < base_children->nelts || j < working_children->nelts) + { + const char *child_name; + svn_boolean_t base_only = FALSE, working_only = FALSE; + added_node_baton_t cnb = { 0 }; + + cnb.pb = nb; + cnb.b = nb->b; + cnb.skip = FALSE; + + svn_pool_clear(iterpool); + if (i >= base_children->nelts) + { + working_only = TRUE; + child_name = APR_ARRAY_IDX(working_children, j, const char *); + } + else if (j >= working_children->nelts) + { + base_only = TRUE; + child_name = APR_ARRAY_IDX(base_children, i, const char *); + } + else + { + const char *base_name = APR_ARRAY_IDX(base_children, i, + const char *); + const char *working_name = APR_ARRAY_IDX(working_children, j, + const char *); + int cmp = strcmp(base_name, working_name); + + if (cmp > 0) + working_only = TRUE; + else if (cmp < 0) + base_only = TRUE; + + child_name = working_only ? working_name : base_name; + } + + cnb.local_relpath = svn_relpath_join(nb->local_relpath, child_name, + iterpool); + + SVN_ERR(update_locally_added_node(&cnb, iterpool)); + + if (!working_only) + ++i; + if (!base_only) + ++j; + + if (nb->skip) /* Does parent now want a skip? */ + break; + } + } + + return SVN_NO_ERROR; +} + +/* The body of svn_wc__db_update_local_add(). */ +static svn_error_t * +update_local_add(svn_revnum_t *new_rev, + svn_wc__db_t *db, + svn_wc__db_wcroot_t *wcroot, + const char *local_relpath, + svn_cancel_func_t cancel_func, + void *cancel_baton, + apr_pool_t *scratch_pool) +{ + update_local_add_baton_t b = { 0 }; + added_node_baton_t nb = { 0 }; + const char *repos_root_url; + const char *repos_uuid; + const char *repos_relpath; + apr_int64_t repos_id; + svn_node_kind_t new_kind; + svn_sqlite__stmt_t *stmt; + + b.add_op_depth = relpath_depth(local_relpath); /* DST op-root */ + + SVN_ERR(verify_write_lock(wcroot, local_relpath, scratch_pool)); + + b.db = db; + b.wcroot = wcroot; + b.cancel_func = cancel_func; + b.cancel_baton = cancel_baton; + + /* Read new version info from the updated BASE node. */ + SVN_ERR(svn_wc__db_base_get_info_internal(NULL, &new_kind, new_rev, + &repos_relpath, &repos_id, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, + wcroot, local_relpath, + scratch_pool, scratch_pool)); + SVN_ERR(svn_wc__db_fetch_repos_info(&repos_root_url, &repos_uuid, wcroot, + repos_id, scratch_pool)); + b.new_version = svn_wc_conflict_version_create2(repos_root_url, repos_uuid, + repos_relpath, *new_rev, + new_kind, scratch_pool); + + /* Create a new, and empty, list for notification information. */ + SVN_ERR(svn_sqlite__exec_statements(wcroot->sdb, + STMT_CREATE_UPDATE_MOVE_LIST)); + + /* Drive the editor... */ + nb.b = &b; + nb.local_relpath = local_relpath; + nb.skip = FALSE; + SVN_ERR(update_locally_added_node(&nb, scratch_pool)); + + /* The conflict victim is now part of the base tree. + * Remove the locally added version of the conflict victim and its children. + * Any children we want to retain are at a higher op-depth so they won't + * be deleted by this statement. */ + SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, + STMT_DELETE_WORKING_OP_DEPTH)); + SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath, + relpath_depth(local_relpath))); + SVN_ERR(svn_sqlite__update(NULL, stmt)); + + /* Remove the tree conflict marker. */ + SVN_ERR(svn_wc__db_op_mark_resolved_internal(wcroot, local_relpath, db, + FALSE, FALSE, TRUE, + NULL, scratch_pool)); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_wc__db_update_local_add(svn_wc__db_t *db, + const char *local_abspath, + svn_cancel_func_t cancel_func, + void *cancel_baton, + svn_wc_notify_func2_t notify_func, + void *notify_baton, + apr_pool_t *scratch_pool) +{ + svn_wc__db_wcroot_t *wcroot; + svn_revnum_t new_rev; + const char *local_relpath; + + SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, + db, local_abspath, + scratch_pool, scratch_pool)); + VERIFY_USABLE_WCROOT(wcroot); + + SVN_WC__DB_WITH_TXN(update_local_add(&new_rev, db, wcroot, + local_relpath, + cancel_func, cancel_baton, + scratch_pool), + wcroot); + + /* Send all queued up notifications. */ + SVN_ERR(svn_wc__db_update_move_list_notify(wcroot, new_rev, new_rev, + notify_func, notify_baton, + scratch_pool)); + if (notify_func) + { + svn_wc_notify_t *notify; + + notify = svn_wc_create_notify(svn_dirent_join(wcroot->abspath, + local_relpath, + scratch_pool), + svn_wc_notify_update_completed, + scratch_pool); + notify->kind = svn_node_none; + notify->content_state = svn_wc_notify_state_inapplicable; + notify->prop_state = svn_wc_notify_state_inapplicable; + notify->revision = new_rev; + notify_func(notify_baton, notify, scratch_pool); + } + + + return SVN_NO_ERROR; +} /* Set *CAN_BUMP to TRUE if DEPTH is sufficient to cover the entire tree LOCAL_RELPATH at OP_DEPTH, to FALSE otherwise. */ static svn_error_t * diff --git a/subversion/libsvn_wc/wc_db_util.c b/subversion/libsvn_wc/wc_db_util.c index 074feffcf9f5..8402c42eaadc 100644 --- a/subversion/libsvn_wc/wc_db_util.c +++ b/subversion/libsvn_wc/wc_db_util.c @@ -127,7 +127,7 @@ svn_wc__db_util_open_db(svn_sqlite__db_t **sdb, { svn_node_kind_t kind; - /* A file stat is much cheaper then a failed database open handled + /* A file stat is much cheaper than a failed database open handled by SQLite. */ SVN_ERR(svn_io_check_path(sdb_abspath, &kind, scratch_pool)); diff --git a/subversion/libsvn_wc/wcroot_anchor.c b/subversion/libsvn_wc/wcroot_anchor.c index 913a61b50ad7..7400aa5c9948 100644 --- a/subversion/libsvn_wc/wcroot_anchor.c +++ b/subversion/libsvn_wc/wcroot_anchor.c @@ -182,6 +182,26 @@ svn_wc__get_wcroot(const char **wcroot_abspath, } +svn_error_t * +svn_wc__get_shelves_dir(char **dir, + svn_wc_context_t *wc_ctx, + const char *local_abspath, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + const char *wcroot_abspath; + + SVN_ERR(svn_wc__get_wcroot(&wcroot_abspath, wc_ctx, local_abspath, + scratch_pool, scratch_pool)); + *dir = svn_dirent_join(wcroot_abspath, ".svn/shelves", result_pool); + + /* Ensure the directory exists. (Other versions of svn don't create it.) */ + SVN_ERR(svn_io_make_dir_recursively(*dir, scratch_pool)); + + return SVN_NO_ERROR; +} + + svn_error_t * svn_wc_get_actual_target2(const char **anchor, const char **target, diff --git a/subversion/libsvn_wc/workqueue.c b/subversion/libsvn_wc/workqueue.c index 18736cc6ff3f..449abcb2192f 100644 --- a/subversion/libsvn_wc/workqueue.c +++ b/subversion/libsvn_wc/workqueue.c @@ -257,7 +257,8 @@ install_committed_file(svn_boolean_t *overwrote_working, if (! same) { - SVN_ERR(svn_io_file_rename(tmp_wfile, file_abspath, scratch_pool)); + SVN_ERR(svn_io_file_rename2(tmp_wfile, file_abspath, FALSE, + scratch_pool)); *overwrote_working = TRUE; } @@ -418,13 +419,13 @@ run_postupgrade(work_item_baton_t *wqb, ### The order may matter for some sufficiently old clients.. but ### this code only runs during upgrade after the files had been ### removed earlier during the upgrade. */ - SVN_ERR(svn_io_write_atomic(format_path, SVN_WC__NON_ENTRIES_STRING, - sizeof(SVN_WC__NON_ENTRIES_STRING) - 1, - NULL, scratch_pool)); + SVN_ERR(svn_io_write_atomic2(format_path, SVN_WC__NON_ENTRIES_STRING, + sizeof(SVN_WC__NON_ENTRIES_STRING) - 1, + NULL, TRUE, scratch_pool)); - SVN_ERR(svn_io_write_atomic(entries_path, SVN_WC__NON_ENTRIES_STRING, - sizeof(SVN_WC__NON_ENTRIES_STRING) - 1, - NULL, scratch_pool)); + SVN_ERR(svn_io_write_atomic2(entries_path, SVN_WC__NON_ENTRIES_STRING, + sizeof(SVN_WC__NON_ENTRIES_STRING) - 1, + NULL, TRUE, scratch_pool)); return SVN_NO_ERROR; } @@ -1127,9 +1128,9 @@ run_prej_install(work_item_baton_t *wqb, scratch_pool, scratch_pool)); /* ... and atomically move it into place. */ - SVN_ERR(svn_io_file_rename(tmp_prejfile_abspath, - prejfile_abspath, - scratch_pool)); + SVN_ERR(svn_io_file_rename2(tmp_prejfile_abspath, + prejfile_abspath, FALSE, + scratch_pool)); return SVN_NO_ERROR; } diff --git a/subversion/svn/cl-conflicts.c b/subversion/svn/cl-conflicts.c index 8507e8c3b309..0dc0abf29114 100644 --- a/subversion/svn/cl-conflicts.c +++ b/subversion/svn/cl-conflicts.c @@ -58,14 +58,6 @@ static const svn_token_map_t map_conflict_reason_xml[] = { NULL, 0 } }; -static const svn_token_map_t map_conflict_kind_xml[] = -{ - { "text", svn_wc_conflict_kind_text }, - { "property", svn_wc_conflict_kind_property }, - { "tree", svn_wc_conflict_kind_tree }, - { NULL, 0 } -}; - /* Return a localised string representation of the local part of a conflict; NULL for non-localised odd cases. */ static const char * @@ -229,14 +221,14 @@ operation_str(svn_wc_operation_t operation) svn_error_t * svn_cl__get_human_readable_prop_conflict_description( const char **desc, - const svn_wc_conflict_description2_t *conflict, + svn_client_conflict_t *conflict, apr_pool_t *pool) { const char *reason_str, *action_str; /* We provide separately translatable strings for the values that we * know about, and a fall-back in case any other values occur. */ - switch (conflict->reason) + switch (svn_client_conflict_get_local_change(conflict)) { case svn_wc_conflict_reason_edited: reason_str = _("local edit"); @@ -251,12 +243,14 @@ svn_cl__get_human_readable_prop_conflict_description( reason_str = _("local obstruction"); break; default: - reason_str = apr_psprintf(pool, _("local %s"), - svn_token__to_word(map_conflict_reason_xml, - conflict->reason)); + reason_str = apr_psprintf( + pool, _("local %s"), + svn_token__to_word( + map_conflict_reason_xml, + svn_client_conflict_get_local_change(conflict))); break; } - switch (conflict->action) + switch (svn_client_conflict_get_incoming_change(conflict)) { case svn_wc_conflict_action_edit: action_str = _("incoming edit"); @@ -268,51 +262,63 @@ svn_cl__get_human_readable_prop_conflict_description( action_str = _("incoming delete"); break; default: - action_str = apr_psprintf(pool, _("incoming %s"), - svn_token__to_word(map_conflict_action_xml, - conflict->action)); + action_str = apr_psprintf( + pool, _("incoming %s"), + svn_token__to_word( + map_conflict_action_xml, + svn_client_conflict_get_incoming_change(conflict))); break; } SVN_ERR_ASSERT(reason_str && action_str); *desc = apr_psprintf(pool, _("%s, %s %s"), reason_str, action_str, - operation_str(conflict->operation)); + operation_str( + svn_client_conflict_get_operation(conflict))); return SVN_NO_ERROR; } svn_error_t * svn_cl__get_human_readable_tree_conflict_description( const char **desc, - const svn_wc_conflict_description2_t *conflict, + svn_client_conflict_t *conflict, apr_pool_t *pool) { const char *action, *reason, *operation; svn_node_kind_t incoming_kind; + svn_wc_conflict_action_t conflict_action; + svn_wc_conflict_reason_t conflict_reason; + svn_wc_operation_t conflict_operation; + svn_node_kind_t conflict_node_kind; + + conflict_action = svn_client_conflict_get_incoming_change(conflict); + conflict_reason = svn_client_conflict_get_local_change(conflict); + conflict_operation = svn_client_conflict_get_operation(conflict); + conflict_node_kind = svn_client_conflict_tree_get_victim_node_kind(conflict); /* Determine the node kind of the incoming change. */ incoming_kind = svn_node_unknown; - if (conflict->action == svn_wc_conflict_action_edit || - conflict->action == svn_wc_conflict_action_delete) + if (conflict_action == svn_wc_conflict_action_edit || + conflict_action == svn_wc_conflict_action_delete) { /* Change is acting on 'src_left' version of the node. */ - if (conflict->src_left_version) - incoming_kind = conflict->src_left_version->node_kind; + SVN_ERR(svn_client_conflict_get_incoming_old_repos_location( + NULL, NULL, &incoming_kind, conflict, pool, pool)); } - else if (conflict->action == svn_wc_conflict_action_add || - conflict->action == svn_wc_conflict_action_replace) + else if (conflict_action == svn_wc_conflict_action_add || + conflict_action == svn_wc_conflict_action_replace) { /* Change is acting on 'src_right' version of the node. * * ### For 'replace', the node kind is ambiguous. However, src_left * ### is NULL for replace, so we must use src_right. */ - if (conflict->src_right_version) - incoming_kind = conflict->src_right_version->node_kind; + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + NULL, NULL, &incoming_kind, conflict, pool, pool)); } - reason = local_reason_str(conflict->node_kind, conflict->reason, - conflict->operation); - action = incoming_action_str(incoming_kind, conflict->action); - operation = operation_str(conflict->operation); + reason = local_reason_str(conflict_node_kind, conflict_reason, + conflict_operation); + action = incoming_action_str(incoming_kind, conflict_action); + operation = operation_str(conflict_operation); SVN_ERR_ASSERT(operation); if (action && reason) @@ -326,12 +332,12 @@ svn_cl__get_human_readable_tree_conflict_description( It will not be pretty, but is closer to an internal error than an ordinary user-facing string. */ *desc = apr_psprintf(pool, _("local: %s %s incoming: %s %s %s"), - svn_node_kind_to_word(conflict->node_kind), + svn_node_kind_to_word(conflict_node_kind), svn_token__to_word(map_conflict_reason_xml, - conflict->reason), + conflict_reason), svn_node_kind_to_word(incoming_kind), svn_token__to_word(map_conflict_action_xml, - conflict->action), + conflict_action), operation); } return SVN_NO_ERROR; @@ -360,13 +366,16 @@ svn_cl__get_human_readable_action_description( /* Helper for svn_cl__append_tree_conflict_info_xml(). - * Appends the attributes of the given VERSION to ATT_HASH. + * Appends the repository location of a conflicted node to ATT_HASH. * SIDE is the content of the version tag's side="..." attribute, * currently one of "source-left" or "source-right".*/ static svn_error_t * add_conflict_version_xml(svn_stringbuf_t **pstr, const char *side, - const svn_wc_conflict_version_t *version, + const char *repos_root_url, + const char *repos_relpath, + svn_revnum_t peg_rev, + svn_node_kind_t node_kind, apr_pool_t *pool) { apr_hash_t *att_hash = apr_hash_make(pool); @@ -374,18 +383,17 @@ add_conflict_version_xml(svn_stringbuf_t **pstr, svn_hash_sets(att_hash, "side", side); - if (version->repos_url) - svn_hash_sets(att_hash, "repos-url", version->repos_url); + if (repos_root_url) + svn_hash_sets(att_hash, "repos-url", repos_root_url); - if (version->path_in_repos) - svn_hash_sets(att_hash, "path-in-repos", version->path_in_repos); + if (repos_relpath) + svn_hash_sets(att_hash, "path-in-repos", repos_relpath); - if (SVN_IS_VALID_REVNUM(version->peg_rev)) - svn_hash_sets(att_hash, "revision", apr_ltoa(pool, version->peg_rev)); + if (SVN_IS_VALID_REVNUM(peg_rev)) + svn_hash_sets(att_hash, "revision", apr_ltoa(pool, peg_rev)); - if (version->node_kind != svn_node_unknown) - svn_hash_sets(att_hash, "kind", - svn_cl__node_kind_str_xml(version->node_kind)); + if (node_kind != svn_node_unknown) + svn_hash_sets(att_hash, "kind", svn_cl__node_kind_str_xml(node_kind)); svn_xml_make_open_tag_hash(pstr, pool, svn_xml_self_closing, "version", att_hash); @@ -395,25 +403,34 @@ add_conflict_version_xml(svn_stringbuf_t **pstr, static svn_error_t * append_tree_conflict_info_xml(svn_stringbuf_t *str, - const svn_wc_conflict_description2_t *conflict, + svn_client_conflict_t *conflict, apr_pool_t *pool) { apr_hash_t *att_hash = apr_hash_make(pool); const char *tmp; + const char *repos_root_url; + const char *repos_relpath; + svn_revnum_t peg_rev; + svn_node_kind_t node_kind; svn_hash_sets(att_hash, "victim", - svn_dirent_basename(conflict->local_abspath, pool)); + svn_dirent_basename( + svn_client_conflict_get_local_abspath(conflict), pool)); svn_hash_sets(att_hash, "kind", - svn_cl__node_kind_str_xml(conflict->node_kind)); + svn_cl__node_kind_str_xml( + svn_client_conflict_tree_get_victim_node_kind(conflict))); svn_hash_sets(att_hash, "operation", - svn_cl__operation_str_xml(conflict->operation, pool)); + svn_cl__operation_str_xml( + svn_client_conflict_get_operation(conflict), pool)); - tmp = svn_token__to_word(map_conflict_action_xml, conflict->action); + tmp = svn_token__to_word(map_conflict_action_xml, + svn_client_conflict_get_incoming_change(conflict)); svn_hash_sets(att_hash, "action", tmp); - tmp = svn_token__to_word(map_conflict_reason_xml, conflict->reason); + tmp = svn_token__to_word(map_conflict_reason_xml, + svn_client_conflict_get_local_change(conflict)); svn_hash_sets(att_hash, "reason", tmp); /* Open the tree-conflict tag. */ @@ -422,17 +439,30 @@ append_tree_conflict_info_xml(svn_stringbuf_t *str, /* Add child tags for OLDER_VERSION and THEIR_VERSION. */ - if (conflict->src_left_version) - SVN_ERR(add_conflict_version_xml(&str, - "source-left", - conflict->src_left_version, - pool)); + SVN_ERR(svn_client_conflict_get_repos_info(&repos_root_url, NULL, conflict, + pool, pool)); + SVN_ERR(svn_client_conflict_get_incoming_old_repos_location(&repos_relpath, + &peg_rev, + &node_kind, + conflict, + pool, + pool)); + if (repos_root_url && repos_relpath) + SVN_ERR(add_conflict_version_xml(&str, "source-left", + repos_root_url, repos_relpath, peg_rev, + node_kind, pool)); - if (conflict->src_right_version) + SVN_ERR(svn_client_conflict_get_incoming_old_repos_location(&repos_relpath, + &peg_rev, + &node_kind, + conflict, + pool, + pool)); + if (repos_root_url && repos_relpath) SVN_ERR(add_conflict_version_xml(&str, "source-right", - conflict->src_right_version, - pool)); + repos_root_url, repos_relpath, peg_rev, + node_kind, pool)); svn_xml_make_close_tag(&str, pool, "tree-conflict"); @@ -441,78 +471,128 @@ append_tree_conflict_info_xml(svn_stringbuf_t *str, svn_error_t * svn_cl__append_conflict_info_xml(svn_stringbuf_t *str, - const svn_wc_conflict_description2_t *conflict, + svn_client_conflict_t *conflict, apr_pool_t *scratch_pool) { apr_hash_t *att_hash; - const char *kind; - if (conflict->kind == svn_wc_conflict_kind_tree) + svn_boolean_t text_conflicted; + apr_array_header_t *props_conflicted; + svn_boolean_t tree_conflicted; + svn_wc_operation_t conflict_operation; + const char *repos_root_url; + const char *repos_relpath; + svn_revnum_t peg_rev; + svn_node_kind_t node_kind; + + conflict_operation = svn_client_conflict_get_operation(conflict); + + SVN_ERR(svn_client_conflict_get_conflicted(&text_conflicted, + &props_conflicted, + &tree_conflicted, + conflict, + scratch_pool, scratch_pool)); + if (tree_conflicted) { /* Uses other element type */ return svn_error_trace( append_tree_conflict_info_xml(str, conflict, scratch_pool)); } + SVN_ERR(svn_client_conflict_get_repos_info(&repos_root_url, NULL, + conflict, + scratch_pool, scratch_pool)); att_hash = apr_hash_make(scratch_pool); svn_hash_sets(att_hash, "operation", - svn_cl__operation_str_xml(conflict->operation, scratch_pool)); - - - kind = svn_token__to_word(map_conflict_kind_xml, conflict->kind); - svn_hash_sets(att_hash, "type", kind); + svn_cl__operation_str_xml(conflict_operation, scratch_pool)); svn_hash_sets(att_hash, "operation", - svn_cl__operation_str_xml(conflict->operation, scratch_pool)); + svn_cl__operation_str_xml(conflict_operation, scratch_pool)); - - /* "" */ - svn_xml_make_open_tag_hash(&str, scratch_pool, - svn_xml_normal, "conflict", att_hash); - - if (conflict->src_left_version) - SVN_ERR(add_conflict_version_xml(&str, - "source-left", - conflict->src_left_version, - scratch_pool)); - - if (conflict->src_right_version) - SVN_ERR(add_conflict_version_xml(&str, - "source-right", - conflict->src_right_version, - scratch_pool)); - - switch (conflict->kind) + if (text_conflicted) { - case svn_wc_conflict_kind_text: - /* " xx " */ - svn_cl__xml_tagged_cdata(&str, scratch_pool, "prev-base-file", - conflict->base_abspath); + const char *base_abspath; + const char *my_abspath; + const char *their_abspath; - /* " xx " */ - svn_cl__xml_tagged_cdata(&str, scratch_pool, "prev-wc-file", - conflict->my_abspath); + svn_hash_sets(att_hash, "type", "text"); - /* " xx " */ - svn_cl__xml_tagged_cdata(&str, scratch_pool, "cur-base-file", - conflict->their_abspath); + /* "" */ + svn_xml_make_open_tag_hash(&str, scratch_pool, + svn_xml_normal, "conflict", att_hash); - break; + SVN_ERR(svn_client_conflict_get_incoming_old_repos_location( + &repos_relpath, &peg_rev, &node_kind, conflict, + scratch_pool, scratch_pool)); + if (repos_root_url && repos_relpath) + SVN_ERR(add_conflict_version_xml(&str, "source-left", + repos_root_url, repos_relpath, peg_rev, + node_kind, scratch_pool)); - case svn_wc_conflict_kind_property: - /* " xx " */ - svn_cl__xml_tagged_cdata(&str, scratch_pool, "prop-file", - conflict->their_abspath); - break; + SVN_ERR(svn_client_conflict_get_incoming_old_repos_location( + &repos_relpath, &peg_rev, &node_kind, conflict, + scratch_pool, scratch_pool)); + if (repos_root_url && repos_relpath) + SVN_ERR(add_conflict_version_xml(&str, "source-right", + repos_root_url, repos_relpath, peg_rev, + node_kind, scratch_pool)); - default: - case svn_wc_conflict_kind_tree: - SVN_ERR_MALFUNCTION(); /* Handled separately */ - break; + SVN_ERR(svn_client_conflict_text_get_contents(NULL, &my_abspath, + &base_abspath, + &their_abspath, + conflict, scratch_pool, + scratch_pool)); + /* " xx " */ + svn_cl__xml_tagged_cdata( + &str, scratch_pool, "prev-base-file", base_abspath); + + /* " xx " */ + svn_cl__xml_tagged_cdata( + &str, scratch_pool, "prev-wc-file", my_abspath); + + /* " xx " */ + svn_cl__xml_tagged_cdata( + &str, scratch_pool, "cur-base-file", their_abspath); + + /* "" */ + svn_xml_make_close_tag(&str, scratch_pool, "conflict"); } - /* "" */ - svn_xml_make_close_tag(&str, scratch_pool, "conflict"); + if (props_conflicted->nelts > 0) + { + const char *reject_abspath; + + svn_hash_sets(att_hash, "type", "property"); + + /* "" */ + svn_xml_make_open_tag_hash(&str, scratch_pool, + svn_xml_normal, "conflict", att_hash); + + SVN_ERR(svn_client_conflict_get_incoming_old_repos_location( + &repos_relpath, &peg_rev, &node_kind, conflict, + scratch_pool, scratch_pool)); + if (repos_root_url && repos_relpath) + SVN_ERR(add_conflict_version_xml(&str, "source-left", + repos_root_url, repos_relpath, peg_rev, + node_kind, scratch_pool)); + + SVN_ERR(svn_client_conflict_get_incoming_old_repos_location( + &repos_relpath, &peg_rev, &node_kind, conflict, + scratch_pool, scratch_pool)); + if (repos_root_url && repos_relpath) + SVN_ERR(add_conflict_version_xml(&str, "source-right", + repos_root_url, repos_relpath, peg_rev, + node_kind, scratch_pool)); + + /* " xx " */ + reject_abspath = + svn_client_conflict_prop_get_reject_abspath(conflict); + svn_cl__xml_tagged_cdata( + &str, scratch_pool, "prop-file", reject_abspath); + + /* "" */ + svn_xml_make_close_tag(&str, scratch_pool, "conflict"); + } return SVN_NO_ERROR; } diff --git a/subversion/svn/cl-conflicts.h b/subversion/svn/cl-conflicts.h index d4880748cd9c..bcc6c1b520f5 100644 --- a/subversion/svn/cl-conflicts.h +++ b/subversion/svn/cl-conflicts.h @@ -31,6 +31,7 @@ #include "svn_types.h" #include "svn_string.h" +#include "svn_client.h" #include "svn_wc.h" #ifdef __cplusplus @@ -48,7 +49,7 @@ extern "C" { svn_error_t * svn_cl__get_human_readable_prop_conflict_description( const char **desc, - const svn_wc_conflict_description2_t *conflict, + svn_client_conflict_t *conflict, apr_pool_t *pool); /** @@ -60,7 +61,7 @@ svn_cl__get_human_readable_prop_conflict_description( svn_error_t * svn_cl__get_human_readable_tree_conflict_description( const char **desc, - const svn_wc_conflict_description2_t *conflict, + svn_client_conflict_t *conflict, apr_pool_t *pool); /* Like svn_cl__get_human_readable_tree_conflict_description but @@ -80,7 +81,7 @@ svn_cl__get_human_readable_action_description( svn_error_t * svn_cl__append_conflict_info_xml( svn_stringbuf_t *str, - const svn_wc_conflict_description2_t *conflict, + svn_client_conflict_t *conflict, apr_pool_t *pool); #ifdef __cplusplus diff --git a/subversion/svn/cl-log.h b/subversion/svn/cl-log.h index 5b4c7aa7a68b..e2d5646351a6 100644 --- a/subversion/svn/cl-log.h +++ b/subversion/svn/cl-log.h @@ -31,6 +31,8 @@ #include "svn_types.h" +#include "private/svn_string_private.h" + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ @@ -70,6 +72,9 @@ typedef struct svn_cl__log_receiver_baton * the log message, or a changed path matches one of these patterns. */ apr_array_header_t *search_patterns; + /* Buffer for Unicode normalization and case folding. */ + svn_membuf_t buffer; + /* Pool for persistent allocations. */ apr_pool_t *pool; } svn_cl__log_receiver_baton; diff --git a/subversion/svn/cl.h b/subversion/svn/cl.h index 42e770e075c5..a5b1d9b948ae 100644 --- a/subversion/svn/cl.h +++ b/subversion/svn/cl.h @@ -83,7 +83,10 @@ typedef enum svn_cl__accept_t svn_cl__accept_edit, /* Launch user's resolver and resolve conflict with edited file. */ - svn_cl__accept_launch + svn_cl__accept_launch, + + /* Use recommended resolution if available, else leave the conflict alone. */ + svn_cl__accept_recommended } svn_cl__accept_t; @@ -97,6 +100,7 @@ typedef enum svn_cl__accept_t #define SVN_CL__ACCEPT_THEIRS_FULL "theirs-full" #define SVN_CL__ACCEPT_EDIT "edit" #define SVN_CL__ACCEPT_LAUNCH "launch" +#define SVN_CL__ACCEPT_RECOMMENDED "recommended" /* Return the svn_cl__accept_t value corresponding to WORD, using exact * case-sensitive string comparison. Return svn_cl__accept_invalid if WORD @@ -174,6 +178,7 @@ typedef struct svn_cl__opt_state_t svn_boolean_t help; /* print usage message */ const char *auth_username; /* auth username */ const char *auth_password; /* auth password */ + svn_boolean_t auth_password_from_stdin; /* read password from stdin */ const char *extensions; /* subprocess extension args */ apr_array_header_t *targets; /* target list from file */ svn_boolean_t xml; /* output in xml, e.g., "svn log --xml" */ @@ -249,12 +254,18 @@ typedef struct svn_cl__opt_state_t svn_boolean_t show_passwords; /* show cached passwords */ svn_boolean_t pin_externals; /* pin externals to last-changed revisions */ const char *show_item; /* print only the given item */ + svn_boolean_t adds_as_modification; /* update 'add vs add' no tree conflict */ + svn_boolean_t vacuum_pristines; /* remove unreferenced pristines */ + svn_boolean_t list; } svn_cl__opt_state_t; +/* Conflict stats for operations such as update and merge. */ +typedef struct svn_cl__conflict_stats_t svn_cl__conflict_stats_t; typedef struct svn_cl__cmd_baton_t { svn_cl__opt_state_t *opt_state; + svn_cl__conflict_stats_t *conflict_stats; svn_client_ctx_t *ctx; } svn_cl__cmd_baton_t; @@ -293,6 +304,9 @@ svn_opt_subcommand_t svn_cl__revert, svn_cl__resolve, svn_cl__resolved, + svn_cl__shelve, + svn_cl__unshelve, + svn_cl__shelves, svn_cl__status, svn_cl__switch, svn_cl__unlock, @@ -335,8 +349,7 @@ svn_cl__try(svn_error_t *err, /* Our cancellation callback. */ -svn_error_t * -svn_cl__check_cancel(void *baton); +extern svn_cancel_func_t svn_cl__check_cancel; @@ -346,9 +359,6 @@ svn_cl__check_cancel(void *baton); typedef struct svn_cl__interactive_conflict_baton_t svn_cl__interactive_conflict_baton_t; -/* Conflict stats for operations such as update and merge. */ -typedef struct svn_cl__conflict_stats_t svn_cl__conflict_stats_t; - /* Return a new, initialized, conflict stats structure, allocated in * POOL. */ svn_cl__conflict_stats_t * @@ -362,6 +372,14 @@ svn_cl__conflict_stats_resolved(svn_cl__conflict_stats_t *conflict_stats, const char *path_local, svn_wc_conflict_kind_t conflict_kind); +/* Set *CONFLICTED_PATHS to the conflicted paths contained in CONFLICT_STATS. + * If no conflicted path exists, set *CONFLICTED_PATHS to NULL. */ +svn_error_t * +svn_cl__conflict_stats_get_paths(apr_array_header_t **conflicted_paths, + svn_cl__conflict_stats_t *conflict_stats, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + /* Print the conflict stats accumulated in CONFLICT_STATS. * * Return any error encountered during printing. @@ -371,36 +389,33 @@ svn_error_t * svn_cl__print_conflict_stats(svn_cl__conflict_stats_t *conflict_stats, apr_pool_t *scratch_pool); -/* Create and return an baton for use with svn_cl__conflict_func_interactive - * in *B, allocated from RESULT_POOL, and initialised with the values - * ACCEPT_WHICH, CONFIG, EDITOR_CMD, CANCEL_FUNC and CANCEL_BATON. */ -svn_error_t * -svn_cl__get_conflict_func_interactive_baton( - svn_cl__interactive_conflict_baton_t **b, - svn_cl__accept_t accept_which, - apr_hash_t *config, - const char *editor_cmd, - svn_cl__conflict_stats_t *conflict_stats, - svn_cancel_func_t cancel_func, - void *cancel_baton, - apr_pool_t *result_pool); - -/* A callback capable of doing interactive conflict resolution. - - The BATON must come from svn_cl__get_conflict_func_interactive_baton(). - Resolves based on the --accept option if one was given to that function, - otherwise prompts the user to choose one of the three fulltexts, edit - the merged file on the spot, or just skip the conflict (to be resolved - later), among other options. - - Implements svn_wc_conflict_resolver_func2_t. +/* + * Interactively resolve the conflict a @a CONFLICT. + * TODO: more docs */ svn_error_t * -svn_cl__conflict_func_interactive(svn_wc_conflict_result_t **result, - const svn_wc_conflict_description2_t *desc, - void *baton, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool); +svn_cl__resolve_conflict(svn_boolean_t *quit, + svn_boolean_t *external_failed, + svn_boolean_t *printed_summary, + svn_client_conflict_t *conflict, + svn_cl__accept_t accept_which, + const char *editor_cmd, + const char *path_prefix, + svn_cmdline_prompt_baton_t *pb, + svn_cl__conflict_stats_t *conflict_stats, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool); + +/* + * Interactively resolve conflicts for all TARGETS. + * TODO: more docs + */ +svn_error_t * +svn_cl__walk_conflicts(apr_array_header_t *targets, + svn_cl__conflict_stats_t *conflict_stats, + svn_cl__opt_state_t *opt_state, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool); /*** Command-line output functions -- printing to the user. ***/ @@ -777,15 +792,18 @@ svn_cl__args_to_target_array_print_reserved(apr_array_header_t **targets_p, svn_boolean_t keep_dest_origpath_on_truepath_collision, apr_pool_t *pool); -/* Return a string showing NODE's kind, URL and revision, to the extent that - * that information is available in NODE. If NODE itself is NULL, this prints - * just a 'none' node kind. +/* Return a string showing a conflicted node's kind, URL and revision, + * to the extent that that information is available. If REPOS_ROOT_URL or + * REPOS_RELPATH are NULL, this prints just a 'none' node kind. * WC_REPOS_ROOT_URL should reflect the target working copy's repository - * root URL. If NODE is from that same URL, the printed URL is abbreviated + * root URL. If the node is from that same URL, the printed URL is abbreviated * to caret notation (^/). WC_REPOS_ROOT_URL may be NULL, in which case * this function tries to print the conflicted node's complete URL. */ const char * -svn_cl__node_description(const svn_wc_conflict_version_t *node, +svn_cl__node_description(const char *repos_root_url, + const char *repos_relpath, + svn_revnum_t peg_rev, + svn_node_kind_t node_kind, const char *wc_repos_root_URL, apr_pool_t *pool); diff --git a/subversion/svn/cleanup-cmd.c b/subversion/svn/cleanup-cmd.c index 6b0b62efe930..516b933f68f4 100644 --- a/subversion/svn/cleanup-cmd.c +++ b/subversion/svn/cleanup-cmd.c @@ -72,13 +72,14 @@ svn_cl__cleanup(apr_getopt_t *os, SVN_ERR(svn_dirent_get_absolute(&target_abspath, target, iterpool)); - if (opt_state->remove_unversioned || opt_state->remove_ignored) + if (opt_state->remove_unversioned || opt_state->remove_ignored || + opt_state->vacuum_pristines) { svn_error_t *err = svn_client_vacuum(target_abspath, opt_state->remove_unversioned, opt_state->remove_ignored, TRUE /* fix_timestamps */, - FALSE /* vacuum_pristines */, + opt_state->vacuum_pristines, opt_state->include_externals, ctx, iterpool); diff --git a/subversion/svn/conflict-callbacks.c b/subversion/svn/conflict-callbacks.c index a9cb39a2ade1..278fffcdb882 100644 --- a/subversion/svn/conflict-callbacks.c +++ b/subversion/svn/conflict-callbacks.c @@ -44,53 +44,9 @@ #include "svn_private_config.h" #define ARRAY_LEN(ary) ((sizeof (ary)) / (sizeof ((ary)[0]))) -#define MAX_ARRAY_LEN(aryx, aryz) \ - (ARRAY_LEN((aryx)) > ARRAY_LEN((aryz)) \ - ? ARRAY_LEN((aryx)) : ARRAY_LEN((aryz))) -struct svn_cl__interactive_conflict_baton_t { - svn_cl__accept_t accept_which; - apr_hash_t *config; - const char *editor_cmd; - svn_boolean_t external_failed; - svn_cmdline_prompt_baton_t *pb; - const char *path_prefix; - svn_boolean_t quit; - svn_cl__conflict_stats_t *conflict_stats; - svn_boolean_t printed_summary; -}; - -svn_error_t * -svn_cl__get_conflict_func_interactive_baton( - svn_cl__interactive_conflict_baton_t **b, - svn_cl__accept_t accept_which, - apr_hash_t *config, - const char *editor_cmd, - svn_cl__conflict_stats_t *conflict_stats, - svn_cancel_func_t cancel_func, - void *cancel_baton, - apr_pool_t *result_pool) -{ - svn_cmdline_prompt_baton_t *pb = apr_palloc(result_pool, sizeof(*pb)); - pb->cancel_func = cancel_func; - pb->cancel_baton = cancel_baton; - - *b = apr_palloc(result_pool, sizeof(**b)); - (*b)->accept_which = accept_which; - (*b)->config = config; - (*b)->editor_cmd = editor_cmd; - (*b)->external_failed = FALSE; - (*b)->pb = pb; - SVN_ERR(svn_dirent_get_absolute(&(*b)->path_prefix, "", result_pool)); - (*b)->quit = FALSE; - (*b)->conflict_stats = conflict_stats; - (*b)->printed_summary = FALSE; - - return SVN_NO_ERROR; -} - svn_cl__accept_t svn_cl__accept_from_word(const char *word) { @@ -122,15 +78,19 @@ svn_cl__accept_from_word(const char *word) if (strcmp(word, SVN_CL__ACCEPT_LAUNCH) == 0 || strcmp(word, "l") == 0 || strcmp(word, ":-l") == 0) return svn_cl__accept_launch; + if (strcmp(word, SVN_CL__ACCEPT_RECOMMENDED) == 0 + || strcmp(word, "r") == 0) + return svn_cl__accept_recommended; /* word is an invalid action. */ return svn_cl__accept_invalid; } /* Print on stdout a diff that shows incoming conflicting changes - * corresponding to the conflict described in DESC. */ + * corresponding to the conflict described in CONFLICT. */ static svn_error_t * -show_diff(const svn_wc_conflict_description2_t *desc, +show_diff(svn_client_conflict_t *conflict, + const char *merged_abspath, const char *path_prefix, svn_cancel_func_t cancel_func, void *cancel_baton, @@ -141,8 +101,13 @@ show_diff(const svn_wc_conflict_description2_t *desc, svn_diff_t *diff; svn_stream_t *output; svn_diff_file_options_t *options; + const char *my_abspath; + const char *their_abspath; - if (desc->merged_file) + SVN_ERR(svn_client_conflict_text_get_contents(NULL, &my_abspath, NULL, + &their_abspath, + conflict, pool, pool)); + if (merged_abspath) { /* For conflicts recorded by the 'merge' operation, show a diff between * 'mine' (the working version of the file as it appeared before the @@ -150,32 +115,32 @@ show_diff(const svn_wc_conflict_description2_t *desc, * as it appears after the merge operation). * * For conflicts recorded by the 'update' and 'switch' operations, - * show a diff beween 'theirs' (the new pristine version of the + * show a diff between 'theirs' (the new pristine version of the * file) and 'merged' (the version of the file as it appears with * local changes merged with the new pristine version). * * This way, the diff is always minimal and clearly identifies changes * brought into the working copy by the update/switch/merge operation. */ - if (desc->operation == svn_wc_operation_merge) + if (svn_client_conflict_get_operation(conflict) == svn_wc_operation_merge) { - path1 = desc->my_abspath; + path1 = my_abspath; label1 = _("MINE"); } else { - path1 = desc->their_abspath; + path1 = their_abspath; label1 = _("THEIRS"); } - path2 = desc->merged_file; + path2 = merged_abspath; label2 = _("MERGED"); } else { /* There's no merged file, but we can show the difference between mine and theirs. */ - path1 = desc->their_abspath; + path1 = their_abspath; label1 = _("THEIRS"); - path2 = desc->my_abspath; + path2 = my_abspath; label2 = _("MINE"); } @@ -204,9 +169,9 @@ show_diff(const svn_wc_conflict_description2_t *desc, /* Print on stdout just the conflict hunks of a diff among the 'base', 'their' - * and 'my' files of DESC. */ + * and 'my' files of CONFLICT. */ static svn_error_t * -show_conflicts(const svn_wc_conflict_description2_t *desc, +show_conflicts(svn_client_conflict_t *conflict, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *pool) @@ -214,89 +179,78 @@ show_conflicts(const svn_wc_conflict_description2_t *desc, svn_diff_t *diff; svn_stream_t *output; svn_diff_file_options_t *options; + const char *base_abspath; + const char *my_abspath; + const char *their_abspath; + SVN_ERR(svn_client_conflict_text_get_contents(NULL, &my_abspath, + &base_abspath, &their_abspath, + conflict, pool, pool)); options = svn_diff_file_options_create(pool); options->ignore_eol_style = TRUE; SVN_ERR(svn_stream_for_stdout(&output, pool)); - SVN_ERR(svn_diff_file_diff3_2(&diff, - desc->base_abspath, - desc->my_abspath, - desc->their_abspath, + SVN_ERR(svn_diff_file_diff3_2(&diff, base_abspath, my_abspath, their_abspath, options, pool)); /* ### Consider putting the markers/labels from ### svn_wc__merge_internal in the conflict description. */ - return svn_diff_file_output_merge3(output, diff, - desc->base_abspath, - desc->my_abspath, - desc->their_abspath, - _("||||||| ORIGINAL"), - _("<<<<<<< MINE (select with 'mc')"), - _(">>>>>>> THEIRS (select with 'tc')"), - "=======", - svn_diff_conflict_display_only_conflicts, - cancel_func, - cancel_baton, - pool); + return svn_diff_file_output_merge3( + output, diff, base_abspath, my_abspath, their_abspath, + _("||||||| ORIGINAL"), + _("<<<<<<< MINE (select with 'mc')"), + _(">>>>>>> THEIRS (select with 'tc')"), + "=======", + svn_diff_conflict_display_only_conflicts, + cancel_func, + cancel_baton, + pool); } /* Perform a 3-way merge of the conflicting values of a property, * and write the result to the OUTPUT stream. * - * If MERGED_ABSPATH is non-NULL, use it as 'my' version instead of - * DESC->MY_ABSPATH. + * If MERGED_PROPVAL is non-NULL, use it as 'my' version instead of + * MY_ABSPATH. * * Assume the values are printable UTF-8 text. */ static svn_error_t * merge_prop_conflict(svn_stream_t *output, - const svn_wc_conflict_description2_t *desc, - const char *merged_abspath, + const svn_string_t *base_propval, + const svn_string_t *my_propval, + const svn_string_t *their_propval, + const svn_string_t *merged_propval, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *pool) { - const char *base_abspath = desc->base_abspath; - const char *my_abspath = desc->my_abspath; - const char *their_abspath = desc->their_abspath; svn_diff_file_options_t *options = svn_diff_file_options_create(pool); svn_diff_t *diff; - /* If any of the property values is missing, use an empty file instead + /* If any of the property values is missing, use an empty value instead * for the purpose of showing a diff. */ - if (! base_abspath || ! my_abspath || ! their_abspath) - { - const char *empty_file; - - SVN_ERR(svn_io_open_unique_file3(NULL, &empty_file, - NULL, svn_io_file_del_on_pool_cleanup, - pool, pool)); - if (! base_abspath) - base_abspath = empty_file; - if (! my_abspath) - my_abspath = empty_file; - if (! their_abspath) - their_abspath = empty_file; - } - + if (base_propval == NULL) + base_propval = svn_string_create_empty(pool); + if (my_propval == NULL) + my_propval = svn_string_create_empty(pool); + if (their_propval == NULL) + their_propval = svn_string_create_empty(pool); + options->ignore_eol_style = TRUE; - SVN_ERR(svn_diff_file_diff3_2(&diff, - base_abspath, - merged_abspath ? merged_abspath : my_abspath, - their_abspath, - options, pool)); - SVN_ERR(svn_diff_file_output_merge3(output, diff, - base_abspath, - merged_abspath ? merged_abspath - : my_abspath, - their_abspath, - _("||||||| ORIGINAL"), - _("<<<<<<< MINE"), - _(">>>>>>> THEIRS"), - "=======", - svn_diff_conflict_display_modified_original_latest, - cancel_func, - cancel_baton, - pool)); + SVN_ERR(svn_diff_mem_string_diff3(&diff, base_propval, + merged_propval ? + merged_propval : my_propval, + their_propval, options, pool)); + SVN_ERR(svn_diff_mem_string_output_merge3( + output, diff, base_propval, + merged_propval ? merged_propval : my_propval, their_propval, + _("||||||| ORIGINAL"), + _("<<<<<<< MINE"), + _(">>>>>>> THEIRS"), + "=======", + svn_diff_conflict_display_modified_original_latest, + cancel_func, + cancel_baton, + pool)); return SVN_NO_ERROR; } @@ -309,8 +263,10 @@ merge_prop_conflict(svn_stream_t *output, * Assume the values are printable UTF-8 text. */ static svn_error_t * -show_prop_conflict(const svn_wc_conflict_description2_t *desc, - const char *merged_abspath, +show_prop_conflict(const svn_string_t *base_propval, + const svn_string_t *my_propval, + const svn_string_t *their_propval, + const svn_string_t *merged_propval, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *pool) @@ -318,13 +274,13 @@ show_prop_conflict(const svn_wc_conflict_description2_t *desc, svn_stream_t *output; SVN_ERR(svn_stream_for_stdout(&output, pool)); - SVN_ERR(merge_prop_conflict(output, desc, merged_abspath, - cancel_func, cancel_baton, pool)); + SVN_ERR(merge_prop_conflict(output, base_propval, my_propval, their_propval, + merged_propval, cancel_func, cancel_baton, pool)); return SVN_NO_ERROR; } -/* Run an external editor, passing it the MERGED_FILE, or, if the +/* Run an external editor, passing it the MERGED_ABSPATH, or, if the * 'merged' file is null, return an error. The tool to use is determined by * B->editor_cmd, B->config and environment variables; see * svn_cl__edit_file_externally() for details. @@ -335,16 +291,17 @@ show_prop_conflict(const svn_wc_conflict_description2_t *desc, * return that error. */ static svn_error_t * open_editor(svn_boolean_t *performed_edit, - const char *merged_file, - svn_cl__interactive_conflict_baton_t *b, + const char *merged_abspath, + const char *editor_cmd, + apr_hash_t *config, apr_pool_t *pool) { svn_error_t *err; - if (merged_file) + if (merged_abspath) { - err = svn_cmdline__edit_file_externally(merged_file, b->editor_cmd, - b->config, pool); + err = svn_cmdline__edit_file_externally(merged_abspath, editor_cmd, + config, pool); if (err && (err->apr_err == SVN_ERR_CL_NO_EXTERNAL_EDITOR || err->apr_err == SVN_ERR_EXTERNAL_PROGRAM)) { @@ -368,34 +325,44 @@ open_editor(svn_boolean_t *performed_edit, return SVN_NO_ERROR; } -/* Run an external editor, passing it the 'merged' property in DESC. +/* Run an external editor on the merged property value with conflict markers. + * Return the edited result in *MERGED_PROPVAL. + * If the edit is aborted, set *MERGED_ABSPATH and *MERGED_PROPVAL to NULL. * The tool to use is determined by B->editor_cmd, B->config and * environment variables; see svn_cl__edit_file_externally() for details. */ static svn_error_t * -edit_prop_conflict(const char **merged_file_path, - const svn_wc_conflict_description2_t *desc, - svn_cl__interactive_conflict_baton_t *b, +edit_prop_conflict(const svn_string_t **merged_propval, + const svn_string_t *base_propval, + const svn_string_t *my_propval, + const svn_string_t *their_propval, + const char *editor_cmd, + apr_hash_t *config, + svn_cmdline_prompt_baton_t *pb, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { - apr_file_t *file; const char *file_path; svn_boolean_t performed_edit = FALSE; svn_stream_t *merged_prop; - SVN_ERR(svn_io_open_unique_file3(&file, &file_path, NULL, - svn_io_file_del_on_pool_cleanup, - result_pool, scratch_pool)); - merged_prop = svn_stream_from_aprfile2(file, TRUE /* disown */, - scratch_pool); - SVN_ERR(merge_prop_conflict(merged_prop, desc, NULL, - b->pb->cancel_func, - b->pb->cancel_baton, + SVN_ERR(svn_stream_open_unique(&merged_prop, &file_path, NULL, + svn_io_file_del_on_pool_cleanup, + scratch_pool, scratch_pool)); + SVN_ERR(merge_prop_conflict(merged_prop, base_propval, my_propval, + their_propval, NULL, + pb->cancel_func, + pb->cancel_baton, scratch_pool)); SVN_ERR(svn_stream_close(merged_prop)); - SVN_ERR(svn_io_file_flush(file, scratch_pool)); - SVN_ERR(open_editor(&performed_edit, file_path, b, scratch_pool)); - *merged_file_path = (performed_edit ? file_path : NULL); + SVN_ERR(open_editor(&performed_edit, file_path, editor_cmd, + config, scratch_pool)); + if (performed_edit && merged_propval) + { + svn_stringbuf_t *buf; + + SVN_ERR(svn_stringbuf_from_file2(&buf, file_path, scratch_pool)); + *merged_propval = svn_string_create_from_buf(buf, result_pool); + } return SVN_NO_ERROR; } @@ -403,169 +370,166 @@ edit_prop_conflict(const char **merged_file_path, /* Maximum line length for the prompt string. */ #define MAX_PROMPT_WIDTH 70 -/* Description of a resolver option */ +/* Description of a resolver option. + * Resolver options are used to build the resolver's conflict prompt. + * The user types a code to select the corresponding conflict resolution option. + * Some resolver options have a corresponding --accept argument. */ typedef struct resolver_option_t { const char *code; /* one or two characters */ - const char *short_desc; /* label in prompt (localized) */ - const char *long_desc; /* longer description (localized) */ - svn_wc_conflict_choice_t choice; - /* or ..._undefined if not a simple choice */ + svn_client_conflict_option_id_t choice; + /* or ..._undefined if not from libsvn_client */ + const char *accept_arg; /* --accept option argument (NOT localized) */ } resolver_option_t; -/* Resolver options for a text conflict */ -/* (opt->code == "" causes a blank line break in help_string()) */ -static const resolver_option_t text_conflict_options[] = +typedef struct client_option_t +{ + const char *code; /* one or two characters */ + const char *label; /* label in prompt (localized) */ + const char *long_desc; /* longer description (localized) */ + svn_client_conflict_option_id_t choice; + /* or ..._undefined if not from libsvn_client */ + const char *accept_arg; /* --accept option argument (NOT localized) */ + svn_boolean_t is_recommended; /* if TRUE, try this option before prompting */ +} client_option_t; + +/* Resolver options for conflict options offered by libsvn_client. */ +static const resolver_option_t builtin_resolver_options[] = +{ + { "r", svn_client_conflict_option_merged_text, + SVN_CL__ACCEPT_WORKING }, + { "mc", svn_client_conflict_option_working_text_where_conflicted, + SVN_CL__ACCEPT_MINE_CONFLICT }, + { "tc", svn_client_conflict_option_incoming_text_where_conflicted, + SVN_CL__ACCEPT_THEIRS_CONFLICT }, + { "mf", svn_client_conflict_option_working_text, + SVN_CL__ACCEPT_MINE_FULL}, + { "tf", svn_client_conflict_option_incoming_text, + SVN_CL__ACCEPT_THEIRS_FULL }, + { "p", svn_client_conflict_option_postpone, + SVN_CL__ACCEPT_POSTPONE }, + + /* This option resolves a tree conflict to the current working copy state. */ + { "r", svn_client_conflict_option_accept_current_wc_state, + SVN_CL__ACCEPT_WORKING }, + + /* These options use the same code since they only occur in + * distinct conflict scenarios. */ + { "u", svn_client_conflict_option_update_move_destination }, + { "u", svn_client_conflict_option_update_any_moved_away_children }, + + /* Options for incoming add vs local add. */ + { "i", svn_client_conflict_option_incoming_add_ignore }, + + /* Options for incoming file add vs local file add upon merge. */ + { "m", svn_client_conflict_option_incoming_added_file_text_merge }, + { "M", svn_client_conflict_option_incoming_added_file_replace_and_merge }, + + /* Options for incoming dir add vs local dir add upon merge. */ + { "m", svn_client_conflict_option_incoming_added_dir_merge }, + { "R", svn_client_conflict_option_incoming_added_dir_replace }, + { "M", svn_client_conflict_option_incoming_added_dir_replace_and_merge }, + + /* Options for incoming delete vs any. */ + { "i", svn_client_conflict_option_incoming_delete_ignore }, + { "a", svn_client_conflict_option_incoming_delete_accept }, + + /* Options for incoming move vs local edit. */ + { "m", svn_client_conflict_option_incoming_move_file_text_merge }, + { "m", svn_client_conflict_option_incoming_move_dir_merge }, + + /* Options for local move vs incoming edit. */ + { "m", svn_client_conflict_option_local_move_file_text_merge }, + + { NULL } +}; + +/* Extra resolver options offered by 'svn' for any conflict. */ +static const client_option_t extra_resolver_options[] = { /* Translators: keep long_desc below 70 characters (wrap with a left - margin of 9 spaces if needed); don't translate the words within square - brackets. */ - { "e", N_("edit file"), N_("change merged file in an editor" - " [edit]"), - svn_wc_conflict_choose_undefined }, - { "df", N_("show diff"), N_("show all changes made to merged file"), - svn_wc_conflict_choose_undefined }, - { "r", N_("mark resolved"), N_("accept merged version of file [working]"), - svn_wc_conflict_choose_merged }, - { "", "", "", svn_wc_conflict_choose_unspecified }, - { "dc", N_("display conflict"), N_("show all conflicts " + margin of 9 spaces if needed) */ + { "q", N_("Quit resolution"), N_("postpone all remaining conflicts"), + svn_client_conflict_option_postpone }, + { NULL } +}; + + +/* Additional resolver options offered by 'svn' for a text conflict. */ +static const client_option_t extra_resolver_options_text[] = +{ + /* Translators: keep long_desc below 70 characters (wrap with a left + margin of 9 spaces if needed) */ + { "e", N_("Edit file"), N_("change merged file in an editor"), + svn_client_conflict_option_undefined, + SVN_CL__ACCEPT_EDIT }, + { "df", N_("Show diff"), N_("show all changes made to merged file"), + svn_client_conflict_option_undefined}, + { "dc", N_("Display conflict"), N_("show all conflicts " "(ignoring merged version)"), - svn_wc_conflict_choose_undefined }, - { "mc", N_("my side of conflict"), N_("accept my version for all conflicts " - "(same) [mine-conflict]"), - svn_wc_conflict_choose_mine_conflict }, - { "tc", N_("their side of conflict"), N_("accept their version for all " - "conflicts (same)" - " [theirs-conflict]"), - svn_wc_conflict_choose_theirs_conflict }, - { "", "", "", svn_wc_conflict_choose_unspecified }, - { "mf", N_("my version"), N_("accept my version of entire file (even " - "non-conflicts) [mine-full]"), - svn_wc_conflict_choose_mine_full }, - { "tf", N_("their version"), N_("accept their version of entire file " - "(same) [theirs-full]"), - svn_wc_conflict_choose_theirs_full }, - { "", "", "", svn_wc_conflict_choose_unspecified }, - { "m", N_("merge"), N_("use merge tool to resolve conflict"), - svn_wc_conflict_choose_undefined }, - { "l", N_("launch tool"), N_("launch external merge tool to resolve " - "conflict [launch]"), - svn_wc_conflict_choose_undefined }, - { "i", N_("internal merge tool"), N_("use built-in merge tool to " + svn_client_conflict_option_undefined }, + { "m", N_("Merge"), N_("use merge tool to resolve conflict"), + svn_client_conflict_option_undefined }, + { "l", N_("Launch tool"), N_("launch external merge tool to resolve " + "conflict"), + svn_client_conflict_option_undefined, + SVN_CL__ACCEPT_LAUNCH }, + { "i", N_("Internal merge tool"), N_("use built-in merge tool to " "resolve conflict"), - svn_wc_conflict_choose_undefined }, - { "p", N_("postpone"), N_("mark the conflict to be resolved later" - " [postpone]"), - svn_wc_conflict_choose_postpone }, - { "q", N_("quit resolution"), N_("postpone all remaining conflicts"), - svn_wc_conflict_choose_postpone }, - { "s", N_("show all options"), N_("show this list (also 'h', '?')"), - svn_wc_conflict_choose_undefined }, + svn_client_conflict_option_undefined }, + { "s", N_("Show all options"), N_("show this list (also 'h', '?')"), + svn_client_conflict_option_undefined }, { NULL } }; -/* Resolver options for a binary file conflict. */ -static const resolver_option_t binary_conflict_options[] = +/* Additional resolver options offered by 'svn' for a property conflict. */ +static const client_option_t extra_resolver_options_prop[] = { /* Translators: keep long_desc below 70 characters (wrap with a left - margin of 9 spaces if needed); don't translate the words within square - brackets. */ - { "r", N_("mark resolved"), N_("accept the working copy version of file " - " [working]"), - svn_wc_conflict_choose_merged }, - { "tf", N_("their version"), N_("accept the incoming version of file " - " [theirs-full]"), - svn_wc_conflict_choose_theirs_full }, - { "p", N_("postpone"), N_("mark the conflict to be resolved later " - " [postpone]"), - svn_wc_conflict_choose_postpone }, - { "q", N_("quit resolution"), N_("postpone all remaining conflicts"), - svn_wc_conflict_choose_postpone }, - { "s", N_("show all options"), N_("show this list (also 'h', '?')"), - svn_wc_conflict_choose_undefined }, + margin of 9 spaces if needed) */ + { "dc", N_("Display conflict"), N_("show conflicts in this property"), + svn_client_conflict_option_undefined }, + { "e", N_("Edit property"), N_("change merged property value in an " + "editor"), + svn_client_conflict_option_undefined, + SVN_CL__ACCEPT_EDIT }, + { "h", N_("Help"), N_("show this help (also '?')"), + svn_client_conflict_option_undefined }, { NULL } }; -/* Resolver options for a property conflict */ -static const resolver_option_t prop_conflict_options[] = +/* Additional resolver options offered by 'svn' for a tree conflict. */ +static const client_option_t extra_resolver_options_tree[] = { - { "mf", N_("my version"), N_("accept my version of entire property (even " - "non-conflicts) [mine-full]"), - svn_wc_conflict_choose_mine_full }, - { "tf", N_("their version"), N_("accept their version of entire property " - "(same) [theirs-full]"), - svn_wc_conflict_choose_theirs_full }, - { "dc", N_("display conflict"), N_("show conflicts in this property"), - svn_wc_conflict_choose_undefined }, - { "e", N_("edit property"), N_("change merged property value in an editor" - " [edit]"), - svn_wc_conflict_choose_undefined }, - { "r", N_("mark resolved"), N_("accept edited version of property"), - svn_wc_conflict_choose_merged }, - { "p", N_("postpone"), N_("mark the conflict to be resolved later" - " [postpone]"), - svn_wc_conflict_choose_postpone }, - { "q", N_("quit resolution"), N_("postpone all remaining conflicts"), - svn_wc_conflict_choose_postpone }, - { "h", N_("help"), N_("show this help (also '?')"), - svn_wc_conflict_choose_undefined }, + /* Translators: keep long_desc below 70 characters (wrap with a left + margin of 9 spaces if needed) */ + { "d", N_("Set repository move destination path"), + N_("pick repository move target from list of possible targets"), + svn_client_conflict_option_undefined }, + + { "w", N_("Set working copy move destination path"), + N_("pick working copy move target from list of possible targets"), + svn_client_conflict_option_undefined }, + + { "h", N_("Help"), N_("show this help (also '?')"), + svn_client_conflict_option_undefined }, + { NULL } }; -/* Resolver options for a tree conflict */ -static const resolver_option_t tree_conflict_options[] = -{ - { "r", N_("mark resolved"), N_("accept current working copy state"), - svn_wc_conflict_choose_merged }, - { "p", N_("postpone"), N_("resolve the conflict later [postpone]"), - svn_wc_conflict_choose_postpone }, - { "q", N_("quit resolution"), N_("postpone all remaining conflicts"), - svn_wc_conflict_choose_postpone }, - { "h", N_("help"), N_("show this help (also '?')"), - svn_wc_conflict_choose_undefined }, - { NULL } -}; - -static const resolver_option_t tree_conflict_options_update_moved_away[] = -{ - { "mc", N_("apply update to move destination (recommended)"), - N_("apply incoming update to move destination" - " [mine-conflict]"), - svn_wc_conflict_choose_mine_conflict }, - { "p", N_("postpone"), N_("resolve the conflict later [postpone]"), - svn_wc_conflict_choose_postpone }, - { "q", N_("quit resolution"), N_("postpone all remaining conflicts"), - svn_wc_conflict_choose_postpone }, - { "h", N_("help"), N_("show this help (also '?')"), - svn_wc_conflict_choose_undefined }, - { NULL } -}; - -static const resolver_option_t tree_conflict_options_update_edit_deleted_dir[] = -{ - { "mc", N_("prepare for updating moved-away children, if any (recommended)"), - N_("allow updating moved-away children " - "with 'svn resolve' [mine-conflict]"), - svn_wc_conflict_choose_mine_conflict }, - { "p", N_("postpone"), N_("resolve the conflict later [postpone]"), - svn_wc_conflict_choose_postpone }, - { "q", N_("quit resolution"), N_("postpone all remaining conflicts"), - svn_wc_conflict_choose_postpone }, - { "h", N_("help"), N_("show this help (also '?')"), - svn_wc_conflict_choose_undefined }, - { NULL } -}; /* Return a pointer to the option description in OPTIONS matching the * one- or two-character OPTION_CODE. Return NULL if not found. */ -static const resolver_option_t * -find_option(const resolver_option_t *options, +static const client_option_t * +find_option(const apr_array_header_t *options, const char *option_code) { - const resolver_option_t *opt; + int i; - for (opt = options; opt->code; opt++) + for (i = 0; i < options->nelts; i++) { + const client_option_t *opt = APR_ARRAY_IDX(options, i, client_option_t *); + /* Ignore code "" (blank lines) which is not a valid answer. */ if (opt->code[0] && strcmp(opt->code, option_code) == 0) return opt; @@ -573,10 +537,76 @@ find_option(const resolver_option_t *options, return NULL; } +/* Find the first recommended option in OPTIONS. */ +static const client_option_t * +find_recommended_option(const apr_array_header_t *options) +{ + int i; + + for (i = 0; i < options->nelts; i++) + { + const client_option_t *opt = APR_ARRAY_IDX(options, i, client_option_t *); + + /* Ignore code "" (blank lines) which is not a valid answer. */ + if (opt->code[0] && opt->is_recommended) + return opt; + } + return NULL; +} + +/* Return a pointer to the client_option_t in OPTIONS matching the ID of + * conflict option BUILTIN_OPTION. @a out will be set to NULL if the + * option was not found. */ +static svn_error_t * +find_option_by_builtin(client_option_t **out, + svn_client_conflict_t *conflict, + const resolver_option_t *options, + svn_client_conflict_option_t *builtin_option, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + const resolver_option_t *opt; + svn_client_conflict_option_id_t id; + svn_client_conflict_option_id_t recommended_id; + + id = svn_client_conflict_option_get_id(builtin_option); + recommended_id = svn_client_conflict_get_recommended_option_id(conflict); + + for (opt = options; opt->code; opt++) + { + if (opt->choice == id) + { + client_option_t *client_opt; + + client_opt = apr_pcalloc(result_pool, sizeof(*client_opt)); + client_opt->choice = id; + client_opt->code = opt->code; + client_opt->label = svn_client_conflict_option_get_label( + builtin_option, + result_pool); + client_opt->long_desc = svn_client_conflict_option_get_description( + builtin_option, + result_pool); + client_opt->accept_arg = opt->accept_arg; + client_opt->is_recommended = + (recommended_id != svn_client_conflict_option_unspecified && + id == recommended_id); + + *out = client_opt; + + return SVN_NO_ERROR; + } + } + + *out = NULL; + + return SVN_NO_ERROR; +} + /* Return a prompt string listing the options OPTIONS. If OPTION_CODES is * non-null, select only the options whose codes are mentioned in it. */ static const char * -prompt_string(const resolver_option_t *options, +prompt_string(const apr_array_header_t *options, const char *const *option_codes, apr_pool_t *pool) { @@ -585,10 +615,11 @@ prompt_string(const resolver_option_t *options, const char *line_sep = apr_psprintf(pool, "\n%*s", left_margin, ""); int this_line_len = left_margin; svn_boolean_t first = TRUE; + int i = 0; while (1) { - const resolver_option_t *opt; + const client_option_t *opt; const char *s; int slen; @@ -597,18 +628,21 @@ prompt_string(const resolver_option_t *options, if (! *option_codes) break; opt = find_option(options, *option_codes++); + if (opt == NULL) + continue; } else { - opt = options++; - if (! opt->code) + if (i >= options->nelts) break; + opt = APR_ARRAY_IDX(options, i, client_option_t *); + i++; } if (! first) result = apr_pstrcat(pool, result, ",", SVN_VA_NULL); - s = apr_psprintf(pool, _(" (%s) %s"), - opt->code, _(opt->short_desc)); + s = apr_psprintf(pool, " (%s) %s", opt->code, + opt->label ? opt->label : opt->long_desc); slen = svn_utf_cstring_utf8_width(s); /* Break the line if adding the next option would make it too long */ if (this_line_len + slen > MAX_PROMPT_WIDTH) @@ -624,33 +658,48 @@ prompt_string(const resolver_option_t *options, } /* Return a help string listing the OPTIONS. */ -static const char * -help_string(const resolver_option_t *options, +static svn_error_t * +help_string(const char **result, + const apr_array_header_t *options, apr_pool_t *pool) { - const char *result = ""; - const resolver_option_t *opt; + apr_pool_t *iterpool; + int i; - for (opt = options; opt->code; opt++) + *result = ""; + iterpool = svn_pool_create(pool); + for (i = 0; i < options->nelts; i++) { + const client_option_t *opt; + svn_pool_clear(iterpool); + + opt = APR_ARRAY_IDX(options, i, + client_option_t *); + /* Append a line describing OPT, or a blank line if its code is "". */ if (opt->code[0]) { const char *s = apr_psprintf(pool, " (%s)", opt->code); - result = apr_psprintf(pool, "%s%-6s - %s\n", - result, s, _(opt->long_desc)); + if (opt->accept_arg) + *result = apr_psprintf(pool, "%s%-6s - %s [%s]\n", + *result, s, opt->long_desc, + opt->accept_arg); + else + *result = apr_psprintf(pool, "%s%-6s - %s\n", *result, s, + opt->long_desc); } else { - result = apr_pstrcat(pool, result, "\n", SVN_VA_NULL); + *result = apr_pstrcat(pool, *result, "\n", SVN_VA_NULL); } } - result = apr_pstrcat(pool, result, + svn_pool_destroy(iterpool); + *result = apr_pstrcat(pool, *result, _("Words in square brackets are the corresponding " "--accept option arguments.\n"), SVN_VA_NULL); - return result; + return SVN_NO_ERROR; } /* Prompt the user with CONFLICT_OPTIONS, restricted to the options listed @@ -659,12 +708,14 @@ help_string(const resolver_option_t *options, * NULL if the answer was not one of them. * * If the answer is the (globally recognized) 'help' option, then display - * the help (on stderr) and return with *OPT == NULL. + * CONFLICT_DESCRIPTION (if not NULL) and help (on stderr) and return with + * *OPT == NULL. */ static svn_error_t * -prompt_user(const resolver_option_t **opt, - const resolver_option_t *conflict_options, +prompt_user(const client_option_t **opt, + const apr_array_header_t *conflict_options, const char *const *options_to_show, + const char *conflict_description, void *prompt_baton, apr_pool_t *scratch_pool) { @@ -675,9 +726,13 @@ prompt_user(const resolver_option_t **opt, SVN_ERR(svn_cmdline_prompt_user2(&answer, prompt, prompt_baton, scratch_pool)); if (strcmp(answer, "h") == 0 || strcmp(answer, "?") == 0) { - SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, "\n%s\n", - help_string(conflict_options, - scratch_pool))); + const char *helpstr; + + if (conflict_description) + SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, "\n%s\n", + conflict_description)); + SVN_ERR(help_string(&helpstr, conflict_options, scratch_pool)); + SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, "\n%s\n", helpstr)); *opt = NULL; } else @@ -692,41 +747,174 @@ prompt_user(const resolver_option_t **opt, return SVN_NO_ERROR; } -/* Ask the user what to do about the text conflict described by DESC. - * Return the answer in RESULT. B is the conflict baton for this - * conflict resolution session. +/* Set *OPTIONS to an array of resolution options for CONFLICT. */ +static svn_error_t * +build_text_conflict_options(apr_array_header_t **options, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + svn_boolean_t is_binary, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + const client_option_t *o; + apr_array_header_t *builtin_options; + int nopt; + int i; + apr_pool_t *iterpool; + + SVN_ERR(svn_client_conflict_text_get_resolution_options(&builtin_options, + conflict, ctx, + scratch_pool, + scratch_pool)); + nopt = builtin_options->nelts + ARRAY_LEN(extra_resolver_options); + if (!is_binary) + nopt += ARRAY_LEN(extra_resolver_options_text); + *options = apr_array_make(result_pool, nopt, sizeof(client_option_t *)); + + iterpool = svn_pool_create(scratch_pool); + for (i = 0; i < builtin_options->nelts; i++) + { + client_option_t *opt; + svn_client_conflict_option_t *builtin_option; + + svn_pool_clear(iterpool); + builtin_option = APR_ARRAY_IDX(builtin_options, i, + svn_client_conflict_option_t *); + SVN_ERR(find_option_by_builtin(&opt, conflict, + builtin_resolver_options, + builtin_option, + result_pool, + iterpool)); + if (opt == NULL) + continue; /* ### unknown option -- assign a code dynamically? */ + + APR_ARRAY_PUSH(*options, client_option_t *) = opt; + } + + for (o = extra_resolver_options; o->code; o++) + APR_ARRAY_PUSH(*options, const client_option_t *) = o; + if (!is_binary) + { + for (o = extra_resolver_options_text; o->code; o++) + APR_ARRAY_PUSH(*options, const client_option_t *) = o; + } + + svn_pool_destroy(iterpool); + + return SVN_NO_ERROR; +} + +/* Mark CONFLICT as resolved to resolution option with ID OPTION_ID. + * If TEXT_CONFLICTED is true, resolve text conflicts described by CONFLICT. + * IF PROPNAME is not NULL, mark the conflict in the specified property as + * resolved. If PROPNAME is "", mark all property conflicts described by + * CONFLICT as resolved. + * If TREE_CONFLICTED is true, resolve tree conflicts described by CONFLICT. + * Adjust CONFLICT_STATS as necessary (PATH_PREFIX is needed for this step). */ +static svn_error_t * +mark_conflict_resolved(svn_client_conflict_t *conflict, + svn_client_conflict_option_id_t option_id, + svn_boolean_t text_conflicted, + const char *propname, + svn_boolean_t tree_conflicted, + const char *path_prefix, + svn_cl__conflict_stats_t *conflict_stats, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + const char *local_relpath + = svn_cl__local_style_skip_ancestor( + path_prefix, svn_client_conflict_get_local_abspath(conflict), + scratch_pool); + + if (text_conflicted) + { + SVN_ERR(svn_client_conflict_text_resolve_by_id(conflict, option_id, + ctx, scratch_pool)); + svn_cl__conflict_stats_resolved(conflict_stats, local_relpath, + svn_wc_conflict_kind_text); + } + + if (propname) + { + SVN_ERR(svn_client_conflict_prop_resolve_by_id(conflict, propname, + option_id, ctx, + scratch_pool)); + svn_cl__conflict_stats_resolved(conflict_stats, local_relpath, + svn_wc_conflict_kind_property); + } + + if (tree_conflicted) + { + SVN_ERR(svn_client_conflict_tree_resolve_by_id(conflict, option_id, + ctx, scratch_pool)); + svn_cl__conflict_stats_resolved(conflict_stats, local_relpath, + svn_wc_conflict_kind_tree); + } + + return SVN_NO_ERROR; +} + +/* Ask the user what to do about the text conflict described by CONFLICT + * and either resolve the conflict accordingly or postpone resolution. * SCRATCH_POOL is used for temporary allocations. */ static svn_error_t * -handle_text_conflict(svn_wc_conflict_result_t *result, - const svn_wc_conflict_description2_t *desc, - svn_cl__interactive_conflict_baton_t *b, +handle_text_conflict(svn_boolean_t *resolved, + svn_boolean_t *postponed, + svn_boolean_t *quit, + svn_boolean_t *printed_description, + svn_client_conflict_t *conflict, + const char *path_prefix, + svn_cmdline_prompt_baton_t *pb, + const char *editor_cmd, + apr_hash_t *config, + svn_cl__conflict_stats_t *conflict_stats, + svn_client_ctx_t *ctx, apr_pool_t *scratch_pool) { apr_pool_t *iterpool = svn_pool_create(scratch_pool); svn_boolean_t diff_allowed = FALSE; - /* Have they done something that might have affected the merged - file (so that we need to save a .edited copy by setting the - result->save_merge flag)? */ + /* Have they done something that might have affected the merged file? */ svn_boolean_t performed_edit = FALSE; /* Have they done *something* (edit, look at diff, etc) to give them a rational basis for choosing (r)esolved? */ svn_boolean_t knows_something = FALSE; const char *local_relpath; + const char *local_abspath = svn_client_conflict_get_local_abspath(conflict); + const char *mime_type = svn_client_conflict_text_get_mime_type(conflict); + svn_boolean_t is_binary = mime_type ? svn_mime_type_is_binary(mime_type) + : FALSE; + const char *base_abspath; + const char *my_abspath; + const char *their_abspath; + const char *merged_abspath = svn_client_conflict_get_local_abspath(conflict); + apr_array_header_t *text_conflict_options; + svn_client_conflict_option_id_t option_id; - SVN_ERR_ASSERT(desc->kind == svn_wc_conflict_kind_text); + option_id = svn_client_conflict_option_unspecified; - local_relpath = svn_cl__local_style_skip_ancestor(b->path_prefix, - desc->local_abspath, - scratch_pool);; + SVN_ERR(svn_client_conflict_text_get_contents(NULL, &my_abspath, + &base_abspath, &their_abspath, + conflict, scratch_pool, + scratch_pool)); - if (desc->is_binary) - SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, - _("Conflict discovered in binary file '%s'.\n"), - local_relpath)); - else - SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, - _("Conflict discovered in file '%s'.\n"), - local_relpath)); + local_relpath = svn_cl__local_style_skip_ancestor(path_prefix, + local_abspath, + scratch_pool); + + if (!*printed_description) + { + if (is_binary) + SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, + _("Merge conflict discovered in binary " + "file '%s'.\n"), + local_relpath)); + else + SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, + _("Merge conflict discovered in file '%s'.\n"), + local_relpath)); + *printed_description = TRUE; + } /* ### TODO This whole feature availability check is grossly outdated. DIFF_ALLOWED needs either to be redefined or to go away. @@ -736,21 +924,18 @@ handle_text_conflict(svn_wc_conflict_result_t *result, markers to the user (this is the typical 3-way merge scenario), or if no base is available, we can show a diff between mine and theirs. */ - if (!desc->is_binary && - ((desc->merged_file && desc->base_abspath) - || (!desc->base_abspath && desc->my_abspath && desc->their_abspath))) + if (!is_binary && + ((merged_abspath && base_abspath) + || (!base_abspath && my_abspath && their_abspath))) diff_allowed = TRUE; + SVN_ERR(build_text_conflict_options(&text_conflict_options, conflict, ctx, + is_binary, scratch_pool, scratch_pool)); while (TRUE) { - const char *options[1 + MAX_ARRAY_LEN(binary_conflict_options, - text_conflict_options)]; - - const resolver_option_t *conflict_options = desc->is_binary - ? binary_conflict_options - : text_conflict_options; - const char **next_option = options; - const resolver_option_t *opt; + const char *suggested_options[9]; /* filled statically below */ + const char **next_option = suggested_options; + const client_option_t *opt; svn_pool_clear(iterpool); @@ -758,30 +943,26 @@ handle_text_conflict(svn_wc_conflict_result_t *result, if (diff_allowed) { /* We need one more path for this feature. */ - if (desc->my_abspath) + if (my_abspath) *next_option++ = "df"; *next_option++ = "e"; /* We need one more path for this feature. */ - if (desc->my_abspath) + if (my_abspath) *next_option++ = "m"; if (knows_something) *next_option++ = "r"; - - *next_option++ = "mc"; - *next_option++ = "tc"; } else { - if (knows_something || desc->is_binary) + if (knows_something || is_binary) *next_option++ = "r"; - /* The 'mine-full' option selects the ".mine" file so only offer - * it if that file exists. It does not exist for binary files, - * for example (questionable historical behaviour since 1.0). */ - if (desc->my_abspath) + /* The 'mine-full' option selects the ".mine" file for texts or + * the current working directory file for binary files. */ + if (my_abspath || is_binary) *next_option++ = "mf"; *next_option++ = "tf"; @@ -789,26 +970,28 @@ handle_text_conflict(svn_wc_conflict_result_t *result, *next_option++ = "s"; *next_option++ = NULL; - SVN_ERR(prompt_user(&opt, conflict_options, options, b->pb, iterpool)); + SVN_ERR(prompt_user(&opt, text_conflict_options, suggested_options, + NULL, pb, iterpool)); if (! opt) continue; if (strcmp(opt->code, "q") == 0) { - result->choice = opt->choice; - b->accept_which = svn_cl__accept_postpone; - b->quit = TRUE; + option_id = opt->choice; + *quit = TRUE; break; } else if (strcmp(opt->code, "s") == 0) { + const char *helpstr; + + SVN_ERR(help_string(&helpstr, text_conflict_options, iterpool)); SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, "\n%s\n", - help_string(conflict_options, - iterpool))); + helpstr)); } else if (strcmp(opt->code, "dc") == 0) { - if (desc->is_binary) + if (is_binary) { SVN_ERR(svn_cmdline_fprintf(stderr, iterpool, _("Invalid option; cannot " @@ -816,24 +999,23 @@ handle_text_conflict(svn_wc_conflict_result_t *result, "binary file.\n\n"))); continue; } - else if (! (desc->my_abspath && desc->base_abspath && - desc->their_abspath)) + else if (! (my_abspath && base_abspath && their_abspath)) { SVN_ERR(svn_cmdline_fprintf(stderr, iterpool, _("Invalid option; original " "files not available.\n\n"))); continue; } - SVN_ERR(show_conflicts(desc, - b->pb->cancel_func, - b->pb->cancel_baton, + SVN_ERR(show_conflicts(conflict, + pb->cancel_func, + pb->cancel_baton, iterpool)); knows_something = TRUE; } else if (strcmp(opt->code, "df") == 0) { /* Re-check preconditions. */ - if (! diff_allowed || ! desc->my_abspath) + if (! diff_allowed || ! my_abspath) { SVN_ERR(svn_cmdline_fprintf(stderr, iterpool, _("Invalid option; there's no " @@ -841,14 +1023,15 @@ handle_text_conflict(svn_wc_conflict_result_t *result, continue; } - SVN_ERR(show_diff(desc, b->path_prefix, - b->pb->cancel_func, b->pb->cancel_baton, + SVN_ERR(show_diff(conflict, merged_abspath, path_prefix, + pb->cancel_func, pb->cancel_baton, iterpool)); knows_something = TRUE; } else if (strcmp(opt->code, "e") == 0 || strcmp(opt->code, ":-E") == 0) { - SVN_ERR(open_editor(&performed_edit, desc->merged_file, b, iterpool)); + SVN_ERR(open_editor(&performed_edit, merged_abspath, editor_cmd, + config, iterpool)); if (performed_edit) knows_something = TRUE; } @@ -858,7 +1041,7 @@ handle_text_conflict(svn_wc_conflict_result_t *result, svn_error_t *err; /* Re-check preconditions. */ - if (! desc->my_abspath) + if (! my_abspath) { SVN_ERR(svn_cmdline_fprintf(stderr, iterpool, _("Invalid option; there's no " @@ -866,11 +1049,11 @@ handle_text_conflict(svn_wc_conflict_result_t *result, continue; } - err = svn_cl__merge_file_externally(desc->base_abspath, - desc->their_abspath, - desc->my_abspath, - desc->merged_file, - desc->local_abspath, b->config, + err = svn_cl__merge_file_externally(base_abspath, + their_abspath, + my_abspath, + merged_abspath, + local_abspath, config, NULL, iterpool); if (err) { @@ -881,16 +1064,16 @@ handle_text_conflict(svn_wc_conflict_result_t *result, /* Try the internal merge tool. */ svn_error_clear(err); SVN_ERR(svn_cl__merge_file(&remains_in_conflict, - desc->base_abspath, - desc->their_abspath, - desc->my_abspath, - desc->merged_file, - desc->local_abspath, - b->path_prefix, - b->editor_cmd, - b->config, - b->pb->cancel_func, - b->pb->cancel_baton, + base_abspath, + their_abspath, + my_abspath, + merged_abspath, + local_abspath, + path_prefix, + editor_cmd, + config, + pb->cancel_func, + pb->cancel_baton, iterpool)); knows_something = !remains_in_conflict; } @@ -922,21 +1105,20 @@ handle_text_conflict(svn_wc_conflict_result_t *result, { /* ### This check should be earlier as it's nasty to offer an option * and then when the user chooses it say 'Invalid option'. */ - /* ### 'merged_file' shouldn't be necessary *before* we launch the + /* ### 'merged_abspath' shouldn't be necessary *before* we launch the * resolver: it should be the *result* of doing so. */ - if (desc->base_abspath && desc->their_abspath && - desc->my_abspath && desc->merged_file) + if (base_abspath && their_abspath && my_abspath && merged_abspath) { svn_error_t *err; char buf[1024]; const char *message; - err = svn_cl__merge_file_externally(desc->base_abspath, - desc->their_abspath, - desc->my_abspath, - desc->merged_file, - desc->local_abspath, - b->config, NULL, iterpool); + err = svn_cl__merge_file_externally(base_abspath, + their_abspath, + my_abspath, + merged_abspath, + local_abspath, + config, NULL, iterpool); if (err && (err->apr_err == SVN_ERR_CL_NO_EXTERNAL_MERGE_TOOL || err->apr_err == SVN_ERR_EXTERNAL_PROGRAM)) { @@ -962,26 +1144,26 @@ handle_text_conflict(svn_wc_conflict_result_t *result, svn_boolean_t remains_in_conflict = TRUE; SVN_ERR(svn_cl__merge_file(&remains_in_conflict, - desc->base_abspath, - desc->their_abspath, - desc->my_abspath, - desc->merged_file, - desc->local_abspath, - b->path_prefix, - b->editor_cmd, - b->config, - b->pb->cancel_func, - b->pb->cancel_baton, + base_abspath, + their_abspath, + my_abspath, + merged_abspath, + local_abspath, + path_prefix, + editor_cmd, + config, + pb->cancel_func, + pb->cancel_baton, iterpool)); if (!remains_in_conflict) knows_something = TRUE; } - else if (opt->choice != svn_wc_conflict_choose_undefined) + else if (opt->choice != svn_client_conflict_option_undefined) { - if ((opt->choice == svn_wc_conflict_choose_mine_conflict - || opt->choice == svn_wc_conflict_choose_theirs_conflict) - && desc->is_binary) + if ((opt->choice == svn_client_conflict_option_working_text_where_conflicted + || opt->choice == svn_client_conflict_option_incoming_text_where_conflicted) + && is_binary) { SVN_ERR(svn_cmdline_fprintf(stderr, iterpool, _("Invalid option; cannot choose " @@ -993,7 +1175,7 @@ handle_text_conflict(svn_wc_conflict_result_t *result, /* We only allow the user accept the merged version of the file if they've edited it, or at least looked at the diff. */ - if (opt->choice == svn_wc_conflict_choose_merged + if (opt->choice == svn_client_conflict_option_merged_text && ! knows_something && diff_allowed) { SVN_ERR(svn_cmdline_fprintf( @@ -1003,59 +1185,137 @@ handle_text_conflict(svn_wc_conflict_result_t *result, continue; } - result->choice = opt->choice; - if (performed_edit) - result->save_merged = TRUE; + option_id = opt->choice; break; } } svn_pool_destroy(iterpool); + if (option_id != svn_client_conflict_option_unspecified && + option_id != svn_client_conflict_option_postpone) + { + SVN_ERR(mark_conflict_resolved(conflict, option_id, + TRUE, NULL, FALSE, + path_prefix, conflict_stats, + ctx, scratch_pool)); + *resolved = TRUE; + } + else + { + *resolved = FALSE; + *postponed = (option_id == svn_client_conflict_option_postpone); + } + return SVN_NO_ERROR; } -/* Ask the user what to do about the property conflict described by DESC. - * Return the answer in RESULT. B is the conflict baton for this - * conflict resolution session. +/* Set *OPTIONS to an array of resolution options for CONFLICT. */ +static svn_error_t * +build_prop_conflict_options(apr_array_header_t **options, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + const client_option_t *o; + apr_array_header_t *builtin_options; + int nopt; + int i; + apr_pool_t *iterpool; + + SVN_ERR(svn_client_conflict_prop_get_resolution_options(&builtin_options, + conflict, ctx, + scratch_pool, + scratch_pool)); + nopt = builtin_options->nelts + ARRAY_LEN(extra_resolver_options) + + ARRAY_LEN(extra_resolver_options_prop); + *options = apr_array_make(result_pool, nopt, sizeof(client_option_t *)); + + iterpool = svn_pool_create(scratch_pool); + for (i = 0; i < builtin_options->nelts; i++) + { + client_option_t *opt; + svn_client_conflict_option_t *builtin_option; + + svn_pool_clear(iterpool); + builtin_option = APR_ARRAY_IDX(builtin_options, i, + svn_client_conflict_option_t *); + SVN_ERR(find_option_by_builtin(&opt, conflict, + builtin_resolver_options, + builtin_option, + result_pool, + iterpool)); + if (opt == NULL) + continue; /* ### unknown option -- assign a code dynamically? */ + + APR_ARRAY_PUSH(*options, client_option_t *) = opt; + } + + svn_pool_destroy(iterpool); + + for (o = extra_resolver_options; o->code; o++) + APR_ARRAY_PUSH(*options, const client_option_t *) = o; + for (o = extra_resolver_options_prop; o->code; o++) + APR_ARRAY_PUSH(*options, const client_option_t *) = o; + + return SVN_NO_ERROR; +} + +/* Ask the user what to do about the conflicted property PROPNAME described + * by CONFLICT and return the corresponding resolution option in *OPTION. * SCRATCH_POOL is used for temporary allocations. */ static svn_error_t * -handle_prop_conflict(svn_wc_conflict_result_t *result, - const svn_wc_conflict_description2_t *desc, - svn_cl__interactive_conflict_baton_t *b, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) +handle_one_prop_conflict(svn_client_conflict_option_t **option, + svn_boolean_t *quit, + const char *path_prefix, + svn_cmdline_prompt_baton_t *pb, + const char *editor_cmd, + apr_hash_t *config, + svn_client_conflict_t *conflict, + const char *propname, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { apr_pool_t *iterpool; - const char *message; - const char *merged_file_path = NULL; + const char *description; + const svn_string_t *merged_propval = NULL; svn_boolean_t resolved_allowed = FALSE; + const svn_string_t *base_propval; + const svn_string_t *my_propval; + const svn_string_t *their_propval; + apr_array_header_t *resolution_options; + apr_array_header_t *prop_conflict_options; - /* ### Work around a historical bug in the provider: the path to the - * conflict description file was put in the 'theirs' field, and - * 'theirs' was put in the 'merged' field. */ - ((svn_wc_conflict_description2_t *)desc)->their_abspath = desc->merged_file; - ((svn_wc_conflict_description2_t *)desc)->merged_file = NULL; - - SVN_ERR_ASSERT(desc->kind == svn_wc_conflict_kind_property); + SVN_ERR(svn_client_conflict_prop_get_propvals(NULL, &my_propval, + &base_propval, &their_propval, + conflict, propname, + scratch_pool)); SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, _("Conflict for property '%s' discovered" " on '%s'.\n"), - desc->property_name, + propname, svn_cl__local_style_skip_ancestor( - b->path_prefix, desc->local_abspath, + path_prefix, + svn_client_conflict_get_local_abspath(conflict), scratch_pool))); + SVN_ERR(svn_client_conflict_prop_get_description(&description, conflict, + scratch_pool, scratch_pool)); + SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, "%s\n", description)); - SVN_ERR(svn_cl__get_human_readable_prop_conflict_description(&message, desc, - scratch_pool)); - SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, "%s\n", message)); - + SVN_ERR(svn_client_conflict_prop_get_resolution_options(&resolution_options, + conflict, ctx, + result_pool, + scratch_pool)); + SVN_ERR(build_prop_conflict_options(&prop_conflict_options, conflict, ctx, + scratch_pool, scratch_pool)); iterpool = svn_pool_create(scratch_pool); while (TRUE) { - const resolver_option_t *opt; - const char *options[ARRAY_LEN(prop_conflict_options)]; - const char **next_option = options; + const client_option_t *opt; + const char *suggested_options[9]; /* filled statically below */ + const char **next_option = suggested_options; *next_option++ = "p"; *next_option++ = "mf"; @@ -1070,29 +1330,32 @@ handle_prop_conflict(svn_wc_conflict_result_t *result, svn_pool_clear(iterpool); - SVN_ERR(prompt_user(&opt, prop_conflict_options, options, b->pb, - iterpool)); + SVN_ERR(prompt_user(&opt, prop_conflict_options, suggested_options, + NULL, pb, iterpool)); if (! opt) continue; if (strcmp(opt->code, "q") == 0) { - result->choice = opt->choice; - b->accept_which = svn_cl__accept_postpone; - b->quit = TRUE; + *option = svn_client_conflict_option_find_by_id(resolution_options, + opt->choice); + *quit = TRUE; break; } else if (strcmp(opt->code, "dc") == 0) { - SVN_ERR(show_prop_conflict(desc, merged_file_path, - b->pb->cancel_func, b->pb->cancel_baton, + SVN_ERR(show_prop_conflict(base_propval, my_propval, their_propval, + merged_propval, + pb->cancel_func, pb->cancel_baton, scratch_pool)); } else if (strcmp(opt->code, "e") == 0) { - SVN_ERR(edit_prop_conflict(&merged_file_path, desc, b, + SVN_ERR(edit_prop_conflict(&merged_propval, + base_propval, my_propval, their_propval, + editor_cmd, config, pb, result_pool, scratch_pool)); - resolved_allowed = (merged_file_path != NULL); + resolved_allowed = (merged_propval != NULL); } else if (strcmp(opt->code, "r") == 0) { @@ -1104,13 +1367,17 @@ handle_prop_conflict(svn_wc_conflict_result_t *result, continue; } - result->merged_file = merged_file_path; - result->choice = svn_wc_conflict_choose_merged; + *option = svn_client_conflict_option_find_by_id( + resolution_options, + svn_client_conflict_option_merged_text); + svn_client_conflict_option_set_merged_propval(*option, + merged_propval); break; } - else if (opt->choice != svn_wc_conflict_choose_undefined) + else if (opt->choice != svn_client_conflict_option_undefined) { - result->choice = opt->choice; + *option = svn_client_conflict_option_find_by_id(resolution_options, + opt->choice); break; } } @@ -1119,252 +1386,854 @@ handle_prop_conflict(svn_wc_conflict_result_t *result, return SVN_NO_ERROR; } -/* Ask the user what to do about the tree conflict described by DESC. - * Return the answer in RESULT. B is the conflict baton for this - * conflict resolution session. +/* Ask the user what to do about the property conflicts described by CONFLICT + * and either resolve them accordingly or postpone resolution. * SCRATCH_POOL is used for temporary allocations. */ static svn_error_t * -handle_tree_conflict(svn_wc_conflict_result_t *result, - const svn_wc_conflict_description2_t *desc, - svn_cl__interactive_conflict_baton_t *b, - apr_pool_t *scratch_pool) +handle_prop_conflicts(svn_boolean_t *resolved, + svn_boolean_t *postponed, + svn_boolean_t *quit, + const svn_string_t **merged_value, + const char *path_prefix, + svn_cmdline_prompt_baton_t *pb, + const char *editor_cmd, + apr_hash_t *config, + svn_client_conflict_t *conflict, + svn_cl__conflict_stats_t *conflict_stats, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { - const char *readable_desc; + apr_array_header_t *props_conflicted; + apr_pool_t *iterpool; + int i; + int nresolved = 0; + + SVN_ERR(svn_client_conflict_get_conflicted(NULL, &props_conflicted, NULL, + conflict, scratch_pool, + scratch_pool)); + + iterpool = svn_pool_create(scratch_pool); + for (i = 0; i < props_conflicted->nelts; i++) + { + const char *propname = APR_ARRAY_IDX(props_conflicted, i, const char *); + svn_client_conflict_option_t *option; + svn_client_conflict_option_id_t option_id; + + svn_pool_clear(iterpool); + + SVN_ERR(handle_one_prop_conflict(&option, quit, path_prefix, pb, + editor_cmd, config, conflict, propname, + ctx, + iterpool, iterpool)); + option_id = svn_client_conflict_option_get_id(option); + + if (option_id != svn_client_conflict_option_unspecified && + option_id != svn_client_conflict_option_postpone) + { + const char *local_relpath = + svn_cl__local_style_skip_ancestor( + path_prefix, svn_client_conflict_get_local_abspath(conflict), + iterpool); + + SVN_ERR(svn_client_conflict_prop_resolve(conflict, propname, option, + ctx, iterpool)); + svn_cl__conflict_stats_resolved(conflict_stats, local_relpath, + svn_wc_conflict_kind_property); + nresolved++; + *postponed = FALSE; + } + else + *postponed = (option_id == svn_client_conflict_option_postpone); + + if (*quit) + break; + } + svn_pool_destroy(iterpool); + + /* Indicate success if no property conflicts remain. */ + *resolved = (nresolved == props_conflicted->nelts); + + return SVN_NO_ERROR; +} + +/* Set *OPTIONS to an array of resolution options for CONFLICT. */ +static svn_error_t * +build_tree_conflict_options( + apr_array_header_t **options, + apr_array_header_t **possible_moved_to_repos_relpaths, + apr_array_header_t **possible_moved_to_abspaths, + svn_boolean_t *all_options_are_dumb, + svn_client_conflict_t *conflict, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + const client_option_t *o; + apr_array_header_t *builtin_options; + int nopt; + int i; + int next_unknown_option_code = 1; apr_pool_t *iterpool; - SVN_ERR(svn_cl__get_human_readable_tree_conflict_description( - &readable_desc, desc, scratch_pool)); - SVN_ERR(svn_cmdline_fprintf( - stderr, scratch_pool, - _("Tree conflict on '%s'\n > %s\n"), - svn_cl__local_style_skip_ancestor(b->path_prefix, - desc->local_abspath, - scratch_pool), - readable_desc)); + if (all_options_are_dumb != NULL) + *all_options_are_dumb = TRUE; + + SVN_ERR(svn_client_conflict_tree_get_resolution_options(&builtin_options, + conflict, ctx, + scratch_pool, + scratch_pool)); + nopt = builtin_options->nelts + ARRAY_LEN(extra_resolver_options_tree) + + ARRAY_LEN(extra_resolver_options); + *options = apr_array_make(result_pool, nopt, sizeof(client_option_t *)); + *possible_moved_to_abspaths = NULL; + *possible_moved_to_repos_relpaths = NULL; + + iterpool = svn_pool_create(scratch_pool); + for (i = 0; i < builtin_options->nelts; i++) + { + client_option_t *opt; + svn_client_conflict_option_t *builtin_option; + svn_client_conflict_option_id_t id; + + svn_pool_clear(iterpool); + builtin_option = APR_ARRAY_IDX(builtin_options, i, + svn_client_conflict_option_t *); + SVN_ERR(find_option_by_builtin(&opt, conflict, + builtin_resolver_options, + builtin_option, + result_pool, + iterpool)); + if (opt == NULL) + { + /* Unkown option. Assign a dynamic option code. */ + opt = apr_pcalloc(result_pool, sizeof(*opt)); + opt->code = apr_psprintf(result_pool, "%d", next_unknown_option_code); + next_unknown_option_code++; + opt->label = svn_client_conflict_option_get_label(builtin_option, + result_pool); + opt->long_desc = svn_client_conflict_option_get_description( + builtin_option, result_pool); + opt->choice = svn_client_conflict_option_get_id(builtin_option); + opt->accept_arg = NULL; + } + + APR_ARRAY_PUSH(*options, client_option_t *) = opt; + + id = svn_client_conflict_option_get_id(builtin_option); + + /* Check if we got a "smart" tree conflict option. */ + if (all_options_are_dumb != NULL && + *all_options_are_dumb && + id != svn_client_conflict_option_postpone && + id != svn_client_conflict_option_accept_current_wc_state) + *all_options_are_dumb = FALSE; + + if (id == svn_client_conflict_option_incoming_move_file_text_merge || + id == svn_client_conflict_option_incoming_move_dir_merge) + { + SVN_ERR( + svn_client_conflict_option_get_moved_to_repos_relpath_candidates( + possible_moved_to_repos_relpaths, builtin_option, + result_pool, iterpool)); + SVN_ERR(svn_client_conflict_option_get_moved_to_abspath_candidates( + possible_moved_to_abspaths, builtin_option, + result_pool, iterpool)); + } + } + + svn_pool_destroy(iterpool); + + for (o = extra_resolver_options_tree; o->code; o++) + { + /* Add move target choice options only if there are multiple + * move targets to choose from. */ + if (strcmp(o->code, "d") == 0 && + (*possible_moved_to_repos_relpaths == NULL || + (*possible_moved_to_repos_relpaths)->nelts <= 1)) + continue; + if (strcmp(o->code, "w") == 0 && + (*possible_moved_to_abspaths == NULL || + (*possible_moved_to_abspaths)->nelts <= 1)) + continue; + + APR_ARRAY_PUSH(*options, const client_option_t *) = o; + } + for (o = extra_resolver_options; o->code; o++) + APR_ARRAY_PUSH(*options, const client_option_t *) = o; + + return SVN_NO_ERROR; +} + +/* Make the user select a move target path for the moved-away VICTIM_ABSPATH. */ +static svn_error_t * +prompt_move_target_path(int *preferred_move_target_idx, + apr_array_header_t *possible_moved_to_paths, + svn_boolean_t paths_are_local, + svn_cmdline_prompt_baton_t *pb, + const char *victim_abspath, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + const char *move_targets_prompt = ""; + const char *move_targets_list = ""; + const char *wcroot_abspath; + const char *victim_relpath; + int i; + apr_int64_t idx; + apr_pool_t *iterpool; + + SVN_ERR(svn_client_get_wc_root(&wcroot_abspath, victim_abspath, + ctx, scratch_pool, scratch_pool)); + victim_relpath = svn_cl__local_style_skip_ancestor(wcroot_abspath, + victim_abspath, + scratch_pool), + iterpool = svn_pool_create(scratch_pool); + + /* Build the prompt. */ + for (i = 0; i < possible_moved_to_paths->nelts; i++) + { + svn_pool_clear(iterpool); + + if (paths_are_local) + { + const char *moved_to_abspath; + const char *moved_to_relpath; + + moved_to_abspath = APR_ARRAY_IDX(possible_moved_to_paths, i, + const char *); + moved_to_relpath = svn_cl__local_style_skip_ancestor( + wcroot_abspath, moved_to_abspath, iterpool), + move_targets_list = apr_psprintf(scratch_pool, "%s (%d): '%s'\n", + move_targets_list, i + 1, + moved_to_relpath); + } + else + { + const char *moved_to_repos_relpath; + + moved_to_repos_relpath = APR_ARRAY_IDX(possible_moved_to_paths, i, + const char *); + move_targets_list = apr_psprintf(scratch_pool, "%s (%d): '^/%s'\n", + move_targets_list, i + 1, + moved_to_repos_relpath); + } + } + if (paths_are_local) + move_targets_prompt = + apr_psprintf(scratch_pool, + _("Possible working copy destinations for moved-away '%s' " + "are:\n%s" + "Only one destination can be a move; the others are " + "copies.\n" + "Specify the correct move target path by number: "), + victim_relpath, move_targets_list); + else + move_targets_prompt = + apr_psprintf(scratch_pool, + _("Possible repository destinations for moved-away '%s' " + "are:\n%s" + "Only one destination can be a move; the others are " + "copies.\n" + "Specify the correct move target path by number: "), + victim_relpath, move_targets_list); + + /* Keep asking the user until we got a valid choice. */ + while (1) + { + const char *answer; + svn_error_t *err; + + svn_pool_clear(iterpool); + + SVN_ERR(svn_cmdline_prompt_user2(&answer, move_targets_prompt, + pb, iterpool)); + err = svn_cstring_strtoi64(&idx, answer, 1, + possible_moved_to_paths->nelts, 10); + if (err) + { + char buf[1024]; + + svn_cmdline_fprintf(stderr, iterpool, "%s\n", + svn_err_best_message(err, buf, sizeof(buf))); + svn_error_clear(err); + continue; + } + + break; + } + + svn_pool_destroy(iterpool); + + SVN_ERR_ASSERT((idx - 1) == (int)(idx - 1)); + *preferred_move_target_idx = (int)(idx - 1); + return SVN_NO_ERROR; +} + +/* Ask the user what to do about the tree conflict described by CONFLICT + * and either resolve the conflict accordingly or postpone resolution. + * SCRATCH_POOL is used for temporary allocations. */ +static svn_error_t * +handle_tree_conflict(svn_boolean_t *resolved, + svn_boolean_t *postponed, + svn_boolean_t *quit, + svn_boolean_t *printed_description, + svn_client_conflict_t *conflict, + const char *path_prefix, + svn_cmdline_prompt_baton_t *pb, + svn_cl__conflict_stats_t *conflict_stats, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + apr_pool_t *iterpool; + apr_array_header_t *tree_conflict_options; + svn_client_conflict_option_id_t option_id; + const char *local_abspath; + const char *conflict_description; + const char *local_change_description; + const char *incoming_change_description; + apr_array_header_t *possible_moved_to_repos_relpaths; + apr_array_header_t *possible_moved_to_abspaths; + svn_boolean_t all_options_are_dumb; + const struct client_option_t *recommended_option; + svn_boolean_t repos_move_target_chosen = FALSE; + svn_boolean_t wc_move_target_chosen = FALSE; + + option_id = svn_client_conflict_option_unspecified; + local_abspath = svn_client_conflict_get_local_abspath(conflict); + + /* Always show the best possible conflict description and options. */ + SVN_ERR(svn_client_conflict_tree_get_details(conflict, ctx, scratch_pool)); + + SVN_ERR(svn_client_conflict_tree_get_description( + &incoming_change_description, &local_change_description, + conflict, ctx, scratch_pool, scratch_pool)); + conflict_description = apr_psprintf(scratch_pool, "%s\n%s", + incoming_change_description, + local_change_description); + if (!*printed_description) + SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, + _("Tree conflict on '%s':\n%s\n"), + svn_cl__local_style_skip_ancestor( + path_prefix, local_abspath, scratch_pool), + conflict_description)); + + SVN_ERR(build_tree_conflict_options(&tree_conflict_options, + &possible_moved_to_repos_relpaths, + &possible_moved_to_abspaths, + &all_options_are_dumb, + conflict, ctx, + scratch_pool, scratch_pool)); + + /* Try a recommended resolution option before prompting. */ + recommended_option = find_recommended_option(tree_conflict_options); + if (recommended_option) + { + svn_error_t *err; + apr_status_t root_cause; + + SVN_ERR(svn_cmdline_printf(scratch_pool, + _("Applying recommended resolution '%s':\n"), + recommended_option->label)); + + err = mark_conflict_resolved(conflict, recommended_option->choice, + FALSE, NULL, TRUE, + path_prefix, conflict_stats, + ctx, scratch_pool); + if (!err) + { + *resolved = TRUE; + return SVN_NO_ERROR; + } + + root_cause = svn_error_root_cause(err)->apr_err; + if (root_cause != SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE && + root_cause != SVN_ERR_WC_OBSTRUCTED_UPDATE && + root_cause != SVN_ERR_WC_FOUND_CONFLICT) + return svn_error_trace(err); + + /* Fall back to interactive prompting. */ + svn_error_clear(err); + } + + if (all_options_are_dumb) + SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, + _("\nSubversion is not smart enough to resolve " + "this tree conflict automatically!\nSee 'svn " + "help resolve' for more information.\n\n"))); iterpool = svn_pool_create(scratch_pool); while (1) { - const resolver_option_t *opt; - const resolver_option_t *tc_opts; + const client_option_t *opt; svn_pool_clear(iterpool); - tc_opts = tree_conflict_options; + if (!repos_move_target_chosen && + possible_moved_to_repos_relpaths && + possible_moved_to_repos_relpaths->nelts > 1) + SVN_ERR(svn_cmdline_printf(scratch_pool, + _("Ambiguous move destinations exist in the repository; " + "try the 'd' option\n"))); + if (!wc_move_target_chosen && possible_moved_to_abspaths && + possible_moved_to_abspaths->nelts > 1) + SVN_ERR(svn_cmdline_printf(scratch_pool, + _("Ambiguous move destinations exist in the working copy; " + "try the 'w' option\n"))); - if (desc->operation == svn_wc_operation_update || - desc->operation == svn_wc_operation_switch) - { - if (desc->reason == svn_wc_conflict_reason_moved_away) - { - tc_opts = tree_conflict_options_update_moved_away; - } - else if (desc->reason == svn_wc_conflict_reason_deleted || - desc->reason == svn_wc_conflict_reason_replaced) - { - if (desc->action == svn_wc_conflict_action_edit && - desc->node_kind == svn_node_dir) - tc_opts = tree_conflict_options_update_edit_deleted_dir; - } - } - - SVN_ERR(prompt_user(&opt, tc_opts, NULL, b->pb, iterpool)); + SVN_ERR(prompt_user(&opt, tree_conflict_options, NULL, + conflict_description, pb, iterpool)); + *printed_description = TRUE; if (! opt) continue; if (strcmp(opt->code, "q") == 0) { - result->choice = opt->choice; - b->accept_which = svn_cl__accept_postpone; - b->quit = TRUE; + option_id = opt->choice; + *quit = TRUE; break; } - else if (opt->choice != svn_wc_conflict_choose_undefined) + else if (strcmp(opt->code, "d") == 0) { - result->choice = opt->choice; + int preferred_move_target_idx; + apr_array_header_t *options; + svn_client_conflict_option_t *conflict_option; + + SVN_ERR(prompt_move_target_path(&preferred_move_target_idx, + possible_moved_to_repos_relpaths, + FALSE, + pb, local_abspath, ctx, iterpool)); + + /* Update preferred move target path. */ + SVN_ERR(svn_client_conflict_tree_get_resolution_options(&options, + conflict, + ctx, + iterpool, + iterpool)); + conflict_option = + svn_client_conflict_option_find_by_id( + options, + svn_client_conflict_option_incoming_move_file_text_merge); + if (conflict_option == NULL) + { + conflict_option = + svn_client_conflict_option_find_by_id( + options, svn_client_conflict_option_incoming_move_dir_merge); + } + + if (conflict_option) + { + SVN_ERR(svn_client_conflict_option_set_moved_to_repos_relpath( + conflict_option, preferred_move_target_idx, + ctx, iterpool)); + repos_move_target_chosen = TRUE; + wc_move_target_chosen = FALSE; + + /* Update option description. */ + SVN_ERR(build_tree_conflict_options( + &tree_conflict_options, + &possible_moved_to_repos_relpaths, + &possible_moved_to_abspaths, + NULL, conflict, ctx, + scratch_pool, scratch_pool)); + + /* Update conflict description. */ + SVN_ERR(svn_client_conflict_tree_get_description( + &incoming_change_description, &local_change_description, + conflict, ctx, scratch_pool, scratch_pool)); + conflict_description = apr_psprintf(scratch_pool, "%s\n%s", + incoming_change_description, + local_change_description); + } + continue; + } + else if (strcmp(opt->code, "w") == 0) + { + int preferred_move_target_idx; + apr_array_header_t *options; + svn_client_conflict_option_t *conflict_option; + + SVN_ERR(prompt_move_target_path(&preferred_move_target_idx, + possible_moved_to_abspaths, TRUE, + pb, local_abspath, ctx, iterpool)); + + /* Update preferred move target path. */ + SVN_ERR(svn_client_conflict_tree_get_resolution_options(&options, + conflict, + ctx, + iterpool, + iterpool)); + conflict_option = + svn_client_conflict_option_find_by_id( + options, + svn_client_conflict_option_incoming_move_file_text_merge); + if (conflict_option == NULL) + { + conflict_option = + svn_client_conflict_option_find_by_id( + options, svn_client_conflict_option_incoming_move_dir_merge); + } + + if (conflict_option) + { + SVN_ERR(svn_client_conflict_option_set_moved_to_abspath( + conflict_option, preferred_move_target_idx, ctx, + iterpool)); + wc_move_target_chosen = TRUE; + + /* Update option description. */ + SVN_ERR(build_tree_conflict_options( + &tree_conflict_options, + &possible_moved_to_repos_relpaths, + &possible_moved_to_abspaths, + NULL, conflict, ctx, + scratch_pool, scratch_pool)); + } + continue; + } + else if (opt->choice != svn_client_conflict_option_undefined) + { + option_id = opt->choice; break; } } svn_pool_destroy(iterpool); + if (option_id != svn_client_conflict_option_unspecified && + option_id != svn_client_conflict_option_postpone) + { + SVN_ERR(mark_conflict_resolved(conflict, option_id, + FALSE, NULL, TRUE, + path_prefix, conflict_stats, + ctx, scratch_pool)); + *resolved = TRUE; + } + else + { + *resolved = FALSE; + *postponed = (option_id == svn_client_conflict_option_postpone); + } return SVN_NO_ERROR; } -/* The body of svn_cl__conflict_func_interactive(). */ static svn_error_t * -conflict_func_interactive(svn_wc_conflict_result_t **result, - const svn_wc_conflict_description2_t *desc, - void *baton, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) +resolve_conflict_interactively(svn_boolean_t *resolved, + svn_boolean_t *postponed, + svn_boolean_t *quit, + svn_boolean_t *external_failed, + svn_boolean_t *printed_summary, + svn_boolean_t *printed_description, + svn_client_conflict_t *conflict, + const char *editor_cmd, + apr_hash_t *config, + const char *path_prefix, + svn_cmdline_prompt_baton_t *pb, + svn_cl__conflict_stats_t *conflict_stats, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { - svn_cl__interactive_conflict_baton_t *b = baton; - svn_error_t *err; + svn_boolean_t text_conflicted; + apr_array_header_t *props_conflicted; + svn_boolean_t tree_conflicted; + const svn_string_t *merged_propval; - /* Start out assuming we're going to postpone the conflict. */ - *result = svn_wc_create_conflict_result(svn_wc_conflict_choose_postpone, - NULL, result_pool); - - switch (b->accept_which) - { - case svn_cl__accept_invalid: - case svn_cl__accept_unspecified: - /* No (or no valid) --accept option, fall through to prompting. */ - break; - case svn_cl__accept_postpone: - (*result)->choice = svn_wc_conflict_choose_postpone; - return SVN_NO_ERROR; - case svn_cl__accept_base: - (*result)->choice = svn_wc_conflict_choose_base; - return SVN_NO_ERROR; - case svn_cl__accept_working: - /* If the caller didn't merge the property values, then I guess - * 'choose working' means 'choose mine'... */ - if (! desc->merged_file) - (*result)->merged_file = desc->my_abspath; - (*result)->choice = svn_wc_conflict_choose_merged; - return SVN_NO_ERROR; - case svn_cl__accept_mine_conflict: - (*result)->choice = svn_wc_conflict_choose_mine_conflict; - return SVN_NO_ERROR; - case svn_cl__accept_theirs_conflict: - (*result)->choice = svn_wc_conflict_choose_theirs_conflict; - return SVN_NO_ERROR; - case svn_cl__accept_mine_full: - (*result)->choice = svn_wc_conflict_choose_mine_full; - return SVN_NO_ERROR; - case svn_cl__accept_theirs_full: - (*result)->choice = svn_wc_conflict_choose_theirs_full; - return SVN_NO_ERROR; - case svn_cl__accept_edit: - if (desc->merged_file) - { - if (b->external_failed) - { - (*result)->choice = svn_wc_conflict_choose_postpone; - return SVN_NO_ERROR; - } - - err = svn_cmdline__edit_file_externally(desc->merged_file, - b->editor_cmd, b->config, - scratch_pool); - if (err && (err->apr_err == SVN_ERR_CL_NO_EXTERNAL_EDITOR || - err->apr_err == SVN_ERR_EXTERNAL_PROGRAM)) - { - char buf[1024]; - const char *message; - - message = svn_err_best_message(err, buf, sizeof(buf)); - SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, "%s\n", - message)); - svn_error_clear(err); - b->external_failed = TRUE; - } - else if (err) - return svn_error_trace(err); - (*result)->choice = svn_wc_conflict_choose_merged; - return SVN_NO_ERROR; - } - /* else, fall through to prompting. */ - break; - case svn_cl__accept_launch: - if (desc->base_abspath && desc->their_abspath - && desc->my_abspath && desc->merged_file) - { - svn_boolean_t remains_in_conflict; - - if (b->external_failed) - { - (*result)->choice = svn_wc_conflict_choose_postpone; - return SVN_NO_ERROR; - } - - err = svn_cl__merge_file_externally(desc->base_abspath, - desc->their_abspath, - desc->my_abspath, - desc->merged_file, - desc->local_abspath, - b->config, - &remains_in_conflict, - scratch_pool); - if (err && (err->apr_err == SVN_ERR_CL_NO_EXTERNAL_MERGE_TOOL || - err->apr_err == SVN_ERR_EXTERNAL_PROGRAM)) - { - char buf[1024]; - const char *message; - - message = svn_err_best_message(err, buf, sizeof(buf)); - SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, "%s\n", - message)); - b->external_failed = TRUE; - return svn_error_trace(err); - } - else if (err) - return svn_error_trace(err); - - if (remains_in_conflict) - (*result)->choice = svn_wc_conflict_choose_postpone; - else - (*result)->choice = svn_wc_conflict_choose_merged; - return SVN_NO_ERROR; - } - /* else, fall through to prompting. */ - break; - } + SVN_ERR(svn_client_conflict_get_conflicted(&text_conflicted, + &props_conflicted, + &tree_conflicted, + conflict, + scratch_pool, + scratch_pool)); /* Print a summary of conflicts before starting interactive resolution */ - if (! b->printed_summary) + if (! *printed_summary) { - SVN_ERR(svn_cl__print_conflict_stats(b->conflict_stats, scratch_pool)); - b->printed_summary = TRUE; + SVN_ERR(svn_cl__print_conflict_stats(conflict_stats, scratch_pool)); + *printed_summary = TRUE; } - /* We're in interactive mode and either the user gave no --accept - option or the option did not apply; let's prompt. */ - - /* Handle the most common cases, which is either: - - Conflicting edits on a file's text, or - Conflicting edits on a property. - */ - if (((desc->kind == svn_wc_conflict_kind_text) - && (desc->action == svn_wc_conflict_action_edit) - && (desc->reason == svn_wc_conflict_reason_edited))) - SVN_ERR(handle_text_conflict(*result, desc, b, scratch_pool)); - else if (desc->kind == svn_wc_conflict_kind_property) - SVN_ERR(handle_prop_conflict(*result, desc, b, result_pool, scratch_pool)); - else if (desc->kind == svn_wc_conflict_kind_tree) - SVN_ERR(handle_tree_conflict(*result, desc, b, scratch_pool)); - - else /* other types of conflicts -- do nothing about them. */ - { - (*result)->choice = svn_wc_conflict_choose_postpone; - } + *resolved = FALSE; + if (text_conflicted + && (svn_client_conflict_get_incoming_change(conflict) == + svn_wc_conflict_action_edit) + && (svn_client_conflict_get_local_change(conflict) == + svn_wc_conflict_reason_edited)) + SVN_ERR(handle_text_conflict(resolved, postponed, quit, printed_description, + conflict, path_prefix, pb, editor_cmd, config, + conflict_stats, ctx, scratch_pool)); + if (props_conflicted->nelts > 0) + SVN_ERR(handle_prop_conflicts(resolved, postponed, quit, &merged_propval, + path_prefix, pb, editor_cmd, config, conflict, + conflict_stats, ctx, result_pool, scratch_pool)); + if (tree_conflicted) + SVN_ERR(handle_tree_conflict(resolved, postponed, quit, printed_description, + conflict, path_prefix, pb, conflict_stats, ctx, + scratch_pool)); return SVN_NO_ERROR; } svn_error_t * -svn_cl__conflict_func_interactive(svn_wc_conflict_result_t **result, - const svn_wc_conflict_description2_t *desc, - void *baton, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) +svn_cl__resolve_conflict(svn_boolean_t *quit, + svn_boolean_t *external_failed, + svn_boolean_t *printed_summary, + svn_client_conflict_t *conflict, + svn_cl__accept_t accept_which, + const char *editor_cmd, + const char *path_prefix, + svn_cmdline_prompt_baton_t *pb, + svn_cl__conflict_stats_t *conflict_stats, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) { - svn_cl__interactive_conflict_baton_t *b = baton; + svn_boolean_t text_conflicted; + apr_array_header_t *props_conflicted; + svn_boolean_t tree_conflicted; + const char *local_abspath; + svn_client_conflict_option_id_t option_id; - SVN_ERR(conflict_func_interactive(result, desc, baton, - result_pool, scratch_pool)); + SVN_ERR(svn_client_conflict_get_conflicted(&text_conflicted, + &props_conflicted, + &tree_conflicted, + conflict, + scratch_pool, + scratch_pool)); + local_abspath = svn_client_conflict_get_local_abspath(conflict); - /* If we are resolving a conflict, adjust the summary of conflicts. */ - if ((*result)->choice != svn_wc_conflict_choose_postpone) + if (accept_which == svn_cl__accept_unspecified) { - const char *local_path - = svn_cl__local_style_skip_ancestor( - b->path_prefix, desc->local_abspath, scratch_pool); - - svn_cl__conflict_stats_resolved(b->conflict_stats, local_path, - desc->kind); + option_id = svn_client_conflict_option_unspecified; } + else if (accept_which == svn_cl__accept_postpone) + { + option_id = svn_client_conflict_option_postpone; + } + else if (accept_which == svn_cl__accept_base) + { + option_id = svn_client_conflict_option_base_text; + } + else if (accept_which == svn_cl__accept_working) + { + option_id = svn_client_conflict_option_merged_text; + + if (text_conflicted) + { + const char *mime_type = + svn_client_conflict_text_get_mime_type(conflict); + + /* There is no merged text for binary conflicts, behave as + * if 'mine-full' was chosen. */ + if (mime_type && svn_mime_type_is_binary(mime_type)) + option_id = svn_client_conflict_option_working_text; + } + else if (tree_conflicted) + { + /* For tree conflicts, map 'working' to 'accept current working + * copy state'. */ + option_id = svn_client_conflict_option_accept_current_wc_state; + } + } + else if (accept_which == svn_cl__accept_theirs_conflict) + { + option_id = svn_client_conflict_option_incoming_text_where_conflicted; + } + else if (accept_which == svn_cl__accept_mine_conflict) + { + option_id = svn_client_conflict_option_working_text_where_conflicted; + + if (tree_conflicted) + { + svn_wc_operation_t operation; + + operation = svn_client_conflict_get_operation(conflict); + if (operation == svn_wc_operation_update || + operation == svn_wc_operation_switch) + { + svn_wc_conflict_reason_t reason; + + reason = svn_client_conflict_get_local_change(conflict); + if (reason == svn_wc_conflict_reason_moved_away) + { + /* Map 'mine-conflict' to 'update move destination'. */ + option_id = + svn_client_conflict_option_update_move_destination; + } + else if (reason == svn_wc_conflict_reason_deleted || + reason == svn_wc_conflict_reason_replaced) + { + svn_wc_conflict_action_t action; + svn_node_kind_t node_kind; + + action = svn_client_conflict_get_incoming_change(conflict); + node_kind = + svn_client_conflict_tree_get_victim_node_kind(conflict); + + if (action == svn_wc_conflict_action_edit && + node_kind == svn_node_dir) + { + /* Map 'mine-conflict' to 'update any moved away + * children'. */ + option_id = + svn_client_conflict_option_update_any_moved_away_children; + } + } + } + } + } + else if (accept_which == svn_cl__accept_theirs_full) + { + option_id = svn_client_conflict_option_incoming_text; + } + else if (accept_which == svn_cl__accept_mine_full) + { + option_id = svn_client_conflict_option_working_text; + } + else if (accept_which == svn_cl__accept_edit) + { + option_id = svn_client_conflict_option_unspecified; + + if (local_abspath) + { + if (*external_failed) + { + option_id = svn_client_conflict_option_postpone; + } + else + { + svn_error_t *err; + + err = svn_cmdline__edit_file_externally(local_abspath, + editor_cmd, + ctx->config, + scratch_pool); + if (err && (err->apr_err == SVN_ERR_CL_NO_EXTERNAL_EDITOR || + err->apr_err == SVN_ERR_EXTERNAL_PROGRAM)) + { + char buf[1024]; + const char *message; + + message = svn_err_best_message(err, buf, sizeof(buf)); + SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, "%s\n", + message)); + svn_error_clear(err); + *external_failed = TRUE; + } + else if (err) + return svn_error_trace(err); + option_id = svn_client_conflict_option_merged_text; + } + } + } + else if (accept_which == svn_cl__accept_launch) + { + const char *base_abspath = NULL; + const char *my_abspath = NULL; + const char *their_abspath = NULL; + + option_id = svn_client_conflict_option_unspecified; + + if (text_conflicted) + SVN_ERR(svn_client_conflict_text_get_contents(NULL, &my_abspath, + &base_abspath, + &their_abspath, + conflict, scratch_pool, + scratch_pool)); + + if (base_abspath && their_abspath && my_abspath && local_abspath) + { + if (*external_failed) + { + option_id = svn_client_conflict_option_postpone; + } + else + { + svn_boolean_t remains_in_conflict; + svn_error_t *err; + + err = svn_cl__merge_file_externally(base_abspath, their_abspath, + my_abspath, local_abspath, + local_abspath, ctx->config, + &remains_in_conflict, + scratch_pool); + if (err && (err->apr_err == SVN_ERR_CL_NO_EXTERNAL_MERGE_TOOL || + err->apr_err == SVN_ERR_EXTERNAL_PROGRAM)) + { + char buf[1024]; + const char *message; + + message = svn_err_best_message(err, buf, sizeof(buf)); + SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, "%s\n", + message)); + *external_failed = TRUE; + return svn_error_trace(err); + } + else if (err) + return svn_error_trace(err); + + if (remains_in_conflict) + option_id = svn_client_conflict_option_postpone; + else + option_id = svn_client_conflict_option_merged_text; + } + } + } + else if (accept_which == svn_cl__accept_recommended) + { + svn_client_conflict_option_id_t recommended_id; + + if (tree_conflicted) + SVN_ERR(svn_client_conflict_tree_get_details(conflict, ctx, + scratch_pool)); + recommended_id = svn_client_conflict_get_recommended_option_id(conflict); + if (recommended_id != svn_client_conflict_option_unspecified) + option_id = recommended_id; + else + option_id = svn_client_conflict_option_postpone; + } + else + SVN_ERR_MALFUNCTION(); + + /* If we are in interactive mode and either the user gave no --accept + * option or the option did not apply, then prompt. */ + if (option_id == svn_client_conflict_option_unspecified) + { + svn_boolean_t resolved = FALSE; + svn_boolean_t postponed = FALSE; + svn_boolean_t printed_description = FALSE; + svn_error_t *err; + + *quit = FALSE; + + while (!resolved && !postponed && !*quit) + { + err = resolve_conflict_interactively(&resolved, &postponed, quit, + external_failed, + printed_summary, + &printed_description, + conflict, + editor_cmd, ctx->config, + path_prefix, pb, + conflict_stats, ctx, + scratch_pool, scratch_pool); + if (err && err->apr_err == SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE) + { + /* Conflict resolution has failed. Let the user try again. + * It is always possible to break out of this loop with + * the 'quit' or 'postpone' options. */ + svn_handle_warning2(stderr, err, "svn: "); + svn_error_clear(err); + err = SVN_NO_ERROR; + } + SVN_ERR(err); + } + } + else if (option_id != svn_client_conflict_option_postpone) + SVN_ERR(mark_conflict_resolved(conflict, option_id, + text_conflicted, + props_conflicted->nelts > 0 ? "" : NULL, + tree_conflicted, + path_prefix, conflict_stats, + ctx, scratch_pool)); + return SVN_NO_ERROR; } diff --git a/subversion/svn/diff-cmd.c b/subversion/svn/diff-cmd.c index 71853c7f2776..9e389ec856a6 100644 --- a/subversion/svn/diff-cmd.c +++ b/subversion/svn/diff-cmd.c @@ -233,6 +233,43 @@ svn_cl__diff(apr_getopt_t *os, svn_xml_make_open_tag(&sb, pool, svn_xml_normal, "paths", SVN_VA_NULL); SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout)); } + if (opt_state->diff.summarize) + { + if (opt_state->diff.use_git_diff_format) + return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("'%s' not valid with '--summarize' option"), + "--git"); + if (opt_state->diff.patch_compatible) + return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("'%s' not valid with '--summarize' option"), + "--patch-compatible"); + if (opt_state->diff.show_copies_as_adds) + return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("'%s' not valid with '--summarize' option"), + "--show-copies-as-adds"); + if (opt_state->diff.internal_diff) + return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("'%s' not valid with '--summarize' option"), + "--internal-diff"); + if (opt_state->diff.diff_cmd) + return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("'%s' not valid with '--summarize' option"), + "--diff-cmd"); + if (opt_state->diff.no_diff_added) + return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("'%s' not valid with '--summarize' option"), + "--no-diff-added"); + if (opt_state->diff.no_diff_deleted) + return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("'%s' not valid with '--summarize' option"), + "--no-diff-deleted"); + if (opt_state->force) + return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("'%s' not valid with '--summarize' option"), + "--force"); + /* Not handling ignore-properties, and properties-only as there should + be a patch adding support for these being applied soon */ + } SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os, opt_state->targets, diff --git a/subversion/svn/help-cmd.c b/subversion/svn/help-cmd.c index b095d30fd1c2..fc3558683033 100644 --- a/subversion/svn/help-cmd.c +++ b/subversion/svn/help-cmd.c @@ -53,8 +53,9 @@ svn_cl__help(apr_getopt_t *os, N_("usage: svn [options] [args]\n" "Subversion command-line client.\n" "Type 'svn help ' for help on a specific subcommand.\n" - "Type 'svn --version' to see the program version and RA modules\n" - " or 'svn --version --quiet' to see just the version number.\n" + "Type 'svn --version' to see the program version and RA modules,\n" + " 'svn --version --verbose' to see dependency versions as well,\n" + " 'svn --version --quiet' to see just the version number.\n" "\n" "Most subcommands take file and/or directory arguments, recursing\n" "on the directories. If no arguments are supplied to such a\n" @@ -147,21 +148,24 @@ svn_cl__help(apr_getopt_t *os, _("\nThe following authentication credential caches are available:\n\n")); /*### There is no API to query available providers at run time. */ + if (config_path) + { #if (defined(WIN32) && !defined(__MINGW32__)) - version_footer = - svn_stringbuf_create(apr_psprintf(pool, _("%s* Wincrypt cache in %s\n"), - version_footer->data, - svn_dirent_local_style(config_path, - pool)), - pool); + version_footer = + svn_stringbuf_create(apr_psprintf(pool, _("%s* Wincrypt cache in %s\n"), + version_footer->data, + svn_dirent_local_style(config_path, + pool)), + pool); #elif !defined(SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE) - version_footer = - svn_stringbuf_create(apr_psprintf(pool, _("%s* Plaintext cache in %s\n"), - version_footer->data, - svn_dirent_local_style(config_path, - pool)), - pool); + version_footer = + svn_stringbuf_create(apr_psprintf(pool, _("%s* Plaintext cache in %s\n"), + version_footer->data, + svn_dirent_local_style(config_path, + pool)), + pool); #endif + } #ifdef SVN_HAVE_GNOME_KEYRING svn_stringbuf_appendcstr(version_footer, "* Gnome Keyring\n"); #endif @@ -181,7 +185,7 @@ svn_cl__help(apr_getopt_t *os, opt_state ? opt_state->quiet : FALSE, opt_state ? opt_state->verbose : FALSE, version_footer->data, - help_header, /* already gettext()'d */ + _(help_header), svn_cl__cmd_table, svn_cl__options, svn_cl__global_options, diff --git a/subversion/svn/info-cmd.c b/subversion/svn/info-cmd.c index fafc398c5f6c..e0c0041b468a 100644 --- a/subversion/svn/info-cmd.c +++ b/subversion/svn/info-cmd.c @@ -162,6 +162,9 @@ typedef struct print_info_baton_t /* Did we already print a line of output? */ svn_boolean_t start_new_line; + + /* The client context. */ + svn_client_ctx_t *ctx; } print_info_baton_t; @@ -391,15 +394,24 @@ print_info_xml(void *baton, if (info->wc_info && info->wc_info->conflicts) { int i; + apr_pool_t *iterpool; + iterpool = svn_pool_create(pool); for (i = 0; i < info->wc_info->conflicts->nelts; i++) { - const svn_wc_conflict_description2_t *conflict = + const svn_wc_conflict_description2_t *desc = APR_ARRAY_IDX(info->wc_info->conflicts, i, const svn_wc_conflict_description2_t *); + svn_client_conflict_t *conflict; - SVN_ERR(svn_cl__append_conflict_info_xml(sb, conflict, pool)); + svn_pool_clear(iterpool); + + SVN_ERR(svn_client_conflict_get(&conflict, desc->local_abspath, + receiver_baton->ctx, + iterpool, iterpool)); + SVN_ERR(svn_cl__append_conflict_info_xml(sb, conflict, iterpool)); } + svn_pool_destroy(iterpool); } if (info->lock) @@ -581,68 +593,93 @@ print_info(void *baton, if (info->wc_info->conflicts) { - svn_boolean_t printed_prop_conflict_file = FALSE; svn_boolean_t printed_tc = FALSE; - int i; + svn_stringbuf_t *conflicted_props = NULL; + svn_client_conflict_t *conflict; + svn_boolean_t text_conflicted; + apr_array_header_t *props_conflicted; + svn_boolean_t tree_conflicted; + const svn_wc_conflict_description2_t *desc2 = + APR_ARRAY_IDX(info->wc_info->conflicts, 0, + const svn_wc_conflict_description2_t *); - for (i = 0; i < info->wc_info->conflicts->nelts; i++) + SVN_ERR(svn_client_conflict_get(&conflict, desc2->local_abspath, + receiver_baton->ctx, pool, pool)); + SVN_ERR(svn_client_conflict_get_conflicted(&text_conflicted, + &props_conflicted, + &tree_conflicted, + conflict, pool, pool)); + if (text_conflicted) { - const svn_wc_conflict_description2_t *conflict = - APR_ARRAY_IDX(info->wc_info->conflicts, i, - const svn_wc_conflict_description2_t *); - const char *desc; + const char *base_abspath = NULL; + const char *my_abspath = NULL; + const char *their_abspath = NULL; - switch (conflict->kind) + SVN_ERR(svn_client_conflict_text_get_contents( + NULL, &my_abspath, &base_abspath, &their_abspath, + conflict, pool, pool)); + + if (base_abspath) + SVN_ERR(svn_cmdline_printf(pool, + _("Conflict Previous Base File: %s\n"), + svn_cl__local_style_skip_ancestor( + receiver_baton->path_prefix, + base_abspath, + pool))); + + if (my_abspath) + SVN_ERR(svn_cmdline_printf(pool, + _("Conflict Previous Working File: %s\n"), + svn_cl__local_style_skip_ancestor( + receiver_baton->path_prefix, + my_abspath, + pool))); + + if (their_abspath) + SVN_ERR(svn_cmdline_printf(pool, + _("Conflict Current Base File: %s\n"), + svn_cl__local_style_skip_ancestor( + receiver_baton->path_prefix, + their_abspath, + pool))); + } + + if (props_conflicted) + { + int i; + + for (i = 0; i < props_conflicted->nelts; i++) { - case svn_wc_conflict_kind_text: - if (conflict->base_abspath) - SVN_ERR(svn_cmdline_printf(pool, - _("Conflict Previous Base File: %s\n"), - svn_cl__local_style_skip_ancestor( - receiver_baton->path_prefix, - conflict->base_abspath, - pool))); + const char *name; - if (conflict->my_abspath) - SVN_ERR(svn_cmdline_printf(pool, - _("Conflict Previous Working File: %s\n"), - svn_cl__local_style_skip_ancestor( - receiver_baton->path_prefix, - conflict->my_abspath, - pool))); - - if (conflict->their_abspath) - SVN_ERR(svn_cmdline_printf(pool, - _("Conflict Current Base File: %s\n"), - svn_cl__local_style_skip_ancestor( - receiver_baton->path_prefix, - conflict->their_abspath, - pool))); - break; - - case svn_wc_conflict_kind_property: - if (! printed_prop_conflict_file) - SVN_ERR(svn_cmdline_printf(pool, - _("Conflict Properties File: %s\n"), - svn_cl__local_style_skip_ancestor( - receiver_baton->path_prefix, - conflict->prop_reject_abspath, - pool))); - printed_prop_conflict_file = TRUE; - break; - - case svn_wc_conflict_kind_tree: - printed_tc = TRUE; - SVN_ERR( - svn_cl__get_human_readable_tree_conflict_description( - &desc, conflict, pool)); - - SVN_ERR(svn_cmdline_printf(pool, "%s: %s\n", - _("Tree conflict"), desc)); - break; + name = APR_ARRAY_IDX(props_conflicted, i, const char *); + if (conflicted_props == NULL) + conflicted_props = svn_stringbuf_create(name, pool); + else + { + svn_stringbuf_appendbyte(conflicted_props, ' '); + svn_stringbuf_appendcstr(conflicted_props, name); + } } } + if (tree_conflicted) + { + const char *desc; + + printed_tc = TRUE; + SVN_ERR( + svn_cl__get_human_readable_tree_conflict_description( + &desc, conflict, pool)); + + SVN_ERR(svn_cmdline_printf(pool, "%s: %s\n", + _("Tree conflict"), desc)); + } + + if (conflicted_props) + SVN_ERR(svn_cmdline_printf(pool, _("Conflicted Properties: %s\n"), + conflicted_props->data)); + /* We only store one left and right version for all conflicts, which is referenced from all conflicts. Print it after the conflicts to match the 1.6/1.7 output where it is @@ -650,30 +687,40 @@ print_info(void *baton, { const char *src_left_version; const char *src_right_version; - const svn_wc_conflict_description2_t *conflict = - APR_ARRAY_IDX(info->wc_info->conflicts, 0, - const svn_wc_conflict_description2_t *); + const char *repos_root_url; + const char *repos_relpath; + svn_revnum_t peg_rev; + svn_node_kind_t node_kind; if (!printed_tc) { const char *desc; SVN_ERR(svn_cl__get_human_readable_action_description(&desc, - svn_wc_conflict_action_edit, - conflict->operation, - conflict->node_kind, pool)); + svn_wc_conflict_action_edit, + svn_client_conflict_get_operation(conflict), + info->kind, + pool)); SVN_ERR(svn_cmdline_printf(pool, "%s: %s\n", _("Conflict Details"), desc)); } + SVN_ERR(svn_client_conflict_get_repos_info(&repos_root_url, NULL, + conflict, pool, pool)); + SVN_ERR(svn_client_conflict_get_incoming_old_repos_location( + &repos_relpath, &peg_rev, &node_kind, conflict, + pool, pool)); src_left_version = - svn_cl__node_description(conflict->src_left_version, - info->repos_root_URL, pool); + svn_cl__node_description(repos_root_url, repos_relpath, + peg_rev, node_kind, info->repos_root_URL, pool); + SVN_ERR(svn_client_conflict_get_incoming_new_repos_location( + &repos_relpath, &peg_rev, &node_kind, conflict, + pool, pool)); src_right_version = - svn_cl__node_description(conflict->src_right_version, - info->repos_root_URL, pool); + svn_cl__node_description(repos_root_url, repos_relpath, + peg_rev, node_kind, info->repos_root_URL, pool); if (src_left_version) SVN_ERR(svn_cmdline_printf(pool, " %s: %s\n", @@ -874,6 +921,8 @@ svn_cl__info(apr_getopt_t *os, /* Add "." if user passed 0 arguments. */ svn_opt_push_implicit_dot_target(targets, pool); + receiver_baton.ctx = ctx; + if (opt_state->xml) { receiver = print_info_xml; diff --git a/subversion/svn/list-cmd.c b/subversion/svn/list-cmd.c index 5ea140fc93d1..da18252243d9 100644 --- a/subversion/svn/list-cmd.c +++ b/subversion/svn/list-cmd.c @@ -351,6 +351,8 @@ svn_cl__list(apr_getopt_t *os, const char *target = APR_ARRAY_IDX(targets, i, const char *); const char *truepath; svn_opt_revision_t peg_revision; + apr_array_header_t *patterns = NULL; + int k; /* Initialize the following variables for every list target. */ @@ -375,8 +377,33 @@ svn_cl__list(apr_getopt_t *os, SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout)); } - err = svn_client_list3(truepath, &peg_revision, - &(opt_state->start_revision), + if (opt_state->search_patterns) + { + patterns = apr_array_make(subpool, 4, sizeof(const char *)); + for (k = 0; k < opt_state->search_patterns->nelts; ++k) + { + apr_array_header_t *pattern_group + = APR_ARRAY_IDX(opt_state->search_patterns, k, + apr_array_header_t *); + const char *pattern; + + /* Should never fail but ... */ + if (pattern_group->nelts != 1) + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("'search-and' option is not supported")); + + pattern = APR_ARRAY_IDX(pattern_group, 0, const char *); +#if defined(WIN32) + /* As we currently can't pass glob patterns via the Windows + CLI, fall back to sub-string search. */ + pattern = apr_psprintf(subpool, "*%s*", pattern); +#endif + APR_ARRAY_PUSH(patterns, const char *) = pattern; + } + } + + err = svn_client_list4(truepath, &peg_revision, + &(opt_state->start_revision), patterns, opt_state->depth, dirent_fields, (opt_state->xml || opt_state->verbose), diff --git a/subversion/svn/log-cmd.c b/subversion/svn/log-cmd.c index 44f8a4cff292..57f841506914 100644 --- a/subversion/svn/log-cmd.c +++ b/subversion/svn/log-cmd.c @@ -38,6 +38,7 @@ #include "private/svn_cmdline_private.h" #include "private/svn_sorts_private.h" +#include "private/svn_utf_private.h" #include "cl.h" #include "cl-log.h" @@ -110,6 +111,24 @@ display_diff(const svn_log_entry_t *log_entry, return SVN_NO_ERROR; } +/* Return TRUE if STR matches PATTERN. Else, return FALSE. Assumes that + * PATTERN is a UTF-8 string prepared for case- and accent-insensitive + * comparison via svn_utf__xfrm(). */ +static svn_boolean_t +match(const char *pattern, const char *str, svn_membuf_t *buf) +{ + svn_error_t *err; + + err = svn_utf__xfrm(&str, str, strlen(str), TRUE, TRUE, buf); + if (err) + { + /* Can't match invalid data. */ + svn_error_clear(err); + return FALSE; + } + + return apr_fnmatch(pattern, str, 0) == APR_SUCCESS; +} /* Return TRUE if SEARCH_PATTERN matches the AUTHOR, DATE, LOG_MESSAGE, * or a path in the set of keys of the CHANGED_PATHS hash. Else, return FALSE. @@ -120,22 +139,22 @@ match_search_pattern(const char *search_pattern, const char *date, const char *log_message, apr_hash_t *changed_paths, + svn_membuf_t *buf, apr_pool_t *pool) { /* Match any substring containing the pattern, like UNIX 'grep' does. */ const char *pattern = apr_psprintf(pool, "*%s*", search_pattern); - int flags = 0; /* Does the author match the search pattern? */ - if (author && apr_fnmatch(pattern, author, flags) == APR_SUCCESS) + if (author && match(pattern, author, buf)) return TRUE; /* Does the date the search pattern? */ - if (date && apr_fnmatch(pattern, date, flags) == APR_SUCCESS) + if (date && match(pattern, date, buf)) return TRUE; /* Does the log message the search pattern? */ - if (log_message && apr_fnmatch(pattern, log_message, flags) == APR_SUCCESS) + if (log_message && match(pattern, log_message, buf)) return TRUE; if (changed_paths) @@ -150,15 +169,14 @@ match_search_pattern(const char *search_pattern, const char *path = apr_hash_this_key(hi); svn_log_changed_path2_t *log_item; - if (apr_fnmatch(pattern, path, flags) == APR_SUCCESS) + if (match(pattern, path, buf)) return TRUE; /* Match copy-from paths, too. */ log_item = apr_hash_this_val(hi); if (log_item->copyfrom_path && SVN_IS_VALID_REVNUM(log_item->copyfrom_rev) - && apr_fnmatch(pattern, - log_item->copyfrom_path, flags) == APR_SUCCESS) + && match(pattern, log_item->copyfrom_path, buf)) return TRUE; } } @@ -168,13 +186,14 @@ match_search_pattern(const char *search_pattern, /* Match all search patterns in SEARCH_PATTERNS against AUTHOR, DATE, MESSAGE, * and CHANGED_PATHS. Return TRUE if any pattern matches, else FALSE. - * SCRACH_POOL is used for temporary allocations. */ + * BUF and SCRATCH_POOL are used for temporary allocations. */ static svn_boolean_t match_search_patterns(apr_array_header_t *search_patterns, const char *author, const char *date, const char *message, apr_hash_t *changed_paths, + svn_membuf_t *buf, apr_pool_t *scratch_pool) { int i; @@ -197,7 +216,7 @@ match_search_patterns(apr_array_header_t *search_patterns, pattern = APR_ARRAY_IDX(pattern_group, j, const char *); match = match_search_pattern(pattern, author, date, message, - changed_paths, iterpool); + changed_paths, buf, iterpool); if (!match) break; } @@ -331,7 +350,7 @@ svn_cl__log_entry_receiver(void *baton, if (lb->search_patterns && ! match_search_patterns(lb->search_patterns, author, date, message, - log_entry->changed_paths2, pool)) + log_entry->changed_paths2, &lb->buffer, pool)) { if (log_entry->has_children) { @@ -535,7 +554,7 @@ svn_cl__log_entry_receiver_xml(void *baton, /* Match search pattern before XML-escaping. */ if (lb->search_patterns && ! match_search_patterns(lb->search_patterns, author, date, message, - log_entry->changed_paths2, pool)) + log_entry->changed_paths2, &lb->buffer, pool)) { if (log_entry->has_children) { @@ -795,6 +814,7 @@ svn_cl__log(apr_getopt_t *os, lb.diff_extensions = opt_state->extensions; lb.merge_stack = NULL; lb.search_patterns = opt_state->search_patterns; + svn_membuf__create(&lb.buffer, 0, pool); lb.pool = pool; if (opt_state->xml) diff --git a/subversion/svn/merge-cmd.c b/subversion/svn/merge-cmd.c index cbc818b89f7c..f5c19198a5b2 100644 --- a/subversion/svn/merge-cmd.c +++ b/subversion/svn/merge-cmd.c @@ -150,6 +150,85 @@ run_merge(svn_boolean_t two_sources_specified, return merge_err; } +/* Baton type for conflict_func_merge_cmd(). */ +struct conflict_func_merge_cmd_baton { + svn_cl__accept_t accept_which; + const char *path_prefix; + svn_cl__conflict_stats_t *conflict_stats; +}; + +/* This implements the `svn_wc_conflict_resolver_func2_t ' interface. + * + * The merge subcommand needs to install this legacy conflict callback + * in case the user passed an --accept option to 'svn merge'. + * Otherwise, merges involving multiple editor drives might encounter a + * conflict during one of the editor drives and abort with an error, + * rather than resolving conflicts as per the --accept option and + * continuing with the next editor drive. + * ### TODO add an svn_client_merge API that makes this callback unnecessary + */ +static svn_error_t * +conflict_func_merge_cmd(svn_wc_conflict_result_t **result, + const svn_wc_conflict_description2_t *desc, + void *baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + struct conflict_func_merge_cmd_baton *b = baton; + svn_wc_conflict_choice_t choice; + + switch (b->accept_which) + { + case svn_cl__accept_postpone: + case svn_cl__accept_invalid: + case svn_cl__accept_unspecified: + case svn_cl__accept_recommended: + /* Postpone or no valid --accept option, postpone the conflict. */ + choice = svn_wc_conflict_choose_postpone; + break; + case svn_cl__accept_base: + choice = svn_wc_conflict_choose_base; + break; + case svn_cl__accept_working: + choice = svn_wc_conflict_choose_merged; + break; + case svn_cl__accept_mine_conflict: + choice = svn_wc_conflict_choose_mine_conflict; + break; + case svn_cl__accept_theirs_conflict: + choice = svn_wc_conflict_choose_theirs_conflict; + break; + case svn_cl__accept_mine_full: + choice = svn_wc_conflict_choose_mine_full; + break; + case svn_cl__accept_theirs_full: + choice = svn_wc_conflict_choose_theirs_full; + break; + case svn_cl__accept_edit: + case svn_cl__accept_launch: + /* The 'edit' and 'launch' options used to be valid in Subversion 1.9 but + * we can't support these options for the purposes of this callback. */ + choice = svn_wc_conflict_choose_postpone; + break; + } + + *result = svn_wc_create_conflict_result(choice, NULL, result_pool); + + /* If we are resolving a conflict, adjust the summary of conflicts. */ + if (choice != svn_wc_conflict_choose_postpone) + { + const char *local_path; + + local_path = svn_cl__local_style_skip_ancestor(b->path_prefix, + desc->local_abspath, + scratch_pool); + svn_cl__conflict_stats_resolved(b->conflict_stats, local_path, + desc->kind); + } + + return SVN_NO_ERROR; +} + /* This implements the `svn_opt_subcommand_t' interface. */ svn_error_t * svn_cl__merge(apr_getopt_t *os, @@ -157,6 +236,8 @@ svn_cl__merge(apr_getopt_t *os, apr_pool_t *pool) { svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state; + svn_cl__conflict_stats_t *conflict_stats = + ((svn_cl__cmd_baton_t *) baton)->conflict_stats; svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx; apr_array_header_t *targets; const char *sourcepath1 = NULL, *sourcepath2 = NULL, *targetpath = ""; @@ -165,6 +246,7 @@ svn_cl__merge(apr_getopt_t *os, svn_opt_revision_t first_range_start, first_range_end, peg_revision1, peg_revision2; apr_array_header_t *options, *ranges_to_merge = opt_state->revision_ranges; + apr_array_header_t *conflicted_paths; svn_boolean_t has_explicit_target = FALSE; /* Merge doesn't support specifying a revision or revision range @@ -432,6 +514,22 @@ svn_cl__merge(apr_getopt_t *os, "with --reintegrate")); } + /* Install a legacy conflict handler if the --accept option was given. + * Else, svn_client_merge5() may abort the merge in an undesirable way. + * See the docstring at conflict_func_merge_cmd() for details */ + if (opt_state->accept_which != svn_cl__accept_unspecified) + { + struct conflict_func_merge_cmd_baton *b = apr_pcalloc(pool, sizeof(*b)); + + b->accept_which = opt_state->accept_which; + SVN_ERR(svn_dirent_get_absolute(&b->path_prefix, "", pool)); + b->conflict_stats = conflict_stats; + + ctx->conflict_func2 = conflict_func_merge_cmd; + ctx->conflict_baton2 = b; + } + +retry: merge_err = run_merge(two_sources_specified, sourcepath1, peg_revision1, sourcepath2, @@ -447,6 +545,31 @@ svn_cl__merge(apr_getopt_t *os, "fix invalid mergeinfo in target with 'svn propset'")); } + /* Run the interactive resolver if conflicts were raised. */ + SVN_ERR(svn_cl__conflict_stats_get_paths(&conflicted_paths, conflict_stats, + pool, pool)); + if (conflicted_paths) + { + SVN_ERR(svn_cl__walk_conflicts(conflicted_paths, conflict_stats, + opt_state, ctx, pool)); + if (merge_err && + svn_error_root_cause(merge_err)->apr_err == SVN_ERR_WC_FOUND_CONFLICT) + { + svn_error_t *err; + + /* Check if all conflicts were resolved just now. */ + err = svn_cl__conflict_stats_get_paths(&conflicted_paths, + conflict_stats, pool, pool); + if (err) + merge_err = svn_error_compose_create(merge_err, err); + else if (conflicted_paths == NULL) + { + svn_error_clear(merge_err); + goto retry; /* ### conflicts resolved; continue merging */ + } + } + } + if (!opt_state->quiet) { svn_error_t *err = svn_cl__notifier_print_conflict_stats( diff --git a/subversion/svn/notify.c b/subversion/svn/notify.c index c530694c7adf..c15301e32b8b 100644 --- a/subversion/svn/notify.c +++ b/subversion/svn/notify.c @@ -39,6 +39,7 @@ #include "svn_hash.h" #include "cl.h" #include "private/svn_subr_private.h" +#include "private/svn_sorts_private.h" #include "private/svn_dep_compat.h" #include "svn_private_config.h" @@ -53,6 +54,7 @@ struct notify_baton svn_boolean_t is_wc_to_repos_copy; svn_boolean_t sent_first_txdelta; int in_external; + svn_revnum_t progress_revision; svn_boolean_t had_print_error; /* Used to not keep printing error messages when we've already had one print error. */ @@ -144,6 +146,76 @@ resolved_str(apr_pool_t *pool, int n_resolved) n_resolved); } +svn_error_t * +svn_cl__conflict_stats_get_paths(apr_array_header_t **conflicted_paths, + svn_cl__conflict_stats_t *conflict_stats, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + + int n_text = apr_hash_count(conflict_stats->text_conflicts); + int n_prop = apr_hash_count(conflict_stats->prop_conflicts); + int n_tree = apr_hash_count(conflict_stats->tree_conflicts); + apr_hash_t *all_conflicts; + + *conflicted_paths = NULL; + if (n_text == 0 && n_prop == 0 && n_tree == 0) + return SVN_NO_ERROR; + + /* Use a hash table to ensure paths with multiple conflicts are + * returned just once. */ + all_conflicts = apr_hash_make(result_pool); + if (n_text > 0) + { + apr_array_header_t *k_text; + int i; + + SVN_ERR(svn_hash_keys(&k_text, conflict_stats->text_conflicts, + scratch_pool)); + for (i = 0; i < k_text->nelts; i++) + { + const char *path = APR_ARRAY_IDX(k_text, i, const char *); + + svn_hash_sets(all_conflicts, path, ""); + } + } + + if (n_prop > 0) + { + apr_array_header_t *k_prop; + int i; + + SVN_ERR(svn_hash_keys(&k_prop, conflict_stats->prop_conflicts, + scratch_pool)); + for (i = 0; i < k_prop->nelts; i++) + { + const char *path = APR_ARRAY_IDX(k_prop, i, const char *); + + svn_hash_sets(all_conflicts, path, ""); + } + } + + if (n_tree > 0) + { + apr_array_header_t *k_tree; + int i; + + SVN_ERR(svn_hash_keys(&k_tree, conflict_stats->tree_conflicts, + scratch_pool)); + for (i = 0; i < k_tree->nelts; i++) + { + const char *path = APR_ARRAY_IDX(k_tree, i, const char *); + + svn_hash_sets(all_conflicts, path, ""); + } + } + + svn_hash_keys(conflicted_paths, all_conflicts, result_pool); + svn_sort__array(*conflicted_paths, svn_sort_compare_paths); + + return SVN_NO_ERROR; +} + svn_error_t * svn_cl__print_conflict_stats(svn_cl__conflict_stats_t *conflict_stats, apr_pool_t *scratch_pool) @@ -253,6 +325,13 @@ notify_body(struct notify_baton *nb, _("Skipped target: '%s' -- copy-source is missing\n"), path_local)); } + else if (n->content_state == svn_wc_notify_state_obstructed) + { + SVN_ERR(svn_cmdline_printf( + pool, + _("Skipped '%s' -- obstructed by unversioned node\n"), + path_local)); + } else { SVN_ERR(svn_cmdline_printf(pool, _("Skipped '%s'\n"), path_local)); @@ -372,6 +451,56 @@ notify_body(struct notify_baton *nb, path_local)); break; + case svn_wc_notify_resolved_text: + SVN_ERR(svn_cmdline_printf(pool, + _("Merge conflicts in '%s' marked as " + "resolved.\n"), + path_local)); + break; + + case svn_wc_notify_resolved_prop: + SVN_ERR_ASSERT(n->prop_name && strlen(n->prop_name) > 0); + SVN_ERR(svn_cmdline_printf(pool, + _("Conflict in property '%s' at '%s' marked " + "as resolved.\n"), + n->prop_name, path_local)); + break; + + case svn_wc_notify_resolved_tree: + SVN_ERR(svn_cmdline_printf(pool, + _("Tree conflict at '%s' marked as " + "resolved.\n"), + path_local)); + break; + + case svn_wc_notify_begin_search_tree_conflict_details: + SVN_ERR(svn_cmdline_printf(pool, + _("Searching tree conflict details for '%s' " + "in repository:\n"), + path_local)); + nb->progress_revision = 0; + break; + + case svn_wc_notify_tree_conflict_details_progress: + /* First printf is to obliterate any previous progress printf, + assuming no more than 10 digit revisions. Avoid i18n so the + text length is known. We only need to do this if the new + revision is 4 digits less than the previous revision but that + requires counting digits. Dividing by 1000 works well + enough: it triggers when needed, it sometimes triggers when + not needed, but in typical cases it doesn't trigger as the + revisions don't vary much. */ + if (n->revision < nb->progress_revision / 1000) + SVN_ERR(svn_cmdline_printf(pool, "\rChecking r ")); + SVN_ERR(svn_cmdline_printf(pool, "\rChecking r%ld...", n->revision)); + nb->progress_revision = n->revision; + break; + + case svn_wc_notify_end_search_tree_conflict_details: + SVN_ERR(svn_cmdline_printf(pool, _(" done\n"))); + nb->progress_revision = 0; + break; + case svn_wc_notify_add: /* We *should* only get the MIME_TYPE if PATH is a file. If we do get it, and the mime-type is not textual, note that this @@ -415,8 +544,10 @@ notify_body(struct notify_baton *nb, store_path(nb, nb->conflict_stats->prop_conflicts, path_local); statchar_buf[1] = 'C'; } + else if (n->prop_state == svn_wc_notify_state_merged) + statchar_buf[1] = 'G'; else if (n->prop_state == svn_wc_notify_state_changed) - statchar_buf[1] = 'U'; + statchar_buf[1] = 'U'; if (statchar_buf[0] != ' ' || statchar_buf[1] != ' ') { @@ -1118,6 +1249,7 @@ svn_cl__get_notifier(svn_wc_notify_func2_t *notify_func_p, nb->is_export = FALSE; nb->is_wc_to_repos_copy = FALSE; nb->in_external = 0; + nb->progress_revision = 0; nb->had_print_error = FALSE; nb->conflict_stats = conflict_stats; SVN_ERR(svn_dirent_get_absolute(&nb->path_prefix, "", pool)); diff --git a/subversion/svn/propdel-cmd.c b/subversion/svn/propdel-cmd.c index 28c95970b41d..b396b5dc3cf6 100644 --- a/subversion/svn/propdel-cmd.c +++ b/subversion/svn/propdel-cmd.c @@ -49,13 +49,13 @@ svn_cl__propdel(apr_getopt_t *os, { svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state; svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx; - const char *pname, *pname_utf8; + const char *pname; apr_array_header_t *args, *targets; /* Get the property's name (and a UTF-8 version of that name). */ SVN_ERR(svn_opt_parse_num_args(&args, os, 1, pool)); pname = APR_ARRAY_IDX(args, 0, const char *); - SVN_ERR(svn_utf_cstring_to_utf8(&pname_utf8, pname, pool)); + SVN_ERR(svn_utf_cstring_to_utf8(&pname, pname, pool)); /* No need to check svn_prop_name_is_valid for *deleting* properties, and it may even be useful to allow, in case invalid properties sneaked through somehow. */ @@ -78,7 +78,7 @@ svn_cl__propdel(apr_getopt_t *os, &URL, ctx, pool)); /* Let libsvn_client do the real work. */ - SVN_ERR(svn_client_revprop_set2(pname_utf8, NULL, NULL, + SVN_ERR(svn_client_revprop_set2(pname, NULL, NULL, URL, &(opt_state->start_revision), &rev, FALSE, ctx, pool)); } @@ -94,7 +94,7 @@ svn_cl__propdel(apr_getopt_t *os, opt_state->depth = svn_depth_empty; /* For each target, remove the property PNAME. */ - SVN_ERR(svn_client_propset_local(pname_utf8, NULL, targets, + SVN_ERR(svn_client_propset_local(pname, NULL, targets, opt_state->depth, FALSE, opt_state->changelists, ctx, pool)); } diff --git a/subversion/svn/propedit-cmd.c b/subversion/svn/propedit-cmd.c index 520fe6c00c87..59ef24bda93b 100644 --- a/subversion/svn/propedit-cmd.c +++ b/subversion/svn/propedit-cmd.c @@ -47,7 +47,7 @@ /*** Code. ***/ struct commit_info_baton { - const char *pname_utf8; + const char *pname; const char *target_local; }; @@ -60,7 +60,7 @@ commit_info_handler(const svn_commit_info_t *commit_info, SVN_ERR(svn_cmdline_printf(pool, _("Set new value for property '%s' on '%s'\n"), - cib->pname_utf8, cib->target_local)); + cib->pname, cib->target_local)); SVN_ERR(svn_cl__print_commit_info(commit_info, NULL, pool)); return SVN_NO_ERROR; @@ -74,23 +74,23 @@ svn_cl__propedit(apr_getopt_t *os, { svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state; svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx; - const char *pname, *pname_utf8; + const char *pname; apr_array_header_t *args, *targets; /* Validate the input and get the property's name (and a UTF-8 version of that name). */ SVN_ERR(svn_opt_parse_num_args(&args, os, 1, pool)); pname = APR_ARRAY_IDX(args, 0, const char *); - SVN_ERR(svn_utf_cstring_to_utf8(&pname_utf8, pname, pool)); - if (! svn_prop_name_is_valid(pname_utf8)) + SVN_ERR(svn_utf_cstring_to_utf8(&pname, pname, pool)); + if (! svn_prop_name_is_valid(pname)) return svn_error_createf(SVN_ERR_CLIENT_PROPERTY_NAME, NULL, _("'%s' is not a valid Subversion property name"), - pname_utf8); + pname); if (!opt_state->force) - SVN_ERR(svn_cl__check_svn_prop_name(pname_utf8, opt_state->revprop, + SVN_ERR(svn_cl__check_svn_prop_name(pname, opt_state->revprop, svn_cl__prop_use_edit, pool)); - if (opt_state->encoding && !svn_prop_needs_translation(pname_utf8)) + if (opt_state->encoding && !svn_prop_needs_translation(pname)) return svn_error_create (SVN_ERR_UNSUPPORTED_FEATURE, NULL, _("--encoding option applies only to textual" @@ -120,7 +120,7 @@ svn_cl__propedit(apr_getopt_t *os, &URL, ctx, pool)); /* Fetch the current property. */ - SVN_ERR(svn_client_revprop_get(pname_utf8, &propval, + SVN_ERR(svn_client_revprop_get(pname, &propval, URL, &(opt_state->start_revision), &rev, ctx, pool)); @@ -145,13 +145,13 @@ svn_cl__propedit(apr_getopt_t *os, opt_state->editor_cmd, temp_dir, propval, "svn-prop", ctx->config, - svn_prop_needs_translation(pname_utf8), + svn_prop_needs_translation(pname), opt_state->encoding, pool)); /* ...and re-set the property's value accordingly. */ if (propval) { - SVN_ERR(svn_client_revprop_set2(pname_utf8, + SVN_ERR(svn_client_revprop_set2(pname, propval, &original_propval, URL, &(opt_state->start_revision), &rev, opt_state->force, ctx, pool)); @@ -160,13 +160,13 @@ svn_cl__propedit(apr_getopt_t *os, (svn_cmdline_printf (pool, _("Set new value for property '%s' on revision %ld\n"), - pname_utf8, rev)); + pname, rev)); } else { SVN_ERR(svn_cmdline_printf (pool, _("No changes to property '%s' on revision %ld\n"), - pname_utf8, rev)); + pname, rev)); } } else if (opt_state->start_revision.kind != svn_opt_revision_unspecified) @@ -174,7 +174,7 @@ svn_cl__propedit(apr_getopt_t *os, return svn_error_createf (SVN_ERR_CL_ARG_PARSING_ERROR, NULL, _("Cannot specify revision for editing versioned property '%s'"), - pname_utf8); + pname); } else /* operate on a normal, versioned property (not a revprop) */ { @@ -206,7 +206,7 @@ svn_cl__propedit(apr_getopt_t *os, SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, pool)); - cib.pname_utf8 = pname_utf8; + cib.pname = pname; /* For each target, edit the property PNAME. */ for (i = 0; i < targets->nelts; i++) @@ -234,7 +234,7 @@ svn_cl__propedit(apr_getopt_t *os, peg_revision.kind = svn_opt_revision_unspecified; /* Fetch the current property. */ - SVN_ERR(svn_client_propget5(&props, NULL, pname_utf8, abspath_or_url, + SVN_ERR(svn_client_propget5(&props, NULL, pname, abspath_or_url, &peg_revision, &(opt_state->start_revision), &base_rev, svn_depth_empty, @@ -282,7 +282,7 @@ svn_cl__propedit(apr_getopt_t *os, "svn-prop", ctx->config, svn_prop_needs_translation - (pname_utf8), + (pname), opt_state->encoding, subpool)); @@ -295,7 +295,7 @@ svn_cl__propedit(apr_getopt_t *os, { svn_error_t *err = SVN_NO_ERROR; - svn_cl__check_boolean_prop_val(pname_utf8, edited_propval->data, + svn_cl__check_boolean_prop_val(pname, edited_propval->data, subpool); if (ctx->log_msg_func3) @@ -304,7 +304,7 @@ svn_cl__propedit(apr_getopt_t *os, subpool)); if (svn_path_is_url(target)) { - err = svn_client_propset_remote(pname_utf8, edited_propval, + err = svn_client_propset_remote(pname, edited_propval, target, opt_state->force, base_rev, opt_state->revprop_table, @@ -319,9 +319,9 @@ svn_cl__propedit(apr_getopt_t *os, APR_ARRAY_PUSH(targs, const char *) = target; SVN_ERR(svn_cl__propset_print_binary_mime_type_warning( - targs, pname_utf8, propval, subpool)); + targs, pname, propval, subpool)); - err = svn_client_propset_local(pname_utf8, edited_propval, + err = svn_client_propset_local(pname, edited_propval, targs, svn_depth_empty, opt_state->force, NULL, ctx, subpool); @@ -339,14 +339,14 @@ svn_cl__propedit(apr_getopt_t *os, if (!svn_path_is_url(target)) SVN_ERR(svn_cmdline_printf( subpool, _("Set new value for property '%s' on '%s'\n"), - pname_utf8, target_local)); + pname, target_local)); } else { SVN_ERR (svn_cmdline_printf (subpool, _("No changes to property '%s' on '%s'\n"), - pname_utf8, target_local)); + pname, target_local)); } } svn_pool_destroy(subpool); diff --git a/subversion/svn/propget-cmd.c b/subversion/svn/propget-cmd.c index fa04c202ce3d..fe2d1bd3fba1 100644 --- a/subversion/svn/propget-cmd.c +++ b/subversion/svn/propget-cmd.c @@ -137,7 +137,7 @@ print_properties_xml(const char *pname, return SVN_NO_ERROR; } -/* Print the property PNAME_UTF with the value PROPVAL set on ABSPATH_OR_URL +/* Print the property PNAME with the value PROPVAL set on ABSPATH_OR_URL to the stream OUT. If INHERITED_PROPERTY is true then the property described is inherited, @@ -153,7 +153,7 @@ print_single_prop(svn_string_t *propval, const char *abspath_or_URL, const char *wc_path_prefix, svn_stream_t *out, - const char *pname_utf8, + const char *pname, svn_boolean_t print_filenames, svn_boolean_t omit_newline, svn_boolean_t like_proplist, @@ -211,14 +211,14 @@ print_single_prop(svn_string_t *propval, /* Print the property name and value just as "proplist -v" does */ apr_hash_t *hash = apr_hash_make(scratch_pool); - svn_hash_sets(hash, pname_utf8, propval); + svn_hash_sets(hash, pname, propval); SVN_ERR(svn_cmdline__print_prop_hash(out, hash, FALSE, scratch_pool)); } else { /* If this is a special Subversion property, it is stored as UTF8, so convert to the native format. */ - if (svn_prop_needs_translation(pname_utf8)) + if (svn_prop_needs_translation(pname)) SVN_ERR(svn_subst_detranslate_string(&propval, propval, TRUE, scratch_pool)); @@ -244,7 +244,7 @@ print_single_prop(svn_string_t *propval, If IS_URL is true, all paths in PROPS are URLs, else all paths are local paths. - PNAME_UTF8 is the property name of all the properties. + PNAME is the property name of all the properties. If PRINT_FILENAMES is true, print the item's path before each property. @@ -255,7 +255,7 @@ print_single_prop(svn_string_t *propval, static svn_error_t * print_properties(svn_stream_t *out, const char *target_abspath_or_url, - const char *pname_utf8, + const char *pname, apr_hash_t *props, apr_array_header_t *inherited_props, svn_boolean_t print_filenames, @@ -282,7 +282,7 @@ print_properties(svn_stream_t *out, iprop->prop_hash)); SVN_ERR(print_single_prop(propval, target_abspath_or_url, iprop->path_or_url, - path_prefix, out, pname_utf8, + path_prefix, out, pname, print_filenames, omit_newline, like_proplist, TRUE, iterpool)); } @@ -298,7 +298,7 @@ print_properties(svn_stream_t *out, svn_pool_clear(iterpool); SVN_ERR(print_single_prop(propval, target_abspath_or_url, filename, - path_prefix, out, pname_utf8, print_filenames, + path_prefix, out, pname, print_filenames, omit_newline, like_proplist, FALSE, iterpool)); } @@ -317,7 +317,7 @@ svn_cl__propget(apr_getopt_t *os, { svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state; svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx; - const char *pname, *pname_utf8; + const char *pname; apr_array_header_t *args, *targets; svn_stream_t *out; svn_boolean_t warned = FALSE; @@ -328,15 +328,14 @@ svn_cl__propget(apr_getopt_t *os, _("--verbose cannot be used with --revprop or " "--no-newline or --xml")); - /* PNAME is first argument (and PNAME_UTF8 will be a UTF-8 version - thereof) */ + /* PNAME is first argument */ SVN_ERR(svn_opt_parse_num_args(&args, os, 1, pool)); pname = APR_ARRAY_IDX(args, 0, const char *); - SVN_ERR(svn_utf_cstring_to_utf8(&pname_utf8, pname, pool)); - if (! svn_prop_name_is_valid(pname_utf8)) + SVN_ERR(svn_utf_cstring_to_utf8(&pname, pname, pool)); + if (! svn_prop_name_is_valid(pname)) return svn_error_createf(SVN_ERR_CLIENT_PROPERTY_NAME, NULL, _("'%s' is not a valid Subversion property name"), - pname_utf8); + pname); SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os, opt_state->targets, @@ -363,7 +362,7 @@ svn_cl__propget(apr_getopt_t *os, &URL, ctx, pool)); /* Let libsvn_client do the real work. */ - SVN_ERR(svn_client_revprop_get(pname_utf8, &propval, + SVN_ERR(svn_client_revprop_get(pname, &propval, URL, &(opt_state->start_revision), &rev, ctx, pool)); @@ -372,7 +371,7 @@ svn_cl__propget(apr_getopt_t *os, return svn_error_createf(SVN_ERR_PROPERTY_NOT_FOUND, NULL, _("Property '%s' not found on " "revision %s"), - pname_utf8, + pname, svn_opt__revision_to_string( &opt_state->start_revision, pool)); @@ -390,7 +389,7 @@ svn_cl__propget(apr_getopt_t *os, "revprops", "rev", revstr, SVN_VA_NULL); - svn_cmdline__print_xml_prop(&sb, pname_utf8, propval, FALSE, + svn_cmdline__print_xml_prop(&sb, pname, propval, FALSE, pool); svn_xml_make_close_tag(&sb, pool, "revprops"); @@ -405,7 +404,7 @@ svn_cl__propget(apr_getopt_t *os, /* If this is a special Subversion property, it is stored as UTF8 and LF, so convert to the native locale and eol-style. */ - if (svn_prop_needs_translation(pname_utf8)) + if (svn_prop_needs_translation(pname)) SVN_ERR(svn_subst_detranslate_string(&printable_val, propval, TRUE, pool)); @@ -462,7 +461,7 @@ svn_cl__propget(apr_getopt_t *os, SVN_ERR(svn_client_propget5( &props, opt_state->show_inherited_props ? &inherited_props : NULL, - pname_utf8, truepath, + pname, truepath, &peg_revision, &(opt_state->start_revision), NULL, opt_state->depth, @@ -491,7 +490,7 @@ svn_cl__propget(apr_getopt_t *os, svn_error_t *err; err = svn_error_createf(SVN_ERR_PROPERTY_NOT_FOUND, NULL, _("Property '%s' not found on '%s'"), - pname_utf8, target); + pname, target); svn_handle_warning2(stderr, err, "svn: "); svn_error_clear(err); warned = TRUE; @@ -499,12 +498,12 @@ svn_cl__propget(apr_getopt_t *os, if (opt_state->xml) SVN_ERR(print_properties_xml( - pname_utf8, props, + pname, props, opt_state->show_inherited_props ? inherited_props : NULL, subpool)); else SVN_ERR(print_properties( - out, truepath, pname_utf8, + out, truepath, pname, props, opt_state->show_inherited_props ? inherited_props : NULL, print_filenames, diff --git a/subversion/svn/propset-cmd.c b/subversion/svn/propset-cmd.c index 07b9bbdb57a4..05087069005a 100644 --- a/subversion/svn/propset-cmd.c +++ b/subversion/svn/propset-cmd.c @@ -51,7 +51,7 @@ svn_cl__propset(apr_getopt_t *os, { svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state; svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx; - const char *pname, *pname_utf8; + const char *pname; svn_string_t *propval = NULL; svn_boolean_t propval_came_from_cmdline; apr_array_header_t *args, *targets; @@ -62,13 +62,13 @@ svn_cl__propset(apr_getopt_t *os, SVN_ERR(svn_opt_parse_num_args(&args, os, opt_state->filedata ? 1 : 2, scratch_pool)); pname = APR_ARRAY_IDX(args, 0, const char *); - SVN_ERR(svn_utf_cstring_to_utf8(&pname_utf8, pname, scratch_pool)); - if (! svn_prop_name_is_valid(pname_utf8)) + SVN_ERR(svn_utf_cstring_to_utf8(&pname, pname, scratch_pool)); + if (! svn_prop_name_is_valid(pname)) return svn_error_createf(SVN_ERR_CLIENT_PROPERTY_NAME, NULL, _("'%s' is not a valid Subversion property name"), - pname_utf8); + pname); if (!opt_state->force) - SVN_ERR(svn_cl__check_svn_prop_name(pname_utf8, opt_state->revprop, + SVN_ERR(svn_cl__check_svn_prop_name(pname, opt_state->revprop, svn_cl__prop_use_set, scratch_pool)); /* Get the PROPVAL from either an external file, or from the command @@ -87,7 +87,7 @@ svn_cl__propset(apr_getopt_t *os, /* We only want special Subversion property values to be in UTF-8 and LF line endings. All other propvals are taken literally. */ - if (svn_prop_needs_translation(pname_utf8)) + if (svn_prop_needs_translation(pname)) SVN_ERR(svn_subst_translate_string2(&propval, NULL, NULL, propval, opt_state->encoding, FALSE, scratch_pool, scratch_pool)); @@ -120,7 +120,7 @@ svn_cl__propset(apr_getopt_t *os, &URL, ctx, scratch_pool)); /* Let libsvn_client do the real work. */ - SVN_ERR(svn_client_revprop_set2(pname_utf8, propval, NULL, + SVN_ERR(svn_client_revprop_set2(pname, propval, NULL, URL, &(opt_state->start_revision), &rev, opt_state->force, ctx, scratch_pool)); @@ -174,17 +174,17 @@ svn_cl__propset(apr_getopt_t *os, } SVN_ERR(svn_cl__propset_print_binary_mime_type_warning(targets, - pname_utf8, + pname, propval, scratch_pool)); - SVN_ERR(svn_client_propset_local(pname_utf8, propval, targets, + SVN_ERR(svn_client_propset_local(pname, propval, targets, opt_state->depth, opt_state->force, opt_state->changelists, ctx, scratch_pool)); if (! opt_state->quiet) - svn_cl__check_boolean_prop_val(pname_utf8, propval->data, scratch_pool); + svn_cl__check_boolean_prop_val(pname, propval->data, scratch_pool); } return SVN_NO_ERROR; diff --git a/subversion/svn/resolve-cmd.c b/subversion/svn/resolve-cmd.c index 035bf29aff5a..bbf9ff548ef5 100644 --- a/subversion/svn/resolve-cmd.c +++ b/subversion/svn/resolve-cmd.c @@ -30,6 +30,7 @@ #include "svn_client.h" #include "svn_error.h" #include "svn_pools.h" +#include "svn_hash.h" #include "cl.h" #include "svn_private_config.h" @@ -38,6 +39,127 @@ /*** Code. ***/ +struct conflict_walker_baton +{ + svn_client_ctx_t *ctx; + svn_cl__accept_t accept_which; + svn_boolean_t quit; + svn_boolean_t external_failed; + svn_boolean_t printed_summary; + const char *editor_cmd; + const char *path_prefix; + svn_cmdline_prompt_baton_t *pb; + svn_cl__conflict_stats_t *conflict_stats; +}; + +/* Implements svn_client_conflict_walk_func_t. */ +static svn_error_t * +conflict_walker(void *baton, svn_client_conflict_t *conflict, + apr_pool_t *scratch_pool) +{ + struct conflict_walker_baton *cwb = baton; + + SVN_ERR(svn_cl__resolve_conflict(&cwb->quit, &cwb->external_failed, + &cwb->printed_summary, conflict, + cwb->accept_which, cwb->editor_cmd, + cwb->path_prefix, cwb->pb, + cwb->conflict_stats, + cwb->ctx, scratch_pool)); + if (cwb->quit) + return svn_error_create(SVN_ERR_CANCELLED, NULL, NULL); + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_cl__walk_conflicts(apr_array_header_t *targets, + svn_cl__conflict_stats_t *conflict_stats, + svn_cl__opt_state_t *opt_state, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + svn_boolean_t had_error = FALSE; + svn_cmdline_prompt_baton_t *pb = apr_palloc(scratch_pool, sizeof(*pb)); + struct conflict_walker_baton cwb = { 0 }; + const char *path_prefix; + svn_error_t *err; + int i; + apr_pool_t *iterpool; + + SVN_ERR(svn_dirent_get_absolute(&path_prefix, "", scratch_pool)); + + pb->cancel_func = ctx->cancel_func; + pb->cancel_baton = ctx->cancel_baton; + + cwb.ctx = ctx; + cwb.accept_which = opt_state->accept_which; + cwb.quit = FALSE; + cwb.external_failed = FALSE; + cwb.printed_summary = FALSE; + cwb.editor_cmd = opt_state->editor_cmd; + cwb.path_prefix = path_prefix; + cwb.pb = pb; + cwb.conflict_stats = conflict_stats; + + iterpool = svn_pool_create(scratch_pool); + for (i = 0; i < targets->nelts; i++) + { + const char *target = APR_ARRAY_IDX(targets, i, const char *); + const char *local_abspath; + svn_client_conflict_t *conflict; + + svn_pool_clear(iterpool); + + SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton)); + + SVN_ERR(svn_dirent_get_absolute(&local_abspath, target, iterpool)); + + if (opt_state->depth == svn_depth_empty) + { + SVN_ERR(svn_client_conflict_get(&conflict, local_abspath, ctx, + iterpool, iterpool)); + err = svn_cl__resolve_conflict(&cwb.quit, &cwb.external_failed, + &cwb.printed_summary, + conflict, opt_state->accept_which, + opt_state->editor_cmd, + path_prefix, pb, conflict_stats, + ctx, iterpool); + } + else + err = svn_client_conflict_walk(local_abspath, opt_state->depth, + conflict_walker, &cwb, ctx, iterpool); + + if (err) + { + svn_error_t *root = svn_error_root_cause(err); + + if (root->apr_err == SVN_ERR_WC_PATH_NOT_FOUND) + { + /* ### Ignore. These errors can happen due to the working copy + * ### being re-arranged during tree conflict resolution. */ + svn_error_clear(err); + continue; + } + else if (root->apr_err == SVN_ERR_CANCELLED) + { + svn_error_clear(err); + break; + } + + svn_handle_warning2(stderr, svn_error_root_cause(err), "svn: "); + svn_error_clear(err); + had_error = TRUE; + } + } + svn_pool_destroy(iterpool); + + if (had_error) + return svn_error_create(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, + _("Failure occurred resolving one or more " + "conflicts")); + return SVN_NO_ERROR; +} + /* This implements the `svn_opt_subcommand_t' interface. */ svn_error_t * svn_cl__resolve(apr_getopt_t *os, @@ -45,44 +167,10 @@ svn_cl__resolve(apr_getopt_t *os, apr_pool_t *scratch_pool) { svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state; + svn_cl__conflict_stats_t *conflict_stats = + ((svn_cl__cmd_baton_t *) baton)->conflict_stats; svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx; - svn_wc_conflict_choice_t conflict_choice; - svn_error_t *err; apr_array_header_t *targets; - int i; - apr_pool_t *iterpool; - svn_boolean_t had_error = FALSE; - - switch (opt_state->accept_which) - { - case svn_cl__accept_working: - conflict_choice = svn_wc_conflict_choose_merged; - break; - case svn_cl__accept_base: - conflict_choice = svn_wc_conflict_choose_base; - break; - case svn_cl__accept_theirs_conflict: - conflict_choice = svn_wc_conflict_choose_theirs_conflict; - break; - case svn_cl__accept_mine_conflict: - conflict_choice = svn_wc_conflict_choose_mine_conflict; - break; - case svn_cl__accept_theirs_full: - conflict_choice = svn_wc_conflict_choose_theirs_full; - break; - case svn_cl__accept_mine_full: - conflict_choice = svn_wc_conflict_choose_mine_full; - break; - case svn_cl__accept_unspecified: - if (opt_state->non_interactive) - return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, - _("missing --accept option")); - conflict_choice = svn_wc_conflict_choose_unspecified; - break; - default: - return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, - _("invalid 'accept' ARG")); - } SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os, opt_state->targets, @@ -103,29 +191,22 @@ svn_cl__resolve(apr_getopt_t *os, SVN_ERR(svn_cl__check_targets_are_local_paths(targets)); - iterpool = svn_pool_create(scratch_pool); - for (i = 0; i < targets->nelts; i++) + if (opt_state->accept_which == svn_cl__accept_unspecified && + opt_state->non_interactive) { - const char *target = APR_ARRAY_IDX(targets, i, const char *); - svn_pool_clear(iterpool); - SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton)); - err = svn_client_resolve(target, - opt_state->depth, conflict_choice, - ctx, - iterpool); - if (err) - { - svn_handle_warning2(stderr, err, "svn: "); - svn_error_clear(err); - had_error = TRUE; - } + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("missing --accept option")); + } + else if (opt_state->accept_which == svn_cl__accept_postpone || + opt_state->accept_which == svn_cl__accept_edit || + opt_state->accept_which == svn_cl__accept_launch) + { + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("invalid 'accept' ARG")); } - svn_pool_destroy(iterpool); - if (had_error) - return svn_error_create(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, - _("Failure occurred resolving one or more " - "conflicts")); + SVN_ERR(svn_cl__walk_conflicts(targets, conflict_stats, + opt_state, ctx, scratch_pool)); return SVN_NO_ERROR; } diff --git a/subversion/svn/shelve-cmd.c b/subversion/svn/shelve-cmd.c new file mode 100644 index 000000000000..df88a651d9c2 --- /dev/null +++ b/subversion/svn/shelve-cmd.c @@ -0,0 +1,369 @@ +/* + * shelve-cmd.c -- Shelve commands. + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + +/* We define this here to remove any further warnings about the usage of + experimental functions in this file. */ +#define SVN_EXPERIMENTAL + +#include "svn_client.h" +#include "svn_error_codes.h" +#include "svn_error.h" +#include "svn_path.h" +#include "svn_utf.h" + +#include "cl.h" + +#include "svn_private_config.h" +#include "private/svn_sorts_private.h" + + +/* First argument should be the name of a shelved change. */ +static svn_error_t * +get_name(const char **name, + apr_getopt_t *os, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + apr_array_header_t *args; + + SVN_ERR(svn_opt_parse_num_args(&args, os, 1, scratch_pool)); + SVN_ERR(svn_utf_cstring_to_utf8(name, + APR_ARRAY_IDX(args, 0, const char *), + result_pool)); + return SVN_NO_ERROR; +} + +/* A comparison function for svn_sort__hash(), comparing the mtime of two + svn_client_shelved_patch_info_t's. */ +static int +compare_shelved_patch_infos_by_mtime(const svn_sort__item_t *a, + const svn_sort__item_t *b) +{ + svn_client_shelved_patch_info_t *a_val = a->value; + svn_client_shelved_patch_info_t *b_val = b->value; + + return (a_val->dirent->mtime < b_val->dirent->mtime) + ? -1 : (a_val->dirent->mtime > b_val->dirent->mtime) ? 1 : 0; +} + +/* Return a list of shelved changes sorted by patch file mtime, oldest first. + */ +static svn_error_t * +list_sorted_by_date(apr_array_header_t **list, + const char *local_abspath, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + apr_hash_t *shelved_patch_infos; + + SVN_ERR(svn_client_shelves_list(&shelved_patch_infos, local_abspath, + ctx, scratch_pool, scratch_pool)); + *list = svn_sort__hash(shelved_patch_infos, + compare_shelved_patch_infos_by_mtime, + scratch_pool); + return SVN_NO_ERROR; +} + +#ifndef WIN32 +/* Run CMD with ARGS. + * Send its stdout to the parent's stdout. Disconnect its stdin and stderr. + */ +static svn_error_t * +run_cmd(const char *cmd, + const char *const *args, + apr_pool_t *scratch_pool) +{ + apr_status_t apr_err; + apr_file_t *outfile; + svn_error_t *err; + int exitcode; + + apr_err = apr_file_open_stdout(&outfile, scratch_pool); + if (apr_err) + return svn_error_wrap_apr(apr_err, "Can't open stdout"); + + err = svn_io_run_cmd(NULL /*path*/, cmd, args, + &exitcode, NULL /*exitwhy*/, + TRUE /*inherit*/, + NULL /*infile*/, outfile, NULL /*errfile*/, + scratch_pool); + if (err || exitcode) + return svn_error_createf(SVN_ERR_EXTERNAL_PROGRAM, err, + _("Could not run external command '%s'"), cmd); + return SVN_NO_ERROR; +} +#endif + +/* Display a list of shelved changes */ +static svn_error_t * +shelves_list(const char *local_abspath, + svn_boolean_t diffstat, + svn_client_ctx_t *ctx, + apr_pool_t *scratch_pool) +{ + apr_array_header_t *list; + int i; + + SVN_ERR(list_sorted_by_date(&list, + local_abspath, ctx, scratch_pool)); + + for (i = 0; i < list->nelts; i++) + { + const svn_sort__item_t *item = &APR_ARRAY_IDX(list, i, svn_sort__item_t); + const char *name = item->key; + svn_client_shelved_patch_info_t *info = item->value; + int age = (int)((apr_time_now() - info->mtime) / 1000000 / 60); + apr_hash_t *paths; + + SVN_ERR(svn_client_shelf_get_paths(&paths, + name, local_abspath, ctx, + scratch_pool, scratch_pool)); + + SVN_ERR(svn_cmdline_printf(scratch_pool, + _("%-30s %6d mins old %10ld bytes %4d paths changed\n"), + name, age, (long)info->dirent->filesize, + apr_hash_count(paths))); + SVN_ERR(svn_cmdline_printf(scratch_pool, + _(" %.50s\n"), + info->message)); + + if (diffstat) + { +#ifndef WIN32 + const char *args[4]; + svn_error_t *err; + + args[0] = "diffstat"; + args[1] = "-p0"; + args[2] = info->patch_path; + args[3] = NULL; + err = run_cmd("diffstat", args, scratch_pool); + if (err) + svn_error_clear(err); + else + SVN_ERR(svn_cmdline_printf(scratch_pool, + "\n")); +#endif + } + } + + return SVN_NO_ERROR; +} + +/* Find the name of the youngest shelved change. + */ +static svn_error_t * +name_of_youngest(const char **name_p, + const char *local_abspath, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + apr_array_header_t *list; + const svn_sort__item_t *youngest_item; + + SVN_ERR(list_sorted_by_date(&list, + local_abspath, ctx, scratch_pool)); + if (list->nelts == 0) + return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, NULL, + _("No shelved changes found")); + + youngest_item = &APR_ARRAY_IDX(list, list->nelts - 1, svn_sort__item_t); + *name_p = youngest_item->key; + return SVN_NO_ERROR; +} + +/* This implements the `svn_opt_subcommand_t' interface. */ +svn_error_t * +svn_cl__shelve(apr_getopt_t *os, + void *baton, + apr_pool_t *pool) +{ + svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state; + svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx; + const char *local_abspath; + const char *name; + apr_array_header_t *targets; + svn_boolean_t has_changes; + + if (opt_state->quiet) + ctx->notify_func2 = NULL; /* Easy out: avoid unneeded work */ + + SVN_ERR(svn_dirent_get_absolute(&local_abspath, "", pool)); + + if (opt_state->list) + { + if (os->ind < os->argc) + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, 0, NULL); + + SVN_ERR(shelves_list(local_abspath, + ! opt_state->quiet /*diffstat*/, + ctx, pool)); + return SVN_NO_ERROR; + } + + SVN_ERR(get_name(&name, os, pool, pool)); + + if (opt_state->remove) + { + if (os->ind < os->argc) + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, 0, NULL); + + SVN_ERR(svn_client_shelves_delete(name, local_abspath, + opt_state->dry_run, + ctx, pool)); + if (! opt_state->quiet) + SVN_ERR(svn_cmdline_printf(pool, "deleted '%s'\n", name)); + return SVN_NO_ERROR; + } + + /* Parse the remaining arguments as paths. */ + SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os, + opt_state->targets, + ctx, FALSE, pool)); + svn_opt_push_implicit_dot_target(targets, pool); + + { + svn_depth_t depth = opt_state->depth; + svn_error_t *err; + + /* shelve has no implicit dot-target `.', so don't you put that + code here! */ + if (!targets->nelts) + return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL); + + SVN_ERR(svn_cl__check_targets_are_local_paths(targets)); + + if (depth == svn_depth_unknown) + depth = svn_depth_infinity; + + SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, pool)); + + if (ctx->log_msg_func3) + SVN_ERR(svn_cl__make_log_msg_baton(&ctx->log_msg_baton3, + opt_state, NULL, ctx->config, + pool)); + err = svn_client_shelve(name, + targets, depth, opt_state->changelists, + opt_state->keep_local, opt_state->dry_run, + ctx, pool); + if (ctx->log_msg_func3) + SVN_ERR(svn_cl__cleanup_log_msg(ctx->log_msg_baton3, + err, pool)); + else + SVN_ERR(err); + } + + /* If no modifications were shelved, throw an error. */ + SVN_ERR(svn_client_shelf_has_changes(&has_changes, + name, local_abspath, ctx, pool)); + if (! has_changes) + { + SVN_ERR(svn_client_shelves_delete(name, local_abspath, + opt_state->dry_run, ctx, pool)); + return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL, + _("No changes were shelved")); + } + + if (! opt_state->quiet) + SVN_ERR(svn_cmdline_printf(pool, "shelved '%s'\n", name)); + + return SVN_NO_ERROR; +} + +/* This implements the `svn_opt_subcommand_t' interface. */ +svn_error_t * +svn_cl__unshelve(apr_getopt_t *os, + void *baton, + apr_pool_t *pool) +{ + svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state; + svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx; + const char *local_abspath; + const char *name; + apr_array_header_t *targets; + + SVN_ERR(svn_dirent_get_absolute(&local_abspath, "", pool)); + + if (opt_state->list) + { + if (os->ind < os->argc) + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, 0, NULL); + + SVN_ERR(shelves_list(local_abspath, + ! opt_state->quiet /*diffstat*/, + ctx, pool)); + return SVN_NO_ERROR; + } + + if (os->ind < os->argc) + { + SVN_ERR(get_name(&name, os, pool, pool)); + } + else + { + SVN_ERR(name_of_youngest(&name, local_abspath, ctx, pool, pool)); + SVN_ERR(svn_cmdline_printf(pool, + _("unshelving the youngest change, '%s'\n"), + name)); + } + + /* There should be no remaining arguments. */ + SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os, + opt_state->targets, + ctx, FALSE, pool)); + if (targets->nelts) + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, 0, NULL); + + if (opt_state->quiet) + ctx->notify_func2 = NULL; /* Easy out: avoid unneeded work */ + + SVN_ERR(svn_client_unshelve(name, local_abspath, + opt_state->keep_local, opt_state->dry_run, + ctx, pool)); + if (! opt_state->quiet) + SVN_ERR(svn_cmdline_printf(pool, "unshelved '%s'\n", name)); + + return SVN_NO_ERROR; +} + +/* This implements the `svn_opt_subcommand_t' interface. */ +svn_error_t * +svn_cl__shelves(apr_getopt_t *os, + void *baton, + apr_pool_t *pool) +{ + svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state; + svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx; + const char *local_abspath; + + /* There should be no remaining arguments. */ + if (os->ind < os->argc) + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, 0, NULL); + + SVN_ERR(svn_dirent_get_absolute(&local_abspath, "", pool)); + SVN_ERR(shelves_list(local_abspath, ! opt_state->quiet /*diffstat*/, + ctx, pool)); + + return SVN_NO_ERROR; +} diff --git a/subversion/svn/status.c b/subversion/svn/status.c index 9ab9c5926c55..409540267b4f 100644 --- a/subversion/svn/status.c +++ b/subversion/svn/status.c @@ -282,11 +282,10 @@ print_status(const char *target_abspath, if (tree_conflicted) { - const svn_wc_conflict_description2_t *tree_conflict; - SVN_ERR(svn_wc__get_tree_conflict(&tree_conflict, ctx->wc_ctx, - local_abspath, pool, pool)); - SVN_ERR_ASSERT(tree_conflict != NULL); + svn_client_conflict_t *tree_conflict; + SVN_ERR(svn_client_conflict_get(&tree_conflict, local_abspath, + ctx, pool, pool)); tree_status_code = 'C'; SVN_ERR(svn_cl__get_human_readable_tree_conflict_description( &desc, tree_conflict, pool)); diff --git a/subversion/svn/svn.c b/subversion/svn/svn.c index 058be707d074..48b894f49983 100644 --- a/subversion/svn/svn.c +++ b/subversion/svn/svn.c @@ -33,7 +33,6 @@ #include #include #include -#include #include "svn_cmdline.h" #include "svn_pools.h" @@ -57,6 +56,7 @@ #include "private/svn_opt_private.h" #include "private/svn_cmdline_private.h" #include "private/svn_subr_private.h" +#include "private/svn_utf_private.h" #include "svn_private_config.h" @@ -68,6 +68,7 @@ use the short option letter as identifier. */ typedef enum svn_cl__longopt_t { opt_auth_password = SVN_OPT_FIRST_LONGOPT_ID, + opt_auth_password_from_stdin, opt_auth_username, opt_autoprops, opt_changelist, @@ -143,6 +144,11 @@ typedef enum svn_cl__longopt_t { opt_show_passwords, opt_pin_externals, opt_show_item, + opt_adds_as_modification, + opt_vacuum_pristines, + opt_delete, + opt_keep_shelved, + opt_list } svn_cl__longopt_t; @@ -198,6 +204,9 @@ const apr_getopt_option_t svn_cl__options[] = N_("specify a password ARG (caution: on many operating\n" " " "systems, other users will be able to see this)")}, + {"password-from-stdin", + opt_auth_password_from_stdin, 0, + N_("read password from stdin")}, {"extensions", 'x', 1, N_("Specify differencing options for external diff or\n" " " @@ -327,9 +336,9 @@ const apr_getopt_option_t svn_cl__options[] = " " "'theirs-conflict', 'mine-full', 'theirs-full',\n" " " - "'edit', 'launch')\n" + "'edit', 'launch', 'recommended') (shorthand:\n" " " - "(shorthand: 'p', 'mc', 'tc', 'mf', 'tf', 'e', 'l')" + "'p', 'mc', 'tc', 'mf', 'tf', 'e', 'l', 'r')" )}, {"show-revs", opt_show_revs, 1, N_("specify which collection of revisions to display\n" @@ -400,7 +409,11 @@ const apr_getopt_option_t svn_cl__options[] = {"show-inherited-props", opt_show_inherited_props, 0, N_("retrieve properties set on parents of the target")}, {"search", opt_search, 1, - N_("use ARG as search pattern (glob syntax)")}, + N_("use ARG as search pattern (glob syntax, case-\n" + " " + "and accent-insensitive, may require quotation marks\n" + " " + "to prevent shell expansion)")}, {"search-and", opt_search_and, 1, N_("combine ARG with the previous search pattern")}, {"log", opt_mergeinfo_log, 0, @@ -415,15 +428,55 @@ const apr_getopt_option_t svn_cl__options[] = " " "current revision (recommended when tagging)")}, {"show-item", opt_show_item, 1, - N_("print only the item identified by ARG ('kind',\n" + N_("print only the item identified by ARG:\n" + " " + " 'kind' node kind of TARGET\n" + " " + " 'url' URL of TARGET in the repository\n" + " " + " 'relative-url'\n" + " " + " repository-relative URL of TARGET\n" + " " + " 'repos-root-url'\n" + " " + " root URL of repository\n" + " " + " 'repos-uuid' UUID of repository\n" + " " + " 'revision' specified or implied revision\n" + " " + " 'last-changed-revision'\n" + " " + " last change of TARGET at or before\n" + " " + " 'revision'\n" + " " + " 'last-changed-date'\n" + " " + " date of 'last-changed-revision'\n" + " " + " 'last-changed-author'\n" + " " + " author of 'last-changed-revision'\n" + " " + " 'wc-root' root of TARGET's working copy")}, + + {"adds-as-modification", opt_adds_as_modification, 0, + N_("Local additions are merged with incoming additions\n" " " - "'url', 'relative-url', 'repos-root-url',\n" + "instead of causing a tree conflict. Use of this\n" " " - "'repos-uuid', 'revision', 'last-changed-revision',\n" + "option is not recommended! Use 'svn resolve' to\n" " " - "'last-changed-date', 'last-changed-author',\n" - " " - "'wc-root')")}, + "resolve tree conflicts instead.")}, + + {"vacuum-pristines", opt_vacuum_pristines, 0, + N_("remove unreferenced pristines from .svn directory")}, + + {"list", opt_list, 0, N_("list shelved patches")}, + {"keep-shelved", opt_keep_shelved, 0, N_("do not delete the shelved patch")}, + {"delete", opt_delete, 0, N_("delete the shelved patch")}, /* Long-opt Aliases * @@ -455,7 +508,8 @@ const apr_getopt_option_t svn_cl__options[] = command to take these arguments allows scripts to just pass them willy-nilly to every invocation of 'svn') . */ const int svn_cl__global_options[] = -{ opt_auth_username, opt_auth_password, opt_no_auth_cache, opt_non_interactive, +{ opt_auth_username, opt_auth_password, opt_auth_password_from_stdin, + opt_no_auth_cache, opt_non_interactive, opt_force_interactive, opt_trust_server_cert, opt_trust_server_cert_failures, opt_config_dir, opt_config_options, 0 @@ -491,7 +545,7 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] = " or more patterns. With the --remove option, remove cached authentication\n" " credentials matching one or more patterns.\n" "\n" - " If more than one pattern is specified credentials are considered only they\n" + " If more than one pattern is specified credentials are considered only if they\n" " match all specified patterns. Patterns are matched case-sensitively and may\n" " contain glob wildcards:\n" " ? matches any single character\n" @@ -571,38 +625,45 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] = {'r', 'q', 'N', opt_depth, opt_force, opt_ignore_externals} }, { "cleanup", svn_cl__cleanup, {0}, N_ - ("Recursively clean up the working copy, removing write locks, resuming\n" - "unfinished operations, etc.\n" - "usage: cleanup [WCPATH...]\n" + ("Either recover from an interrupted operation that left the working copy locked,\n" + "or remove unwanted files.\n" + "usage: 1. cleanup [WCPATH...]\n" + " 2. cleanup --remove-unversioned [WCPATH...]\n" + " cleanup --remove-ignored [WCPATH...]\n" + " 3. cleanup --vacuum-pristines [WCPATH...]\n" "\n" - " By default, finish any unfinished business in the working copy at WCPATH,\n" - " and remove write locks (shown as 'L' by the 'svn status' command) from\n" - " the working copy. Usually, this is only necessary if a Subversion client\n" - " has crashed while using the working copy, leaving it in an unusable state.\n" + " 1. When none of the options --remove-unversioned, --remove-ignored, and\n" + " --vacuum-pristines is specified, remove all write locks (shown as 'L' by\n" + " the 'svn status' command) from the working copy. Usually, this is only\n" + " necessary if a Subversion client has crashed while using the working copy,\n" + " leaving it in an unusable state.\n" "\n" - " WARNING: There is no mechanism that will protect write locks still\n" - " being used by other Subversion clients. Running this command\n" - " while another client is using the working copy can corrupt\n" - " the working copy beyond repair!\n" + " WARNING: There is no mechanism that will protect write locks still\n" + " being used by other Subversion clients. Running this command\n" + " without any options while another client is using the working\n" + " copy can corrupt the working copy beyond repair!\n" "\n" - " If the --remove-unversioned option or the --remove-ignored option\n" - " is given, remove any unversioned or ignored items within WCPATH.\n" - " To prevent accidental working copy corruption, unversioned or ignored\n" - " items can only be removed if the working copy is not already locked\n" - " for writing by another Subversion client.\n" - " Note that the 'svn status' command shows unversioned items as '?',\n" - " and ignored items as 'I' if the --no-ignore option is given to it.\n"), - {opt_merge_cmd, opt_remove_unversioned, opt_remove_ignored, - opt_include_externals, 'q'} }, - + " 2. If the --remove-unversioned option or the --remove-ignored option\n" + " is given, remove any unversioned or ignored items within WCPATH.\n" + " Note that the 'svn status' command shows unversioned items as '?',\n" + " and ignored items as 'I' if the --no-ignore option is given to it.\n" + "\n" + " 3. If the --vacuum-pristines option is given, remove pristine copies of\n" + " files which are stored inside the .svn directory and which are no longer\n" + " referenced by any file in the working copy.\n"), + { opt_remove_unversioned, opt_remove_ignored, opt_vacuum_pristines, + opt_include_externals, 'q', opt_merge_cmd }, + { { opt_merge_cmd, N_("deprecated and ignored") } } }, + { "commit", svn_cl__commit, {"ci"}, N_("Send changes from your working copy to the repository.\n" "usage: commit [PATH...]\n" "\n" " A log message must be provided, but it can be empty. If it is not\n" " given by a --message or --file option, an editor will be started.\n" + "\n" " If any targets are (or contain) locked items, those will be\n" - " unlocked after a successful commit.\n" + " unlocked after a successful commit, unless --no-unlock is given.\n" "\n" " If --include-externals is given, also commit file and directory\n" " externals reached by recursion. Do not commit externals with a\n" @@ -619,8 +680,9 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] = " WC -> URL: immediately commit a copy of WC to URL\n" " URL -> WC: check out URL into WC, schedule for addition\n" " URL -> URL: complete server-side copy; used to branch and tag\n" - " All the SRCs must be of the same type. When copying multiple sources,\n" - " they will be added as children of DST, which must be a directory.\n" + " All the SRCs must be of the same type. If DST is an existing directory,\n" + " the sources will be added as children of DST. When copying multiple\n" + " sources, DST must be an existing directory.\n" "\n" " WARNING: For compatibility with previous versions of Subversion,\n" " copies performed using two working copy paths (WC -> WC) will not\n" @@ -734,28 +796,19 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] = "usage: info [TARGET[@REV]...]\n" "\n" " Print information about each TARGET (default: '.').\n" - " TARGET may be either a working-copy path or URL. If specified, REV\n" - " determines in which revision the target is first looked up.\n" + " TARGET may be either a working-copy path or a URL. If specified, REV\n" + " determines in which revision the target is first looked up; the default\n" + " is HEAD for a URL or BASE for a WC path.\n" "\n" " With --show-item, print only the value of one item of information\n" - " about TARGET. One of the following items can be selected:\n" - " kind the kind of TARGET\n" - " url the URL of TARGET in the repository\n" - " relative-url the repository-relative URL\n" - " repos-root-url the repository root URL\n" - " repos-uuid the repository UUID\n" - " revision the revision of TARGET (defaults to BASE\n" - " for working copy paths and HEAD for URLs)\n" - " last-changed-revision the most recent revision in which TARGET\n" - " was changed\n" - " last-changed-date the date of the last-changed revision\n" - " last-changed-author the author of the last-changed revision\n" - " wc-root the root of TARGET's working copy\n"), + " about TARGET.\n"), {'r', 'R', opt_depth, opt_targets, opt_incremental, opt_xml, opt_changelist, opt_include_externals, opt_show_item, opt_no_newline} }, - { "list", svn_cl__list, {"ls"}, N_ + { "list", svn_cl__list, {"ls"}, +#if defined(WIN32) + N_ ("List directory entries in the repository.\n" "usage: list [TARGET[@REV]...]\n" "\n" @@ -767,6 +820,11 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] = " The default TARGET is '.', meaning the repository URL of the current\n" " working directory.\n" "\n" + " Multiple --search patterns may be specified and the output will be\n" + " reduced to those paths whose last segment - i.e. the file or directory\n" + " name - contains a sub-string matching at least one of these patterns\n" + " (Windows only).\n" + "\n" " With --verbose, the following fields will be shown for each item:\n" "\n" " Revision number of the last commit\n" @@ -774,19 +832,45 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] = " If locked, the letter 'O'. (Use 'svn info URL' to see details)\n" " Size (in bytes)\n" " Date and time of the last commit\n"), +#else + N_ + ("List directory entries in the repository.\n" + "usage: list [TARGET[@REV]...]\n" + "\n" + " List each TARGET file and the contents of each TARGET directory as\n" + " they exist in the repository. If TARGET is a working copy path, the\n" + " corresponding repository URL will be used. If specified, REV determines\n" + " in which revision the target is first looked up.\n" + "\n" + " The default TARGET is '.', meaning the repository URL of the current\n" + " working directory.\n" + "\n" + " Multiple --search patterns may be specified and the output will be\n" + " reduced to those paths whose last segment - i.e. the file or directory\n" + " name - matches at least one of these patterns.\n" + "\n" + " With --verbose, the following fields will be shown for each item:\n" + "\n" + " Revision number of the last commit\n" + " Author of the last commit\n" + " If locked, the letter 'O'. (Use 'svn info URL' to see details)\n" + " Size (in bytes)\n" + " Date and time of the last commit\n"), +#endif {'r', 'v', 'R', opt_depth, opt_incremental, opt_xml, - opt_include_externals}, }, + opt_include_externals, opt_search}, }, { "lock", svn_cl__lock, {0}, N_ ("Lock working copy paths or URLs in the repository, so that\n" "no other user can commit changes to them.\n" "usage: lock TARGET...\n" "\n" - " Use --force to steal the lock from another user or working copy.\n"), - { opt_targets, 'm', 'F', opt_force_log, opt_encoding, opt_force }, + " Use --force to steal a lock from another user or working copy.\n"), + { opt_targets, 'm', 'F', opt_force_log, opt_encoding, opt_force, 'q' }, {{'F', N_("read lock comment from file ARG")}, {'m', N_("specify lock comment ARG")}, - {opt_force_log, N_("force validity of lock comment source")}} }, + {opt_force_log, N_("force validity of lock comment source")}, + {opt_force, N_("steal locks")}} }, { "log", svn_cl__log, {0}, N_ ("Show the log messages for a set of revision(s) and/or path(s).\n" @@ -810,6 +894,17 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] = " reverse ranges is allowed.\n" "\n" " With -v, also print all affected paths with each log message.\n" + " Each changed path is preceded with a symbol describing the change:\n" + " A: The path was added or copied.\n" + " D: The path was deleted.\n" + " R: The path was replaced (deleted and re-added in the same revision).\n" + " M: The path's file and/or property content was modified.\n" + " If an added or replaced path was copied from somewhere else, the copy\n" + " source path and revision are shown in parentheses.\n" + " If a file or directory was moved from one path to another with 'svn move'\n" + " the old path will be listed as deleted and the new path will be listed\n" + " as copied from the old path at a prior revision.\n" + "\n" " With -q, don't print the log message body itself (note that this is\n" " compatible with -v).\n" "\n" @@ -862,7 +957,12 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] = "\n" " Show the log message for the revision in which /branches/foo\n" " was created:\n" - " svn log --stop-on-copy --limit 1 -r0:HEAD ^/branches/foo\n"), + " svn log --stop-on-copy --limit 1 -r0:HEAD ^/branches/foo\n" + "\n" + " If ^/trunk/foo.c was moved to ^/trunk/bar.c' in revision 22, 'svn log -v'\n" + " shows a deletion and a copy in its changed paths list, such as:\n" + " D /trunk/foo.c\n" + " A /trunk/bar.c (from /trunk/foo.c:21)\n"), {'r', 'c', 'q', 'v', 'g', opt_targets, opt_stop_on_copy, opt_incremental, opt_xml, 'l', opt_with_all_revprops, opt_with_no_revprops, opt_with_revprop, opt_depth, opt_diff, opt_diff_cmd, @@ -1267,18 +1367,18 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] = " be committed later (with or without further changes)\n" " URL -> URL: move an item in the repository directly, immediately\n" " creating a new revision in the repository\n" - " All the SRCs must be of the same type. When moving multiple sources,\n" - " they will be added as children of DST, which must be a directory.\n" + " All the SRCs must be of the same type. If DST is an existing directory,\n" + " the sources will be added as children of DST. When moving multiple\n" + " sources, DST must be an existing directory.\n" "\n" " SRC and DST of WC -> WC moves must be committed in the same revision.\n" " Furthermore, WC -> WC moves will refuse to move a mixed-revision subtree.\n" " To avoid unnecessary conflicts, it is recommended to run 'svn update'\n" " to update the subtree to a single revision before moving it.\n" - " The --allow-mixed-revisions option is provided for backward compatibility.\n" - "\n" - " The --revision option has no use and is deprecated.\n"), - {'r', 'q', opt_force, opt_parents, opt_allow_mixed_revisions, - SVN_CL__LOG_MSG_OPTIONS} }, + " The --allow-mixed-revisions option is provided for backward compatibility.\n"), + {'q', opt_force, opt_parents, opt_allow_mixed_revisions, + SVN_CL__LOG_MSG_OPTIONS, 'r'}, + {{'r', "deprecated and ignored"}} }, { "patch", svn_cl__patch, {0}, N_ ("Apply a patch to a working copy.\n" @@ -1519,7 +1619,48 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] = "\n" " The --accept=ARG option prevents interactive prompting and forces\n" " conflicts on PATH to be resolved in the manner specified by ARG.\n" - " In this mode, the command is not recursive by default (depth 'empty').\n"), + " In this mode, the command is not recursive by default (depth 'empty').\n" + "\n" + " A conflicted path cannot be committed with 'svn commit' until it\n" + " has been marked as resolved with 'svn resolve'.\n" + "\n" + " Subversion knows three types of conflicts:\n" + " Text conflicts, Property conflicts, and Tree conflicts.\n" + "\n" + " Text conflicts occur when overlapping changes to file contents were\n" + " made. Text conflicts are usually resolved by editing the conflicted\n" + " file or by using a merge tool (which may be an external program).\n" + " 'svn resolve' provides options which can be used to automatically\n" + " edit files (such as 'mine-full' or 'theirs-conflict'), but these are\n" + " only useful in situations where it is acceptable to discard local or\n" + " incoming changes altogether.\n" + "\n" + " Property conflicts are usually resolved by editing the value of the\n" + " conflicted property (either from the interactive prompt, or with\n" + " 'svn propedit'). As with text conflicts, options exist to edit a\n" + " property automatically, discarding some changes in favour of others.\n" + "\n" + " Tree conflicts occur when a change to the directory structure was\n" + " made, and when this change cannot be applied to the working copy\n" + " without affecting other changes (text changes, property changes,\n" + " or other changes to the directory structure). Brief information about\n" + " tree conflicts is shown by the 'svn status' and 'svn info' commands.\n" + " In interactive mode, 'svn resolve' will attempt to describe tree conflicts\n" + " in detail, and may offer options to resolve the conflict automatically.\n" + " It is recommended to use these automatic options whenever possible,\n" + " rather than attempting manual tree conflict resolution.\n" + "\n" + " If a tree conflict cannot be resolved automatically, it is recommended\n" + " to figure out why the conflict occurred before attempting to resolve it.\n" + " The 'svn log -v' command can be used to inspect structural changes\n" + " made in past revisions, and perhaps even on other branches.\n" + " 'svn help log' describes how these structural changes are presented.\n" + " Once the conflicting \"incoming\" change has been identified with 'svn log'\n" + " the current \"local\" working copy state should be examined and adjusted\n" + " in a way such that the conflict is resolved. This may involve editing\n" + " files manually or with 'svn merge'. It may be necessary to discard some\n" + " local changes with 'svn revert'. Files or directories might have to be\n" + " copied, deleted, or moved.\n"), {opt_targets, 'R', opt_depth, 'q', opt_accept}, {{opt_accept, N_("specify automatic conflict resolution source\n" " " @@ -1685,20 +1826,23 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] = " svn switch --relocate http:// svn://\n" " svn switch --relocate http://www.example.com/repo/project \\\n" " svn://svn.example.com/repo/project\n"), - { 'r', 'N', opt_depth, opt_set_depth, 'q', opt_merge_cmd, opt_relocate, - opt_ignore_externals, opt_ignore_ancestry, opt_force, opt_accept}, + { 'r', 'N', opt_depth, opt_set_depth, 'q', opt_merge_cmd, + opt_ignore_externals, opt_ignore_ancestry, opt_force, opt_accept, + opt_relocate }, {{opt_ignore_ancestry, N_("allow switching to a node with no common ancestor")}, {opt_force, - N_("handle unversioned obstructions as changes")}} + N_("handle unversioned obstructions as changes")}, + {opt_relocate,N_("deprecated; use 'svn relocate'")}} }, { "unlock", svn_cl__unlock, {0}, N_ ("Unlock working copy paths or URLs.\n" "usage: unlock TARGET...\n" "\n" - " Use --force to break the lock.\n"), - { opt_targets, opt_force } }, + " Use --force to break a lock held by another user or working copy.\n"), + { opt_targets, opt_force, 'q' }, + {{opt_force, N_("break locks")}} }, { "update", svn_cl__update, {"up"}, N_ ("Bring changes from the repository into the working copy.\n" @@ -1748,7 +1892,7 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] = " targets of this operation.\n"), {'r', 'N', opt_depth, opt_set_depth, 'q', opt_merge_cmd, opt_force, opt_ignore_externals, opt_changelist, opt_editor_cmd, opt_accept, - opt_parents}, + opt_parents, opt_adds_as_modification}, { {opt_force, N_("handle unversioned obstructions as changes")} } }, @@ -1759,6 +1903,74 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] = " Local modifications are preserved.\n"), { 'q' } }, + { "x-shelve", svn_cl__shelve, {"shelve"}, N_ + ("Put a local change aside, as if putting it on a shelf.\n" + "usage: 1. x-shelve [--keep-local] NAME [PATH...]\n" + " 2. x-shelve --delete NAME\n" + " 3. x-shelve --list\n" + "\n" + " 1. Save the local change in the given PATHs to a patch file, and\n" + " revert that change from the WC unless '--keep-local' is given.\n" + " If a log message is given with '-m' or '-F', include it at the\n" + " beginning of the patch file.\n" + "\n" + " 2. Delete the shelved change NAME.\n" + " (A backup is kept, named with a '.bak' extension.)\n" + "\n" + " 3. List shelved changes. Include the first line of any log message\n" + " and some details about the contents of the change, unless '-q' is\n" + " given.\n" + "\n" + " The kinds of change you can shelve are those supported by 'svn diff'\n" + " and 'svn patch'. The following are currently NOT supported:\n" + " mergeinfo changes, copies, moves, mkdir, rmdir,\n" + " 'binary' content, uncommittable states\n" + "\n" + " To bring back a shelved change, use 'svn x-unshelve NAME'.\n" + "\n" + " Shelved changes are stored in /.svn/shelves/\n" + "\n" + " The shelving feature is EXPERIMENTAL. This command is likely to change\n" + " in the next release, and there is no promise of backward compatibility.\n" + ), + {opt_delete, opt_list, 'q', opt_dry_run, opt_keep_local, + opt_depth, opt_targets, opt_changelist, + /* almost SVN_CL__LOG_MSG_OPTIONS but not currently opt_with_revprop: */ + 'm', 'F', opt_force_log, opt_editor_cmd, opt_encoding, + } }, + + { "x-unshelve", svn_cl__unshelve, {"unshelve"}, N_ + ("Bring a shelved change back to a local change in the WC.\n" + "usage: 1. x-unshelve [--keep-shelved] [NAME]\n" + " 2. x-unshelve --list\n" + "\n" + " 1. Apply the shelved change NAME to the working copy.\n" + " Delete the patch unless the '--keep-shelved' option is given.\n" + " (A backup is kept, named with a '.bak' extension.)\n" + " NAME defaults to the most recent shelved change.\n" + "\n" + " 2. List shelved changes. Include the first line of any log message\n" + " and some details about the contents of the change, unless '-q' is\n" + " given.\n" + "\n" + " Any conflict between the change being unshelved and a change\n" + " already in the WC is handled the same way as by 'svn patch',\n" + " creating a 'reject' file.\n" + "\n" + " The shelving feature is EXPERIMENTAL. This command is likely to change\n" + " in the next release, and there is no promise of backward compatibility.\n" + ), + {opt_keep_shelved, opt_list, 'q', opt_dry_run} }, + + { "x-shelves", svn_cl__shelves, {"shelves"}, N_ + ("List shelved changes.\n" + "usage: x-shelves\n" + "\n" + " The shelving feature is EXPERIMENTAL. This command is likely to change\n" + " in the next release, and there is no promise of backward compatibility.\n" + ), + {'q'} }, + { NULL, NULL, {0}, NULL, {0} } }; @@ -1782,29 +1994,8 @@ check_lib_versions(void) return svn_ver_check_list2(&my_version, checklist, svn_ver_equal); } - -/* A flag to see if we've been cancelled by the client or not. */ -static volatile sig_atomic_t cancelled = FALSE; - -/* A signal handler to support cancellation. */ -static void -signal_handler(int signum) -{ - apr_signal(signum, SIG_IGN); - cancelled = TRUE; -} - -/* Our cancellation callback. */ -svn_error_t * -svn_cl__check_cancel(void *baton) -{ - /* Cancel baton should be always NULL in command line client. */ - SVN_ERR_ASSERT(baton == NULL); - if (cancelled) - return svn_error_create(SVN_ERR_CANCELLED, NULL, _("Caught signal")); - else - return SVN_NO_ERROR; -} +/* The cancelation handler setup by the cmdline library. */ +svn_cancel_func_t svn_cl__check_cancel = NULL; /* Add a --search argument to OPT_STATE. * These options start a new search pattern group. */ @@ -1877,6 +2068,8 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) svn_boolean_t reading_file_from_stdin = FALSE; apr_hash_t *changelists; apr_hash_t *cfg_hash; + svn_membuf_t buf; + svn_boolean_t read_pass_from_stdin = FALSE; received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); @@ -1897,6 +2090,9 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) /* Init our changelists hash. */ changelists = apr_hash_make(pool); + /* Init the temporary buffer. */ + svn_membuf__create(&buf, 0, pool); + /* Begin processing arguments. */ opt_state.start_revision.kind = svn_opt_revision_unspecified; opt_state.end_revision.kind = svn_opt_revision_unspecified; @@ -2112,6 +2308,9 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) case opt_dry_run: opt_state.dry_run = TRUE; break; + case opt_list: + opt_state.list = TRUE; + break; case opt_revprop: opt_state.revprop = TRUE; break; @@ -2166,6 +2365,9 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) SVN_ERR(svn_utf_cstring_to_utf8(&opt_state.auth_password, opt_arg, pool)); break; + case opt_auth_password_from_stdin: + read_pass_from_stdin = TRUE; + break; case opt_encoding: opt_state.encoding = apr_pstrdup(pool, opt_arg); break; @@ -2292,6 +2494,7 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) opt_state.diff.summarize = TRUE; break; case opt_remove: + case opt_delete: opt_state.remove = TRUE; break; case opt_changelist: @@ -2307,6 +2510,7 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) opt_state.keep_changelists = TRUE; break; case opt_keep_local: + case opt_keep_shelved: opt_state.keep_local = TRUE; break; case opt_with_all_revprops: @@ -2401,11 +2605,20 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) break; case opt_search: SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool)); - add_search_pattern_group(&opt_state, utf8_opt_arg, pool); + SVN_ERR(svn_utf__xfrm(&utf8_opt_arg, utf8_opt_arg, + strlen(utf8_opt_arg), TRUE, TRUE, &buf)); + add_search_pattern_group(&opt_state, + apr_pstrdup(pool, utf8_opt_arg), + pool); break; case opt_search_and: SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool)); - add_search_pattern_to_latest_group(&opt_state, utf8_opt_arg, pool); + SVN_ERR(svn_utf__xfrm(&utf8_opt_arg, utf8_opt_arg, + strlen(utf8_opt_arg), TRUE, TRUE, &buf)); + add_search_pattern_to_latest_group(&opt_state, + apr_pstrdup(pool, utf8_opt_arg), + pool); + break; case opt_remove_unversioned: opt_state.remove_unversioned = TRUE; break; @@ -2426,6 +2639,12 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool)); opt_state.show_item = utf8_opt_arg; break; + case opt_adds_as_modification: + opt_state.adds_as_modification = TRUE; + break; + case opt_vacuum_pristines: + opt_state.vacuum_pristines = TRUE; + break; default: /* Hmmm. Perhaps this would be a good place to squirrel away opts that commands like svn diff might need. Hmmm indeed. */ @@ -2499,22 +2718,22 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) } else { - const char *first_arg = os->argv[os->ind++]; + const char *first_arg; + + SVN_ERR(svn_utf_cstring_to_utf8(&first_arg, os->argv[os->ind++], + pool)); subcommand = svn_opt_get_canonical_subcommand2(svn_cl__cmd_table, first_arg); if (subcommand == NULL) { - const char *first_arg_utf8; - SVN_ERR(svn_utf_cstring_to_utf8(&first_arg_utf8, - first_arg, pool)); svn_error_clear (svn_cmdline_fprintf(stderr, pool, _("Unknown subcommand: '%s'\n"), - first_arg_utf8)); + first_arg)); svn_error_clear(svn_cl__help(NULL, NULL, pool)); /* Be kind to people who try 'svn undo'. */ - if (strcmp(first_arg_utf8, "undo") == 0) + if (strcmp(first_arg, "undo") == 0) { svn_error_clear (svn_cmdline_fprintf(stderr, pool, @@ -2645,6 +2864,14 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) "--non-interactive")); } + /* --password-from-stdin can only be used with --non-interactive */ + if (read_pass_from_stdin && !opt_state.non_interactive) + { + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("--password-from-stdin requires " + "--non-interactive")); + } + /* Disallow simultaneous use of both --diff-cmd and --internal-diff. */ if (opt_state.diff.diff_cmd && opt_state.diff.internal_diff) @@ -2780,6 +3007,7 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) /* Create a client context object. */ command_baton.opt_state = &opt_state; + command_baton.conflict_stats = conflict_stats; SVN_ERR(svn_client_create_context2(&ctx, cfg_hash, pool)); command_baton.ctx = ctx; @@ -2795,7 +3023,8 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) || subcommand->cmd_func == svn_cl__mkdir || subcommand->cmd_func == svn_cl__move || subcommand->cmd_func == svn_cl__lock - || subcommand->cmd_func == svn_cl__propedit)) + || subcommand->cmd_func == svn_cl__propedit + || subcommand->cmd_func == svn_cl__shelve)) { /* If the -F argument is a file that's under revision control, that's probably not what the user intended. */ @@ -2803,9 +3032,9 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) { svn_node_kind_t kind; const char *local_abspath; - const char *fname_utf8 = svn_dirent_internal_style(dash_F_arg, pool); + const char *fname = svn_dirent_internal_style(dash_F_arg, pool); - err = svn_dirent_get_absolute(&local_abspath, fname_utf8, pool); + err = svn_dirent_get_absolute(&local_abspath, fname, pool); if (!err) { @@ -2933,31 +3162,15 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) conflict_stats, pool)); } + /* Get password from stdin if necessary */ + if (read_pass_from_stdin) + { + SVN_ERR(svn_cmdline__stdin_readline(&opt_state.auth_password, pool, pool)); + } + /* Set up our cancellation support. */ + svn_cl__check_cancel = svn_cmdline__setup_cancellation_handler(); ctx->cancel_func = svn_cl__check_cancel; - apr_signal(SIGINT, signal_handler); -#ifdef SIGBREAK - /* SIGBREAK is a Win32 specific signal generated by ctrl-break. */ - apr_signal(SIGBREAK, signal_handler); -#endif -#ifdef SIGHUP - apr_signal(SIGHUP, signal_handler); -#endif -#ifdef SIGTERM - apr_signal(SIGTERM, signal_handler); -#endif - -#ifdef SIGPIPE - /* Disable SIGPIPE generation for the platforms that have it. */ - apr_signal(SIGPIPE, SIG_IGN); -#endif - -#ifdef SIGXFSZ - /* Disable SIGXFSZ generation for the platforms that have it, otherwise - * working with large files when compiled against an APR that doesn't have - * large file support will crash the program, which is uncool. */ - apr_signal(SIGXFSZ, SIG_IGN); -#endif /* Set up Authentication stuff. */ SVN_ERR(svn_cmdline_create_auth_baton2( @@ -2996,10 +3209,11 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) SVN_CL__ACCEPT_LAUNCH); } - /* The default action when we're non-interactive is to postpone - * conflict resolution. */ + /* The default action when we're non-interactive is to use the + * recommended conflict resolution (this will postpone conflicts + * for which no recommended resolution is available). */ if (opt_state.accept_which == svn_cl__accept_unspecified) - opt_state.accept_which = svn_cl__accept_postpone; + opt_state.accept_which = svn_cl__accept_recommended; } /* Check whether interactive conflict resolution is disabled by @@ -3021,20 +3235,12 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) opt_state.accept_which = svn_cl__accept_postpone; } - /* Install the default conflict handler. */ + /* We don't use legacy libsvn_wc conflict handlers by default. */ { - svn_cl__interactive_conflict_baton_t *b; - ctx->conflict_func = NULL; ctx->conflict_baton = NULL; - - ctx->conflict_func2 = svn_cl__conflict_func_interactive; - SVN_ERR(svn_cl__get_conflict_func_interactive_baton( - &b, - opt_state.accept_which, - ctx->config, opt_state.editor_cmd, conflict_stats, - ctx->cancel_func, ctx->cancel_baton, pool)); - ctx->conflict_baton2 = b; + ctx->conflict_func2 = NULL; + ctx->conflict_baton2 = NULL; } /* And now we finally run the subcommand. */ @@ -3136,5 +3342,8 @@ main(int argc, const char *argv[]) } svn_pool_destroy(pool); + + svn_cmdline__cancellation_exit(); + return exit_code; } diff --git a/subversion/svn/switch-cmd.c b/subversion/svn/switch-cmd.c index aaef2b56ae8b..7cab8d980a59 100644 --- a/subversion/svn/switch-cmd.c +++ b/subversion/svn/switch-cmd.c @@ -96,8 +96,11 @@ svn_cl__switch(apr_getopt_t *os, svn_error_t *err = SVN_NO_ERROR; svn_error_t *externals_err = SVN_NO_ERROR; svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state; + svn_cl__conflict_stats_t *conflict_stats = + ((svn_cl__cmd_baton_t *) baton)->conflict_stats; svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx; apr_array_header_t *targets; + apr_array_header_t *conflicted_paths; const char *target, *switch_url; svn_opt_revision_t peg_revision; svn_depth_t depth; @@ -188,6 +191,13 @@ svn_cl__switch(apr_getopt_t *os, _("Failure occurred processing one or " "more externals definitions")); + /* Run the interactive resolver if conflicts were raised. */ + SVN_ERR(svn_cl__conflict_stats_get_paths(&conflicted_paths, conflict_stats, + scratch_pool, scratch_pool)); + if (conflicted_paths) + SVN_ERR(svn_cl__walk_conflicts(conflicted_paths, conflict_stats, + opt_state, ctx, scratch_pool)); + if (! opt_state->quiet) { err = svn_cl__notifier_print_conflict_stats(nwb.wrapped_baton, scratch_pool); diff --git a/subversion/svn/update-cmd.c b/subversion/svn/update-cmd.c index 77c28f97ca40..2820615ea8c2 100644 --- a/subversion/svn/update-cmd.c +++ b/subversion/svn/update-cmd.c @@ -111,12 +111,15 @@ svn_cl__update(apr_getopt_t *os, apr_pool_t *scratch_pool) { svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state; + svn_cl__conflict_stats_t *conflict_stats = + ((svn_cl__cmd_baton_t *) baton)->conflict_stats; svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx; apr_array_header_t *targets; svn_depth_t depth; svn_boolean_t depth_is_sticky; struct svn_cl__check_externals_failed_notify_baton nwb; apr_array_header_t *result_revs; + apr_array_header_t *conflicted_paths; svn_error_t *err = SVN_NO_ERROR; svn_error_t *externals_err = SVN_NO_ERROR; @@ -167,7 +170,8 @@ svn_cl__update(apr_getopt_t *os, &(opt_state->start_revision), depth, depth_is_sticky, opt_state->ignore_externals, - opt_state->force, TRUE /* adds_as_modification */, + opt_state->force, + opt_state->adds_as_modification, opt_state->parents, ctx, scratch_pool)); @@ -177,6 +181,13 @@ svn_cl__update(apr_getopt_t *os, _("Failure occurred processing one or " "more externals definitions")); + /* Run the interactive resolver if conflicts were raised. */ + SVN_ERR(svn_cl__conflict_stats_get_paths(&conflicted_paths, conflict_stats, + scratch_pool, scratch_pool)); + if (conflicted_paths) + SVN_ERR(svn_cl__walk_conflicts(conflicted_paths, conflict_stats, + opt_state, ctx, scratch_pool)); + if (! opt_state->quiet) { err = print_update_summary(targets, result_revs, scratch_pool); diff --git a/subversion/svn/util.c b/subversion/svn/util.c index 88ae27b14824..a18e5f37c9f7 100644 --- a/subversion/svn/util.c +++ b/subversion/svn/util.c @@ -614,6 +614,7 @@ svn_cl__try(svn_error_t *err, if (! quiet) svn_handle_warning2(stderr, err, "svn: "); svn_error_clear(err); + va_end(ap); return SVN_NO_ERROR; } } @@ -907,14 +908,17 @@ svn_cl__time_cstring_to_human_cstring(const char **human_cstring, } const char * -svn_cl__node_description(const svn_wc_conflict_version_t *node, +svn_cl__node_description(const char *repos_root_url, + const char *repos_relpath, + svn_revnum_t peg_rev, + svn_node_kind_t node_kind, const char *wc_repos_root_URL, apr_pool_t *pool) { const char *root_str = "^"; const char *path_str = "..."; - if (!node) + if (!repos_root_url || !repos_relpath || !SVN_IS_VALID_REVNUM(peg_rev)) /* Printing "(none)" the harder way to ensure conformity (mostly with * translations). */ return apr_psprintf(pool, "(%s)", @@ -923,18 +927,18 @@ svn_cl__node_description(const svn_wc_conflict_version_t *node, /* Construct a "caret notation" ^/URL if NODE matches WC_REPOS_ROOT_URL. * Otherwise show the complete URL, and if we can't, show dots. */ - if (node->repos_url && + if (repos_root_url && (wc_repos_root_URL == NULL || - strcmp(node->repos_url, wc_repos_root_URL) != 0)) - root_str = node->repos_url; + strcmp(repos_root_url, wc_repos_root_URL) != 0)) + root_str = repos_root_url; - if (node->path_in_repos) - path_str = node->path_in_repos; + if (repos_relpath) + path_str = repos_relpath; return apr_psprintf(pool, "(%s) %s@%ld", - svn_cl__node_kind_str_human_readable(node->node_kind), + svn_cl__node_kind_str_human_readable(node_kind), svn_path_url_add_component2(root_str, path_str, pool), - node->peg_rev); + peg_rev); } svn_error_t * diff --git a/subversion/svn_private_config.h.in b/subversion/svn_private_config.h.in index 3e9d5923b2fa..dbc52450c40b 100644 --- a/subversion/svn_private_config.h.in +++ b/subversion/svn_private_config.h.in @@ -145,6 +145,9 @@ /* Defined if plaintext password/passphrase storage is disabled */ #undef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE +/* Shared library file name suffix format */ +#undef SVN_DSO_SUFFIX_FMT + /* The desired major version for the Berkeley DB */ #undef SVN_FS_WANT_DB_MAJOR @@ -166,12 +169,18 @@ /* Is Mac OS KeyChain support enabled? */ #undef SVN_HAVE_KEYCHAIN_SERVICES +/* Defined if KF5 available */ +#undef SVN_HAVE_KF5 + /* Defined if KWallet support is enabled */ #undef SVN_HAVE_KWALLET /* Defined if libmagic support is enabled */ #undef SVN_HAVE_LIBMAGIC +/* Is libsecret support enabled? */ +#undef SVN_HAVE_LIBSECRET + /* Is Mach-O low-level _dyld API available? */ #undef SVN_HAVE_MACHO_ITERATE @@ -190,14 +199,11 @@ /* Defined if support for Serf is enabled */ #undef SVN_HAVE_SERF -/* Defined if libsvn_client should link against libsvn_ra_local */ -#undef SVN_LIBSVN_CLIENT_LINKS_RA_LOCAL +/* Define to use internal LZ4 code */ +#undef SVN_INTERNAL_LZ4 -/* Defined if libsvn_client should link against libsvn_ra_serf */ -#undef SVN_LIBSVN_CLIENT_LINKS_RA_SERF - -/* Defined if libsvn_client should link against libsvn_ra_svn */ -#undef SVN_LIBSVN_CLIENT_LINKS_RA_SVN +/* Define to use internal UTF8PROC code */ +#undef SVN_INTERNAL_UTF8PROC /* Defined if libsvn_fs should link against libsvn_fs_base */ #undef SVN_LIBSVN_FS_LINKS_FS_BASE @@ -208,6 +214,15 @@ /* Defined if libsvn_fs should link against libsvn_fs_x */ #undef SVN_LIBSVN_FS_LINKS_FS_X +/* Defined if libsvn_ra should link against libsvn_ra_local */ +#undef SVN_LIBSVN_RA_LINKS_RA_LOCAL + +/* Defined if libsvn_ra should link against libsvn_ra_serf */ +#undef SVN_LIBSVN_RA_LINKS_RA_SERF + +/* Defined if libsvn_ra should link against libsvn_ra_svn */ +#undef SVN_LIBSVN_RA_LINKS_RA_SVN + /* Defined to be the path to the installed locale dirs */ #undef SVN_LOCALE_DIR diff --git a/subversion/svn_private_config.hw b/subversion/svn_private_config.hw index 4ac6bad1d00b..c6f69c1ec940 100644 --- a/subversion/svn_private_config.hw +++ b/subversion/svn_private_config.hw @@ -61,10 +61,10 @@ #define SVN_LIBSVN_FS_LINKS_FS_X /* Link local repos access library to client */ -#define SVN_LIBSVN_CLIENT_LINKS_RA_LOCAL +#define SVN_LIBSVN_RA_LINKS_RA_LOCAL /* Link pipe repos access library to client */ -#define SVN_LIBSVN_CLIENT_LINKS_RA_SVN +#define SVN_LIBSVN_RA_LINKS_RA_SVN /* Defined to be the path to the installed binaries */ #define SVN_BINDIR "/usr/local/bin" @@ -122,6 +122,14 @@ Supresses compiler warnings about the variable being unused. */ #define SVN_UNUSED(v) ( (void)(v) ) +#if defined(_MSC_VER) && _MSC_VER >= 1600 +#define HAVE_STDINT_H +#endif + +#if defined(_MSC_VER) && _MSC_VER >= 1800 +#define HAVE_STDBOOL_H +#endif + #endif /* SVN_PRIVATE_CONFIG_HW */ /* Inclusion of Berkeley DB header */ diff --git a/subversion/svnadmin/svnadmin.c b/subversion/svnadmin/svnadmin.c index 2ee5410d24e3..eb26c5a8f0fc 100644 --- a/subversion/svnadmin/svnadmin.c +++ b/subversion/svnadmin/svnadmin.c @@ -23,7 +23,6 @@ #include -#include #include "svn_hash.h" #include "svn_pools.h" @@ -48,6 +47,8 @@ #include "private/svn_opt_private.h" #include "private/svn_sorts_private.h" #include "private/svn_subr_private.h" +#include "private/svn_cmdline_private.h" +#include "private/svn_fspath.h" #include "svn_private_config.h" @@ -59,46 +60,7 @@ * The current threshold is 64MB. */ #define BLOCK_READ_CACHE_THRESHOLD (0x40 * 0x100000) -/* A flag to see if we've been cancelled by the client or not. */ -static volatile sig_atomic_t cancelled = FALSE; - -/* A signal handler to support cancellation. */ -static void -signal_handler(int signum) -{ - apr_signal(signum, SIG_IGN); - cancelled = TRUE; -} - - -/* A helper to set up the cancellation signal handlers. */ -static void -setup_cancellation_signals(void (*handler)(int signum)) -{ - apr_signal(SIGINT, handler); -#ifdef SIGBREAK - /* SIGBREAK is a Win32 specific signal generated by ctrl-break. */ - apr_signal(SIGBREAK, handler); -#endif -#ifdef SIGHUP - apr_signal(SIGHUP, handler); -#endif -#ifdef SIGTERM - apr_signal(SIGTERM, handler); -#endif -} - - -/* Our cancellation callback. */ -static svn_error_t * -check_cancel(void *baton) -{ - if (cancelled) - return svn_error_create(SVN_ERR_CANCELLED, NULL, _("Caught signal")); - else - return SVN_NO_ERROR; -} - +static svn_cancel_func_t check_cancel = NULL; /* Custom filesystem warning function. */ static void @@ -111,34 +73,6 @@ warning_func(void *baton, } -/* Helper to open a repository and set a warning func (so we don't - * SEGFAULT when libsvn_fs's default handler gets run). */ -static svn_error_t * -open_repos(svn_repos_t **repos, - const char *path, - apr_pool_t *pool) -{ - /* Enable the "block-read" feature (where it applies)? */ - svn_boolean_t use_block_read - = svn_cache_config_get()->cache_size > BLOCK_READ_CACHE_THRESHOLD; - - /* construct FS configuration parameters: enable caches for r/o data */ - apr_hash_t *fs_config = apr_hash_make(pool); - svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_DELTAS, "1"); - svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS, "1"); - svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_REVPROPS, "2"); - svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_NS, - svn_uuid_generate(pool)); - svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_BLOCK_READ, - use_block_read ? "1" : "0"); - - /* now, open the requested repository */ - SVN_ERR(svn_repos_open3(repos, path, fs_config, pool, pool)); - svn_fs_set_warning_func(svn_repos_fs(*repos), warning_func, NULL); - return SVN_NO_ERROR; -} - - /* Version compatibility check */ static svn_error_t * check_lib_versions(void) @@ -166,11 +100,13 @@ static svn_opt_subcommand_t subcommand_delrevprop, subcommand_deltify, subcommand_dump, + subcommand_dump_revprops, subcommand_freeze, subcommand_help, subcommand_hotcopy, subcommand_info, subcommand_load, + subcommand_load_revprops, subcommand_list_dblogs, subcommand_list_unused_dblogs, subcommand_lock, @@ -214,7 +150,12 @@ enum svnadmin__cmdline_options_t svnadmin__pre_1_6_compatible, svnadmin__compatible_version, svnadmin__check_normalization, - svnadmin__metadata_only + svnadmin__metadata_only, + svnadmin__no_flush_to_disk, + svnadmin__normalize_props, + svnadmin__exclude, + svnadmin__include, + svnadmin__glob }; /* Option codes and descriptions. @@ -333,6 +274,26 @@ static const apr_getopt_option_t options_table[] = " checking against external corruption in\n" " Subversion 1.9+ format repositories.\n")}, + {"no-flush-to-disk", svnadmin__no_flush_to_disk, 0, + N_("disable flushing to disk during the operation\n" + " (faster, but unsafe on power off)")}, + + {"normalize-props", svnadmin__normalize_props, 0, + N_("normalize property values found in the dumpstream\n" + " (currently, only translates non-LF line endings)")}, + + {"exclude", svnadmin__exclude, 1, + N_("filter out nodes with given prefix(es) from dump")}, + + {"include", svnadmin__include, 1, + N_("filter out nodes without given prefix(es) from dump")}, + + {"pattern", svnadmin__glob, 0, + N_("treat the path prefixes as file glob patterns.\n" + " Glob special characters are '*' '?' '[]' and '\\'.\n" + " Character '/' is not treated specially, so\n" + " pattern /*/foo matches paths /a/foo and /a/b/foo.") }, + {NULL} }; @@ -359,7 +320,7 @@ static const svn_opt_subcommand_desc2_t cmd_table[] = {"delrevprop", subcommand_delrevprop, {0}, N_ ("usage: 1. svnadmin delrevprop REPOS_PATH -r REVISION NAME\n" - " 2. svnadmin delrevprop REPO_PATH -t TXN NAME\n\n" + " 2. svnadmin delrevprop REPOS_PATH -t TXN NAME\n\n" "1. Delete the property NAME on revision REVISION.\n\n" "Use --use-pre-revprop-change-hook/--use-post-revprop-change-hook to\n" "trigger the revision property-related hooks (for example, if you want\n" @@ -389,8 +350,24 @@ static const svn_opt_subcommand_desc2_t cmd_table[] = "only the paths changed in that revision; otherwise it will describe\n" "every path present in the repository as of that revision. (In either\n" "case, the second and subsequent revisions, if any, describe only paths\n" - "changed in those revisions.)\n"), - {'r', svnadmin__incremental, svnadmin__deltas, 'q', 'M'} }, + "changed in those revisions.)\n" + "\n" + "Using --exclude or --include gives results equivalent to authz-based\n" + "path exclusions. In particular, when the source of a copy is\n" + "excluded, the copy is transformed into an add (unlike in 'svndumpfilter').\n"), + {'r', svnadmin__incremental, svnadmin__deltas, 'q', 'M', 'F', + svnadmin__exclude, svnadmin__include, svnadmin__glob }, + {{'F', N_("write to file ARG instead of stdout")}} }, + + {"dump-revprops", subcommand_dump_revprops, {0}, N_ + ("usage: svnadmin dump-revprops REPOS_PATH [-r LOWER[:UPPER]]\n\n" + "Dump the revision properties of filesystem to stdout in a 'dumpfile'\n" + "portable format, sending feedback to stderr. Dump revisions\n" + "LOWER rev through UPPER rev. If no revisions are given, dump the\n" + "properties for all revisions. If only LOWER is given, dump the\n" + "properties for that one revision.\n"), + {'r', 'q', 'F'}, + {{'F', N_("write to file ARG instead of stdout")}} }, {"freeze", subcommand_freeze, {0}, N_ ("usage: 1. svnadmin freeze REPOS_PATH PROGRAM [ARG...]\n" @@ -401,7 +378,8 @@ static const svn_opt_subcommand_desc2_t cmd_table[] = "2. Like 1 except all repositories listed in FILE are locked. The file\n" " format is repository paths separated by newlines. Repositories are\n" " locked in the same order as they are listed in the file.\n"), - {'F'} }, + {'F'}, + {{'F', N_("read repository paths from file ARG")}} }, {"help", subcommand_help, {"?", "h"}, N_ ("usage: svnadmin help [SUBCOMMAND...]\n\n" @@ -443,14 +421,28 @@ static const svn_opt_subcommand_desc2_t cmd_table[] = {'q', 'r', svnadmin__ignore_uuid, svnadmin__force_uuid, svnadmin__ignore_dates, svnadmin__use_pre_commit_hook, svnadmin__use_post_commit_hook, - svnadmin__parent_dir, svnadmin__bypass_prop_validation, 'M'} }, + svnadmin__parent_dir, svnadmin__normalize_props, + svnadmin__bypass_prop_validation, 'M', + svnadmin__no_flush_to_disk, 'F'}, + {{'F', N_("read from file ARG instead of stdin")}} }, + + {"load-revprops", subcommand_load_revprops, {0}, N_ + ("usage: svnadmin load-revprops REPOS_PATH\n\n" + "Read a 'dumpfile'-formatted stream from stdin, setting the revision\n" + "properties in the repository's filesystem. Revisions not found in the\n" + "repository will cause an error. Progress feedback is sent to stdout.\n" + "If --revision is specified, limit the loaded revisions to only those\n" + "in the dump stream whose revision numbers match the specified range.\n"), + {'q', 'r', svnadmin__force_uuid, svnadmin__normalize_props, + svnadmin__bypass_prop_validation, svnadmin__no_flush_to_disk, 'F'}, + {{'F', N_("read from file ARG instead of stdin")}} }, {"lock", subcommand_lock, {0}, N_ ("usage: svnadmin lock REPOS_PATH PATH USERNAME COMMENT-FILE [TOKEN]\n\n" "Lock PATH by USERNAME setting comments from COMMENT-FILE.\n" "If provided, use TOKEN as lock token. Use --bypass-hooks to avoid\n" "triggering the pre-lock and post-lock hook scripts.\n"), - {svnadmin__bypass_hooks} }, + {svnadmin__bypass_hooks, 'q'} }, {"lslocks", subcommand_lslocks, {0}, N_ ("usage: svnadmin lslocks REPOS_PATH [PATH-IN-REPOS]\n\n" @@ -460,8 +452,12 @@ static const svn_opt_subcommand_desc2_t cmd_table[] = {"lstxns", subcommand_lstxns, {0}, N_ ("usage: svnadmin lstxns REPOS_PATH\n\n" - "Print the names of all uncommitted transactions.\n"), - {0} }, + "Print the names of uncommitted transactions. With -rN skip the output\n" + "of those that have a base revision more recent than rN. Transactions\n" + "with base revisions much older than HEAD are likely to have been\n" + "abandonded and are candidates to be removed.\n"), + {'r'}, + { {'r', "transaction base revision ARG"} } }, {"pack", subcommand_pack, {0}, N_ ("usage: svnadmin pack REPOS_PATH\n\n" @@ -480,7 +476,7 @@ static const svn_opt_subcommand_desc2_t cmd_table[] = {"rmlocks", subcommand_rmlocks, {0}, N_ ("usage: svnadmin rmlocks REPOS_PATH LOCKED_PATH...\n\n" "Unconditionally remove lock from each LOCKED_PATH.\n"), - {0} }, + {'q'} }, {"rmtxns", subcommand_rmtxns, {0}, N_ ("usage: svnadmin rmtxns REPOS_PATH TXN_NAME...\n\n" @@ -524,7 +520,7 @@ static const svn_opt_subcommand_desc2_t cmd_table[] = "Unlock LOCKED_PATH (as USERNAME) after verifying that the token\n" "associated with the lock matches TOKEN. Use --bypass-hooks to avoid\n" "triggering the pre-unlock and post-unlock hook scripts.\n"), - {svnadmin__bypass_hooks} }, + {svnadmin__bypass_hooks, 'q'} }, {"upgrade", subcommand_upgrade, {0}, N_ ("usage: svnadmin upgrade REPOS_PATH\n\n" @@ -576,16 +572,53 @@ struct svnadmin_opt_state svn_boolean_t metadata_only; /* --metadata-only */ svn_boolean_t bypass_prop_validation; /* --bypass-prop-validation */ svn_boolean_t ignore_dates; /* --ignore-dates */ + svn_boolean_t no_flush_to_disk; /* --no-flush-to-disk */ + svn_boolean_t normalize_props; /* --normalize_props */ enum svn_repos_load_uuid uuid_action; /* --ignore-uuid, --force-uuid */ apr_uint64_t memory_cache_size; /* --memory-cache-size M */ const char *parent_dir; /* --parent-dir */ - svn_stringbuf_t *filedata; /* --file */ + const char *file; /* --file */ + apr_array_header_t *exclude; /* --exclude */ + apr_array_header_t *include; /* --include */ + svn_boolean_t glob; /* --pattern */ const char *config_dir; /* Overriding Configuration Directory */ }; +/* Helper to open a repository and set a warning func (so we don't + * SEGFAULT when libsvn_fs's default handler gets run). */ +static svn_error_t * +open_repos(svn_repos_t **repos, + const char *path, + struct svnadmin_opt_state *opt_state, + apr_pool_t *pool) +{ + /* Enable the "block-read" feature (where it applies)? */ + svn_boolean_t use_block_read + = svn_cache_config_get()->cache_size > BLOCK_READ_CACHE_THRESHOLD; + + /* construct FS configuration parameters: enable caches for r/o data */ + apr_hash_t *fs_config = apr_hash_make(pool); + svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_DELTAS, "1"); + svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS, "1"); + svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_NODEPROPS, "1"); + svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_REVPROPS, "2"); + svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_CACHE_NS, + svn_uuid_generate(pool)); + svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_BLOCK_READ, + use_block_read ? "1" : "0"); + svn_hash_sets(fs_config, SVN_FS_CONFIG_NO_FLUSH_TO_DISK, + opt_state->no_flush_to_disk ? "1" : "0"); + + /* now, open the requested repository */ + SVN_ERR(svn_repos_open3(repos, path, fs_config, pool, pool)); + svn_fs_set_warning_func(svn_repos_fs(*repos), warning_func, NULL); + return SVN_NO_ERROR; +} + + /* Set *REVNUM to the revision specified by REVISION (or to SVN_INVALID_REVNUM if that has the type 'unspecified'), possibly making use of the YOUNGEST revision number in REPOS. */ @@ -614,16 +647,25 @@ get_revnum(svn_revnum_t *revnum, const svn_opt_revision_t *revision, return SVN_NO_ERROR; } -/* Set *PATH to an internal-style, UTF8-encoded, local dirent path - allocated from POOL and parsed from raw command-line argument ARG. */ +/* Set *FSPATH to an internal-style fspath parsed from ARG. */ +static svn_error_t * +target_arg_to_fspath(const char **fspath, + const char *arg, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + /* ### Using a private API. This really shouldn't be needed. */ + *fspath = svn_fspath__canonicalize(arg, result_pool); + return SVN_NO_ERROR; +} + +/* Set *DIRENT to an internal-style, local dirent path + allocated from POOL and parsed from PATH. */ static svn_error_t * target_arg_to_dirent(const char **dirent, - const char *arg, + const char *path, apr_pool_t *pool) { - const char *path; - - SVN_ERR(svn_utf_cstring_to_utf8(&path, arg, pool)); if (svn_path_is_url(path)) return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, _("Path '%s' is not a local path"), path); @@ -665,8 +707,12 @@ parse_args(apr_array_header_t **args, if (num_args) while (os->ind < os->argc) - APR_ARRAY_PUSH(*args, const char *) = - apr_pstrdup(pool, os->argv[os->ind++]); + { + const char *arg; + + SVN_ERR(svn_utf_cstring_to_utf8(&arg, os->argv[os->ind++], pool)); + APR_ARRAY_PUSH(*args, const char *) = arg; + } } return SVN_NO_ERROR; @@ -692,7 +738,7 @@ subcommand_crashtest(apr_getopt_t *os, void *baton, apr_pool_t *pool) svn_repos_t *repos; (void)svn_error_set_malfunction_handler(crashtest_malfunction_handler); - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); SVN_ERR(svn_cmdline_printf(pool, _("Successfully opened repository '%s'.\n" "Will now crash to simulate a crashing " @@ -809,7 +855,7 @@ subcommand_deltify(apr_getopt_t *os, void *baton, apr_pool_t *pool) /* Expect no more arguments. */ SVN_ERR(parse_args(NULL, os, 0, 0, pool)); - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); fs = svn_repos_fs(repos); SVN_ERR(svn_fs_youngest_rev(&youngest, fs, pool)); @@ -1066,8 +1112,7 @@ repos_notify_handler(void *baton, return; case svn_repos_notify_mutex_acquired: - /* Enable cancellation signal handlers. */ - setup_cancellation_signals(signal_handler); + svn_cmdline__setup_cancellation_handler(); return; case svn_repos_notify_recover_start: @@ -1126,6 +1171,24 @@ repos_notify_handler(void *baton, _("* Copied revisions from %ld to %ld.\n"), notify->start_revision, notify->end_revision)); } + return; + + case svn_repos_notify_pack_noop: + /* For best backward compatibility, we keep silent if there were just + no more shards to pack. */ + if (notify->shard == -1) + { + svn_error_clear(svn_stream_printf(feedback_stream, scratch_pool, + _("svnadmin: Warning - this repository is not sharded." + " Packing has no effect.\n"))); + } + return; + + case svn_repos_notify_load_revprop_set: + svn_error_clear(svn_stream_printf(feedback_stream, scratch_pool, + _("Properties set on revision %ld.\n"), + notify->new_revision)); + return; default: return; @@ -1172,6 +1235,100 @@ recode_stream_create(FILE *std_stream, apr_pool_t *pool) return rw_stream; } +/* Read the min / max revision from the OPT_STATE, verify them against REPOS + and return them in *LOWER and *UPPER, respectively. Use SCRATCH_POOL + for temporary allocations. */ +static svn_error_t * +get_dump_range(svn_revnum_t *lower, + svn_revnum_t *upper, + svn_repos_t *repos, + struct svnadmin_opt_state *opt_state, + apr_pool_t *scratch_pool) +{ + svn_fs_t *fs; + svn_revnum_t youngest; + + *lower = SVN_INVALID_REVNUM; + *upper = SVN_INVALID_REVNUM; + + fs = svn_repos_fs(repos); + SVN_ERR(svn_fs_youngest_rev(&youngest, fs, scratch_pool)); + + /* Find the revision numbers at which to start and end. */ + SVN_ERR(get_revnum(lower, &opt_state->start_revision, + youngest, repos, scratch_pool)); + SVN_ERR(get_revnum(upper, &opt_state->end_revision, + youngest, repos, scratch_pool)); + + /* Fill in implied revisions if necessary. */ + if (*lower == SVN_INVALID_REVNUM) + { + *lower = 0; + *upper = youngest; + } + else if (*upper == SVN_INVALID_REVNUM) + { + *upper = *lower; + } + + if (*lower > *upper) + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("First revision cannot be higher than second")); + + return SVN_NO_ERROR; +} + +/* Compare the node-path PATH with the (const char *) prefixes in PFXLIST. + * Return TRUE if any prefix is a prefix of PATH (matching whole path + * components); FALSE otherwise. + * PATH starts with a '/', as do the (const char *) paths in PREFIXES. */ +/* This function is a duplicate of svndumpfilter.c:ary_prefix_match(). */ +static svn_boolean_t +ary_prefix_match(const apr_array_header_t *pfxlist, const char *path) +{ + int i; + size_t path_len = strlen(path); + + for (i = 0; i < pfxlist->nelts; i++) + { + const char *pfx = APR_ARRAY_IDX(pfxlist, i, const char *); + size_t pfx_len = strlen(pfx); + + if (path_len < pfx_len) + continue; + if (strncmp(path, pfx, pfx_len) == 0 + && (pfx_len == 1 || path[pfx_len] == '\0' || path[pfx_len] == '/')) + return TRUE; + } + + return FALSE; +} + +/* Baton for dump_filter_func(). */ +struct dump_filter_baton_t +{ + apr_array_header_t *prefixes; + svn_boolean_t glob; + svn_boolean_t do_exclude; +}; + +/* Implements svn_repos_dump_filter_func_t. */ +static svn_error_t * +dump_filter_func(svn_boolean_t *include, + svn_fs_root_t *root, + const char *path, + void *baton, + apr_pool_t *scratch_pool) +{ + struct dump_filter_baton_t *b = baton; + const svn_boolean_t matches = + (b->glob + ? svn_cstring_match_glob_list(path, b->prefixes) + : ary_prefix_match(b->prefixes, path)); + + *include = b->do_exclude ? !matches : matches; + return SVN_NO_ERROR; +} /* This implements `svn_opt_subcommand_t'. */ static svn_error_t * @@ -1179,50 +1336,106 @@ subcommand_dump(apr_getopt_t *os, void *baton, apr_pool_t *pool) { struct svnadmin_opt_state *opt_state = baton; svn_repos_t *repos; - svn_fs_t *fs; - svn_stream_t *stdout_stream; - svn_revnum_t lower = SVN_INVALID_REVNUM, upper = SVN_INVALID_REVNUM; - svn_revnum_t youngest; + svn_stream_t *out_stream; + svn_revnum_t lower, upper; svn_stream_t *feedback_stream = NULL; + struct dump_filter_baton_t filter_baton = {0}; /* Expect no more arguments. */ SVN_ERR(parse_args(NULL, os, 0, 0, pool)); - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); - fs = svn_repos_fs(repos); - SVN_ERR(svn_fs_youngest_rev(&youngest, fs, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); + SVN_ERR(get_dump_range(&lower, &upper, repos, opt_state, pool)); - /* Find the revision numbers at which to start and end. */ - SVN_ERR(get_revnum(&lower, &opt_state->start_revision, - youngest, repos, pool)); - SVN_ERR(get_revnum(&upper, &opt_state->end_revision, - youngest, repos, pool)); - - /* Fill in implied revisions if necessary. */ - if (lower == SVN_INVALID_REVNUM) + /* Open the file or STDOUT, depending on whether -F was specified. */ + if (opt_state->file) { - lower = 0; - upper = youngest; - } - else if (upper == SVN_INVALID_REVNUM) - { - upper = lower; - } + apr_file_t *file; - if (lower > upper) - return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, - _("First revision cannot be higher than second")); - - SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool)); + /* Overwrite existing files, same as with > redirection. */ + SVN_ERR(svn_io_file_open(&file, opt_state->file, + APR_WRITE | APR_CREATE | APR_TRUNCATE + | APR_BUFFERED, APR_OS_DEFAULT, pool)); + out_stream = svn_stream_from_aprfile2(file, FALSE, pool); + } + else + SVN_ERR(svn_stream_for_stdout(&out_stream, pool)); /* Progress feedback goes to STDERR, unless they asked to suppress it. */ if (! opt_state->quiet) feedback_stream = recode_stream_create(stderr, pool); - SVN_ERR(svn_repos_dump_fs3(repos, stdout_stream, lower, upper, + /* Initialize the filter baton. */ + filter_baton.glob = opt_state->glob; + + if (opt_state->exclude && !opt_state->include) + { + filter_baton.prefixes = opt_state->exclude; + filter_baton.do_exclude = TRUE; + } + else if (opt_state->include && !opt_state->exclude) + { + filter_baton.prefixes = opt_state->include; + filter_baton.do_exclude = FALSE; + } + else if (opt_state->include && opt_state->exclude) + { + return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("'--exclude' and '--include' options " + "cannot be used simultaneously")); + } + + SVN_ERR(svn_repos_dump_fs4(repos, out_stream, lower, upper, opt_state->incremental, opt_state->use_deltas, + TRUE, TRUE, !opt_state->quiet ? repos_notify_handler : NULL, - feedback_stream, check_cancel, NULL, pool)); + feedback_stream, + filter_baton.prefixes ? dump_filter_func : NULL, + &filter_baton, + check_cancel, NULL, pool)); + + return SVN_NO_ERROR; +} + +/* This implements `svn_opt_subcommand_t'. */ +static svn_error_t * +subcommand_dump_revprops(apr_getopt_t *os, void *baton, apr_pool_t *pool) +{ + struct svnadmin_opt_state *opt_state = baton; + svn_repos_t *repos; + svn_stream_t *out_stream; + svn_revnum_t lower, upper; + svn_stream_t *feedback_stream = NULL; + + /* Expect no more arguments. */ + SVN_ERR(parse_args(NULL, os, 0, 0, pool)); + + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); + SVN_ERR(get_dump_range(&lower, &upper, repos, opt_state, pool)); + + /* Open the file or STDOUT, depending on whether -F was specified. */ + if (opt_state->file) + { + apr_file_t *file; + + /* Overwrite existing files, same as with > redirection. */ + SVN_ERR(svn_io_file_open(&file, opt_state->file, + APR_WRITE | APR_CREATE | APR_TRUNCATE + | APR_BUFFERED, APR_OS_DEFAULT, pool)); + out_stream = svn_stream_from_aprfile2(file, FALSE, pool); + } + else + SVN_ERR(svn_stream_for_stdout(&out_stream, pool)); + + /* Progress feedback goes to STDERR, unless they asked to suppress it. */ + if (! opt_state->quiet) + feedback_stream = recode_stream_create(stderr, pool); + + SVN_ERR(svn_repos_dump_fs4(repos, out_stream, lower, upper, + FALSE, FALSE, TRUE, FALSE, + !opt_state->quiet ? repos_notify_handler : NULL, + feedback_stream, NULL, NULL, + check_cancel, NULL, pool)); return SVN_NO_ERROR; } @@ -1268,13 +1481,13 @@ subcommand_freeze(apr_getopt_t *os, void *baton, apr_pool_t *pool) int i; struct freeze_baton_t b; - SVN_ERR(svn_opt_parse_all_args(&args, os, pool)); + SVN_ERR(parse_args(&args, os, -1, -1, pool)); if (!args->nelts) return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, 0, _("No program provided")); - if (!opt_state->filedata) + if (!opt_state->file) { /* One repository on the command line. */ paths = apr_array_make(pool, 1, sizeof(const char *)); @@ -1282,9 +1495,11 @@ subcommand_freeze(apr_getopt_t *os, void *baton, apr_pool_t *pool) } else { + svn_stringbuf_t *buf; const char *utf8; - /* All repositories in filedata. */ - SVN_ERR(svn_utf_cstring_to_utf8(&utf8, opt_state->filedata->data, pool)); + /* Read repository paths from the -F file. */ + SVN_ERR(svn_stringbuf_from_file2(&buf, opt_state->file, pool)); + SVN_ERR(svn_utf_cstring_to_utf8(&utf8, buf->data, pool)); paths = svn_cstring_split(utf8, "\r\n", FALSE, pool); } @@ -1362,6 +1577,38 @@ optrev_to_revnum(svn_revnum_t *revnum, const svn_opt_revision_t *opt_rev) return SVN_NO_ERROR; } +/* Read the min / max revision from the OPT_STATE, verify them and return + them in *LOWER and *UPPER, respectively. */ +static svn_error_t * +get_load_range(svn_revnum_t *lower, + svn_revnum_t *upper, + struct svnadmin_opt_state *opt_state) +{ + /* Find the revision numbers at which to start and end. We only + support a limited set of revision kinds: number and unspecified. */ + SVN_ERR(optrev_to_revnum(lower, &opt_state->start_revision)); + SVN_ERR(optrev_to_revnum(upper, &opt_state->end_revision)); + + /* Fill in implied revisions if necessary. */ + if ((*upper == SVN_INVALID_REVNUM) && (*lower != SVN_INVALID_REVNUM)) + { + *upper = *lower; + } + else if ((*upper != SVN_INVALID_REVNUM) && (*lower == SVN_INVALID_REVNUM)) + { + *lower = *upper; + } + + /* Ensure correct range ordering. */ + if (*lower > *upper) + { + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("First revision cannot be higher than second")); + } + + return SVN_NO_ERROR; +} + /* This implements `svn_opt_subcommand_t'. */ static svn_error_t * @@ -1370,8 +1617,8 @@ subcommand_load(apr_getopt_t *os, void *baton, apr_pool_t *pool) svn_error_t *err; struct svnadmin_opt_state *opt_state = baton; svn_repos_t *repos; - svn_revnum_t lower = SVN_INVALID_REVNUM, upper = SVN_INVALID_REVNUM; - svn_stream_t *stdin_stream; + svn_revnum_t lower, upper; + svn_stream_t *in_stream; svn_stream_t *feedback_stream = NULL; /* Expect no more arguments. */ @@ -1379,52 +1626,107 @@ subcommand_load(apr_getopt_t *os, void *baton, apr_pool_t *pool) /* Find the revision numbers at which to start and end. We only support a limited set of revision kinds: number and unspecified. */ - SVN_ERR(optrev_to_revnum(&lower, &opt_state->start_revision)); - SVN_ERR(optrev_to_revnum(&upper, &opt_state->end_revision)); + SVN_ERR(get_load_range(&lower, &upper, opt_state)); - /* Fill in implied revisions if necessary. */ - if ((upper == SVN_INVALID_REVNUM) && (lower != SVN_INVALID_REVNUM)) - { - upper = lower; - } - else if ((upper != SVN_INVALID_REVNUM) && (lower == SVN_INVALID_REVNUM)) - { - lower = upper; - } + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); - /* Ensure correct range ordering. */ - if (lower > upper) - { - return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, - _("First revision cannot be higher than second")); - } - - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); - - /* Read the stream from STDIN. Users can redirect a file. */ - SVN_ERR(svn_stream_for_stdin(&stdin_stream, pool)); + /* Open the file or STDIN, depending on whether -F was specified. */ + if (opt_state->file) + SVN_ERR(svn_stream_open_readonly(&in_stream, opt_state->file, + pool, pool)); + else + SVN_ERR(svn_stream_for_stdin2(&in_stream, TRUE, pool)); /* Progress feedback goes to STDOUT, unless they asked to suppress it. */ if (! opt_state->quiet) feedback_stream = recode_stream_create(stdout, pool); - err = svn_repos_load_fs5(repos, stdin_stream, lower, upper, + err = svn_repos_load_fs6(repos, in_stream, lower, upper, opt_state->uuid_action, opt_state->parent_dir, opt_state->use_pre_commit_hook, opt_state->use_post_commit_hook, !opt_state->bypass_prop_validation, opt_state->ignore_dates, + opt_state->normalize_props, opt_state->quiet ? NULL : repos_notify_handler, feedback_stream, check_cancel, NULL, pool); - if (err && err->apr_err == SVN_ERR_BAD_PROPERTY_VALUE) - return svn_error_quick_wrap(err, - _("Invalid property value found in " - "dumpstream; consider repairing the source " - "or using --bypass-prop-validation while " - "loading.")); + + if (svn_error_find_cause(err, SVN_ERR_BAD_PROPERTY_VALUE_EOL)) + { + return svn_error_quick_wrap(err, + _("A property with invalid line ending " + "found in dumpstream; consider using " + "--normalize-props while loading.")); + } + else if (err && err->apr_err == SVN_ERR_BAD_PROPERTY_VALUE) + { + return svn_error_quick_wrap(err, + _("Invalid property value found in " + "dumpstream; consider repairing the " + "source or using --bypass-prop-validation " + "while loading.")); + } + return err; } +static svn_error_t * +subcommand_load_revprops(apr_getopt_t *os, void *baton, apr_pool_t *pool) +{ + svn_error_t *err; + struct svnadmin_opt_state *opt_state = baton; + svn_repos_t *repos; + svn_revnum_t lower, upper; + svn_stream_t *in_stream; + + svn_stream_t *feedback_stream = NULL; + + /* Expect no more arguments. */ + SVN_ERR(parse_args(NULL, os, 0, 0, pool)); + + /* Find the revision numbers at which to start and end. We only + support a limited set of revision kinds: number and unspecified. */ + SVN_ERR(get_load_range(&lower, &upper, opt_state)); + + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); + + /* Open the file or STDIN, depending on whether -F was specified. */ + if (opt_state->file) + SVN_ERR(svn_stream_open_readonly(&in_stream, opt_state->file, + pool, pool)); + else + SVN_ERR(svn_stream_for_stdin2(&in_stream, TRUE, pool)); + + /* Progress feedback goes to STDOUT, unless they asked to suppress it. */ + if (! opt_state->quiet) + feedback_stream = recode_stream_create(stdout, pool); + + err = svn_repos_load_fs_revprops(repos, in_stream, lower, upper, + !opt_state->bypass_prop_validation, + opt_state->ignore_dates, + opt_state->normalize_props, + opt_state->quiet ? NULL + : repos_notify_handler, + feedback_stream, check_cancel, NULL, pool); + + if (svn_error_find_cause(err, SVN_ERR_BAD_PROPERTY_VALUE_EOL)) + { + return svn_error_quick_wrap(err, + _("A property with invalid line ending " + "found in dumpstream; consider using " + "--normalize-props while loading.")); + } + else if (err && err->apr_err == SVN_ERR_BAD_PROPERTY_VALUE) + { + return svn_error_quick_wrap(err, + _("Invalid property value found in " + "dumpstream; consider repairing the " + "source or using --bypass-prop-validation " + "while loading.")); + } + + return err; +} /* This implements `svn_opt_subcommand_t'. */ static svn_error_t * @@ -1434,21 +1736,46 @@ subcommand_lstxns(apr_getopt_t *os, void *baton, apr_pool_t *pool) svn_repos_t *repos; svn_fs_t *fs; apr_array_header_t *txns; + apr_pool_t *iterpool; + svn_revnum_t youngest, limit; int i; /* Expect no more arguments. */ SVN_ERR(parse_args(NULL, os, 0, 0, pool)); + if (opt_state->end_revision.kind != svn_opt_revision_unspecified) + return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("Revision range is not allowed")); - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); fs = svn_repos_fs(repos); SVN_ERR(svn_fs_list_transactions(&txns, fs, pool)); - /* Loop, printing revisions. */ + SVN_ERR(svn_fs_youngest_rev(&youngest, fs, pool)); + SVN_ERR(get_revnum(&limit, &opt_state->start_revision, youngest, repos, + pool)); + + iterpool = svn_pool_create(pool); for (i = 0; i < txns->nelts; i++) { - SVN_ERR(svn_cmdline_printf(pool, "%s\n", - APR_ARRAY_IDX(txns, i, const char *))); + const char *name = APR_ARRAY_IDX(txns, i, const char *); + svn_boolean_t show = TRUE; + + svn_pool_clear(iterpool); + if (limit != SVN_INVALID_REVNUM) + { + svn_fs_txn_t *txn; + svn_revnum_t base; + + SVN_ERR(svn_fs_open_txn(&txn, fs, name, iterpool)); + base = svn_fs_txn_base_revision(txn); + + if (base > limit) + show = FALSE; + } + if (show) + SVN_ERR(svn_cmdline_printf(pool, "%s\n", name)); } + svn_pool_destroy(iterpool); return SVN_NO_ERROR; } @@ -1472,7 +1799,7 @@ subcommand_recover(apr_getopt_t *os, void *baton, apr_pool_t *pool) /* Restore default signal handlers until after we have acquired the * exclusive lock so that the user interrupt before we actually * touch the repository. */ - setup_cancellation_signals(SIG_DFL); + svn_cmdline__disable_cancellation_handler(); err = svn_repos_recover4(opt_state->repository_path, TRUE, repos_notify_handler, feedback_stream, @@ -1502,7 +1829,7 @@ subcommand_recover(apr_getopt_t *os, void *baton, apr_pool_t *pool) /* Since db transactions may have been replayed, it's nice to tell people what the latest revision is. It also proves that the recovery actually worked. */ - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); SVN_ERR(svn_fs_youngest_rev(&youngest_rev, svn_repos_fs(repos), pool)); SVN_ERR(svn_cmdline_printf(pool, _("The latest repos revision is %ld.\n"), youngest_rev)); @@ -1533,12 +1860,12 @@ list_dblogs(apr_getopt_t *os, void *baton, svn_boolean_t only_unused, style before printing. */ for (i = 0; i < logfiles->nelts; i++) { - const char *log_utf8; - log_utf8 = svn_dirent_join(opt_state->repository_path, + const char *log_path; + log_path = svn_dirent_join(opt_state->repository_path, APR_ARRAY_IDX(logfiles, i, const char *), pool); - log_utf8 = svn_dirent_local_style(log_utf8, pool); - SVN_ERR(svn_cmdline_printf(pool, "%s\n", log_utf8)); + log_path = svn_dirent_local_style(log_path, pool); + SVN_ERR(svn_cmdline_printf(pool, "%s\n", log_path)); } return SVN_NO_ERROR; @@ -1578,24 +1905,21 @@ subcommand_rmtxns(apr_getopt_t *os, void *baton, apr_pool_t *pool) int i; apr_pool_t *subpool = svn_pool_create(pool); - SVN_ERR(svn_opt_parse_all_args(&args, os, pool)); + SVN_ERR(parse_args(&args, os, -1, -1, pool)); - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); fs = svn_repos_fs(repos); /* All the rest of the arguments are transaction names. */ for (i = 0; i < args->nelts; i++) { const char *txn_name = APR_ARRAY_IDX(args, i, const char *); - const char *txn_name_utf8; svn_error_t *err; svn_pool_clear(subpool); - SVN_ERR(svn_utf_cstring_to_utf8(&txn_name_utf8, txn_name, subpool)); - /* Try to open the txn. If that succeeds, try to abort it. */ - err = svn_fs_open_txn(&txn, fs, txn_name_utf8, subpool); + err = svn_fs_open_txn(&txn, fs, txn_name, subpool); if (! err) err = svn_fs_abort_txn(txn, subpool); @@ -1606,7 +1930,7 @@ subcommand_rmtxns(apr_getopt_t *os, void *baton, apr_pool_t *pool) if (err && (err->apr_err == SVN_ERR_FS_TRANSACTION_DEAD)) { svn_error_clear(err); - err = svn_fs_purge_txn(fs, txn_name_utf8, subpool); + err = svn_fs_purge_txn(fs, txn_name, subpool); } /* If we had a real from the txn open, abort, or purge, we clear @@ -1660,7 +1984,7 @@ set_revprop(const char *prop_name, const char *filename, } /* Open the filesystem */ - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); if (opt_state->txn_id) { @@ -1736,7 +2060,7 @@ subcommand_setuuid(apr_getopt_t *os, void *baton, apr_pool_t *pool) if (args->nelts == 1) uuid = APR_ARRAY_IDX(args, 0, const char *); - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); fs = svn_repos_fs(repos); return svn_fs_set_uuid(fs, uuid, pool); } @@ -1784,7 +2108,7 @@ subcommand_pack(apr_getopt_t *os, void *baton, apr_pool_t *pool) /* Expect no more arguments. */ SVN_ERR(parse_args(NULL, os, 0, 0, pool)); - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); /* Progress feedback goes to STDOUT, unless they asked to suppress it. */ if (! opt_state->quiet) @@ -1819,7 +2143,7 @@ subcommand_verify(apr_getopt_t *os, void *baton, apr_pool_t *pool) "are mutually exclusive")); } - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); fs = svn_repos_fs(repos); SVN_ERR(svn_fs_youngest_rev(&youngest, fs, pool)); @@ -1970,11 +2294,12 @@ subcommand_info(apr_getopt_t *os, void *baton, apr_pool_t *pool) svn_fs_t *fs; int fs_format; const char *uuid; + svn_revnum_t head_rev; /* Expect no more arguments. */ SVN_ERR(parse_args(NULL, os, 0, 0, pool)); - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); fs = svn_repos_fs(repos); SVN_ERR(svn_cmdline_printf(pool, _("Path: %s\n"), svn_dirent_local_style(svn_repos_path(repos, pool), @@ -1982,6 +2307,9 @@ subcommand_info(apr_getopt_t *os, void *baton, apr_pool_t *pool) SVN_ERR(svn_fs_get_uuid(fs, &uuid, pool)); SVN_ERR(svn_cmdline_printf(pool, _("UUID: %s\n"), uuid)); + + SVN_ERR(svn_fs_youngest_rev(&head_rev, fs, pool)); + SVN_ERR(svn_cmdline_printf(pool, _("Revisions: %ld\n"), head_rev)); { int repos_format, minor; svn_version_t *repos_version, *fs_version; @@ -2036,8 +2364,6 @@ subcommand_info(apr_getopt_t *os, void *baton, apr_pool_t *pool) if (!strcmp(info->fs_type, SVN_FS_TYPE_FSFS)) { const svn_fs_fsfs_info_t *fsfs_info = (const void *)info; - svn_revnum_t youngest; - SVN_ERR(svn_fs_youngest_rev(&youngest, fs, pool)); if (fsfs_info->shard_size) SVN_ERR(svn_cmdline_printf(pool, _("FSFS Sharded: yes\n"))); @@ -2053,7 +2379,7 @@ subcommand_info(apr_getopt_t *os, void *baton, apr_pool_t *pool) { const int shard_size = fsfs_info->shard_size; const long shards_packed = fsfs_info->min_unpacked_rev / shard_size; - const long shards_full = (youngest + 1) / shard_size; + const long shards_full = (head_rev + 1) / shard_size; SVN_ERR(svn_cmdline_printf(pool, _("FSFS Shards Packed: %ld/%ld\n"), shards_packed, shards_full)); } @@ -2063,6 +2389,19 @@ subcommand_info(apr_getopt_t *os, void *baton, apr_pool_t *pool) else SVN_ERR(svn_cmdline_printf(pool, _("FSFS Logical Addressing: no\n"))); } + else if (!strcmp(info->fs_type, SVN_FS_TYPE_FSX)) + { + const svn_fs_fsx_info_t *fsx_info = (const void *)info; + + const int shard_size = fsx_info->shard_size; + const long shards_packed = fsx_info->min_unpacked_rev / shard_size; + long shards_full = (head_rev + 1) / shard_size; + + SVN_ERR(svn_cmdline_printf(pool, _("FSX Shard Size: %d\n"), + shard_size)); + SVN_ERR(svn_cmdline_printf(pool, _("FSX Shards Packed: %ld/%ld\n"), + shards_packed, shards_full)); + } } { @@ -2097,7 +2436,6 @@ subcommand_lock(apr_getopt_t *os, void *baton, apr_pool_t *pool) const char *lock_path; const char *comment_file_name; svn_stringbuf_t *file_contents; - const char *lock_path_utf8; svn_lock_t *lock; const char *lock_token = NULL; @@ -2113,7 +2451,7 @@ subcommand_lock(apr_getopt_t *os, void *baton, apr_pool_t *pool) SVN_ERR(target_arg_to_dirent(&comment_file_name, comment_file_name, pool)); - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); fs = svn_repos_fs(repos); /* Create an access context describing the user. */ @@ -2124,10 +2462,10 @@ subcommand_lock(apr_getopt_t *os, void *baton, apr_pool_t *pool) SVN_ERR(svn_stringbuf_from_file2(&file_contents, comment_file_name, pool)); - SVN_ERR(svn_utf_cstring_to_utf8(&lock_path_utf8, lock_path, pool)); + SVN_ERR(target_arg_to_fspath(&lock_path, lock_path, pool, pool)); if (opt_state->bypass_hooks) - SVN_ERR(svn_fs_lock(&lock, fs, lock_path_utf8, + SVN_ERR(svn_fs_lock(&lock, fs, lock_path, lock_token, file_contents->data, /* comment */ 0, /* is_dav_comment */ @@ -2135,7 +2473,7 @@ subcommand_lock(apr_getopt_t *os, void *baton, apr_pool_t *pool) SVN_INVALID_REVNUM, FALSE, pool)); else - SVN_ERR(svn_repos_fs_lock(&lock, repos, lock_path_utf8, + SVN_ERR(svn_repos_fs_lock(&lock, repos, lock_path, lock_token, file_contents->data, /* comment */ 0, /* is_dav_comment */ @@ -2143,8 +2481,10 @@ subcommand_lock(apr_getopt_t *os, void *baton, apr_pool_t *pool) SVN_INVALID_REVNUM, FALSE, pool)); - SVN_ERR(svn_cmdline_printf(pool, _("'%s' locked by user '%s'.\n"), - lock_path, username)); + if (! opt_state->quiet) + SVN_ERR(svn_cmdline_printf(pool, _("'%s' locked by user '%s'.\n"), + lock_path, username)); + return SVN_NO_ERROR; } @@ -2154,7 +2494,7 @@ subcommand_lslocks(apr_getopt_t *os, void *baton, apr_pool_t *pool) struct svnadmin_opt_state *opt_state = baton; apr_array_header_t *targets; svn_repos_t *repos; - const char *fs_path = "/"; + const char *fs_path; apr_hash_t *locks; apr_hash_index_t *hi; apr_pool_t *iterpool = svn_pool_create(pool); @@ -2168,8 +2508,11 @@ subcommand_lslocks(apr_getopt_t *os, void *baton, apr_pool_t *pool) _("Too many arguments given")); if (targets->nelts) fs_path = APR_ARRAY_IDX(targets, 0, const char *); + else + fs_path = "/"; + SVN_ERR(target_arg_to_fspath(&fs_path, fs_path, pool, pool)); - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); /* Fetch all locks on or below the root directory. */ SVN_ERR(svn_repos_fs_get_locks2(&locks, repos, fs_path, svn_depth_infinity, @@ -2227,7 +2570,7 @@ subcommand_rmlocks(apr_getopt_t *os, void *baton, apr_pool_t *pool) const char *username; apr_pool_t *subpool = svn_pool_create(pool); - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); fs = svn_repos_fs(repos); /* svn_fs_unlock() demands that some username be associated with the @@ -2243,7 +2586,7 @@ subcommand_rmlocks(apr_getopt_t *os, void *baton, apr_pool_t *pool) SVN_ERR(svn_fs_set_access(fs, access)); /* Parse out any options. */ - SVN_ERR(svn_opt_parse_all_args(&args, os, pool)); + SVN_ERR(parse_args(&args, os, -1, -1, pool)); /* Our usage requires at least one FS path. */ if (args->nelts == 0) @@ -2254,31 +2597,34 @@ subcommand_rmlocks(apr_getopt_t *os, void *baton, apr_pool_t *pool) for (i = 0; i < args->nelts; i++) { const char *lock_path = APR_ARRAY_IDX(args, i, const char *); - const char *lock_path_utf8; svn_lock_t *lock; - SVN_ERR(svn_utf_cstring_to_utf8(&lock_path_utf8, lock_path, subpool)); + SVN_ERR(target_arg_to_fspath(&lock_path, lock_path, subpool, subpool)); /* Fetch the path's svn_lock_t. */ - err = svn_fs_get_lock(&lock, fs, lock_path_utf8, subpool); + err = svn_fs_get_lock(&lock, fs, lock_path, subpool); if (err) goto move_on; if (! lock) { - SVN_ERR(svn_cmdline_printf(subpool, - _("Path '%s' isn't locked.\n"), - lock_path)); + if (! opt_state->quiet) + SVN_ERR(svn_cmdline_printf(subpool, + _("Path '%s' isn't locked.\n"), + lock_path)); continue; } + lock = NULL; /* Don't access LOCK after this point. */ /* Now forcibly destroy the lock. */ - err = svn_fs_unlock(fs, lock_path_utf8, - lock->token, 1 /* force */, subpool); + err = svn_fs_unlock(fs, lock_path, + NULL, 1 /* force */, subpool); if (err) goto move_on; - SVN_ERR(svn_cmdline_printf(subpool, - _("Removed lock on '%s'.\n"), lock->path)); + if (! opt_state->quiet) + SVN_ERR(svn_cmdline_printf(subpool, + _("Removed lock on '%s'.\n"), + lock_path)); move_on: if (err) @@ -2307,7 +2653,6 @@ subcommand_unlock(apr_getopt_t *os, void *baton, apr_pool_t *pool) apr_array_header_t *args; const char *username; const char *lock_path; - const char *lock_path_utf8; const char *lock_token = NULL; /* Expect three more arguments: PATH USERNAME TOKEN */ @@ -2318,21 +2663,23 @@ subcommand_unlock(apr_getopt_t *os, void *baton, apr_pool_t *pool) /* Open the repos/FS, and associate an access context containing USERNAME. */ - SVN_ERR(open_repos(&repos, opt_state->repository_path, pool)); + SVN_ERR(open_repos(&repos, opt_state->repository_path, opt_state, pool)); fs = svn_repos_fs(repos); SVN_ERR(svn_fs_create_access(&access, username, pool)); SVN_ERR(svn_fs_set_access(fs, access)); - SVN_ERR(svn_utf_cstring_to_utf8(&lock_path_utf8, lock_path, pool)); + SVN_ERR(target_arg_to_fspath(&lock_path, lock_path, pool, pool)); if (opt_state->bypass_hooks) - SVN_ERR(svn_fs_unlock(fs, lock_path_utf8, lock_token, + SVN_ERR(svn_fs_unlock(fs, lock_path, lock_token, FALSE, pool)); else - SVN_ERR(svn_repos_fs_unlock(repos, lock_path_utf8, lock_token, + SVN_ERR(svn_repos_fs_unlock(repos, lock_path, lock_token, FALSE, pool)); - SVN_ERR(svn_cmdline_printf(pool, _("'%s' unlocked by user '%s'.\n"), - lock_path, username)); + if (! opt_state->quiet) + SVN_ERR(svn_cmdline_printf(pool, _("'%s' unlocked by user '%s'.\n"), + lock_path, username)); + return SVN_NO_ERROR; } @@ -2351,7 +2698,7 @@ subcommand_upgrade(apr_getopt_t *os, void *baton, apr_pool_t *pool) SVN_ERR(svn_stream_for_stdout(&feedback_stream, pool)); /* Restore default signal handlers. */ - setup_cancellation_signals(SIG_DFL); + svn_cmdline__disable_cancellation_handler(); err = svn_repos_upgrade2(opt_state->repository_path, TRUE, repos_notify_handler, feedback_stream, pool); @@ -2532,14 +2879,17 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) opt_state.help = TRUE; break; case 'M': - opt_state.memory_cache_size - = 0x100000 * apr_strtoi64(opt_arg, NULL, 0); + { + apr_uint64_t sz_val; + SVN_ERR(svn_cstring_atoui64(&sz_val, opt_arg)); + + opt_state.memory_cache_size = 0x100000 * sz_val; + } break; case 'F': - SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool)); - SVN_ERR(svn_stringbuf_from_file2(&(opt_state.filedata), - utf8_opt_arg, pool)); + SVN_ERR(svn_utf_cstring_to_utf8(&(opt_state.file), opt_arg, pool)); dash_F_arg = TRUE; + break; case svnadmin__version: opt_state.version = TRUE; break; @@ -2662,6 +3012,29 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) case svnadmin__wait: opt_state.wait = TRUE; break; + case svnadmin__no_flush_to_disk: + opt_state.no_flush_to_disk = TRUE; + break; + case svnadmin__normalize_props: + opt_state.normalize_props = TRUE; + break; + case svnadmin__exclude: + SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool)); + + if (! opt_state.exclude) + opt_state.exclude = apr_array_make(pool, 1, sizeof(const char *)); + APR_ARRAY_PUSH(opt_state.exclude, const char *) = utf8_opt_arg; + break; + case svnadmin__include: + SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool)); + + if (! opt_state.include) + opt_state.include = apr_array_make(pool, 1, sizeof(const char *)); + APR_ARRAY_PUSH(opt_state.include, const char *) = utf8_opt_arg; + break; + case svnadmin__glob: + opt_state.glob = TRUE; + break; default: { SVN_ERR(subcommand_help(NULL, NULL, pool)); @@ -2706,17 +3079,17 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) } else { - const char *first_arg = os->argv[os->ind++]; + const char *first_arg; + + SVN_ERR(svn_utf_cstring_to_utf8(&first_arg, os->argv[os->ind++], + pool)); subcommand = svn_opt_get_canonical_subcommand2(cmd_table, first_arg); if (subcommand == NULL) { - const char *first_arg_utf8; - SVN_ERR(svn_utf_cstring_to_utf8(&first_arg_utf8, - first_arg, pool)); svn_error_clear( svn_cmdline_fprintf(stderr, pool, _("Unknown subcommand: '%s'\n"), - first_arg_utf8)); + first_arg)); SVN_ERR(subcommand_help(NULL, NULL, pool)); *exit_code = EXIT_FAILURE; return SVN_NO_ERROR; @@ -2781,20 +3154,7 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) } } - /* Set up our cancellation support. */ - setup_cancellation_signals(signal_handler); - -#ifdef SIGPIPE - /* Disable SIGPIPE generation for the platforms that have it. */ - apr_signal(SIGPIPE, SIG_IGN); -#endif - -#ifdef SIGXFSZ - /* Disable SIGXFSZ generation for the platforms that have it, otherwise - * working with large files when compiled against an APR that doesn't have - * large file support will crash the program, which is uncool. */ - apr_signal(SIGXFSZ, SIG_IGN); -#endif + check_cancel = svn_cmdline__setup_cancellation_handler(); /* Configure FSFS caches for maximum efficiency with svnadmin. * Also, apply the respective command line parameters, if given. */ @@ -2854,5 +3214,8 @@ main(int argc, const char *argv[]) } svn_pool_destroy(pool); + + svn_cmdline__cancellation_exit(); + return exit_code; } diff --git a/subversion/svnbench/cl.h b/subversion/svnbench/cl.h index 5b15fe5bb15f..f14e25532b84 100644 --- a/subversion/svnbench/cl.h +++ b/subversion/svnbench/cl.h @@ -95,6 +95,7 @@ typedef struct svn_cl__opt_state_t svn_boolean_t trust_server_cert_expired; svn_boolean_t trust_server_cert_not_yet_valid; svn_boolean_t trust_server_cert_other_failure; + apr_array_header_t* search_patterns; /* pattern arguments for --search */ } svn_cl__opt_state_t; @@ -150,8 +151,7 @@ svn_cl__try(svn_error_t *err, /* Our cancellation callback. */ -svn_error_t * -svn_cl__check_cancel(void *baton); +extern svn_cancel_func_t svn_cl__check_cancel; diff --git a/subversion/svnbench/null-export-cmd.c b/subversion/svnbench/null-export-cmd.c index 8220bfbe91d0..7b3904e42c16 100644 --- a/subversion/svnbench/null-export-cmd.c +++ b/subversion/svnbench/null-export-cmd.c @@ -165,6 +165,15 @@ close_file(void *file_baton, return SVN_NO_ERROR; } +/* Implement svn_write_fn_t, simply counting the incoming data. */ +static svn_error_t * +file_write_handler(void *baton, const char *data, apr_size_t *len) +{ + edit_baton_t *eb = baton; + eb->byte_count += *len; + + return SVN_NO_ERROR; +} /*** Public Interfaces ***/ @@ -198,6 +207,7 @@ bench_null_export(svn_revnum_t *result_rev, svn_client__pathrev_t *loc; svn_ra_session_t *ra_session; svn_node_kind_t kind; + edit_baton_t *eb = baton; /* Get the RA connection. */ SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &loc, @@ -211,6 +221,11 @@ bench_null_export(svn_revnum_t *result_rev, { apr_hash_t *props; + /* Since we don't use the editor, we must count "manually". */ + svn_stream_t *stream = svn_stream_create(eb, pool); + svn_stream_set_write(stream, file_write_handler); + eb->file_count++; + /* Since you cannot actually root an editor at a file, we * manually drive a few functions of our editor. */ @@ -218,8 +233,7 @@ bench_null_export(svn_revnum_t *result_rev, * to the repository. */ /* ### note: the stream will not be closed */ SVN_ERR(svn_ra_get_file(ra_session, "", loc->rev, - svn_stream_empty(pool), - NULL, &props, pool)); + stream, NULL, &props, pool)); } else if (kind == svn_node_dir) { @@ -268,6 +282,10 @@ bench_null_export(svn_revnum_t *result_rev, NULL, pool)); SVN_ERR(reporter->finish_report(report_baton, pool)); + + /* We don't receive the "add directory" callback for the starting + * node. */ + eb->dir_count++; } else if (kind == svn_node_none) { diff --git a/subversion/svnbench/null-list-cmd.c b/subversion/svnbench/null-list-cmd.c index 3f1920924072..582fca1b6ced 100644 --- a/subversion/svnbench/null-list-cmd.c +++ b/subversion/svnbench/null-list-cmd.c @@ -48,6 +48,12 @@ struct print_baton { svn_client_ctx_t *ctx; }; +/* Field flags required for this function */ +static const apr_uint32_t print_dirent_fields = SVN_DIRENT_KIND; +static const apr_uint32_t print_dirent_fields_verbose = ( + SVN_DIRENT_KIND | SVN_DIRENT_SIZE | SVN_DIRENT_TIME | + SVN_DIRENT_CREATED_REV | SVN_DIRENT_LAST_AUTHOR); + /* This implements the svn_client_list_func2_t API, printing a single directory entry in text format. */ static svn_error_t * @@ -100,9 +106,9 @@ svn_cl__null_list(apr_getopt_t *os, svn_opt_push_implicit_dot_target(targets, pool); if (opt_state->verbose) - dirent_fields = SVN_DIRENT_ALL; + dirent_fields = print_dirent_fields_verbose; else - dirent_fields = SVN_DIRENT_KIND; /* the only thing we actually need... */ + dirent_fields = print_dirent_fields; pb.ctx = ctx; pb.verbose = opt_state->verbose; @@ -116,6 +122,8 @@ svn_cl__null_list(apr_getopt_t *os, const char *target = APR_ARRAY_IDX(targets, i, const char *); const char *truepath; svn_opt_revision_t peg_revision; + apr_array_header_t *patterns = NULL; + int k; svn_pool_clear(subpool); @@ -125,8 +133,27 @@ svn_cl__null_list(apr_getopt_t *os, SVN_ERR(svn_opt_parse_path(&peg_revision, &truepath, target, subpool)); - err = svn_client_list3(truepath, &peg_revision, - &(opt_state->start_revision), + if (opt_state->search_patterns) + { + patterns = apr_array_make(subpool, 4, sizeof(const char *)); + for (k = 0; k < opt_state->search_patterns->nelts; ++k) + { + apr_array_header_t *pattern_group + = APR_ARRAY_IDX(opt_state->search_patterns, k, + apr_array_header_t *); + + /* Should never fail but ... */ + if (pattern_group->nelts != 1) + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("'search-and' option is not supported")); + + APR_ARRAY_PUSH(patterns, const char *) + = APR_ARRAY_IDX(pattern_group, 0, const char *); + } + } + + err = svn_client_list4(truepath, &peg_revision, + &(opt_state->start_revision), patterns, opt_state->depth, dirent_fields, opt_state->verbose, diff --git a/subversion/svnbench/null-log-cmd.c b/subversion/svnbench/null-log-cmd.c index e8f9734f6950..d8ad61b69b20 100644 --- a/subversion/svnbench/null-log-cmd.c +++ b/subversion/svnbench/null-log-cmd.c @@ -198,10 +198,14 @@ svn_cl__null_log(apr_getopt_t *os, lb.quiet = opt_state->quiet; revprops = apr_array_make(pool, 3, sizeof(char *)); - APR_ARRAY_PUSH(revprops, const char *) = SVN_PROP_REVISION_AUTHOR; - APR_ARRAY_PUSH(revprops, const char *) = SVN_PROP_REVISION_DATE; - if (!opt_state->quiet) - APR_ARRAY_PUSH(revprops, const char *) = SVN_PROP_REVISION_LOG; + if (!opt_state->no_revprops) + { + APR_ARRAY_PUSH(revprops, const char *) = SVN_PROP_REVISION_AUTHOR; + APR_ARRAY_PUSH(revprops, const char *) = SVN_PROP_REVISION_DATE; + if (!opt_state->quiet) + APR_ARRAY_PUSH(revprops, const char *) = SVN_PROP_REVISION_LOG; + } + SVN_ERR(svn_client_log5(targets, &target_peg_revision, opt_state->revision_ranges, diff --git a/subversion/svnbench/svnbench.c b/subversion/svnbench/svnbench.c index bd67e0b35752..80a872842b6f 100644 --- a/subversion/svnbench/svnbench.c +++ b/subversion/svnbench/svnbench.c @@ -30,8 +30,6 @@ #include #include -#include - #include "svn_cmdline.h" #include "svn_dirent_uri.h" #include "svn_pools.h" @@ -42,6 +40,8 @@ #include "private/svn_opt_private.h" #include "private/svn_cmdline_private.h" +#include "private/svn_string_private.h" +#include "private/svn_utf_private.h" #include "svn_private_config.h" @@ -53,6 +53,7 @@ use the short option letter as identifier. */ typedef enum svn_cl__longopt_t { opt_auth_password = SVN_OPT_FIRST_LONGOPT_ID, + opt_auth_password_from_stdin, opt_auth_username, opt_config_dir, opt_config_options, @@ -68,7 +69,8 @@ typedef enum svn_cl__longopt_t { opt_with_no_revprops, opt_trust_server_cert, opt_trust_server_cert_failures, - opt_changelist + opt_changelist, + opt_search } svn_cl__longopt_t; @@ -111,6 +113,8 @@ const apr_getopt_option_t svn_cl__options[] = {"verbose", 'v', 0, N_("print extra information")}, {"username", opt_auth_username, 1, N_("specify a username ARG")}, {"password", opt_auth_password, 1, N_("specify a password ARG")}, + {"password-from-stdin", + opt_auth_password_from_stdin, 0, N_("read password from stdin")}, {"targets", opt_targets, 1, N_("pass contents of file ARG as additional args")}, {"depth", opt_depth, 1, @@ -165,6 +169,8 @@ const apr_getopt_option_t svn_cl__options[] = N_("use/display additional information from merge\n" " " "history")}, + {"search", opt_search, 1, + N_("use ARG as search pattern (glob syntax)")}, /* Long-opt Aliases * @@ -194,7 +200,8 @@ const apr_getopt_option_t svn_cl__options[] = command to take these arguments allows scripts to just pass them willy-nilly to every invocation of 'svn') . */ const int svn_cl__global_options[] = -{ opt_auth_username, opt_auth_password, opt_no_auth_cache, opt_non_interactive, +{ opt_auth_username, opt_auth_password, opt_auth_password_from_stdin, + opt_no_auth_cache, opt_non_interactive, opt_trust_server_cert, opt_trust_server_cert_failures, opt_config_dir, opt_config_options, 0 }; @@ -257,7 +264,7 @@ const svn_opt_subcommand_desc2_t svn_cl__cmd_table[] = " If locked, the letter 'O'. (Use 'svn info URL' to see details)\n" " Size (in bytes)\n" " Date and time of the last commit\n"), - {'r', 'v', 'q', 'R', opt_depth} }, + {'r', 'v', 'q', 'R', opt_depth, opt_search} }, { "null-log", svn_cl__null_log, {0}, N_ ("Fetch the log messages for a set of revision(s) and/or path(s).\n" @@ -326,25 +333,42 @@ check_lib_versions(void) } -/* A flag to see if we've been cancelled by the client or not. */ -static volatile sig_atomic_t cancelled = FALSE; - -/* A signal handler to support cancellation. */ -static void -signal_handler(int signum) +/* Baton for ra_progress_func() callback. */ +typedef struct ra_progress_baton_t { - apr_signal(signum, SIG_IGN); - cancelled = TRUE; + apr_off_t bytes_transferred; +} ra_progress_baton_t; + +/* Implements svn_ra_progress_notify_func_t. */ +static void +ra_progress_func(apr_off_t progress, + apr_off_t total, + void *baton, + apr_pool_t *pool) +{ + ra_progress_baton_t *b = baton; + b->bytes_transferred = progress; } /* Our cancellation callback. */ -svn_error_t * -svn_cl__check_cancel(void *baton) +svn_cancel_func_t svn_cl__check_cancel = NULL; + +/* Add a --search argument to OPT_STATE. + * These options start a new search pattern group. */ +static void +add_search_pattern_group(svn_cl__opt_state_t *opt_state, + const char *pattern, + apr_pool_t *result_pool) { - if (cancelled) - return svn_error_create(SVN_ERR_CANCELLED, NULL, _("Caught signal")); - else - return SVN_NO_ERROR; + apr_array_header_t *group = NULL; + + if (opt_state->search_patterns == NULL) + opt_state->search_patterns = apr_array_make(result_pool, 1, + sizeof(apr_array_header_t *)); + + group = apr_array_make(result_pool, 1, sizeof(const char *)); + APR_ARRAY_PUSH(group, const char *) = pattern; + APR_ARRAY_PUSH(opt_state->search_patterns, apr_array_header_t *) = group; } @@ -371,9 +395,16 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) svn_config_t *cfg_config; svn_boolean_t descend = TRUE; svn_boolean_t use_notifier = TRUE; + apr_time_t start_time, time_taken; + ra_progress_baton_t ra_progress_baton = {0}; + svn_membuf_t buf; + svn_boolean_t read_pass_from_stdin = FALSE; received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); + /* Init the temporary buffer. */ + svn_membuf__create(&buf, 0, pool); + /* Check library versions */ SVN_ERR(check_lib_versions()); @@ -534,10 +565,10 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) opt_arg, pool) != 0) { SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool)); - return svn_error_createf - (SVN_ERR_CL_ARG_PARSING_ERROR, NULL, - _("Syntax error in revision argument '%s'"), - utf8_opt_arg); + return svn_error_createf( + SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("Syntax error in revision argument '%s'"), + utf8_opt_arg); } break; case 'v': @@ -599,6 +630,9 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) SVN_ERR(svn_utf_cstring_to_utf8(&opt_state.auth_password, opt_arg, pool)); break; + case opt_auth_password_from_stdin: + read_pass_from_stdin = TRUE; + break; case opt_stop_on_copy: opt_state.stop_on_copy = TRUE; break; @@ -656,6 +690,14 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) case 'g': opt_state.use_merge_history = TRUE; break; + case opt_search: + SVN_ERR(svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool)); + SVN_ERR(svn_utf__xfrm(&utf8_opt_arg, utf8_opt_arg, + strlen(utf8_opt_arg), TRUE, TRUE, &buf)); + add_search_pattern_group(&opt_state, + apr_pstrdup(pool, utf8_opt_arg), + pool); + break; default: /* Hmmm. Perhaps this would be a good place to squirrel away opts that commands like svn diff might need. Hmmm indeed. */ @@ -713,18 +755,18 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) } else { - const char *first_arg = os->argv[os->ind++]; + const char *first_arg; + + SVN_ERR(svn_utf_cstring_to_utf8(&first_arg, os->argv[os->ind++], + pool)); subcommand = svn_opt_get_canonical_subcommand2(svn_cl__cmd_table, first_arg); if (subcommand == NULL) { - const char *first_arg_utf8; - SVN_ERR(svn_utf_cstring_to_utf8(&first_arg_utf8, - first_arg, pool)); svn_error_clear (svn_cmdline_fprintf(stderr, pool, _("Unknown subcommand: '%s'\n"), - first_arg_utf8)); + first_arg)); SVN_ERR(svn_cl__help(NULL, NULL, pool)); *exit_code = EXIT_FAILURE; return SVN_NO_ERROR; @@ -755,9 +797,9 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) if (subcommand->name[0] == '-') SVN_ERR(svn_cl__help(NULL, NULL, pool)); else - svn_error_clear - (svn_cmdline_fprintf - (stderr, pool, _("Subcommand '%s' doesn't accept option '%s'\n" + svn_error_clear( + svn_cmdline_fprintf( + stderr, pool, _("Subcommand '%s' doesn't accept option '%s'\n" "Type 'svnbench help %s' for usage.\n"), subcommand->name, optstr, subcommand->name)); *exit_code = EXIT_FAILURE; @@ -808,6 +850,14 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) "--non-interactive")); } + /* --password-from-stdin can only be used with --non-interactive */ + if (read_pass_from_stdin && !opt_state.non_interactive) + { + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("--password-from-stdin requires " + "--non-interactive")); + } + /* Ensure that 'revision_ranges' has at least one item, and make 'start_revision' and 'end_revision' match that item. */ if (opt_state.revision_ranges->nelts == 0) @@ -885,31 +935,15 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) pool)); } + /* Get password from stdin if necessary */ + if (read_pass_from_stdin) + { + SVN_ERR(svn_cmdline__stdin_readline(&opt_state.auth_password, pool, pool)); + } + /* Set up our cancellation support. */ + svn_cl__check_cancel = svn_cmdline__setup_cancellation_handler(); ctx->cancel_func = svn_cl__check_cancel; - apr_signal(SIGINT, signal_handler); -#ifdef SIGBREAK - /* SIGBREAK is a Win32 specific signal generated by ctrl-break. */ - apr_signal(SIGBREAK, signal_handler); -#endif -#ifdef SIGHUP - apr_signal(SIGHUP, signal_handler); -#endif -#ifdef SIGTERM - apr_signal(SIGTERM, signal_handler); -#endif - -#ifdef SIGPIPE - /* Disable SIGPIPE generation for the platforms that have it. */ - apr_signal(SIGPIPE, SIG_IGN); -#endif - -#ifdef SIGXFSZ - /* Disable SIGXFSZ generation for the platforms that have it, otherwise - * working with large files when compiled against an APR that doesn't have - * large file support will crash the program, which is uncool. */ - apr_signal(SIGXFSZ, SIG_IGN); -#endif /* Set up Authentication stuff. */ SVN_ERR(svn_cmdline_create_auth_baton2( @@ -938,8 +972,17 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) ctx->conflict_func2 = NULL; ctx->conflict_baton2 = NULL; + if (!opt_state.quiet) + { + ctx->progress_func = ra_progress_func; + ctx->progress_baton = &ra_progress_baton; + } + /* And now we finally run the subcommand. */ + start_time = apr_time_now(); err = (*subcommand->cmd_func)(os, &command_baton, pool); + time_taken = apr_time_now() - start_time; + if (err) { /* For argument-related problems, suggest using the 'help' @@ -968,6 +1011,23 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) return err; } + else if ((subcommand->cmd_func != svn_cl__help) && !opt_state.quiet) + { + /* This formatting lines up nicely with the output of our sub-commands + * and gives musec resolution while not overflowing for 30 years. */ + SVN_ERR(svn_cmdline_printf(pool, + _("%15.6f seconds taken\n"), + time_taken / 1.0e6)); + + /* Report how many bytes transferred over network if RA layer provided + this information. */ + if (ra_progress_baton.bytes_transferred > 0) + SVN_ERR(svn_cmdline_printf(pool, + _("%15s bytes transferred over network\n"), + svn__i64toa_sep( + ra_progress_baton.bytes_transferred, ',', + pool))); + } return SVN_NO_ERROR; } @@ -1001,5 +1061,8 @@ main(int argc, const char *argv[]) } svn_pool_destroy(pool); + + svn_cmdline__cancellation_exit(); + return exit_code; } diff --git a/subversion/svndumpfilter/svndumpfilter.c b/subversion/svndumpfilter/svndumpfilter.c index 922482b6787d..b17ccd2e6588 100644 --- a/subversion/svndumpfilter/svndumpfilter.c +++ b/subversion/svndumpfilter/svndumpfilter.c @@ -48,42 +48,8 @@ #include "private/svn_cmdline_private.h" #include "private/svn_sorts_private.h" -#ifdef _WIN32 -typedef apr_status_t (__stdcall *open_fn_t)(apr_file_t **, apr_pool_t *); -#else -typedef apr_status_t (*open_fn_t)(apr_file_t **, apr_pool_t *); -#endif - /*** Code. ***/ -/* Helper to open stdio streams */ - -/* NOTE: we used to call svn_stream_from_stdio(), which wraps a stream - around a standard stdio.h FILE pointer. The problem is that these - pointers operate through C Run Time (CRT) on Win32, which does all - sorts of translation on them: LF's become CRLF's, and ctrl-Z's - embedded in Word documents are interpreted as premature EOF's. - - So instead, we use apr_file_open_std*, which bypass the CRT and - directly wrap the OS's file-handles, which don't know or care about - translation. Thus dump/load works correctly on Win32. -*/ -static svn_error_t * -create_stdio_stream(svn_stream_t **stream, - open_fn_t open_fn, - apr_pool_t *pool) -{ - apr_file_t *stdio_file; - apr_status_t apr_err = open_fn(&stdio_file, pool); - - if (apr_err) - return svn_error_wrap_apr(apr_err, _("Can't open stdio file")); - - *stream = svn_stream_from_aprfile2(stdio_file, TRUE, pool); - return SVN_NO_ERROR; -} - - /* Writes a property in dumpfile format to given stringbuf. */ static void write_prop_to_stringbuf(svn_stringbuf_t *strbuf, @@ -143,6 +109,7 @@ write_propdel_to_stringbuf(svn_stringbuf_t **strbuf, * Return TRUE if any prefix is a prefix of PATH (matching whole path * components); FALSE otherwise. * PATH starts with a '/', as do the (const char *) paths in PREFIXES. */ +/* This function is a duplicate of svnadmin.c:ary_prefix_match(). */ static svn_boolean_t ary_prefix_match(const apr_array_header_t *pfxlist, const char *path) { @@ -640,7 +607,7 @@ new_node_record(void **node_baton, cf_orig_rev = SVN_STR_TO_REV(val); cf_renum_val = apr_hash_get(pb->renumber_history, &cf_orig_rev, - sizeof(svn_revnum_t)); + sizeof(cf_orig_rev)); if (! (cf_renum_val && SVN_IS_VALID_REVNUM(cf_renum_val->rev))) return svn_error_createf (SVN_ERR_NODE_UNEXPECTED_KIND, NULL, @@ -730,14 +697,14 @@ adjust_mergeinfo(svn_string_t **final_val, const svn_string_t *initial_val, svn_merge_range_t *); revmap_start = apr_hash_get(pb->renumber_history, - &range->start, sizeof(svn_revnum_t)); + &range->start, sizeof(range->start)); if (! (revmap_start && SVN_IS_VALID_REVNUM(revmap_start->rev))) return svn_error_createf (SVN_ERR_NODE_UNEXPECTED_KIND, NULL, _("No valid revision range 'start' in filtered stream")); revmap_end = apr_hash_get(pb->renumber_history, - &range->end, sizeof(svn_revnum_t)); + &range->end, sizeof(range->end)); if (! (revmap_end && SVN_IS_VALID_REVNUM(revmap_end->rev))) return svn_error_createf (SVN_ERR_NODE_UNEXPECTED_KIND, NULL, @@ -984,7 +951,10 @@ static const apr_getopt_option_t options_table[] = {"quiet", svndumpfilter__quiet, 0, N_("Do not display filtering statistics.") }, {"pattern", svndumpfilter__glob, 0, - N_("Treat the path prefixes as file glob patterns.") }, + N_("Treat the path prefixes as file glob patterns.\n" + " Glob special characters are '*' '?' '[]' and '\\'.\n" + " Character '/' is not treated specially, so\n" + " pattern /*/foo matches paths /a/foo and /a/b/foo.") }, {"drop-empty-revs", svndumpfilter__drop_empty_revs, 0, N_("Remove revisions emptied by filtering.")}, {"drop-all-empty-revs", svndumpfilter__drop_all_empty_revs, 0, @@ -1065,12 +1035,10 @@ parse_baton_initialize(struct parse_baton_t **pb, struct parse_baton_t *baton = apr_palloc(pool, sizeof(*baton)); /* Read the stream from STDIN. Users can redirect a file. */ - SVN_ERR(create_stdio_stream(&(baton->in_stream), - apr_file_open_stdin, pool)); + SVN_ERR(svn_stream_for_stdin2(&baton->in_stream, TRUE, pool)); /* Have the parser dump results to STDOUT. Users can redirect a file. */ - SVN_ERR(create_stdio_stream(&(baton->out_stream), - apr_file_open_stdout, pool)); + SVN_ERR(svn_stream_for_stdout(&baton->out_stream, pool)); baton->do_exclude = do_exclude; @@ -1404,7 +1372,8 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) opt_state.skip_missing_merge_sources = TRUE; break; case svndumpfilter__targets: - opt_state.targets_file = opt_arg; + SVN_ERR(svn_utf_cstring_to_utf8(&opt_state.targets_file, + opt_arg, pool)); break; default: { @@ -1461,18 +1430,17 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) } else { - const char *first_arg = os->argv[os->ind++]; + const char *first_arg; + + SVN_ERR(svn_utf_cstring_to_utf8(&first_arg, os->argv[os->ind++], + pool)); subcommand = svn_opt_get_canonical_subcommand2(cmd_table, first_arg); if (subcommand == NULL) { - const char* first_arg_utf8; - SVN_ERR(svn_utf_cstring_to_utf8(&first_arg_utf8, first_arg, - pool)); - svn_error_clear( svn_cmdline_fprintf(stderr, pool, _("Unknown subcommand: '%s'\n"), - first_arg_utf8)); + first_arg)); SVN_ERR(subcommand_help(NULL, NULL, pool)); *exit_code = EXIT_FAILURE; return SVN_NO_ERROR; @@ -1505,18 +1473,13 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) if (opt_state.targets_file) { svn_stringbuf_t *buffer, *buffer_utf8; - const char *utf8_targets_file; apr_array_header_t *targets = apr_array_make(pool, 0, sizeof(const char *)); /* We need to convert to UTF-8 now, even before we divide the targets into an array, because otherwise we wouldn't know what delimiter to use for svn_cstring_split(). */ - - SVN_ERR(svn_utf_cstring_to_utf8(&utf8_targets_file, - opt_state.targets_file, pool)); - - SVN_ERR(svn_stringbuf_from_file2(&buffer, utf8_targets_file, + SVN_ERR(svn_stringbuf_from_file2(&buffer, opt_state.targets_file, pool)); SVN_ERR(svn_utf_stringbuf_to_utf8(&buffer_utf8, buffer, pool)); diff --git a/subversion/svnfsfs/load-index-cmd.c b/subversion/svnfsfs/load-index-cmd.c index 4df86bd0946b..e3b5c0d718bf 100644 --- a/subversion/svnfsfs/load-index-cmd.c +++ b/subversion/svnfsfs/load-index-cmd.c @@ -186,7 +186,7 @@ subcommand__load_index(apr_getopt_t *os, void *baton, apr_pool_t *pool) svnfsfs__opt_state *opt_state = baton; svn_stream_t *input; - SVN_ERR(svn_stream_for_stdin(&input, pool)); + SVN_ERR(svn_stream_for_stdin2(&input, TRUE, pool)); SVN_ERR(load_index(opt_state->repository_path, input, pool)); return SVN_NO_ERROR; diff --git a/subversion/svnfsfs/stats-cmd.c b/subversion/svnfsfs/stats-cmd.c index 6e820cb61d4b..2cd294a52147 100644 --- a/subversion/svnfsfs/stats-cmd.c +++ b/subversion/svnfsfs/stats-cmd.c @@ -74,7 +74,8 @@ print_rep_stats(svn_fs_fs__representation_stats_t *stats, "%20s bytes expanded size\n" "%20s bytes expanded shared size\n" "%20s bytes with rep-sharing off\n" - "%20s shared references\n"), + "%20s shared references\n" + "%20.3f average delta chain length\n"), svn__ui64toa_sep(stats->total.packed_size, ',', pool), svn__ui64toa_sep(stats->total.count, ',', pool), svn__ui64toa_sep(stats->shared.packed_size, ',', pool), @@ -82,7 +83,8 @@ print_rep_stats(svn_fs_fs__representation_stats_t *stats, svn__ui64toa_sep(stats->total.expanded_size, ',', pool), svn__ui64toa_sep(stats->shared.expanded_size, ',', pool), svn__ui64toa_sep(stats->expanded_size, ',', pool), - svn__ui64toa_sep(stats->references - stats->total.count, ',', pool)); + svn__ui64toa_sep(stats->references - stats->total.count, ',', pool), + stats->chain_len / MAX(1.0, (double)stats->total.count)); } /* Print the (used) contents of CHANGES. Use POOL for allocations. @@ -375,7 +377,7 @@ print_stats(svn_fs_fs__stats_t *stats, apr_pool_t *pool) { /* print results */ - printf("\nGlobal statistics:\n"); + printf("\n\nGlobal statistics:\n"); printf(_("%20s bytes in %12s revisions\n" "%20s bytes in %12s changes\n" "%20s bytes in %12s node revision records\n" @@ -413,6 +415,7 @@ print_stats(svn_fs_fs__stats_t *stats, "%20s bytes in %12s representations of added file nodes\n" "%20s bytes in %12s directory property representations\n" "%20s bytes in %12s file property representations\n" + " with %12.3f average delta chain length\n" "%20s bytes in header & footer overhead\n"), svn__ui64toa_sep(stats->total_rep_stats.total.packed_size, ',', pool), @@ -433,8 +436,10 @@ print_stats(svn_fs_fs__stats_t *stats, svn__ui64toa_sep(stats->file_prop_rep_stats.total.packed_size, ',', pool), svn__ui64toa_sep(stats->file_prop_rep_stats.total.count, ',', pool), + stats->total_rep_stats.chain_len + / (double)stats->total_rep_stats.total.count, svn__ui64toa_sep(stats->total_rep_stats.total.overhead_size, ',', - pool)); + pool)); printf("\nDirectory representation statistics:\n"); print_rep_stats(&stats->dir_rep_stats, pool); diff --git a/subversion/svnfsfs/svnfsfs.c b/subversion/svnfsfs/svnfsfs.c index f8b1e4b19992..ed3e66470d92 100644 --- a/subversion/svnfsfs/svnfsfs.c +++ b/subversion/svnfsfs/svnfsfs.c @@ -21,8 +21,6 @@ * ==================================================================== */ -#include - #include "svn_pools.h" #include "svn_cmdline.h" #include "svn_opt.h" @@ -42,45 +40,7 @@ /*** Code. ***/ -/* A flag to see if we've been cancelled by the client or not. */ -static volatile sig_atomic_t cancelled = FALSE; - -/* A signal handler to support cancellation. */ -static void -signal_handler(int signum) -{ - apr_signal(signum, SIG_IGN); - cancelled = TRUE; -} - - -/* A helper to set up the cancellation signal handlers. */ -static void -setup_cancellation_signals(void (*handler)(int signum)) -{ - apr_signal(SIGINT, handler); -#ifdef SIGBREAK - /* SIGBREAK is a Win32 specific signal generated by ctrl-break. */ - apr_signal(SIGBREAK, handler); -#endif -#ifdef SIGHUP - apr_signal(SIGHUP, handler); -#endif -#ifdef SIGTERM - apr_signal(SIGTERM, handler); -#endif -} - - -svn_error_t * -check_cancel(void *baton) -{ - if (cancelled) - return svn_error_create(SVN_ERR_CANCELLED, NULL, _("Caught signal")); - else - return SVN_NO_ERROR; -} - +svn_cancel_func_t check_cancel = NULL; /* Custom filesystem warning function. */ static void @@ -341,8 +301,12 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) opt_state.help = TRUE; break; case 'M': - opt_state.memory_cache_size - = 0x100000 * apr_strtoi64(opt_arg, NULL, 0); + { + apr_uint64_t sz_val; + SVN_ERR(svn_cstring_atoui64(&sz_val, opt_arg)); + + opt_state.memory_cache_size = 0x100000 * sz_val; + } break; case svnfsfs__version: opt_state.version = TRUE; @@ -391,17 +355,17 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) } else { - const char *first_arg = os->argv[os->ind++]; + const char *first_arg; + + SVN_ERR(svn_utf_cstring_to_utf8(&first_arg, os->argv[os->ind++], + pool)); subcommand = svn_opt_get_canonical_subcommand2(cmd_table, first_arg); if (subcommand == NULL) { - const char *first_arg_utf8; - SVN_ERR(svn_utf_cstring_to_utf8(&first_arg_utf8, - first_arg, pool)); svn_error_clear( svn_cmdline_fprintf(stderr, pool, _("Unknown subcommand: '%s'\n"), - first_arg_utf8)); + first_arg)); SVN_ERR(subcommand__help(NULL, NULL, pool)); *exit_code = EXIT_FAILURE; return SVN_NO_ERROR; @@ -465,19 +429,7 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) } /* Set up our cancellation support. */ - setup_cancellation_signals(signal_handler); - -#ifdef SIGPIPE - /* Disable SIGPIPE generation for the platforms that have it. */ - apr_signal(SIGPIPE, SIG_IGN); -#endif - -#ifdef SIGXFSZ - /* Disable SIGXFSZ generation for the platforms that have it, otherwise - * working with large files when compiled against an APR that doesn't have - * large file support will crash the program, which is uncool. */ - apr_signal(SIGXFSZ, SIG_IGN); -#endif + check_cancel = svn_cmdline__setup_cancellation_handler(); /* Configure FSFS caches for maximum efficiency with svnfsfs. * Also, apply the respective command line parameters, if given. */ @@ -537,5 +489,8 @@ main(int argc, const char *argv[]) } svn_pool_destroy(pool); + + svn_cmdline__cancellation_exit(); + return exit_code; } diff --git a/subversion/svnfsfs/svnfsfs.h b/subversion/svnfsfs/svnfsfs.h index 132b2bc038b7..80c53234904d 100644 --- a/subversion/svnfsfs/svnfsfs.h +++ b/subversion/svnfsfs/svnfsfs.h @@ -63,8 +63,7 @@ open_fs(svn_fs_t **fs, apr_pool_t *pool); /* Our cancellation callback. */ -svn_error_t * -check_cancel(void *baton); +extern svn_cancel_func_t check_cancel; #ifdef __cplusplus } diff --git a/subversion/svnlook/svnlook.c b/subversion/svnlook/svnlook.c index 53ff2977d59b..261909c00607 100644 --- a/subversion/svnlook/svnlook.c +++ b/subversion/svnlook/svnlook.c @@ -28,7 +28,6 @@ #include #include #include -#include #define APR_WANT_STDIO #define APR_WANT_STRFUNC @@ -43,6 +42,7 @@ #include "svn_dirent_uri.h" #include "svn_path.h" #include "svn_repos.h" +#include "svn_cache_config.h" #include "svn_fs.h" #include "svn_time.h" #include "svn_utf.h" @@ -144,6 +144,13 @@ static const apr_getopt_option_t options_table[] = {"properties-only", svnlook__properties_only, 0, N_("show only properties during the operation")}, + {"memory-cache-size", 'M', 1, + N_("size of the extra in-memory cache in MB used to\n" + " " + "minimize redundant operations. Default: 16.\n" + " " + "[used for FSFS repositories only]")}, + {"no-newline", svnlook__no_newline, 0, N_("do not output the trailing newline")}, @@ -296,7 +303,7 @@ static const svn_opt_subcommand_desc2_t cmd_table[] = N_("usage: svnlook tree REPOS_PATH [PATH_IN_REPOS]\n\n" "Print the tree, starting at PATH_IN_REPOS (if supplied, at the root\n" "of the tree otherwise), optionally showing node revision ids.\n"), - {'r', 't', 'N', svnlook__show_ids, svnlook__full_paths} }, + {'r', 't', 'N', svnlook__show_ids, svnlook__full_paths, 'M'} }, {"uuid", subcommand_uuid, {0}, N_("usage: svnlook uuid REPOS_PATH\n\n" @@ -340,6 +347,7 @@ struct svnlook_opt_state const char *diff_cmd; /* --diff-cmd */ svn_boolean_t show_inherited_props; /* --show-inherited-props */ svn_boolean_t no_newline; /* --no-newline */ + apr_uint64_t memory_cache_size; /* --memory-cache-size */ }; @@ -365,30 +373,10 @@ typedef struct svnlook_ctxt_t } svnlook_ctxt_t; -/* A flag to see if we've been cancelled by the client or not. */ -static volatile sig_atomic_t cancelled = FALSE; - /*** Helper functions. ***/ -/* A signal handler to support cancellation. */ -static void -signal_handler(int signum) -{ - apr_signal(signum, SIG_IGN); - cancelled = TRUE; -} - -/* Our cancellation callback. */ -static svn_error_t * -check_cancel(void *baton) -{ - if (cancelled) - return svn_error_create(SVN_ERR_CANCELLED, NULL, _("Caught signal")); - else - return SVN_NO_ERROR; -} - +static svn_cancel_func_t check_cancel = NULL; /* Version compatibility check */ static svn_error_t * @@ -426,8 +414,8 @@ get_property(svn_string_t **prop_value, /* ...or revision property -- it's your call. */ else - SVN_ERR(svn_fs_revision_prop(&raw_value, c->fs, c->rev_id, - prop_name, pool)); + SVN_ERR(svn_fs_revision_prop2(&raw_value, c->fs, c->rev_id, + prop_name, TRUE, pool, pool)); *prop_value = raw_value; @@ -755,8 +743,9 @@ generate_label(const char **label, if (svn_fs_is_revision_root(root)) { rev = svn_fs_revision_root_revision(root); - SVN_ERR(svn_fs_revision_prop(&date, fs, rev, - SVN_PROP_REVISION_DATE, pool)); + SVN_ERR(svn_fs_revision_prop2(&date, fs, rev, + SVN_PROP_REVISION_DATE, TRUE, + pool, pool)); } else { @@ -1861,7 +1850,8 @@ do_plist(svnlook_ctxt_t *c, } else if (c->is_revision) { - SVN_ERR(svn_fs_revision_proplist(&props, c->fs, c->rev_id, pool)); + SVN_ERR(svn_fs_revision_proplist2(&props, c->fs, c->rev_id, TRUE, + pool, pool)); revprop = TRUE; } else @@ -2472,6 +2462,7 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) /* Initialize opt_state. */ memset(&opt_state, 0, sizeof(opt_state)); opt_state.rev = SVN_INVALID_REVNUM; + opt_state.memory_cache_size = svn_cache_config_get()->cache_size; /* Parse options. */ SVN_ERR(svn_cmdline__getopt_init(&os, argc, argv, pool)); @@ -2513,6 +2504,15 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) opt_state.txn = opt_arg; break; + case 'M': + { + apr_uint64_t sz_val; + SVN_ERR(svn_cstring_atoui64(&sz_val, opt_arg)); + + opt_state.memory_cache_size = 0x100000 * sz_val; + } + break; + case 'N': opt_state.non_recursive = TRUE; break; @@ -2665,21 +2665,21 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) } else { - const char *first_arg = os->argv[os->ind++]; + const char *first_arg; + + SVN_ERR(svn_utf_cstring_to_utf8(&first_arg, os->argv[os->ind++], + pool)); subcommand = svn_opt_get_canonical_subcommand2(cmd_table, first_arg); if (subcommand == NULL) { - const char *first_arg_utf8; - SVN_ERR(svn_utf_cstring_to_utf8(&first_arg_utf8, first_arg, - pool)); svn_error_clear( svn_cmdline_fprintf(stderr, pool, _("Unknown subcommand: '%s'\n"), - first_arg_utf8)); + first_arg)); SVN_ERR(subcommand_help(NULL, NULL, pool)); /* Be kind to people who try 'svnlook verify'. */ - if (strcmp(first_arg_utf8, "verify") == 0) + if (strcmp(first_arg, "verify") == 0) { svn_error_clear( svn_cmdline_fprintf(stderr, pool, @@ -2783,30 +2783,18 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) } } - /* Set up our cancellation support. */ - apr_signal(SIGINT, signal_handler); -#ifdef SIGBREAK - /* SIGBREAK is a Win32 specific signal generated by ctrl-break. */ - apr_signal(SIGBREAK, signal_handler); -#endif -#ifdef SIGHUP - apr_signal(SIGHUP, signal_handler); -#endif -#ifdef SIGTERM - apr_signal(SIGTERM, signal_handler); -#endif + check_cancel = svn_cmdline__setup_cancellation_handler(); -#ifdef SIGPIPE - /* Disable SIGPIPE generation for the platforms that have it. */ - apr_signal(SIGPIPE, SIG_IGN); -#endif + /* Configure FSFS caches for maximum efficiency with svnadmin. + * Also, apply the respective command line parameters, if given. */ + { + svn_cache_config_t settings = *svn_cache_config_get(); -#ifdef SIGXFSZ - /* Disable SIGXFSZ generation for the platforms that have it, otherwise - * working with large files when compiled against an APR that doesn't have - * large file support will crash the program, which is uncool. */ - apr_signal(SIGXFSZ, SIG_IGN); -#endif + settings.cache_size = opt_state.memory_cache_size; + settings.single_threaded = TRUE; + + svn_cache_config_set(&settings); + } /* Run the subcommand. */ err = (*subcommand->cmd_func)(os, &opt_state, pool); @@ -2855,5 +2843,8 @@ main(int argc, const char *argv[]) } svn_pool_destroy(pool); + + svn_cmdline__cancellation_exit(); + return exit_code; } diff --git a/subversion/svnmucc/svnmucc.c b/subversion/svnmucc/svnmucc.c index 1d2be38bba9b..d9f893e774d4 100644 --- a/subversion/svnmucc/svnmucc.c +++ b/subversion/svnmucc/svnmucc.c @@ -74,6 +74,7 @@ check_lib_versions(void) return svn_ver_check_list2(&my_version, checklist, svn_ver_equal); } +/* Implements svn_commit_callback2_t */ static svn_error_t * commit_callback(const svn_commit_info_t *commit_info, void *baton, @@ -84,6 +85,15 @@ commit_callback(const svn_commit_info_t *commit_info, (commit_info->author ? commit_info->author : "(no author)"), commit_info->date)); + + /* Writing to stdout, as there maybe systems that consider the + * presence of stderr as an indication of commit failure. + * OTOH, this is only of informational nature to the user as + * the commit has succeeded. */ + if (commit_info->post_commit_err) + SVN_ERR(svn_cmdline_printf(pool, _("\nWarning: %s\n"), + commit_info->post_commit_err)); + return SVN_NO_ERROR; } @@ -193,7 +203,7 @@ execute(const apr_array_header_t *actions, SVN_ERR(svn_stream_open_readonly(&src, action->path[1], pool, iterpool)); else - SVN_ERR(svn_stream_for_stdin(&src, pool)); + SVN_ERR(svn_stream_for_stdin2(&src, TRUE, pool)); if (kind == svn_node_file) @@ -287,6 +297,7 @@ help(FILE *stream, apr_pool_t *pool) " -F [--file] ARG : read log message from file ARG\n" " -u [--username] ARG : commit the changes as username ARG\n" " -p [--password] ARG : use ARG as the password\n" + " --password-from-stdin : read password from stdin\n" " -U [--root-url] ARG : interpret all action URLs relative to ARG\n" " -r [--revision] ARG : use revision ARG as baseline for changes\n" " --with-revprop ARG : set revision property in the following format:\n" @@ -471,12 +482,14 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) force_interactive_opt, trust_server_cert_opt, trust_server_cert_failures_opt, + password_from_stdin_opt }; static const apr_getopt_option_t options[] = { {"message", 'm', 1, ""}, {"file", 'F', 1, ""}, {"username", 'u', 1, ""}, {"password", 'p', 1, ""}, + {"password-from-stdin", password_from_stdin_opt, 0, ""}, {"root-url", 'U', 1, ""}, {"revision", 'r', 1, ""}, {"with-revprop", with_revprop_opt, 1, ""}, @@ -517,10 +530,14 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) svn_client_ctx_t *ctx; struct log_message_baton lmb; int i; + svn_boolean_t read_pass_from_stdin = FALSE; /* Check library versions */ SVN_ERR(check_lib_versions()); + /* Initialize the RA library. */ + SVN_ERR(svn_ra_initialize(pool)); + config_options = apr_array_make(pool, 0, sizeof(svn_cmdline__config_argument_t*)); @@ -548,9 +565,9 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) break; case 'F': { - const char *arg_utf8; - SVN_ERR(svn_utf_cstring_to_utf8(&arg_utf8, arg, pool)); - SVN_ERR(svn_stringbuf_from_file2(&filedata, arg, pool)); + const char *filename; + SVN_ERR(svn_utf_cstring_to_utf8(&filename, arg, pool)); + SVN_ERR(svn_stringbuf_from_file2(&filedata, filename, pool)); } break; case 'u': @@ -559,6 +576,9 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) case 'p': password = apr_pstrdup(pool, arg); break; + case password_from_stdin_opt: + read_pass_from_stdin = TRUE; + break; case 'U': SVN_ERR(svn_utf_cstring_to_utf8(&root_url, arg, pool)); if (! svn_path_is_url(root_url)) @@ -585,7 +605,7 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) SVN_ERR(svn_opt_parse_revprop(&revprops, arg, pool)); break; case 'X': - extra_args_file = apr_pstrdup(pool, arg); + SVN_ERR(svn_utf_cstring_to_utf8(&extra_args_file, arg, pool)); break; case non_interactive_opt: non_interactive = TRUE; @@ -659,27 +679,33 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) "--non-interactive")); } + /* --password-from-stdin can only be used with --non-interactive */ + if (read_pass_from_stdin && !non_interactive) + { + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("--password-from-stdin requires " + "--non-interactive")); + } + + /* Copy the rest of our command-line arguments to an array, UTF-8-ing them along the way. */ action_args = apr_array_make(pool, opts->argc, sizeof(const char *)); while (opts->ind < opts->argc) { - const char *arg = opts->argv[opts->ind++]; - SVN_ERR(svn_utf_cstring_to_utf8(&APR_ARRAY_PUSH(action_args, - const char *), - arg, pool)); + const char *arg; + + SVN_ERR(svn_utf_cstring_to_utf8(&arg, opts->argv[opts->ind++], pool)); + APR_ARRAY_PUSH(action_args, const char *) = arg; } /* If there are extra arguments in a supplementary file, tack those on, too (again, in UTF8 form). */ if (extra_args_file) { - const char *extra_args_file_utf8; svn_stringbuf_t *contents, *contents_utf8; - SVN_ERR(svn_utf_cstring_to_utf8(&extra_args_file_utf8, - extra_args_file, pool)); - SVN_ERR(svn_stringbuf_from_file2(&contents, extra_args_file_utf8, pool)); + SVN_ERR(svn_stringbuf_from_file2(&contents, extra_args_file, pool)); SVN_ERR(svn_utf_stringbuf_to_utf8(&contents_utf8, contents, pool)); svn_cstring_split_append(action_args, contents_utf8->data, "\n\r", FALSE, pool); @@ -711,6 +737,12 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) "svnmucc: ", "--config-option")); } + /* Get password from stdin if necessary */ + if (read_pass_from_stdin) + { + SVN_ERR(svn_cmdline__stdin_readline(&password, pool, pool)); + } + SVN_ERR(svn_client_create_context2(&ctx, cfg_hash, pool)); cfg_config = svn_hash_gets(cfg_hash, SVN_CONFIG_CATEGORY_CONFIG); diff --git a/subversion/svnrdump/dump_editor.c b/subversion/svnrdump/dump_editor.c index bf4f81c8bdab..f900e209e276 100644 --- a/subversion/svnrdump/dump_editor.c +++ b/subversion/svnrdump/dump_editor.c @@ -879,7 +879,7 @@ close_file(void *file_baton, { struct file_baton *fb = file_baton; struct dump_edit_baton *eb = fb->eb; - apr_finfo_t *info = apr_pcalloc(pool, sizeof(apr_finfo_t)); + svn_filesize_t text_content_length = 0; svn_stringbuf_t *propstring = NULL; svn_repos__dumpfile_headers_t *headers; @@ -903,15 +903,12 @@ close_file(void *file_baton, /* Dump the text headers */ if (fb->dump_text) { - apr_status_t err; - /* Text-delta: true */ svn_repos__dumpfile_header_push( headers, SVN_REPOS_DUMPFILE_TEXT_DELTA, "true"); - err = apr_file_info_get(info, APR_FINFO_SIZE, eb->delta_file); - if (err) - SVN_ERR(svn_error_wrap_apr(err, NULL)); + SVN_ERR(svn_io_file_size_get(&text_content_length, eb->delta_file, + pool)); if (fb->base_checksum) /* Text-delta-base-md5: */ @@ -925,7 +922,7 @@ close_file(void *file_baton, /* Dump the headers and props now */ SVN_ERR(svn_repos__dump_node_record(eb->stream, headers, propstring, - fb->dump_text, info->size, + fb->dump_text, text_content_length, FALSE /*content_length_always*/, pool)); diff --git a/subversion/svnrdump/load_editor.c b/subversion/svnrdump/load_editor.c index 15dac6e98f18..2ebacf79e1b5 100644 --- a/subversion/svnrdump/load_editor.c +++ b/subversion/svnrdump/load_editor.c @@ -167,8 +167,7 @@ set_revision_mapping(apr_hash_t *rev_map, sizeof(svn_revnum_t) * 2); mapped_revs[0] = from_rev; mapped_revs[1] = to_rev; - apr_hash_set(rev_map, mapped_revs, - sizeof(svn_revnum_t), mapped_revs + 1); + apr_hash_set(rev_map, mapped_revs, sizeof(*mapped_revs), mapped_revs + 1); } /* Return the revision to which FROM_REV maps in REV_MAP, or @@ -392,7 +391,7 @@ new_revision_record(void **revision_baton, { struct revision_baton *rb; struct parse_baton *pb; - apr_hash_index_t *hi; + const char *rev_str; svn_revnum_t head_rev; rb = apr_pcalloc(pool, sizeof(*rb)); @@ -401,14 +400,9 @@ new_revision_record(void **revision_baton, rb->pb = pb; rb->db = NULL; - for (hi = apr_hash_first(pool, headers); hi; hi = apr_hash_next(hi)) - { - const char *hname = apr_hash_this_key(hi); - const char *hval = apr_hash_this_val(hi); - - if (strcmp(hname, SVN_REPOS_DUMPFILE_REVISION_NUMBER) == 0) - rb->rev = atoi(hval); - } + rev_str = svn_hash_gets(headers, SVN_REPOS_DUMPFILE_REVISION_NUMBER); + if (rev_str) + rb->rev = SVN_STR_TO_REV(rev_str); SVN_ERR(svn_ra_get_latest_revnum(pb->session, &head_rev, pool)); @@ -499,6 +493,7 @@ new_node_record(void **node_baton, const struct svn_delta_editor_t *commit_editor = rb->pb->commit_editor; void *commit_edit_baton = rb->pb->commit_edit_baton; struct node_baton *nb; + svn_revnum_t head_rev_before_commit = rb->rev - rb->rev_offset - 1; apr_hash_index_t *hi; void *child_baton; const char *nb_dirname; @@ -537,7 +532,7 @@ new_node_record(void **node_baton, rb->pb->commit_edit_baton = commit_edit_baton; SVN_ERR(commit_editor->open_root(commit_edit_baton, - rb->rev - rb->rev_offset - 1, + head_rev_before_commit, rb->pool, &child_baton)); /* child_baton corresponds to the root directory baton here */ @@ -570,7 +565,7 @@ new_node_record(void **node_baton, if (strcmp(hname, SVN_REPOS_DUMPFILE_TEXT_DELTA_BASE_MD5) == 0) nb->base_checksum = apr_pstrdup(rb->pool, hval); if (strcmp(hname, SVN_REPOS_DUMPFILE_NODE_COPYFROM_REV) == 0) - nb->copyfrom_rev = atoi(hval); + nb->copyfrom_rev = SVN_STR_TO_REV(hval); if (strcmp(hname, SVN_REPOS_DUMPFILE_NODE_COPYFROM_PATH) == 0) nb->copyfrom_path = apr_pstrdup(rb->pool, hval); } @@ -617,7 +612,7 @@ new_node_record(void **node_baton, rb->pool); SVN_ERR(commit_editor->open_directory(relpath_compose, rb->db->baton, - rb->rev - rb->rev_offset - 1, + head_rev_before_commit, rb->pool, &child_baton)); push_directory(rb, child_baton, relpath_compose, TRUE /*is_added*/, NULL, SVN_INVALID_REVNUM); @@ -660,7 +655,7 @@ new_node_record(void **node_baton, case svn_node_action_delete: case svn_node_action_replace: SVN_ERR(commit_editor->delete_entry(nb->path, - rb->rev - rb->rev_offset - 1, + head_rev_before_commit, rb->db->baton, rb->pool)); if (nb->action == svn_node_action_delete) break; @@ -698,7 +693,7 @@ new_node_record(void **node_baton, break; default: SVN_ERR(commit_editor->open_directory(nb->path, rb->db->baton, - rb->rev - rb->rev_offset - 1, + head_rev_before_commit, rb->pool, &child_baton)); push_directory(rb, child_baton, nb->path, FALSE /*is_added*/, NULL, SVN_INVALID_REVNUM); @@ -718,16 +713,15 @@ set_revision_property(void *baton, { struct revision_baton *rb = baton; - SVN_ERR(svn_rdump__normalize_prop(name, &value, rb->pool)); - + SVN_ERR(svn_repos__normalize_prop(&value, NULL, name, value, + rb->pool, rb->pool)); SVN_ERR(svn_repos__validate_prop(name, value, rb->pool)); if (rb->rev > 0) { if (! svn_hash_gets(rb->pb->skip_revprops, name)) svn_hash_sets(rb->revprop_table, - apr_pstrdup(rb->pool, name), - svn_string_dup(value, rb->pool)); + apr_pstrdup(rb->pool, name), value); } else if (rb->rev_offset == -1 && ! svn_hash_gets(rb->pb->skip_revprops, name)) @@ -742,9 +736,9 @@ set_revision_property(void *baton, /* Remember any datestamp/ author that passes through (see comment in close_revision). */ if (!strcmp(name, SVN_PROP_REVISION_DATE)) - rb->datestamp = svn_string_dup(value, rb->pool); + rb->datestamp = value; if (!strcmp(name, SVN_PROP_REVISION_AUTHOR)) - rb->author = svn_string_dup(value, rb->pool); + rb->author = value; return SVN_NO_ERROR; } @@ -781,13 +775,13 @@ set_node_property(void *baton, value = new_value; } - SVN_ERR(svn_rdump__normalize_prop(name, &value, pool)); + SVN_ERR(svn_repos__normalize_prop(&value, NULL, name, value, pool, pool)); SVN_ERR(svn_repos__validate_prop(name, value, pool)); prop = apr_palloc(nb->rb->pool, sizeof (*prop)); prop->name = apr_pstrdup(pool, name); - prop->value = svn_string_dup(value, pool); + prop->value = value; svn_hash_sets(nb->prop_changes, prop->name, prop); return SVN_NO_ERROR; @@ -988,6 +982,7 @@ close_revision(void *baton) } else { + svn_revnum_t head_rev_before_commit = rb->rev - rb->rev_offset - 1; void *child_baton; /* Legitimate revision with no node information */ @@ -997,7 +992,7 @@ close_revision(void *baton) NULL, FALSE, rb->pool)); SVN_ERR(commit_editor->open_root(commit_edit_baton, - rb->rev - rb->rev_offset - 1, + head_rev_before_commit, rb->pool, &child_baton)); SVN_ERR(commit_editor->close_directory(child_baton, rb->pool)); diff --git a/subversion/svnrdump/svnrdump.c b/subversion/svnrdump/svnrdump.c index df0286bca562..50b8a8983b66 100644 --- a/subversion/svnrdump/svnrdump.c +++ b/subversion/svnrdump/svnrdump.c @@ -22,7 +22,6 @@ * ==================================================================== */ -#include #include #include "svn_pools.h" @@ -47,27 +46,8 @@ /*** Cancellation ***/ -/* A flag to see if we've been cancelled by the client or not. */ -static volatile sig_atomic_t cancelled = FALSE; - -/* A signal handler to support cancellation. */ -static void -signal_handler(int signum) -{ - apr_signal(signum, SIG_IGN); - cancelled = TRUE; -} - /* Our cancellation callback. */ -static svn_error_t * -check_cancel(void *baton) -{ - if (cancelled) - return svn_error_create(SVN_ERR_CANCELLED, NULL, _("Caught signal")); - else - return SVN_NO_ERROR; -} - +static svn_cancel_func_t check_cancel = NULL; @@ -79,6 +59,7 @@ enum svn_svnrdump__longopt_t opt_config_option, opt_auth_username, opt_auth_password, + opt_auth_password_from_stdin, opt_auth_nocache, opt_non_interactive, opt_skip_revprop, @@ -93,6 +74,7 @@ enum svn_svnrdump__longopt_t opt_config_option, \ opt_auth_username, \ opt_auth_password, \ + opt_auth_password_from_stdin, \ opt_auth_nocache, \ opt_trust_server_cert, \ opt_trust_server_cert_failures, \ @@ -134,6 +116,8 @@ static const apr_getopt_option_t svnrdump__options[] = N_("specify a username ARG")}, {"password", opt_auth_password, 1, N_("specify a password ARG")}, + {"password-from-stdin", opt_auth_password_from_stdin, 0, + N_("read password from stdin")}, {"non-interactive", opt_non_interactive, 0, N_("do no interactive prompting (default is to prompt\n" " " @@ -174,6 +158,7 @@ static const apr_getopt_option_t svnrdump__options[] = "valid certificate) and 'other' (all other not\n" " " "separately classified certificate errors).")}, + {"dumpfile", 'F', 1, N_("Read or write to a dumpfile instead of stdin/stdout")}, {0, 0, 0, 0} }; @@ -194,6 +179,7 @@ typedef struct opt_baton_t { svn_client_ctx_t *ctx; svn_ra_session_t *session; const char *url; + const char *dumpfile; svn_boolean_t help; svn_boolean_t version; svn_opt_revision_t start_revision; @@ -483,31 +469,39 @@ replay_revisions(svn_ra_session_t *session, svn_revnum_t end_revision, svn_boolean_t quiet, svn_boolean_t incremental, + const char *dumpfile, apr_pool_t *pool) { struct replay_baton *replay_baton; const char *uuid; - svn_stream_t *stdout_stream; + svn_stream_t *output_stream; - SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool)); + if (dumpfile) + { + SVN_ERR(svn_stream_open_writable(&output_stream, dumpfile, pool, pool)); + } + else + { + SVN_ERR(svn_stream_for_stdout(&output_stream, pool)); + } replay_baton = apr_pcalloc(pool, sizeof(*replay_baton)); - replay_baton->stdout_stream = stdout_stream; + replay_baton->stdout_stream = output_stream; replay_baton->extra_ra_session = extra_ra_session; replay_baton->quiet = quiet; /* Write the magic header and UUID */ - SVN_ERR(svn_stream_printf(stdout_stream, pool, + SVN_ERR(svn_stream_printf(output_stream, pool, SVN_REPOS_DUMPFILE_MAGIC_HEADER ": %d\n\n", SVN_REPOS_DUMPFILE_FORMAT_VERSION)); SVN_ERR(svn_ra_get_uuid2(session, &uuid, pool)); - SVN_ERR(svn_stream_printf(stdout_stream, pool, + SVN_ERR(svn_stream_printf(output_stream, pool, SVN_REPOS_DUMPFILE_UUID ": %s\n\n", uuid)); /* Fake revision 0 if necessary */ if (start_revision == 0) { - SVN_ERR(dump_revision_header(session, stdout_stream, + SVN_ERR(dump_revision_header(session, output_stream, start_revision, pool)); /* Revision 0 has no tree changes, so we're done. */ @@ -526,7 +520,7 @@ replay_revisions(svn_ra_session_t *session, if (!incremental) { SVN_ERR(dump_initial_full_revision(session, extra_ra_session, - stdout_stream, start_revision, + output_stream, start_revision, quiet, pool)); start_revision++; } @@ -546,7 +540,6 @@ replay_revisions(svn_ra_session_t *session, #endif } - SVN_ERR(svn_stream_close(stdout_stream)); return SVN_NO_ERROR; } @@ -559,23 +552,26 @@ replay_revisions(svn_ra_session_t *session, static svn_error_t * load_revisions(svn_ra_session_t *session, svn_ra_session_t *aux_session, - const char *url, + const char *dumpfile, svn_boolean_t quiet, apr_hash_t *skip_revprops, apr_pool_t *pool) { - apr_file_t *stdin_file; - svn_stream_t *stdin_stream; + svn_stream_t *output_stream; - apr_file_open_stdin(&stdin_file, pool); - stdin_stream = svn_stream_from_aprfile2(stdin_file, FALSE, pool); + if (dumpfile) + { + SVN_ERR(svn_stream_open_readonly(&output_stream, dumpfile, pool, pool)); + } + else + { + SVN_ERR(svn_stream_for_stdin2(&output_stream, TRUE, pool)); + } - SVN_ERR(svn_rdump__load_dumpstream(stdin_stream, session, aux_session, + SVN_ERR(svn_rdump__load_dumpstream(output_stream, session, aux_session, quiet, skip_revprops, check_cancel, NULL, pool)); - SVN_ERR(svn_stream_close(stdin_stream)); - return SVN_NO_ERROR; } @@ -641,7 +637,8 @@ dump_cmd(apr_getopt_t *os, return replay_revisions(opt_baton->session, extra_ra_session, opt_baton->start_revision.value.number, opt_baton->end_revision.value.number, - opt_baton->quiet, opt_baton->incremental, pool); + opt_baton->quiet, opt_baton->incremental, + opt_baton->dumpfile, pool); } /* Handle the "load" subcommand. Implements `svn_opt_subcommand_t'. */ @@ -655,8 +652,9 @@ load_cmd(apr_getopt_t *os, SVN_ERR(svn_client_open_ra_session2(&aux_session, opt_baton->url, NULL, opt_baton->ctx, pool, pool)); - return load_revisions(opt_baton->session, aux_session, opt_baton->url, - opt_baton->quiet, opt_baton->skip_revprops, pool); + return load_revisions(opt_baton->session, aux_session, + opt_baton->dumpfile, opt_baton->quiet, + opt_baton->skip_revprops, pool); } /* Handle the "help" subcommand. Implements `svn_opt_subcommand_t'. */ @@ -795,42 +793,23 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) svn_boolean_t force_interactive = FALSE; apr_array_header_t *config_options = NULL; apr_getopt_t *os; - const char *first_arg; apr_array_header_t *received_opts; int i; + svn_boolean_t read_pass_from_stdin = FALSE; opt_baton = apr_pcalloc(pool, sizeof(*opt_baton)); opt_baton->start_revision.kind = svn_opt_revision_unspecified; opt_baton->end_revision.kind = svn_opt_revision_unspecified; opt_baton->url = NULL; opt_baton->skip_revprops = apr_hash_make(pool); + opt_baton->dumpfile = NULL; SVN_ERR(svn_cmdline__getopt_init(&os, argc, argv, pool)); os->interleave = TRUE; /* Options and arguments can be interleaved */ /* Set up our cancellation support. */ - apr_signal(SIGINT, signal_handler); -#ifdef SIGBREAK - /* SIGBREAK is a Win32 specific signal generated by ctrl-break. */ - apr_signal(SIGBREAK, signal_handler); -#endif -#ifdef SIGHUP - apr_signal(SIGHUP, signal_handler); -#endif -#ifdef SIGTERM - apr_signal(SIGTERM, signal_handler); -#endif -#ifdef SIGPIPE - /* Disable SIGPIPE generation for the platforms that have it. */ - apr_signal(SIGPIPE, SIG_IGN); -#endif -#ifdef SIGXFSZ - /* Disable SIGXFSZ generation for the platforms that have it, otherwise - * working with large files when compiled against an APR that doesn't have - * large file support will crash the program, which is uncool. */ - apr_signal(SIGXFSZ, SIG_IGN); -#endif + check_cancel = svn_cmdline__setup_cancellation_handler(); received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int)); @@ -896,6 +875,9 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) case opt_auth_password: SVN_ERR(svn_utf_cstring_to_utf8(&password, opt_arg, pool)); break; + case opt_auth_password_from_stdin: + read_pass_from_stdin = TRUE; + break; case opt_auth_nocache: no_auth_cache = TRUE; break; @@ -936,6 +918,11 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) opt_arg, "svnrdump: ", pool)); + break; + case 'F': + SVN_ERR(svn_utf_cstring_to_utf8(&opt_arg, opt_arg, pool)); + opt_baton->dumpfile = opt_arg; + break; } } @@ -977,19 +964,19 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) } else { - first_arg = os->argv[os->ind++]; + const char *first_arg; + + SVN_ERR(svn_utf_cstring_to_utf8(&first_arg, os->argv[os->ind++], + pool)); subcommand = svn_opt_get_canonical_subcommand2(svnrdump__cmd_table, first_arg); if (subcommand == NULL) { - const char *first_arg_utf8; - SVN_ERR(svn_utf_cstring_to_utf8(&first_arg_utf8, first_arg, - pool)); svn_error_clear( svn_cmdline_fprintf(stderr, pool, _("Unknown subcommand: '%s'\n"), - first_arg_utf8)); + first_arg)); SVN_ERR(help_cmd(NULL, NULL, pool)); *exit_code = EXIT_FAILURE; return SVN_NO_ERROR; @@ -1051,6 +1038,24 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) "--non-interactive")); } + if (read_pass_from_stdin && !non_interactive) + { + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("--password-from-stdin requires " + "--non-interactive")); + } + + if (strcmp(subcommand->name, "load") == 0) + { + if (read_pass_from_stdin && opt_baton->dumpfile == NULL) + { + /* error here, since load cannot process a password over stdin */ + return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL, + _("load subcommand with " + "--password-from-stdin requires -F")); + } + } + /* Expect one more non-option argument: the repository URL. */ if (os->ind != os->argc - 1) { @@ -1085,6 +1090,12 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) force_interactive = (username == NULL || password == NULL); } + /* Get password from stdin if necessary */ + if (read_pass_from_stdin) + { + SVN_ERR(svn_cmdline__stdin_readline(&password, pool, pool)); + } + non_interactive = !svn_cmdline__be_interactive(non_interactive, force_interactive); @@ -1162,5 +1173,8 @@ main(int argc, const char *argv[]) } svn_pool_destroy(pool); + + svn_cmdline__cancellation_exit(); + return exit_code; } diff --git a/subversion/svnrdump/svnrdump.h b/subversion/svnrdump/svnrdump.h index 919ea5e1e844..b6ac7c1bf2bc 100644 --- a/subversion/svnrdump/svnrdump.h +++ b/subversion/svnrdump/svnrdump.h @@ -100,29 +100,12 @@ svn_rdump__load_dumpstream(svn_stream_t *stream, * currently all svn:* props) so that they contain only LF (\n) line endings. * * Put the normalized props into NORMAL_PROPS, allocated in RESULT_POOL. - * - * Note: this function does not do a deep copy; it is expected that PROPS has - * a longer lifetime than NORMAL_PROPS. */ svn_error_t * svn_rdump__normalize_props(apr_hash_t **normal_props, apr_hash_t *props, apr_pool_t *result_pool); -/* Normalize the line ending style of a single property that "needs - * translation" (according to svn_prop_needs_translation(), - * currently all svn:* props) so that they contain only LF (\n) line endings. - * "\r" characters found mid-line are replaced with "\n". - * "\r\n" sequences are replaced with "\n" - * - * NAME is used to check that VALUE should be normalized, and if this is the - * case, VALUE is then normalized, allocated from RESULT_POOL - */ -svn_error_t * -svn_rdump__normalize_prop(const char *name, - const svn_string_t **value, - apr_pool_t *result_pool); - #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/subversion/svnrdump/util.c b/subversion/svnrdump/util.c index 9a89c8918da9..e612b12b48af 100644 --- a/subversion/svnrdump/util.c +++ b/subversion/svnrdump/util.c @@ -21,53 +21,35 @@ * ==================================================================== */ -#include "svn_error.h" -#include "svn_pools.h" -#include "svn_string.h" -#include "svn_props.h" -#include "svn_subst.h" +#include "private/svn_repos_private.h" #include "svnrdump.h" -svn_error_t * -svn_rdump__normalize_prop(const char *name, - const svn_string_t **value, - apr_pool_t *result_pool) -{ - if (svn_prop_needs_translation(name) && *value) - { - const char *cstring; - - SVN_ERR(svn_subst_translate_cstring2((*value)->data, &cstring, - "\n", TRUE, - NULL, FALSE, - result_pool)); - - *value = svn_string_create(cstring, result_pool); - } - return SVN_NO_ERROR; -} - svn_error_t * svn_rdump__normalize_props(apr_hash_t **normal_props, apr_hash_t *props, apr_pool_t *result_pool) { apr_hash_index_t *hi; + apr_pool_t *iterpool; *normal_props = apr_hash_make(result_pool); + iterpool = svn_pool_create(result_pool); for (hi = apr_hash_first(result_pool, props); hi; hi = apr_hash_next(hi)) { const char *key = apr_hash_this_key(hi); const svn_string_t *value = apr_hash_this_val(hi); - SVN_ERR(svn_rdump__normalize_prop(key, &value, - result_pool)); + svn_pool_clear(iterpool); + SVN_ERR(svn_repos__normalize_prop(&value, NULL, key, value, + result_pool, iterpool)); svn_hash_sets(*normal_props, key, value); } + svn_pool_destroy(iterpool); + return SVN_NO_ERROR; } diff --git a/subversion/svnserve/cyrus_auth.c b/subversion/svnserve/cyrus_auth.c index 40f4228a999f..f02a6f14073f 100644 --- a/subversion/svnserve/cyrus_auth.c +++ b/subversion/svnserve/cyrus_auth.c @@ -112,11 +112,12 @@ static svn_error_t *initialize(void *baton, apr_pool_t *pool) /* The second parameter tells SASL to look for a configuration file named subversion.conf. */ - result = sasl_server_init(callbacks, SVN_RA_SVN_SASL_NAME); + result = svn_sasl__server_init(callbacks, SVN_RA_SVN_SASL_NAME); if (result != SASL_OK) { - svn_error_t *err = svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL, - sasl_errstring(result, NULL, NULL)); + svn_error_t *err = svn_error_create( + SVN_ERR_RA_NOT_AUTHORIZED, NULL, + svn_sasl__errstring(result, NULL, NULL)); return svn_error_quick_wrap(err, _("Could not initialize the SASL library")); } @@ -135,7 +136,7 @@ svn_error_t *cyrus_init(apr_pool_t *pool) static svn_error_t * fail_auth(svn_ra_svn_conn_t *conn, apr_pool_t *pool, sasl_conn_t *sasl_ctx) { - const char *msg = sasl_errdetail(sasl_ctx); + const char *msg = svn_sasl__errdetail(sasl_ctx); SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w(c)", "failure", msg)); return svn_ra_svn__flush(conn, pool); } @@ -156,7 +157,7 @@ static svn_error_t * fail_cmd(svn_ra_svn_conn_t *conn, apr_pool_t *pool, sasl_conn_t *sasl_ctx) { svn_error_t *err = svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL, - sasl_errdetail(sasl_ctx)); + svn_sasl__errdetail(sasl_ctx)); SVN_ERR(write_failure(conn, pool, &err)); return svn_ra_svn__flush(conn, pool); } @@ -192,16 +193,17 @@ static svn_error_t *try_auth(svn_ra_svn_conn_t *conn, return svn_error_createf(SVN_ERR_RA_NOT_AUTHORIZED, NULL, _("Initial token is too long")); - result = sasl_server_start(sasl_ctx, mech, - in ? in->data : NULL, - in ? (unsigned int) in->len : 0, &out, &outlen); + result = svn_sasl__server_start(sasl_ctx, mech, + in ? in->data : NULL, + in ? (unsigned int) in->len : 0, + &out, &outlen); if (result != SASL_OK && result != SASL_CONTINUE) return fail_auth(conn, pool, sasl_ctx); while (result == SASL_CONTINUE) { - svn_ra_svn_item_t *item; + svn_ra_svn__item_t *item; arg = svn_string_ncreate(out, outlen, pool); /* Encode what we send to the client. */ @@ -215,7 +217,7 @@ static svn_error_t *try_auth(svn_ra_svn_conn_t *conn, if (item->kind != SVN_RA_SVN_STRING) return SVN_NO_ERROR; - in = item->u.string; + in = &item->u.string; if (use_base64) in = svn_base64_decode_string(in, pool); @@ -223,8 +225,9 @@ static svn_error_t *try_auth(svn_ra_svn_conn_t *conn, return svn_error_createf(SVN_ERR_RA_NOT_AUTHORIZED, NULL, _("Step response is too long")); - result = sasl_server_step(sasl_ctx, in->data, (unsigned int) in->len, - &out, &outlen); + result = svn_sasl__server_step(sasl_ctx, in->data, + (unsigned int) in->len, + &out, &outlen); } if (result != SASL_OK) @@ -246,7 +249,7 @@ static svn_error_t *try_auth(svn_ra_svn_conn_t *conn, static apr_status_t sasl_dispose_cb(void *data) { sasl_conn_t *sasl_ctx = (sasl_conn_t*) data; - sasl_dispose(&sasl_ctx); + svn_sasl__dispose(&sasl_ctx); return APR_SUCCESS; } @@ -278,15 +281,16 @@ svn_error_t *cyrus_auth_request(svn_ra_svn_conn_t *conn, /* Create a SASL context. SASL_SUCCESS_DATA tells SASL that the protocol supports sending data along with the final "success" message. */ - result = sasl_server_new(SVN_RA_SVN_SASL_NAME, - hostname, b->repository->realm, - localaddrport, remoteaddrport, - NULL, SASL_SUCCESS_DATA, - &sasl_ctx); + result = svn_sasl__server_new(SVN_RA_SVN_SASL_NAME, + hostname, b->repository->realm, + localaddrport, remoteaddrport, + NULL, SASL_SUCCESS_DATA, + &sasl_ctx); if (result != SASL_OK) { - svn_error_t *err = svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL, - sasl_errstring(result, NULL, NULL)); + svn_error_t *err = svn_error_create( + SVN_ERR_RA_NOT_AUTHORIZED, NULL, + svn_sasl__errstring(result, NULL, NULL)); SVN_ERR(write_failure(conn, pool, &err)); return svn_ra_svn__flush(conn, pool); } @@ -307,20 +311,20 @@ svn_error_t *cyrus_auth_request(svn_ra_svn_conn_t *conn, secprops.max_ssf = b->repository->max_ssf; /* Set security properties. */ - result = sasl_setprop(sasl_ctx, SASL_SEC_PROPS, &secprops); + result = svn_sasl__setprop(sasl_ctx, SASL_SEC_PROPS, &secprops); if (result != SASL_OK) return fail_cmd(conn, pool, sasl_ctx); /* SASL needs to know if we are externally authenticated. */ if (b->client_info->tunnel_user) - result = sasl_setprop(sasl_ctx, SASL_AUTH_EXTERNAL, - b->client_info->tunnel_user); + result = svn_sasl__setprop(sasl_ctx, SASL_AUTH_EXTERNAL, + b->client_info->tunnel_user); if (result != SASL_OK) return fail_cmd(conn, pool, sasl_ctx); /* Get the list of mechanisms. */ - result = sasl_listmech(sasl_ctx, NULL, NULL, " ", NULL, - &mechlist, NULL, &mech_count); + result = svn_sasl__listmech(sasl_ctx, NULL, NULL, " ", NULL, + &mechlist, NULL, &mech_count); if (result != SASL_OK) return fail_cmd(conn, pool, sasl_ctx); @@ -356,7 +360,7 @@ svn_error_t *cyrus_auth_request(svn_ra_svn_conn_t *conn, const void *user; /* Get the authenticated username. */ - result = sasl_getprop(sasl_ctx, SASL_USERNAME, &user); + result = svn_sasl__getprop(sasl_ctx, SASL_USERNAME, &user); if (result != SASL_OK) return fail_cmd(conn, pool, sasl_ctx); diff --git a/subversion/svnserve/serve.c b/subversion/svnserve/serve.c index 91f1d5af961c..5192e7c9a66f 100644 --- a/subversion/svnserve/serve.c +++ b/subversion/svnserve/serve.c @@ -87,6 +87,9 @@ typedef struct log_baton_t { const char *fs_path; svn_ra_svn_conn_t *conn; int stack_depth; + + /* Set to TRUE when at least one changed path has been sent. */ + svn_boolean_t started; } log_baton_t; typedef struct file_revs_baton_t { @@ -223,8 +226,8 @@ load_pwdb_config(repository_t *repository, pwdb_path = svn_dirent_internal_style(pwdb_path, pool); pwdb_path = svn_dirent_join(repository->base, pwdb_path, pool); - err = svn_repos__config_pool_get(&repository->pwdb, NULL, config_pool, - pwdb_path, TRUE, FALSE, + err = svn_repos__config_pool_get(&repository->pwdb, config_pool, + pwdb_path, TRUE, repository->repos, pool); if (err) { @@ -282,8 +285,8 @@ canonicalize_access_file(const char **access_file, repository_t *repository, return SVN_NO_ERROR; } -/* Load the authz database for the listening server through AUTHZ_POOL - based on the entries in the SERVER struct. +/* Load the authz database for the listening server based on the entries + in the SERVER struct. SERVER and CONN must not be NULL. The real errors will be logged with SERVER and CONN but return generic errors to the client. */ @@ -291,7 +294,6 @@ static svn_error_t * load_authz_config(repository_t *repository, const char *repos_root, svn_config_t *cfg, - svn_repos__authz_pool_t *authz_pool, apr_pool_t *pool) { const char *authzdb_path; @@ -319,9 +321,9 @@ load_authz_config(repository_t *repository, repos_root, pool); if (!err) - err = svn_repos__authz_pool_get(&repository->authzdb, authz_pool, - authzdb_path, groupsdb_path, TRUE, - repository->repos, pool); + err = svn_repos_authz_read3(&repository->authzdb, authzdb_path, + groupsdb_path, TRUE, repository->repos, + pool, pool); if (err) return svn_error_create(SVN_ERR_AUTHZ_INVALID_CONFIG, err, NULL); @@ -443,7 +445,7 @@ static svn_error_t *authz_check_access(svn_boolean_t *allowed, absolute path. Passing such a malformed path to the authz routines throws them into an infinite loop and makes them miss ACLs. */ - if (path) + if (path && *path != '/') path = svn_fspath__canonicalize(path, pool); /* If we have a username, and we've not yet used it + any username @@ -627,11 +629,12 @@ create_fs_access(server_baton_t *b, apr_pool_t *pool) * On authentication failure, report failure to the client and set * *success to FALSE. On communications failure, return an error. * If NEEDS_USERNAME is TRUE, don't allow anonymous authentication. */ -static svn_error_t *auth(svn_ra_svn_conn_t *conn, apr_pool_t *pool, +static svn_error_t *auth(svn_boolean_t *success, + svn_ra_svn_conn_t *conn, const char *mech, const char *mecharg, server_baton_t *b, enum access_type required, svn_boolean_t needs_username, - svn_boolean_t *success) + apr_pool_t *scratch_pool) { const char *user; *success = FALSE; @@ -640,10 +643,10 @@ static svn_error_t *auth(svn_ra_svn_conn_t *conn, apr_pool_t *pool, && b->client_info->tunnel_user && strcmp(mech, "EXTERNAL") == 0) { if (*mecharg && strcmp(mecharg, b->client_info->tunnel_user) != 0) - return svn_ra_svn__write_tuple(conn, pool, "w(c)", "failure", + return svn_ra_svn__write_tuple(conn, scratch_pool, "w(c)", "failure", "Requested username does not match"); b->client_info->user = b->client_info->tunnel_user; - SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w()", "success")); + SVN_ERR(svn_ra_svn__write_tuple(conn, scratch_pool, "w()", "success")); *success = TRUE; return SVN_NO_ERROR; } @@ -651,7 +654,7 @@ static svn_error_t *auth(svn_ra_svn_conn_t *conn, apr_pool_t *pool, if (b->repository->anon_access >= required && strcmp(mech, "ANONYMOUS") == 0 && ! needs_username) { - SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w()", "success")); + SVN_ERR(svn_ra_svn__write_tuple(conn, scratch_pool, "w()", "success")); *success = TRUE; return SVN_NO_ERROR; } @@ -659,13 +662,13 @@ static svn_error_t *auth(svn_ra_svn_conn_t *conn, apr_pool_t *pool, if (b->repository->auth_access >= required && b->repository->pwdb && strcmp(mech, "CRAM-MD5") == 0) { - SVN_ERR(svn_ra_svn_cram_server(conn, pool, b->repository->pwdb, + SVN_ERR(svn_ra_svn_cram_server(conn, scratch_pool, b->repository->pwdb, &user, success)); b->client_info->user = apr_pstrdup(b->pool, user); return SVN_NO_ERROR; } - return svn_ra_svn__write_tuple(conn, pool, "w(c)", "failure", + return svn_ra_svn__write_tuple(conn, scratch_pool, "w(c)", "failure", "Must authenticate with listed mechanism"); } @@ -677,19 +680,26 @@ internal_auth_request(svn_ra_svn_conn_t *conn, apr_pool_t *pool, { svn_boolean_t success; const char *mech, *mecharg; + apr_pool_t *iterpool; SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w((!", "success")); SVN_ERR(send_mechs(conn, pool, b, required, needs_username)); SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "!)c)", b->repository->realm)); + + iterpool = svn_pool_create(pool); do { + svn_pool_clear(iterpool); + SVN_ERR(svn_ra_svn__read_tuple(conn, pool, "w(?c)", &mech, &mecharg)); if (!*mech) break; - SVN_ERR(auth(conn, pool, mech, mecharg, b, required, needs_username, - &success)); + SVN_ERR(auth(&success, conn, mech, mecharg, b, required, + needs_username, iterpool)); } while (!success); + svn_pool_destroy(iterpool); + return SVN_NO_ERROR; } @@ -830,7 +840,7 @@ static svn_error_t *must_have_access(svn_ra_svn_conn_t *conn, */ static svn_error_t *set_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) + svn_ra_svn__list_t *params, void *baton) { report_driver_baton_t *b = baton; const char *path, *lock_token, *depth_word; @@ -839,9 +849,9 @@ static svn_error_t *set_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool, svn_depth_t depth = svn_depth_infinity; svn_boolean_t start_empty; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "crb?(?c)?w", - &path, &rev, &start_empty, &lock_token, - &depth_word)); + SVN_ERR(svn_ra_svn__parse_tuple(params, "crb?(?c)?w", + &path, &rev, &start_empty, &lock_token, + &depth_word)); if (depth_word) depth = svn_depth_from_word(depth_word); path = svn_relpath_canonicalize(path, pool); @@ -857,12 +867,12 @@ static svn_error_t *set_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool, } static svn_error_t *delete_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) + svn_ra_svn__list_t *params, void *baton) { report_driver_baton_t *b = baton; const char *path; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c", &path)); + SVN_ERR(svn_ra_svn__parse_tuple(params, "c", &path)); path = svn_relpath_canonicalize(path, pool); if (!b->err) b->err = svn_repos_delete_path(b->report_baton, path, pool); @@ -870,7 +880,7 @@ static svn_error_t *delete_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool, } static svn_error_t *link_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) + svn_ra_svn__list_t *params, void *baton) { report_driver_baton_t *b = baton; const char *path, *url, *lock_token, *fs_path, *depth_word; @@ -879,7 +889,7 @@ static svn_error_t *link_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool, /* Default to infinity, for old clients that don't send depth. */ svn_depth_t depth = svn_depth_infinity; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "ccrb?(?c)?w", + SVN_ERR(svn_ra_svn__parse_tuple(params, "ccrb?(?c)?w", &path, &url, &rev, &start_empty, &lock_token, &depth_word)); @@ -901,7 +911,7 @@ static svn_error_t *link_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool, } static svn_error_t *finish_report(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) + svn_ra_svn__list_t *params, void *baton) { report_driver_baton_t *b = baton; @@ -912,8 +922,11 @@ static svn_error_t *finish_report(svn_ra_svn_conn_t *conn, apr_pool_t *pool, return SVN_NO_ERROR; } -static svn_error_t *abort_report(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) +static svn_error_t * +abort_report(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { report_driver_baton_t *b = baton; @@ -922,12 +935,12 @@ static svn_error_t *abort_report(svn_ra_svn_conn_t *conn, apr_pool_t *pool, return SVN_NO_ERROR; } -static const svn_ra_svn_cmd_entry_t report_commands[] = { +static const svn_ra_svn__cmd_entry_t report_commands[] = { { "set-path", set_path }, { "delete-path", delete_path }, { "link-path", link_path }, - { "finish-report", finish_report, TRUE }, - { "abort-report", abort_report, TRUE }, + { "finish-report", finish_report, NULL, TRUE }, + { "abort-report", abort_report, NULL, TRUE }, { NULL } }; @@ -1092,14 +1105,17 @@ get_props(apr_hash_t **props, } /* Set BATON->FS_PATH for the repository URL found in PARAMS. */ -static svn_error_t *reparent(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) +static svn_error_t * +reparent(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { server_baton_t *b = baton; const char *url; const char *fs_path; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c", &url)); + SVN_ERR(svn_ra_svn__parse_tuple(params, "c", &url)); url = svn_uri_canonicalize(url, pool); SVN_ERR(trivial_auth_request(conn, pool, b)); SVN_CMD_ERR(get_fs_path(svn_path_uri_decode(b->repository->repos_url, pool), @@ -1111,8 +1127,11 @@ static svn_error_t *reparent(svn_ra_svn_conn_t *conn, apr_pool_t *pool, return SVN_NO_ERROR; } -static svn_error_t *get_latest_rev(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) +static svn_error_t * +get_latest_rev(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { server_baton_t *b = baton; svn_revnum_t rev; @@ -1125,15 +1144,18 @@ static svn_error_t *get_latest_rev(svn_ra_svn_conn_t *conn, apr_pool_t *pool, return SVN_NO_ERROR; } -static svn_error_t *get_dated_rev(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) +static svn_error_t * +get_dated_rev(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { server_baton_t *b = baton; svn_revnum_t rev; apr_time_t tm; const char *timestr; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c", ×tr)); + SVN_ERR(svn_ra_svn__parse_tuple(params, "c", ×tr)); SVN_ERR(log_command(b, conn, pool, "get-dated-rev %s", timestr)); SVN_ERR(trivial_auth_request(conn, pool, b)); @@ -1171,8 +1193,11 @@ static svn_error_t *do_change_rev_prop(svn_ra_svn_conn_t *conn, return SVN_NO_ERROR; } -static svn_error_t *change_rev_prop2(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) +static svn_error_t * +change_rev_prop2(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { server_baton_t *b = baton; svn_revnum_t rev; @@ -1182,7 +1207,7 @@ static svn_error_t *change_rev_prop2(svn_ra_svn_conn_t *conn, apr_pool_t *pool, svn_string_t *old_value; svn_boolean_t dont_care; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "rc(?s)(b?s)", + SVN_ERR(svn_ra_svn__parse_tuple(params, "rc(?s)(b?s)", &rev, &name, &value, &dont_care, &old_value)); @@ -1208,8 +1233,11 @@ static svn_error_t *change_rev_prop2(svn_ra_svn_conn_t *conn, apr_pool_t *pool, return SVN_NO_ERROR; } -static svn_error_t *change_rev_prop(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) +static svn_error_t * +change_rev_prop(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { server_baton_t *b = baton; svn_revnum_t rev; @@ -1218,15 +1246,18 @@ static svn_error_t *change_rev_prop(svn_ra_svn_conn_t *conn, apr_pool_t *pool, /* Because the revprop value was at one time mandatory, the usual optional element pattern "(?s)" isn't used. */ - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "rc?s", &rev, &name, &value)); + SVN_ERR(svn_ra_svn__parse_tuple(params, "rc?s", &rev, &name, &value)); SVN_ERR(do_change_rev_prop(conn, b, rev, name, NULL, value, pool)); return SVN_NO_ERROR; } -static svn_error_t *rev_proplist(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) +static svn_error_t * +rev_proplist(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { server_baton_t *b = baton; svn_revnum_t rev; @@ -1236,7 +1267,7 @@ static svn_error_t *rev_proplist(svn_ra_svn_conn_t *conn, apr_pool_t *pool, ab.server = b; ab.conn = conn; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "r", &rev)); + SVN_ERR(svn_ra_svn__parse_tuple(params, "r", &rev)); SVN_ERR(log_command(b, conn, pool, "%s", svn_log__rev_proplist(rev, pool))); SVN_ERR(trivial_auth_request(conn, pool, b)); @@ -1250,8 +1281,11 @@ static svn_error_t *rev_proplist(svn_ra_svn_conn_t *conn, apr_pool_t *pool, return SVN_NO_ERROR; } -static svn_error_t *rev_prop(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) +static svn_error_t * +rev_prop(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { server_baton_t *b = baton; svn_revnum_t rev; @@ -1262,7 +1296,7 @@ static svn_error_t *rev_prop(svn_ra_svn_conn_t *conn, apr_pool_t *pool, ab.server = b; ab.conn = conn; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "rc", &rev, &name)); + SVN_ERR(svn_ra_svn__parse_tuple(params, "rc", &rev, &name)); SVN_ERR(log_command(b, conn, pool, "%s", svn_log__rev_prop(rev, name, pool))); @@ -1291,14 +1325,15 @@ static svn_error_t *commit_done(const svn_commit_info_t *commit_info, /* Add the LOCK_TOKENS (if any) to the filesystem access context, * checking path authorizations using the state in SB as we go. - * LOCK_TOKENS is an array of svn_ra_svn_item_t structs. Return a + * LOCK_TOKENS is an array of svn_ra_svn__item_t structs. Return a * client error if LOCK_TOKENS is not a list of lists. If a lock * violates the authz configuration, return SVN_ERR_RA_NOT_AUTHORIZED * to the client. Use POOL for temporary allocations only. */ -static svn_error_t *add_lock_tokens(const apr_array_header_t *lock_tokens, - server_baton_t *sb, - apr_pool_t *pool) +static svn_error_t * +add_lock_tokens(const svn_ra_svn__list_t *lock_tokens, + server_baton_t *sb, + apr_pool_t *pool) { int i; svn_fs_access_t *fs_access; @@ -1312,24 +1347,23 @@ static svn_error_t *add_lock_tokens(const apr_array_header_t *lock_tokens, for (i = 0; i < lock_tokens->nelts; ++i) { const char *path, *token, *full_path; - svn_ra_svn_item_t *path_item, *token_item; - svn_ra_svn_item_t *item = &APR_ARRAY_IDX(lock_tokens, i, - svn_ra_svn_item_t); + svn_ra_svn__item_t *path_item, *token_item; + svn_ra_svn__item_t *item = &SVN_RA_SVN__LIST_ITEM(lock_tokens, i); if (item->kind != SVN_RA_SVN_LIST) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, "Lock tokens aren't a list of lists"); - path_item = &APR_ARRAY_IDX(item->u.list, 0, svn_ra_svn_item_t); + path_item = &SVN_RA_SVN__LIST_ITEM(&item->u.list, 0); if (path_item->kind != SVN_RA_SVN_STRING) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, "Lock path isn't a string"); - token_item = &APR_ARRAY_IDX(item->u.list, 1, svn_ra_svn_item_t); + token_item = &SVN_RA_SVN__LIST_ITEM(&item->u.list, 1); if (token_item->kind != SVN_RA_SVN_STRING) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, "Lock token isn't a string"); - path = path_item->u.string->data; + path = path_item->u.string.data; full_path = svn_fspath__join(sb->repository->fs_path->data, svn_relpath_canonicalize(path, pool), pool); @@ -1338,7 +1372,7 @@ static svn_error_t *add_lock_tokens(const apr_array_header_t *lock_tokens, return error_create_and_log(SVN_ERR_RA_NOT_AUTHORIZED, NULL, NULL, sb); - token = token_item->u.string->data; + token = token_item->u.string.data; SVN_ERR(svn_fs_access_add_lock_token2(fs_access, path, token)); } @@ -1361,10 +1395,11 @@ lock_cb(void *baton, } /* Unlock the paths with lock tokens in LOCK_TOKENS, ignoring any errors. - LOCK_TOKENS contains svn_ra_svn_item_t elements, assumed to be lists. */ -static svn_error_t *unlock_paths(const apr_array_header_t *lock_tokens, - server_baton_t *sb, - apr_pool_t *pool) + LOCK_TOKENS contains svn_ra_svn__item_t elements, assumed to be lists. */ +static svn_error_t * +unlock_paths(const svn_ra_svn__list_t *lock_tokens, + server_baton_t *sb, + apr_pool_t *pool) { int i; apr_pool_t *subpool = svn_pool_create(pool); @@ -1373,18 +1408,18 @@ static svn_error_t *unlock_paths(const apr_array_header_t *lock_tokens, for (i = 0; i < lock_tokens->nelts; ++i) { - svn_ra_svn_item_t *item, *path_item, *token_item; + svn_ra_svn__item_t *item, *path_item, *token_item; const char *path, *token, *full_path; - item = &APR_ARRAY_IDX(lock_tokens, i, svn_ra_svn_item_t); - path_item = &APR_ARRAY_IDX(item->u.list, 0, svn_ra_svn_item_t); - token_item = &APR_ARRAY_IDX(item->u.list, 1, svn_ra_svn_item_t); + item = &SVN_RA_SVN__LIST_ITEM(lock_tokens, i); + path_item = &SVN_RA_SVN__LIST_ITEM(&item->u.list, 0); + token_item = &SVN_RA_SVN__LIST_ITEM(&item->u.list, 1); - path = path_item->u.string->data; + path = path_item->u.string.data; full_path = svn_fspath__join(sb->repository->fs_path->data, svn_relpath_canonicalize(path, subpool), subpool); - token = token_item->u.string->data; + token = token_item->u.string.data; svn_hash_sets(targets, full_path, token); } @@ -1401,17 +1436,20 @@ static svn_error_t *unlock_paths(const apr_array_header_t *lock_tokens, return SVN_NO_ERROR; } -static svn_error_t *commit(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) +static svn_error_t * +commit(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { server_baton_t *b = baton; const char *log_msg, *date = NULL, *author = NULL, *post_commit_err = NULL; - apr_array_header_t *lock_tokens; + svn_ra_svn__list_t *lock_tokens; svn_boolean_t keep_locks; - apr_array_header_t *revprop_list; + svn_ra_svn__list_t *revprop_list; apr_hash_t *revprop_table; const svn_delta_editor_t *editor; void *edit_baton; @@ -1427,7 +1465,7 @@ static svn_error_t *commit(svn_ra_svn_conn_t *conn, apr_pool_t *pool, { /* Clients before 1.2 don't send lock-tokens, keep-locks, and rev-props fields. */ - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c", &log_msg)); + SVN_ERR(svn_ra_svn__parse_tuple(params, "c", &log_msg)); lock_tokens = NULL; keep_locks = TRUE; revprop_list = NULL; @@ -1435,7 +1473,7 @@ static svn_error_t *commit(svn_ra_svn_conn_t *conn, apr_pool_t *pool, else { /* Clients before 1.5 don't send the rev-props field. */ - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "clb?l", &log_msg, + SVN_ERR(svn_ra_svn__parse_tuple(params, "clb?l", &log_msg, &lock_tokens, &keep_locks, &revprop_list)); } @@ -1513,8 +1551,11 @@ static svn_error_t *commit(svn_ra_svn_conn_t *conn, apr_pool_t *pool, return SVN_NO_ERROR; } -static svn_error_t *get_file(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) +static svn_error_t * +get_file(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { server_baton_t *b = baton; const char *path, *full_path, *hex_digest; @@ -1537,7 +1578,7 @@ static svn_error_t *get_file(svn_ra_svn_conn_t *conn, apr_pool_t *pool, ab.conn = conn; /* Parse arguments. */ - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c(?r)bb?B", &path, &rev, + SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)bb?B", &path, &rev, &want_props, &want_contents, &wants_inherited_props)); @@ -1637,8 +1678,69 @@ static svn_error_t *get_file(svn_ra_svn_conn_t *conn, apr_pool_t *pool, return SVN_NO_ERROR; } -static svn_error_t *get_dir(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) +/* Translate all the words in DIRENT_FIELDS_LIST into the flags in + * DIRENT_FIELDS_P. If DIRENT_FIELDS_LIST is NULL, set all flags. */ +static svn_error_t * +parse_dirent_fields(apr_uint32_t *dirent_fields_p, + svn_ra_svn__list_t *dirent_fields_list) +{ + static const svn_string_t str_kind + = SVN__STATIC_STRING(SVN_RA_SVN_DIRENT_KIND); + static const svn_string_t str_size + = SVN__STATIC_STRING(SVN_RA_SVN_DIRENT_SIZE); + static const svn_string_t str_has_props + = SVN__STATIC_STRING(SVN_RA_SVN_DIRENT_HAS_PROPS); + static const svn_string_t str_created_rev + = SVN__STATIC_STRING(SVN_RA_SVN_DIRENT_CREATED_REV); + static const svn_string_t str_time + = SVN__STATIC_STRING(SVN_RA_SVN_DIRENT_TIME); + static const svn_string_t str_last_author + = SVN__STATIC_STRING(SVN_RA_SVN_DIRENT_LAST_AUTHOR); + + apr_uint32_t dirent_fields; + + if (! dirent_fields_list) + { + dirent_fields = SVN_DIRENT_ALL; + } + else + { + int i; + dirent_fields = 0; + + for (i = 0; i < dirent_fields_list->nelts; ++i) + { + svn_ra_svn__item_t *elt + = &SVN_RA_SVN__LIST_ITEM(dirent_fields_list, i); + + if (elt->kind != SVN_RA_SVN_WORD) + return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, + "Dirent field not a word"); + + if (svn_string_compare(&str_kind, &elt->u.word)) + dirent_fields |= SVN_DIRENT_KIND; + else if (svn_string_compare(&str_size, &elt->u.word)) + dirent_fields |= SVN_DIRENT_SIZE; + else if (svn_string_compare(&str_has_props, &elt->u.word)) + dirent_fields |= SVN_DIRENT_HAS_PROPS; + else if (svn_string_compare(&str_created_rev, &elt->u.word)) + dirent_fields |= SVN_DIRENT_CREATED_REV; + else if (svn_string_compare(&str_time, &elt->u.word)) + dirent_fields |= SVN_DIRENT_TIME; + else if (svn_string_compare(&str_last_author, &elt->u.word)) + dirent_fields |= SVN_DIRENT_LAST_AUTHOR; + } + } + + *dirent_fields_p = dirent_fields; + return SVN_NO_ERROR; +} + +static svn_error_t * +get_dir(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { server_baton_t *b = baton; const char *path, *full_path; @@ -1650,16 +1752,15 @@ static svn_error_t *get_dir(svn_ra_svn_conn_t *conn, apr_pool_t *pool, apr_pool_t *subpool; svn_boolean_t want_props, want_contents; apr_uint64_t wants_inherited_props; - apr_uint64_t dirent_fields; - apr_array_header_t *dirent_fields_list = NULL; - svn_ra_svn_item_t *elt; + apr_uint32_t dirent_fields; + svn_ra_svn__list_t *dirent_fields_list = NULL; int i; authz_baton_t ab; ab.server = b; ab.conn = conn; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c(?r)bb?l?B", &path, &rev, + SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)bb?l?B", &path, &rev, &want_props, &want_contents, &dirent_fields_list, &wants_inherited_props)); @@ -1667,37 +1768,7 @@ static svn_error_t *get_dir(svn_ra_svn_conn_t *conn, apr_pool_t *pool, if (wants_inherited_props == SVN_RA_SVN_UNSPECIFIED_NUMBER) wants_inherited_props = FALSE; - if (! dirent_fields_list) - { - dirent_fields = SVN_DIRENT_ALL; - } - else - { - dirent_fields = 0; - - for (i = 0; i < dirent_fields_list->nelts; ++i) - { - elt = &APR_ARRAY_IDX(dirent_fields_list, i, svn_ra_svn_item_t); - - if (elt->kind != SVN_RA_SVN_WORD) - return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, - "Dirent field not a string"); - - if (strcmp(SVN_RA_SVN_DIRENT_KIND, elt->u.word) == 0) - dirent_fields |= SVN_DIRENT_KIND; - else if (strcmp(SVN_RA_SVN_DIRENT_SIZE, elt->u.word) == 0) - dirent_fields |= SVN_DIRENT_SIZE; - else if (strcmp(SVN_RA_SVN_DIRENT_HAS_PROPS, elt->u.word) == 0) - dirent_fields |= SVN_DIRENT_HAS_PROPS; - else if (strcmp(SVN_RA_SVN_DIRENT_CREATED_REV, elt->u.word) == 0) - dirent_fields |= SVN_DIRENT_CREATED_REV; - else if (strcmp(SVN_RA_SVN_DIRENT_TIME, elt->u.word) == 0) - dirent_fields |= SVN_DIRENT_TIME; - else if (strcmp(SVN_RA_SVN_DIRENT_LAST_AUTHOR, elt->u.word) == 0) - dirent_fields |= SVN_DIRENT_LAST_AUTHOR; - } - } - + SVN_ERR(parse_dirent_fields(&dirent_fields, dirent_fields_list)); full_path = svn_fspath__join(b->repository->fs_path->data, svn_relpath_canonicalize(path, pool), pool); @@ -1773,7 +1844,7 @@ static svn_error_t *get_dir(svn_ra_svn_conn_t *conn, apr_pool_t *pool, entry_kind = fsent->kind; if (dirent_fields & SVN_DIRENT_SIZE) - if (entry_kind != svn_node_dir) + if (fsent->kind != svn_node_dir) SVN_CMD_ERR(svn_fs_file_length(&entry_size, root, file_path, subpool)); @@ -1838,8 +1909,11 @@ static svn_error_t *get_dir(svn_ra_svn_conn_t *conn, apr_pool_t *pool, return svn_ra_svn__write_tuple(conn, pool, "!))"); } -static svn_error_t *update(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) +static svn_error_t * +update(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { server_baton_t *b = baton; svn_revnum_t rev; @@ -1853,7 +1927,7 @@ static svn_error_t *update(svn_ra_svn_conn_t *conn, apr_pool_t *pool, svn_boolean_t is_checkout; /* Parse the arguments. */ - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "(?r)cb?w3?3", &rev, &target, + SVN_ERR(svn_ra_svn__parse_tuple(params, "(?r)cb?w3?3", &rev, &target, &recurse, &depth_word, &send_copyfrom_args, &ignore_ancestry)); target = svn_relpath_canonicalize(target, pool); @@ -1893,8 +1967,11 @@ static svn_error_t *update(svn_ra_svn_conn_t *conn, apr_pool_t *pool, return SVN_NO_ERROR; } -static svn_error_t *switch_cmd(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) +static svn_error_t * +switch_cmd(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { server_baton_t *b = baton; svn_revnum_t rev; @@ -1908,7 +1985,7 @@ static svn_error_t *switch_cmd(svn_ra_svn_conn_t *conn, apr_pool_t *pool, svn_tristate_t ignore_ancestry; /* Optional; default TRUE */ /* Parse the arguments. */ - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "(?r)cbc?w?33", &rev, &target, + SVN_ERR(svn_ra_svn__parse_tuple(params, "(?r)cbc?w?33", &rev, &target, &recurse, &switch_url, &depth_word, &send_copyfrom_args, &ignore_ancestry)); target = svn_relpath_canonicalize(target, pool); @@ -1943,8 +2020,11 @@ static svn_error_t *switch_cmd(svn_ra_svn_conn_t *conn, apr_pool_t *pool, (ignore_ancestry != svn_tristate_false)); } -static svn_error_t *status(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) +static svn_error_t * +status(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { server_baton_t *b = baton; svn_revnum_t rev; @@ -1955,7 +2035,7 @@ static svn_error_t *status(svn_ra_svn_conn_t *conn, apr_pool_t *pool, svn_depth_t depth = svn_depth_unknown; /* Parse the arguments. */ - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "cb?(?r)?w", + SVN_ERR(svn_ra_svn__parse_tuple(params, "cb?(?r)?w", &target, &recurse, &rev, &depth_word)); target = svn_relpath_canonicalize(target, pool); @@ -1979,8 +2059,11 @@ static svn_error_t *status(svn_ra_svn_conn_t *conn, apr_pool_t *pool, depth, FALSE, FALSE); } -static svn_error_t *diff(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) +static svn_error_t * +diff(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { server_baton_t *b = baton; svn_revnum_t rev; @@ -1995,14 +2078,14 @@ static svn_error_t *diff(svn_ra_svn_conn_t *conn, apr_pool_t *pool, if (params->nelts == 5) { /* Clients before 1.4 don't send the text_deltas boolean or depth. */ - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "(?r)cbbc", &rev, &target, + SVN_ERR(svn_ra_svn__parse_tuple(params, "(?r)cbbc", &rev, &target, &recurse, &ignore_ancestry, &versus_url)); text_deltas = TRUE; depth_word = NULL; } else { - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "(?r)cbbcb?w", + SVN_ERR(svn_ra_svn__parse_tuple(params, "(?r)cbbcb?w", &rev, &target, &recurse, &ignore_ancestry, &versus_url, &text_deltas, &depth_word)); @@ -2039,31 +2122,92 @@ static svn_error_t *diff(svn_ra_svn_conn_t *conn, apr_pool_t *pool, return SVN_NO_ERROR; } +/* Baton type to be used with mergeinfo_receiver. */ +typedef struct mergeinfo_receiver_baton_t +{ + /* Send the response over this connection. */ + svn_ra_svn_conn_t *conn; + + /* Start path of the query; report paths relative to this one. */ + const char *fs_path; + + /* Did we already send the opening sequence? */ + svn_boolean_t starting_tuple_sent; +} mergeinfo_receiver_baton_t; + +/* Utility method sending the start of the "get m/i" response once + over BATON->CONN. */ +static svn_error_t * +send_mergeinfo_starting_tuple(mergeinfo_receiver_baton_t *baton, + apr_pool_t *scratch_pool) +{ + if (baton->starting_tuple_sent) + return SVN_NO_ERROR; + + SVN_ERR(svn_ra_svn__write_tuple(baton->conn, scratch_pool, + "w((!", "success")); + baton->starting_tuple_sent = TRUE; + + return SVN_NO_ERROR; +} + +/* Implements svn_repos_mergeinfo_receiver_t, sending the MERGEINFO + * out over the connection in the mergeinfo_receiver_baton_t * BATON. */ +static svn_error_t * +mergeinfo_receiver(const char *path, + svn_mergeinfo_t mergeinfo, + void *baton, + apr_pool_t *scratch_pool) +{ + mergeinfo_receiver_baton_t *b = baton; + svn_string_t *mergeinfo_string; + + /* Delay starting the response until we checked that the initial + request went through. We are at that point now b/c we've got + the first results in. */ + SVN_ERR(send_mergeinfo_starting_tuple(b, scratch_pool)); + + /* Adjust the path info and send the m/i. */ + path = svn_fspath__skip_ancestor(b->fs_path, path); + SVN_ERR(svn_mergeinfo_to_string(&mergeinfo_string, mergeinfo, + scratch_pool)); + SVN_ERR(svn_ra_svn__write_tuple(b->conn, scratch_pool, "cs", path, + mergeinfo_string)); + + return SVN_NO_ERROR; +} + /* Regardless of whether a client's capabilities indicate an understanding of this command (by way of SVN_RA_SVN_CAP_MERGEINFO), we provide a response. ASSUMPTION: When performing a 'merge' with two URLs at different revisions, the client will call this command more than once. */ -static svn_error_t *get_mergeinfo(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) +static svn_error_t * +get_mergeinfo(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { server_baton_t *b = baton; svn_revnum_t rev; - apr_array_header_t *paths, *canonical_paths; - svn_mergeinfo_catalog_t mergeinfo; + svn_ra_svn__list_t *paths; + apr_array_header_t *canonical_paths; int i; - apr_hash_index_t *hi; const char *inherit_word; svn_mergeinfo_inheritance_t inherit; svn_boolean_t include_descendants; - apr_pool_t *iterpool; authz_baton_t ab; + mergeinfo_receiver_baton_t mergeinfo_baton; ab.server = b; ab.conn = conn; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "l(?r)wb", &paths, &rev, + mergeinfo_baton.conn = conn; + mergeinfo_baton.fs_path = b->repository->fs_path->data; + mergeinfo_baton.starting_tuple_sent = FALSE; + + SVN_ERR(svn_ra_svn__parse_tuple(params, "l(?r)wb", &paths, &rev, &inherit_word, &include_descendants)); inherit = svn_inheritance_from_word(inherit_word); @@ -2071,13 +2215,13 @@ static svn_error_t *get_mergeinfo(svn_ra_svn_conn_t *conn, apr_pool_t *pool, canonical_paths = apr_array_make(pool, paths->nelts, sizeof(const char *)); for (i = 0; i < paths->nelts; i++) { - svn_ra_svn_item_t *item = &APR_ARRAY_IDX(paths, i, svn_ra_svn_item_t); + svn_ra_svn__item_t *item = &SVN_RA_SVN__LIST_ITEM(paths, i); const char *full_path; if (item->kind != SVN_RA_SVN_STRING) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Path is not a string")); - full_path = svn_relpath_canonicalize(item->u.string->data, pool); + full_path = svn_relpath_canonicalize(item->u.string.data, pool); full_path = svn_fspath__join(b->repository->fs_path->data, full_path, pool); APR_ARRAY_PUSH(canonical_paths, const char *) = full_path; } @@ -2088,42 +2232,76 @@ static svn_error_t *get_mergeinfo(svn_ra_svn_conn_t *conn, apr_pool_t *pool, pool))); SVN_ERR(trivial_auth_request(conn, pool, b)); - SVN_CMD_ERR(svn_repos_fs_get_mergeinfo(&mergeinfo, b->repository->repos, - canonical_paths, rev, - inherit, - include_descendants, - authz_check_access_cb_func(b), &ab, - pool)); - SVN_ERR(svn_mergeinfo__remove_prefix_from_catalog(&mergeinfo, mergeinfo, - b->repository->fs_path->data, pool)); - SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "w((!", "success")); - iterpool = svn_pool_create(pool); - for (hi = apr_hash_first(pool, mergeinfo); hi; hi = apr_hash_next(hi)) - { - const char *key = apr_hash_this_key(hi); - svn_mergeinfo_t value = apr_hash_this_val(hi); - svn_string_t *mergeinfo_string; - svn_pool_clear(iterpool); + SVN_CMD_ERR(svn_repos_fs_get_mergeinfo2(b->repository->repos, + canonical_paths, rev, + inherit, + include_descendants, + authz_check_access_cb_func(b), &ab, + mergeinfo_receiver, + &mergeinfo_baton, + pool)); - SVN_ERR(svn_mergeinfo_to_string(&mergeinfo_string, value, iterpool)); - SVN_ERR(svn_ra_svn__write_tuple(conn, iterpool, "cs", key, - mergeinfo_string)); - } - svn_pool_destroy(iterpool); + /* We might not have sent anything + => ensure to begin the response in any case. */ + SVN_ERR(send_mergeinfo_starting_tuple(&mergeinfo_baton, pool)); SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "!))")); return SVN_NO_ERROR; } -/* Send a log entry to the client. */ -static svn_error_t *log_receiver(void *baton, - svn_log_entry_t *log_entry, - apr_pool_t *pool) +/* Send a changed paths list entry to the client. + This implements svn_repos_path_change_receiver_t. */ +static svn_error_t * +path_change_receiver(void *baton, + svn_repos_path_change_t *change, + apr_pool_t *scratch_pool) +{ + const char symbol[] = "MADR"; + + log_baton_t *b = baton; + svn_ra_svn_conn_t *conn = b->conn; + + /* Sanitize and convert change kind to ra-svn level action. + + Pushing that conversion down into libsvn_ra_svn would add yet another + API dependency there. */ + char action = ( change->change_kind < svn_fs_path_change_modify + || change->change_kind > svn_fs_path_change_replace) + ? 0 + : symbol[change->change_kind]; + + /* Open lists once: LOG_ENTRY and LOG_ENTRY->CHANGED_PATHS. */ + if (!b->started) + { + SVN_ERR(svn_ra_svn__start_list(conn, scratch_pool)); + SVN_ERR(svn_ra_svn__start_list(conn, scratch_pool)); + b->started = TRUE; + } + + /* Serialize CHANGE. */ + SVN_ERR(svn_ra_svn__write_data_log_changed_path( + conn, scratch_pool, + &change->path, + action, + change->copyfrom_path, + change->copyfrom_rev, + change->node_kind, + change->text_mod, + change->prop_mod)); + + return SVN_NO_ERROR; +} + +/* Send a the meta data and the revpros for LOG_ENTRY to the client. + This implements svn_log_entry_receiver_t. */ +static svn_error_t * +revision_receiver(void *baton, + svn_repos_log_entry_t *log_entry, + apr_pool_t *scratch_pool) { log_baton_t *b = baton; svn_ra_svn_conn_t *conn = b->conn; - apr_hash_index_t *h; svn_boolean_t invalid_revnum = FALSE; const svn_string_t *author, *date, *message; unsigned revprop_count; @@ -2144,55 +2322,52 @@ static svn_error_t *log_receiver(void *baton, svn_compat_log_revprops_out_string(&author, &date, &message, log_entry->revprops); - svn_compat_log_revprops_clear(log_entry->revprops); - if (log_entry->revprops) - revprop_count = apr_hash_count(log_entry->revprops); - else - revprop_count = 0; - /* send LOG_ENTRY */ - SVN_ERR(svn_ra_svn__start_list(conn, pool)); - - /* send LOG_ENTRY->CHANGED_PATHS2 */ - SVN_ERR(svn_ra_svn__start_list(conn, pool)); - if (log_entry->changed_paths2) + /* Revprops list filtering is somewhat expensive. + Avoid doing that for the 90% case where only the standard revprops + have been requested and delivered. */ + if (author && date && message && apr_hash_count(log_entry->revprops) == 3) { - for (h = apr_hash_first(pool, log_entry->changed_paths2); h; - h = apr_hash_next(h)) - { - const char *path = apr_hash_this_key(h); - svn_log_changed_path2_t *change = apr_hash_this_val(h); - - SVN_ERR(svn_ra_svn__write_data_log_changed_path( - conn, pool, - path, - change->action, - change->copyfrom_path, - change->copyfrom_rev, - change->node_kind, - /* text_modified and props_modified are never unknown */ - change->text_modified == svn_tristate_true, - change->props_modified == svn_tristate_true)); - } + revprop_count = 0; } - SVN_ERR(svn_ra_svn__end_list(conn, pool)); + else + { + svn_compat_log_revprops_clear(log_entry->revprops); + if (log_entry->revprops) + revprop_count = apr_hash_count(log_entry->revprops); + else + revprop_count = 0; + } + + /* Open lists once: LOG_ENTRY and LOG_ENTRY->CHANGED_PATHS. */ + if (!b->started) + { + SVN_ERR(svn_ra_svn__start_list(conn, scratch_pool)); + SVN_ERR(svn_ra_svn__start_list(conn, scratch_pool)); + } + + /* Close LOG_ENTRY->CHANGED_PATHS. */ + SVN_ERR(svn_ra_svn__end_list(conn, scratch_pool)); + b->started = FALSE; /* send LOG_ENTRY main members */ - SVN_ERR(svn_ra_svn__write_data_log_entry(conn, pool, + SVN_ERR(svn_ra_svn__write_data_log_entry(conn, scratch_pool, log_entry->revision, author, date, message, log_entry->has_children, invalid_revnum, revprop_count)); /* send LOG_ENTRY->REVPROPS */ - SVN_ERR(svn_ra_svn__start_list(conn, pool)); + SVN_ERR(svn_ra_svn__start_list(conn, scratch_pool)); if (revprop_count) - SVN_ERR(svn_ra_svn__write_proplist(conn, pool, log_entry->revprops)); - SVN_ERR(svn_ra_svn__end_list(conn, pool)); + SVN_ERR(svn_ra_svn__write_proplist(conn, scratch_pool, + log_entry->revprops)); + SVN_ERR(svn_ra_svn__end_list(conn, scratch_pool)); /* send LOG_ENTRY members that were added in later SVN releases */ - SVN_ERR(svn_ra_svn__write_boolean(conn, pool, log_entry->subtractive_merge)); - SVN_ERR(svn_ra_svn__end_list(conn, pool)); + SVN_ERR(svn_ra_svn__write_boolean(conn, scratch_pool, + log_entry->subtractive_merge)); + SVN_ERR(svn_ra_svn__end_list(conn, scratch_pool)); if (log_entry->has_children) b->stack_depth++; @@ -2200,17 +2375,21 @@ static svn_error_t *log_receiver(void *baton, return SVN_NO_ERROR; } -static svn_error_t *log_cmd(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) +static svn_error_t * +log_cmd(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { svn_error_t *err, *write_err; server_baton_t *b = baton; svn_revnum_t start_rev, end_rev; const char *full_path; svn_boolean_t send_changed_paths, strict_node, include_merged_revisions; - apr_array_header_t *paths, *full_paths, *revprop_items, *revprops; + apr_array_header_t *full_paths, *revprops; + svn_ra_svn__list_t *paths, *revprop_items; char *revprop_word; - svn_ra_svn_item_t *elt; + svn_ra_svn__item_t *elt; int i; apr_uint64_t limit, include_merged_revs_param; log_baton_t lb; @@ -2219,7 +2398,7 @@ static svn_error_t *log_cmd(svn_ra_svn_conn_t *conn, apr_pool_t *pool, ab.server = b; ab.conn = conn; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "l(?r)(?r)bb?n?Bwl", &paths, + SVN_ERR(svn_ra_svn__parse_tuple(params, "l(?r)(?r)bb?n?Bwl", &paths, &start_rev, &end_rev, &send_changed_paths, &strict_node, &limit, &include_merged_revs_param, @@ -2243,11 +2422,11 @@ static svn_error_t *log_cmd(svn_ra_svn_conn_t *conn, apr_pool_t *pool, sizeof(char *)); for (i = 0; i < revprop_items->nelts; i++) { - elt = &APR_ARRAY_IDX(revprop_items, i, svn_ra_svn_item_t); + elt = &SVN_RA_SVN__LIST_ITEM(revprop_items, i); if (elt->kind != SVN_RA_SVN_STRING) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Log revprop entry not a string")); - APR_ARRAY_PUSH(revprops, const char *) = elt->u.string->data; + APR_ARRAY_PUSH(revprops, const char *) = elt->u.string.data; } } else @@ -2265,11 +2444,11 @@ static svn_error_t *log_cmd(svn_ra_svn_conn_t *conn, apr_pool_t *pool, full_paths = apr_array_make(pool, paths->nelts, sizeof(const char *)); for (i = 0; i < paths->nelts; i++) { - elt = &APR_ARRAY_IDX(paths, i, svn_ra_svn_item_t); + elt = &SVN_RA_SVN__LIST_ITEM(paths, i); if (elt->kind != SVN_RA_SVN_STRING) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Log path entry not a string")); - full_path = svn_relpath_canonicalize(elt->u.string->data, pool), + full_path = svn_relpath_canonicalize(elt->u.string.data, pool), full_path = svn_fspath__join(b->repository->fs_path->data, full_path, pool); APR_ARRAY_PUSH(full_paths, const char *) = full_path; @@ -2286,11 +2465,14 @@ static svn_error_t *log_cmd(svn_ra_svn_conn_t *conn, apr_pool_t *pool, lb.fs_path = b->repository->fs_path->data; lb.conn = conn; lb.stack_depth = 0; - err = svn_repos_get_logs4(b->repository->repos, full_paths, start_rev, - end_rev, (int) limit, send_changed_paths, + lb.started = FALSE; + err = svn_repos_get_logs5(b->repository->repos, full_paths, start_rev, + end_rev, (int) limit, strict_node, include_merged_revisions, revprops, authz_check_access_cb_func(b), &ab, - log_receiver, &lb, pool); + send_changed_paths ? path_change_receiver : NULL, + send_changed_paths ? &lb : NULL, + revision_receiver, &lb, pool); write_err = svn_ra_svn__write_word(conn, pool, "done"); if (write_err) @@ -2303,8 +2485,11 @@ static svn_error_t *log_cmd(svn_ra_svn_conn_t *conn, apr_pool_t *pool, return SVN_NO_ERROR; } -static svn_error_t *check_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) +static svn_error_t * +check_path(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { server_baton_t *b = baton; svn_revnum_t rev; @@ -2312,7 +2497,7 @@ static svn_error_t *check_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool, svn_fs_root_t *root; svn_node_kind_t kind; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c(?r)", &path, &rev)); + SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)", &path, &rev)); full_path = svn_fspath__join(b->repository->fs_path->data, svn_relpath_canonicalize(path, pool), pool); @@ -2333,8 +2518,11 @@ static svn_error_t *check_path(svn_ra_svn_conn_t *conn, apr_pool_t *pool, return SVN_NO_ERROR; } -static svn_error_t *stat_cmd(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) +static svn_error_t * +stat_cmd(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { server_baton_t *b = baton; svn_revnum_t rev; @@ -2342,7 +2530,7 @@ static svn_error_t *stat_cmd(svn_ra_svn_conn_t *conn, apr_pool_t *pool, svn_fs_root_t *root; svn_dirent_t *dirent; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c(?r)", &path, &rev)); + SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)", &path, &rev)); full_path = svn_fspath__join(b->repository->fs_path->data, svn_relpath_canonicalize(path, pool), pool); @@ -2380,14 +2568,18 @@ static svn_error_t *stat_cmd(svn_ra_svn_conn_t *conn, apr_pool_t *pool, return SVN_NO_ERROR; } -static svn_error_t *get_locations(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) +static svn_error_t * +get_locations(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { svn_error_t *err, *write_err; server_baton_t *b = baton; svn_revnum_t revision; - apr_array_header_t *location_revisions, *loc_revs_proto; - svn_ra_svn_item_t *elt; + apr_array_header_t *location_revisions; + svn_ra_svn__list_t *loc_revs_proto; + svn_ra_svn__item_t *elt; int i; const char *relative_path; svn_revnum_t peg_revision; @@ -2399,7 +2591,7 @@ static svn_error_t *get_locations(svn_ra_svn_conn_t *conn, apr_pool_t *pool, ab.conn = conn; /* Parse the arguments. */ - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "crl", &relative_path, + SVN_ERR(svn_ra_svn__parse_tuple(params, "crl", &relative_path, &peg_revision, &loc_revs_proto)); relative_path = svn_relpath_canonicalize(relative_path, pool); @@ -2411,7 +2603,7 @@ static svn_error_t *get_locations(svn_ra_svn_conn_t *conn, apr_pool_t *pool, sizeof(svn_revnum_t)); for (i = 0; i < loc_revs_proto->nelts; i++) { - elt = &APR_ARRAY_IDX(loc_revs_proto, i, svn_ra_svn_item_t); + elt = &SVN_RA_SVN__LIST_ITEM(loc_revs_proto, i); if (elt->kind != SVN_RA_SVN_NUMBER) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, "Get-locations location revisions entry " @@ -2479,10 +2671,11 @@ static svn_error_t *gls_receiver(svn_location_segment_t *segment, segment->path); } -static svn_error_t *get_location_segments(svn_ra_svn_conn_t *conn, - apr_pool_t *pool, - apr_array_header_t *params, - void *baton) +static svn_error_t * +get_location_segments(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { svn_error_t *err, *write_err; server_baton_t *b = baton; @@ -2495,7 +2688,7 @@ static svn_error_t *get_location_segments(svn_ra_svn_conn_t *conn, ab.conn = conn; /* Parse the arguments. */ - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c(?r)(?r)(?r)", + SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)(?r)(?r)", &relative_path, &peg_revision, &start_rev, &end_rev)); relative_path = svn_relpath_canonicalize(relative_path, pool); @@ -2538,7 +2731,7 @@ static svn_error_t *get_location_segments(svn_ra_svn_conn_t *conn, if (end_rev > start_rev) { err = svn_ra_svn__write_word(conn, pool, "done"); - err = svn_error_createf(SVN_ERR_INCORRECT_PARAMS, err, + err = svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, err, "Get-location-segments end revision must not be " "younger than start revision"); return log_fail_and_flush(err, b, conn, pool); @@ -2547,7 +2740,7 @@ static svn_error_t *get_location_segments(svn_ra_svn_conn_t *conn, if (start_rev > peg_revision) { err = svn_ra_svn__write_word(conn, pool, "done"); - err = svn_error_createf(SVN_ERR_INCORRECT_PARAMS, err, + err = svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, err, "Get-location-segments start revision must not " "be younger than peg revision"); return log_fail_and_flush(err, b, conn, pool); @@ -2628,15 +2821,9 @@ static svn_error_t *file_rev_handler(void *baton, const char *path, svn_stream_set_write(stream, svndiff_handler); svn_stream_set_close(stream, svndiff_close_handler); - /* If the connection does not support SVNDIFF1 or if we don't want to use - * compression, use the non-compressing "version 0" implementation */ - if ( svn_ra_svn_compression_level(frb->conn) > 0 - && svn_ra_svn_has_capability(frb->conn, SVN_RA_SVN_CAP_SVNDIFF1)) - svn_txdelta_to_svndiff3(d_handler, d_baton, stream, 1, - svn_ra_svn_compression_level(frb->conn), pool); - else - svn_txdelta_to_svndiff3(d_handler, d_baton, stream, 0, - svn_ra_svn_compression_level(frb->conn), pool); + svn_txdelta_to_svndiff3(d_handler, d_baton, stream, + svn_ra_svn__svndiff_version(frb->conn), + svn_ra_svn_compression_level(frb->conn), pool); } else SVN_ERR(svn_ra_svn__write_cstring(frb->conn, pool, "")); @@ -2644,8 +2831,11 @@ static svn_error_t *file_rev_handler(void *baton, const char *path, return SVN_NO_ERROR; } -static svn_error_t *get_file_revs(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) +static svn_error_t * +get_file_revs(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { server_baton_t *b = baton; svn_error_t *err, *write_err; @@ -2661,7 +2851,7 @@ static svn_error_t *get_file_revs(svn_ra_svn_conn_t *conn, apr_pool_t *pool, ab.conn = conn; /* Parse arguments. */ - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c(?r)(?r)?B", + SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)(?r)?B", &path, &start_rev, &end_rev, &include_merged_revs_param)); path = svn_relpath_canonicalize(path, pool); @@ -2697,8 +2887,11 @@ static svn_error_t *get_file_revs(svn_ra_svn_conn_t *conn, apr_pool_t *pool, return SVN_NO_ERROR; } -static svn_error_t *lock(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) +static svn_error_t * +lock(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { server_baton_t *b = baton; const char *path; @@ -2708,7 +2901,7 @@ static svn_error_t *lock(svn_ra_svn_conn_t *conn, apr_pool_t *pool, svn_revnum_t current_rev; svn_lock_t *l; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c(?c)b(?r)", &path, &comment, + SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?c)b(?r)", &path, &comment, &steal_lock, ¤t_rev)); full_path = svn_fspath__join(b->repository->fs_path->data, svn_relpath_canonicalize(path, pool), pool); @@ -2771,11 +2964,14 @@ clear_lock_result_hash(apr_hash_t *results, } } -static svn_error_t *lock_many(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) +static svn_error_t * +lock_many(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { server_baton_t *b = baton; - apr_array_header_t *path_revs; + svn_ra_svn__list_t *path_revs; const char *comment; svn_boolean_t steal_lock; int i; @@ -2786,7 +2982,7 @@ static svn_error_t *lock_many(svn_ra_svn_conn_t *conn, apr_pool_t *pool, apr_hash_index_t *hi; struct lock_many_baton_t lmb; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "(?c)bl", &comment, &steal_lock, + SVN_ERR(svn_ra_svn__parse_tuple(params, "(?c)bl", &comment, &steal_lock, &path_revs)); subpool = svn_pool_create(pool); @@ -2802,8 +2998,7 @@ static svn_error_t *lock_many(svn_ra_svn_conn_t *conn, apr_pool_t *pool, { const char *path, *full_path; svn_revnum_t current_rev; - svn_ra_svn_item_t *item = &APR_ARRAY_IDX(path_revs, i, - svn_ra_svn_item_t); + svn_ra_svn__item_t *item = &SVN_RA_SVN__LIST_ITEM(path_revs, i); svn_fs_lock_target_t *target; svn_pool_clear(subpool); @@ -2812,7 +3007,7 @@ static svn_error_t *lock_many(svn_ra_svn_conn_t *conn, apr_pool_t *pool, return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, "Lock requests should be list of lists"); - SVN_ERR(svn_ra_svn__parse_tuple(item->u.list, subpool, "c(?r)", &path, + SVN_ERR(svn_ra_svn__parse_tuple(&item->u.list, "c(?r)", &path, ¤t_rev)); full_path = svn_fspath__join(b->repository->fs_path->data, @@ -2866,14 +3061,13 @@ static svn_error_t *lock_many(svn_ra_svn_conn_t *conn, apr_pool_t *pool, { const char *path, *full_path; svn_revnum_t current_rev; - svn_ra_svn_item_t *item = &APR_ARRAY_IDX(path_revs, i, - svn_ra_svn_item_t); + svn_ra_svn__item_t *item = &SVN_RA_SVN__LIST_ITEM(path_revs, i); struct lock_result_t *result; svn_pool_clear(subpool); - write_err = svn_ra_svn__parse_tuple(item->u.list, subpool, "c(?r)", &path, - ¤t_rev); + write_err = svn_ra_svn__parse_tuple(&item->u.list, "c(?r)", + &path, ¤t_rev); if (write_err) break; @@ -2927,14 +3121,17 @@ static svn_error_t *lock_many(svn_ra_svn_conn_t *conn, apr_pool_t *pool, return SVN_NO_ERROR; } -static svn_error_t *unlock(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) +static svn_error_t * +unlock(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { server_baton_t *b = baton; const char *path, *token, *full_path; svn_boolean_t break_lock; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c(?c)b", &path, &token, + SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?c)b", &path, &token, &break_lock)); full_path = svn_fspath__join(b->repository->fs_path->data, @@ -2954,12 +3151,15 @@ static svn_error_t *unlock(svn_ra_svn_conn_t *conn, apr_pool_t *pool, return SVN_NO_ERROR; } -static svn_error_t *unlock_many(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) +static svn_error_t * +unlock_many(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { server_baton_t *b = baton; svn_boolean_t break_lock; - apr_array_header_t *unlock_tokens; + svn_ra_svn__list_t *unlock_tokens; int i; apr_pool_t *subpool; svn_error_t *err = SVN_NO_ERROR, *write_err = SVN_NO_ERROR; @@ -2968,8 +3168,7 @@ static svn_error_t *unlock_many(svn_ra_svn_conn_t *conn, apr_pool_t *pool, apr_hash_index_t *hi; struct lock_many_baton_t lmb; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "bl", &break_lock, - &unlock_tokens)); + SVN_ERR(svn_ra_svn__parse_tuple(params, "bl", &break_lock, &unlock_tokens)); /* Username required unless break_lock was specified. */ SVN_ERR(must_have_access(conn, pool, b, svn_authz_write, NULL, ! break_lock)); @@ -2979,8 +3178,7 @@ static svn_error_t *unlock_many(svn_ra_svn_conn_t *conn, apr_pool_t *pool, /* Parse the unlock requests from PATH_REVS into TARGETS. */ for (i = 0; i < unlock_tokens->nelts; i++) { - svn_ra_svn_item_t *item = &APR_ARRAY_IDX(unlock_tokens, i, - svn_ra_svn_item_t); + svn_ra_svn__item_t *item = &SVN_RA_SVN__LIST_ITEM(unlock_tokens, i); const char *path, *full_path, *token; svn_pool_clear(subpool); @@ -2989,7 +3187,7 @@ static svn_error_t *unlock_many(svn_ra_svn_conn_t *conn, apr_pool_t *pool, return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, "Unlock request should be a list of lists"); - SVN_ERR(svn_ra_svn__parse_tuple(item->u.list, subpool, "c(?c)", &path, + SVN_ERR(svn_ra_svn__parse_tuple(&item->u.list, "c(?c)", &path, &token)); if (!token) token = ""; @@ -3042,14 +3240,13 @@ static svn_error_t *unlock_many(svn_ra_svn_conn_t *conn, apr_pool_t *pool, for (i = 0; i < unlock_tokens->nelts; ++i) { const char *path, *token, *full_path; - svn_ra_svn_item_t *item = &APR_ARRAY_IDX(unlock_tokens, i, - svn_ra_svn_item_t); + svn_ra_svn__item_t *item = &SVN_RA_SVN__LIST_ITEM(unlock_tokens, i); struct lock_result_t *result; svn_pool_clear(subpool); - write_err = svn_ra_svn__parse_tuple(item->u.list, subpool, "c(?c)", &path, - &token); + write_err = svn_ra_svn__parse_tuple(&item->u.list, "c(?c)", + &path, &token); if (write_err) break; @@ -3096,15 +3293,18 @@ static svn_error_t *unlock_many(svn_ra_svn_conn_t *conn, apr_pool_t *pool, return SVN_NO_ERROR; } -static svn_error_t *get_lock(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) +static svn_error_t * +get_lock(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { server_baton_t *b = baton; const char *path; const char *full_path; svn_lock_t *l; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c", &path)); + SVN_ERR(svn_ra_svn__parse_tuple(params, "c", &path)); full_path = svn_fspath__join(b->repository->fs_path->data, svn_relpath_canonicalize(path, pool), pool); @@ -3124,8 +3324,11 @@ static svn_error_t *get_lock(svn_ra_svn_conn_t *conn, apr_pool_t *pool, return SVN_NO_ERROR; } -static svn_error_t *get_locks(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) +static svn_error_t * +get_locks(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { server_baton_t *b = baton; const char *path; @@ -3140,7 +3343,7 @@ static svn_error_t *get_locks(svn_ra_svn_conn_t *conn, apr_pool_t *pool, ab.server = b; ab.conn = conn; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c?(?w)", &path, &depth_word)); + SVN_ERR(svn_ra_svn__parse_tuple(params, "c?(?w)", &path, &depth_word)); depth = depth_word ? svn_depth_from_word(depth_word) : svn_depth_infinity; if ((depth != svn_depth_empty) && @@ -3213,14 +3416,17 @@ static svn_error_t *replay_one_revision(svn_ra_svn_conn_t *conn, return svn_ra_svn__write_cmd_finish_replay(conn, pool); } -static svn_error_t *replay(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) +static svn_error_t * +replay(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { svn_revnum_t rev, low_water_mark; svn_boolean_t send_deltas; server_baton_t *b = baton; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "rrb", &rev, &low_water_mark, + SVN_ERR(svn_ra_svn__parse_tuple(params, "rrb", &rev, &low_water_mark, &send_deltas)); SVN_ERR(trivial_auth_request(conn, pool, b)); @@ -3233,8 +3439,11 @@ static svn_error_t *replay(svn_ra_svn_conn_t *conn, apr_pool_t *pool, return SVN_NO_ERROR; } -static svn_error_t *replay_range(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, void *baton) +static svn_error_t * +replay_range(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) { svn_revnum_t start_rev, end_rev, rev, low_water_mark; svn_boolean_t send_deltas; @@ -3245,7 +3454,7 @@ static svn_error_t *replay_range(svn_ra_svn_conn_t *conn, apr_pool_t *pool, ab.server = b; ab.conn = conn; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "rrrb", &start_rev, + SVN_ERR(svn_ra_svn__parse_tuple(params, "rrrb", &start_rev, &end_rev, &low_water_mark, &send_deltas)); @@ -3281,7 +3490,7 @@ static svn_error_t *replay_range(svn_ra_svn_conn_t *conn, apr_pool_t *pool, static svn_error_t * get_deleted_rev(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, + svn_ra_svn__list_t *params, void *baton) { server_baton_t *b = baton; @@ -3290,7 +3499,7 @@ get_deleted_rev(svn_ra_svn_conn_t *conn, svn_revnum_t end_revision; svn_revnum_t revision_deleted; - SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "crr", + SVN_ERR(svn_ra_svn__parse_tuple(params, "crr", &path, &peg_revision, &end_revision)); full_path = svn_fspath__join(b->repository->fs_path->data, svn_relpath_canonicalize(path, pool), pool); @@ -3305,7 +3514,7 @@ get_deleted_rev(svn_ra_svn_conn_t *conn, static svn_error_t * get_inherited_props(svn_ra_svn_conn_t *conn, apr_pool_t *pool, - apr_array_header_t *params, + svn_ra_svn__list_t *params, void *baton) { server_baton_t *b = baton; @@ -3316,12 +3525,13 @@ get_inherited_props(svn_ra_svn_conn_t *conn, int i; apr_pool_t *iterpool = svn_pool_create(pool); authz_baton_t ab; + svn_node_kind_t node_kind; ab.server = b; ab.conn = conn; /* Parse arguments. */ - SVN_ERR(svn_ra_svn__parse_tuple(params, iterpool, "c(?r)", &path, &rev)); + SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)", &path, &rev)); full_path = svn_fspath__join(b->repository->fs_path->data, svn_relpath_canonicalize(path, iterpool), @@ -3331,15 +3541,18 @@ get_inherited_props(svn_ra_svn_conn_t *conn, SVN_ERR(must_have_access(conn, iterpool, b, svn_authz_read, full_path, FALSE)); - if (!SVN_IS_VALID_REVNUM(rev)) - SVN_CMD_ERR(svn_fs_youngest_rev(&rev, b->repository->fs, pool)); - SVN_ERR(log_command(b, conn, pool, "%s", svn_log__get_inherited_props(full_path, rev, iterpool))); /* Fetch the properties and a stream for the contents. */ SVN_CMD_ERR(svn_fs_revision_root(&root, b->repository->fs, rev, iterpool)); + SVN_CMD_ERR(svn_fs_check_path(&node_kind, root, full_path, pool)); + if (node_kind == svn_node_none) + { + SVN_CMD_ERR(svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL, + _("'%s' path not found"), full_path)); + } SVN_CMD_ERR(get_props(NULL, &inherited_props, &ab, root, full_path, pool)); /* Send successful command response with revision and props. */ @@ -3365,7 +3578,115 @@ get_inherited_props(svn_ra_svn_conn_t *conn, return SVN_NO_ERROR; } -static const svn_ra_svn_cmd_entry_t main_commands[] = { +/* Baton type to be used with list_receiver. */ +typedef struct list_receiver_baton_t +{ + /* Send the data through this connection. */ + svn_ra_svn_conn_t *conn; + + /* Send the field selected by these flags. */ + apr_uint32_t dirent_fields; +} list_receiver_baton_t; + +/* Implements svn_repos_dirent_receiver_t, sending DIRENT and PATH to the + * client. BATON must be a list_receiver_baton_t. */ +static svn_error_t * +list_receiver(const char *path, + svn_dirent_t *dirent, + void *baton, + apr_pool_t *pool) +{ + list_receiver_baton_t *b = baton; + return svn_error_trace(svn_ra_svn__write_dirent(b->conn, pool, path, dirent, + b->dirent_fields)); +} + +static svn_error_t * +list(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn__list_t *params, + void *baton) +{ + server_baton_t *b = baton; + const char *path, *full_path; + svn_revnum_t rev; + svn_depth_t depth; + apr_array_header_t *patterns = NULL; + svn_fs_root_t *root; + const char *depth_word; + svn_boolean_t path_info_only; + svn_ra_svn__list_t *dirent_fields_list = NULL; + svn_ra_svn__list_t *patterns_list = NULL; + int i; + list_receiver_baton_t rb; + svn_error_t *err, *write_err; + + authz_baton_t ab; + ab.server = b; + ab.conn = conn; + + /* Read the command parameters. */ + SVN_ERR(svn_ra_svn__parse_tuple(params, "c(?r)w?l?l", &path, &rev, + &depth_word, &dirent_fields_list, + &patterns_list)); + + rb.conn = conn; + SVN_ERR(parse_dirent_fields(&rb.dirent_fields, dirent_fields_list)); + + depth = svn_depth_from_word(depth_word); + full_path = svn_fspath__join(b->repository->fs_path->data, + svn_relpath_canonicalize(path, pool), pool); + + /* Read the patterns list. */ + if (patterns_list) + { + patterns = apr_array_make(pool, 0, sizeof(const char *)); + for (i = 0; i < patterns_list->nelts; ++i) + { + svn_ra_svn__item_t *elt = &SVN_RA_SVN__LIST_ITEM(patterns_list, i); + + if (elt->kind != SVN_RA_SVN_STRING) + return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, + "Pattern field not a string"); + + APR_ARRAY_PUSH(patterns, const char *) = elt->u.string.data; + } + } + + /* Check authorizations */ + SVN_ERR(must_have_access(conn, pool, b, svn_authz_read, + full_path, FALSE)); + + if (!SVN_IS_VALID_REVNUM(rev)) + SVN_CMD_ERR(svn_fs_youngest_rev(&rev, b->repository->fs, pool)); + + SVN_ERR(log_command(b, conn, pool, "%s", + svn_log__list(full_path, rev, patterns, depth, + rb.dirent_fields, pool))); + + /* Fetch the root of the appropriate revision. */ + SVN_CMD_ERR(svn_fs_revision_root(&root, b->repository->fs, rev, pool)); + + /* Fetch the directory entries if requested and send them immediately. */ + path_info_only = (rb.dirent_fields & ~SVN_DIRENT_KIND) == 0; + err = svn_repos_list(root, full_path, patterns, depth, path_info_only, + authz_check_access_cb_func(b), &ab, list_receiver, + &rb, NULL, NULL, pool); + + + /* Finish response. */ + write_err = svn_ra_svn__write_word(conn, pool, "done"); + if (write_err) + { + svn_error_clear(err); + return write_err; + } + SVN_CMD_ERR(err); + + return svn_error_trace(svn_ra_svn__write_cmd_response(conn, pool, "")); +} + +static const svn_ra_svn__cmd_entry_t main_commands[] = { { "reparent", reparent }, { "get-latest-rev", get_latest_rev }, { "get-dated-rev", get_dated_rev }, @@ -3397,6 +3718,7 @@ static const svn_ra_svn_cmd_entry_t main_commands[] = { { "replay-range", replay_range }, { "get-deleted-rev", get_deleted_rev }, { "get-iprops", get_inherited_props }, + { "list", list }, { NULL } }; @@ -3457,8 +3779,7 @@ repos_path_valid(const char *path) * and fs_path fields of REPOSITORY. VHOST and READ_ONLY flags are the * same as in the server baton. * - * CONFIG_POOL and AUTHZ_POOL shall be used to load any object of the - * respective type. + * CONFIG_POOL shall be used to load config objects. * * Use SCRATCH_POOL for temporary allocations. * @@ -3471,13 +3792,13 @@ find_repos(const char *url, svn_config_t *cfg, repository_t *repository, svn_repos__config_pool_t *config_pool, - svn_repos__authz_pool_t *authz_pool, apr_hash_t *fs_config, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { const char *path, *full_path, *fs_path, *hooks_env; svn_stringbuf_t *url_buf; + svn_boolean_t sasl_requested; /* Skip past the scheme and authority part. */ path = skip_scheme_part(url); @@ -3540,25 +3861,27 @@ find_repos(const char *url, { repository->base = svn_repos_conf_dir(repository->repos, result_pool); - SVN_ERR(svn_repos__config_pool_get(&cfg, NULL, config_pool, + SVN_ERR(svn_repos__config_pool_get(&cfg, config_pool, svn_repos_svnserve_conf (repository->repos, result_pool), - FALSE, FALSE, repository->repos, + FALSE, repository->repos, result_pool)); } SVN_ERR(load_pwdb_config(repository, cfg, config_pool, result_pool)); SVN_ERR(load_authz_config(repository, repository->repos_root, cfg, - authz_pool, result_pool)); + result_pool)); -#ifdef SVN_HAVE_SASL + /* Should we use Cyrus SASL? */ + SVN_ERR(svn_config_get_bool(cfg, &sasl_requested, + SVN_CONFIG_SECTION_SASL, + SVN_CONFIG_OPTION_USE_SASL, FALSE)); + if (sasl_requested) { +#ifdef SVN_HAVE_SASL const char *val; - /* Should we use Cyrus SASL? */ - SVN_ERR(svn_config_get_bool(cfg, &repository->use_sasl, - SVN_CONFIG_SECTION_SASL, - SVN_CONFIG_OPTION_USE_SASL, FALSE)); + repository->use_sasl = sasl_requested; svn_config_get(cfg, &val, SVN_CONFIG_SECTION_SASL, SVN_CONFIG_OPTION_MIN_SSF, "0"); @@ -3567,8 +3890,18 @@ find_repos(const char *url, svn_config_get(cfg, &val, SVN_CONFIG_SECTION_SASL, SVN_CONFIG_OPTION_MAX_SSF, "256"); SVN_ERR(svn_cstring_atoui(&repository->max_ssf, val)); +#else /* !SVN_HAVE_SASL */ + return svn_error_createf(SVN_ERR_BAD_CONFIG_VALUE, NULL, + _("SASL requested but not compiled in; " + "set '%s' to 'false' or recompile " + "svnserve with SASL support"), + SVN_CONFIG_OPTION_USE_SASL); +#endif /* SVN_HAVE_SASL */ + } + else + { + repository->use_sasl = FALSE; } -#endif /* Use the repository UUID as the default realm. */ SVN_ERR(svn_fs_get_uuid(repository->fs, &repository->realm, scratch_pool)); @@ -3771,7 +4104,7 @@ construct_server_baton(server_baton_t **baton, svn_error_t *err, *io_err; apr_uint64_t ver; const char *client_url, *ra_client_string, *client_string; - apr_array_header_t *caplist; + svn_ra_svn__list_t *caplist; apr_pool_t *conn_pool = svn_ra_svn__get_pool(conn); server_baton_t *b = apr_pcalloc(conn_pool, sizeof(*b)); fs_warning_baton_t *warn_baton; @@ -3796,10 +4129,11 @@ construct_server_baton(server_baton_t **baton, * send an empty mechlist. */ if (params->compression_level > 0) SVN_ERR(svn_ra_svn__write_cmd_response(conn, scratch_pool, - "nn()(wwwwwwwwwww)", + "nn()(wwwwwwwwwwwww)", (apr_uint64_t) 2, (apr_uint64_t) 2, SVN_RA_SVN_CAP_EDIT_PIPELINE, SVN_RA_SVN_CAP_SVNDIFF1, + SVN_RA_SVN_CAP_SVNDIFF2_ACCEPTED, SVN_RA_SVN_CAP_ABSENT_ENTRIES, SVN_RA_SVN_CAP_COMMIT_REVPROPS, SVN_RA_SVN_CAP_DEPTH, @@ -3808,11 +4142,12 @@ construct_server_baton(server_baton_t **baton, SVN_RA_SVN_CAP_PARTIAL_REPLAY, SVN_RA_SVN_CAP_INHERITED_PROPS, SVN_RA_SVN_CAP_EPHEMERAL_TXNPROPS, - SVN_RA_SVN_CAP_GET_FILE_REVS_REVERSE + SVN_RA_SVN_CAP_GET_FILE_REVS_REVERSE, + SVN_RA_SVN_CAP_LIST )); else SVN_ERR(svn_ra_svn__write_cmd_response(conn, scratch_pool, - "nn()(wwwwwwwwww)", + "nn()(wwwwwwwwwww)", (apr_uint64_t) 2, (apr_uint64_t) 2, SVN_RA_SVN_CAP_EDIT_PIPELINE, SVN_RA_SVN_CAP_ABSENT_ENTRIES, @@ -3823,7 +4158,8 @@ construct_server_baton(server_baton_t **baton, SVN_RA_SVN_CAP_PARTIAL_REPLAY, SVN_RA_SVN_CAP_INHERITED_PROPS, SVN_RA_SVN_CAP_EPHEMERAL_TXNPROPS, - SVN_RA_SVN_CAP_GET_FILE_REVS_REVERSE + SVN_RA_SVN_CAP_GET_FILE_REVS_REVERSE, + SVN_RA_SVN_CAP_LIST )); /* Read client response, which we assume to be in version 2 format: @@ -3837,7 +4173,7 @@ construct_server_baton(server_baton_t **baton, return SVN_NO_ERROR; client_url = svn_uri_canonicalize(client_url, conn_pool); - SVN_ERR(svn_ra_svn_set_capabilities(conn, caplist)); + SVN_ERR(svn_ra_svn__set_capabilities(conn, caplist)); /* All released versions of Subversion support edit-pipeline, * so we do not accept connections from clients that do not. */ @@ -3848,22 +4184,25 @@ construct_server_baton(server_baton_t **baton, they get handed to the start-commit hook). While we could add a new interface to re-retrieve them from conn and convert the result to a list, it's simpler to just convert caplist by hand - here, since we already have it and turning 'svn_ra_svn_item_t's + here, since we already have it and turning 'svn_ra_svn__item_t's into 'const char *'s is pretty easy. We only record capabilities we care about. The client may report more (because it doesn't know what the server cares about). */ { int i; - svn_ra_svn_item_t *item; + svn_ra_svn__item_t *item; b->repository->capabilities = apr_array_make(conn_pool, 1, sizeof(const char *)); for (i = 0; i < caplist->nelts; i++) { - item = &APR_ARRAY_IDX(caplist, i, svn_ra_svn_item_t); + static const svn_string_t str_cap_mergeinfo + = SVN__STATIC_STRING(SVN_RA_SVN_CAP_MERGEINFO); + + item = &SVN_RA_SVN__LIST_ITEM(caplist, i); /* ra_svn_set_capabilities() already type-checked for us */ - if (strcmp(item->u.word, SVN_RA_SVN_CAP_MERGEINFO) == 0) + if (svn_string_compare(&item->u.word, &str_cap_mergeinfo)) { APR_ARRAY_PUSH(b->repository->capabilities, const char *) = SVN_RA_CAPABILITY_MERGEINFO; @@ -3871,14 +4210,14 @@ construct_server_baton(server_baton_t **baton, /* Save for operational log. */ if (cap_log->len > 0) svn_stringbuf_appendcstr(cap_log, " "); - svn_stringbuf_appendcstr(cap_log, item->u.word); + svn_stringbuf_appendcstr(cap_log, item->u.word.data); } } err = handle_config_error(find_repos(client_url, params->root, b->vhost, b->read_only, params->cfg, b->repository, params->config_pool, - params->authz_pool, params->fs_config, + params->fs_config, conn_pool, scratch_pool), b); if (!err) @@ -3980,7 +4319,7 @@ serve_interruptable(svn_boolean_t *terminate_p, { svn_boolean_t terminate = FALSE; svn_error_t *err = NULL; - const svn_ra_svn_cmd_entry_t *command; + const svn_ra_svn__cmd_entry_t *command; apr_pool_t *iterpool = svn_pool_create(pool); /* Prepare command parser. */ @@ -4009,10 +4348,12 @@ serve_interruptable(svn_boolean_t *terminate_p, /* create the connection, configure ports etc. */ connection->conn - = svn_ra_svn_create_conn4(connection->usock, NULL, NULL, + = svn_ra_svn_create_conn5(connection->usock, NULL, NULL, connection->params->compression_level, connection->params->zero_copy_limit, connection->params->error_check_interval, + connection->params->max_request_size, + connection->params->max_response_size, connection->pool); /* Construct server baton and open the repository for the first time. */ diff --git a/subversion/svnserve/server.h b/subversion/svnserve/server.h index d366e0cd4c6e..c26a76a1aae2 100644 --- a/subversion/svnserve/server.h +++ b/subversion/svnserve/server.h @@ -65,8 +65,10 @@ typedef struct repository_t { enum username_case_type username_case; /* Case-normalize the username? */ svn_boolean_t use_sasl; /* Use Cyrus SASL for authentication; always false if SVN_HAVE_SASL not defined */ +#ifdef SVN_HAVE_SASL unsigned min_ssf; /* min-encryption SASL parameter */ unsigned max_ssf; /* max-encryption SASL parameter */ +#endif enum access_type auth_access; /* access granted to authenticated users */ enum access_type anon_access; /* access granted to annonymous users */ @@ -125,9 +127,6 @@ typedef struct serve_params_t { /* all configurations should be opened through this factory */ svn_repos__config_pool_t *config_pool; - /* all authz data should be opened through this factory */ - svn_repos__authz_pool_t *authz_pool; - /* The FS configuration to be applied to all repositories. It mainly contains things like cache settings. */ apr_hash_t *fs_config; @@ -152,6 +151,12 @@ typedef struct serve_params_t { coming in from the client. */ apr_size_t error_check_interval; + /* If not 0, error out on requests exceeding this value. */ + apr_uint64_t max_request_size; + + /* If not 0, stop sending a response once it exceeds this value. */ + apr_uint64_t max_response_size; + /* Use virtual-host-based path to repo. */ svn_boolean_t vhost; } serve_params_t; diff --git a/subversion/svnserve/svnserve.c b/subversion/svnserve/svnserve.c index f3a483dbd920..b4ad64fdbf67 100644 --- a/subversion/svnserve/svnserve.c +++ b/subversion/svnserve/svnserve.c @@ -155,6 +155,15 @@ enum run_mode { */ #define ACCEPT_BACKLOG 128 +/* Default limit to the client request size in MBytes. This effectively + * limits the size of a paths and individual property values to about + * this value. + * + * Note that (MAX_REQUEST_SIZE + 4M) * THREADPOOL_MAX_SIZE is roughly + * the peak memory usage of the RA layer. + */ +#define MAX_REQUEST_SIZE 16 + #ifdef WIN32 static apr_os_sock_t winservice_svnserve_accept_socket = INVALID_SOCKET; @@ -210,6 +219,20 @@ void winservice_notify_stop(void) #define SVNSERVE_OPT_MIN_THREADS 271 #define SVNSERVE_OPT_MAX_THREADS 272 #define SVNSERVE_OPT_BLOCK_READ 273 +#define SVNSERVE_OPT_MAX_REQUEST 274 +#define SVNSERVE_OPT_MAX_RESPONSE 275 +#define SVNSERVE_OPT_CACHE_NODEPROPS 276 + +/* Text macro because we can't use #ifdef sections inside a N_("...") + macro expansion. */ +#ifdef CONNECTION_HAVE_THREAD_OPTION +#define ONLY_AVAILABLE_WITH_THEADS \ + "\n" \ + " "\ + "[used only with --threads]" +#else +#define ONLY_AVAILABLE_WITH_THEADS "" +#endif static const apr_getopt_option_t svnserve__options[] = { @@ -296,6 +319,12 @@ static const apr_getopt_option_t svnserve__options[] = "Default is no.\n" " " "[used for FSFS and FSX repositories only]")}, + {"cache-nodeprops", SVNSERVE_OPT_CACHE_NODEPROPS, 1, + N_("enable or disable caching of node properties\n" + " " + "Default is yes.\n" + " " + "[used for FSFS repositories only]")}, {"client-speed", SVNSERVE_OPT_CLIENT_SPEED, 1, N_("Optimize network handling based on the assumption\n" " " @@ -317,34 +346,46 @@ static const apr_getopt_option_t svnserve__options[] = * ### this option never exists when --service exists. */ {"threads", 'T', 0, N_("use threads instead of fork " "[mode: daemon]")}, +#endif +#if APR_HAS_THREADS {"min-threads", SVNSERVE_OPT_MIN_THREADS, 1, N_("Minimum number of server threads, even if idle.\n" " " "Capped to max-threads; minimum value is 0.\n" " " - "Default is 1.\n" - " " - "[used only with --threads]")}, -#if (APR_SIZEOF_VOIDP <= 4) + "Default is 1." + ONLY_AVAILABLE_WITH_THEADS)}, {"max-threads", SVNSERVE_OPT_MAX_THREADS, 1, N_("Maximum number of server threads, even if there\n" " " "are more connections. Minimum value is 1.\n" " " - "Default is 64.\n" - " " - "[used only with --threads]")}, -#else - {"max-threads", SVNSERVE_OPT_MAX_THREADS, 1, - N_("Maximum number of server threads, even if there\n" - " " - "are more connections. Minimum value is 1.\n" - " " - "Default is 256.\n" - " " - "[used only with --threads]")}, -#endif + "Default is " APR_STRINGIFY(THREADPOOL_MAX_SIZE) "." + ONLY_AVAILABLE_WITH_THEADS)}, #endif + {"max-request-size", SVNSERVE_OPT_MAX_REQUEST, 1, + N_("Maximum acceptable size of a client request in MB.\n" + " " + "This implicitly limits the length of paths and\n" + " " + "property values that can be sent to the server.\n" + " " + "Also the peak memory usage for protocol handling\n" + " " + "per server thread or sub-process.\n" + " " + "0 disables the size check; default is " + APR_STRINGIFY(MAX_REQUEST_SIZE) ".")}, + {"max-response-size", SVNSERVE_OPT_MAX_RESPONSE, 1, + N_("Maximum acceptable server response size in MB.\n" + " " + "Longer responses get truncated and return an\n" + " " + "error. This limits the server load e.g. when\n" + " " + "checking out at the wrong path level.\n" + " " + "Default is 0 (disabled).")}, {"foreground", SVNSERVE_OPT_FOREGROUND, 0, N_("run in foreground (useful for debugging)\n" " " @@ -680,6 +721,7 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) svn_boolean_t is_multi_threaded; enum connection_handling_mode handling_mode = CONNECTION_DEFAULT; svn_boolean_t cache_fulltexts = TRUE; + svn_boolean_t cache_nodeprops = TRUE; svn_boolean_t cache_txdeltas = TRUE; svn_boolean_t cache_revprops = FALSE; svn_boolean_t use_block_read = FALSE; @@ -710,6 +752,9 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) /* Initialize the FS library. */ SVN_ERR(svn_fs_initialize(pool)); + /* Initialize the efficient Authz support. */ + SVN_ERR(svn_repos_authz_initialize(pool)); + SVN_ERR(svn_cmdline__getopt_init(&os, argc, argv, pool)); params.root = "/"; @@ -721,13 +766,14 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) params.compression_level = SVN_DELTA_COMPRESSION_LEVEL_DEFAULT; params.logger = NULL; params.config_pool = NULL; - params.authz_pool = NULL; params.fs_config = NULL; params.vhost = FALSE; params.username_case = CASE_ASIS; params.memory_cache_size = (apr_uint64_t)-1; params.zero_copy_limit = 0; params.error_check_interval = 4096; + params.max_request_size = MAX_REQUEST_SIZE * 0x100000; + params.max_response_size = 0; while (1) { @@ -855,7 +901,12 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) break; case 'M': - params.memory_cache_size = 0x100000 * apr_strtoi64(arg, NULL, 0); + { + apr_uint64_t sz_val; + SVN_ERR(svn_cstring_atoui64(&sz_val, arg)); + + params.memory_cache_size = 0x100000 * sz_val; + } break; case SVNSERVE_OPT_CACHE_TXDELTAS: @@ -870,6 +921,10 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) cache_revprops = svn_tristate__from_word(arg) == svn_tristate_true; break; + case SVNSERVE_OPT_CACHE_NODEPROPS: + cache_nodeprops = svn_tristate__from_word(arg) == svn_tristate_true; + break; + case SVNSERVE_OPT_BLOCK_READ: use_block_read = svn_tristate__from_word(arg) == svn_tristate_true; break; @@ -891,6 +946,14 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) } break; + case SVNSERVE_OPT_MAX_REQUEST: + params.max_request_size = 0x100000 * apr_strtoi64(arg, NULL, 0); + break; + + case SVNSERVE_OPT_MAX_RESPONSE: + params.max_response_size = 0x100000 * apr_strtoi64(arg, NULL, 0); + break; + case SVNSERVE_OPT_MIN_THREADS: min_thread_count = (apr_size_t)apr_strtoi64(arg, NULL, 0); break; @@ -980,6 +1043,8 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) cache_txdeltas ? "1" :"0"); svn_hash_sets(params.fs_config, SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS, cache_fulltexts ? "1" :"0"); + svn_hash_sets(params.fs_config, SVN_FS_CONFIG_FSFS_CACHE_NODEPROPS, + cache_nodeprops ? "1" :"0"); svn_hash_sets(params.fs_config, SVN_FS_CONFIG_FSFS_CACHE_REVPROPS, cache_revprops ? "2" :"0"); svn_hash_sets(params.fs_config, SVN_FS_CONFIG_FSFS_BLOCK_READ, @@ -988,10 +1053,6 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) SVN_ERR(svn_repos__config_pool_create(¶ms.config_pool, is_multi_threaded, pool)); - SVN_ERR(svn_repos__authz_pool_create(¶ms.authz_pool, - params.config_pool, - is_multi_threaded, - pool)); /* If a configuration file is specified, load it and any referenced * password and authorization files. */ @@ -999,11 +1060,10 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) { params.base = svn_dirent_dirname(config_filename, pool); - SVN_ERR(svn_repos__config_pool_get(¶ms.cfg, NULL, + SVN_ERR(svn_repos__config_pool_get(¶ms.cfg, params.config_pool, config_filename, TRUE, /* must_exist */ - FALSE, /* names_case_sensitive */ NULL, pool)); } @@ -1030,17 +1090,21 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) apr_pool_cleanup_register(pool, pool, apr_pool_cleanup_null, redirect_stdout); - SVN_ERR(svn_stream_for_stdin(&stdin_stream, pool)); + /* We are an interactive server, i.e. can't use APR buffering on + * stdin. */ + SVN_ERR(svn_stream_for_stdin2(&stdin_stream, FALSE, pool)); SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool)); /* Use a subpool for the connection to ensure that if SASL is used * the pool cleanup handlers that call sasl_dispose() (connection_pool) * and sasl_done() (pool) are run in the right order. See issue #3664. */ connection_pool = svn_pool_create(pool); - conn = svn_ra_svn_create_conn4(NULL, stdin_stream, stdout_stream, + conn = svn_ra_svn_create_conn5(NULL, stdin_stream, stdout_stream, params.compression_level, params.zero_copy_limit, params.error_check_interval, + params.max_request_size, + params.max_response_size, connection_pool); err = serve(conn, ¶ms, connection_pool); svn_pool_destroy(connection_pool); diff --git a/subversion/svnsync/svnsync.c b/subversion/svnsync/svnsync.c index 6dde1f108866..9f50897273a4 100644 --- a/subversion/svnsync/svnsync.c +++ b/subversion/svnsync/svnsync.c @@ -43,7 +43,6 @@ #include "svn_private_config.h" -#include #include static svn_opt_subcommand_t initialize_cmd, @@ -71,6 +70,7 @@ enum svnsync__opt { svnsync_opt_trust_server_cert_failures_src, svnsync_opt_trust_server_cert_failures_dst, svnsync_opt_allow_non_empty, + svnsync_opt_skip_unchanged, svnsync_opt_steal_lock }; @@ -148,9 +148,14 @@ static const svn_opt_subcommand_desc2_t svnsync_cmd_table[] = "if untrusted users/administrators may have write access to the\n" "DEST_URL repository.\n" "\n" + "Unless you need to trigger the destination repositoy's revprop\n" + "change hooks for all revision properties, it is recommended to use\n" + "the --skip-unchanged option for best performance.\n" + "\n" "Form 2 is deprecated syntax, equivalent to specifying \"-rREV[:REV2]\".\n"), { SVNSYNC_OPTS_DEFAULT, svnsync_opt_source_prop_encoding, 'q', 'r', - svnsync_opt_disable_locking, svnsync_opt_steal_lock, 'M' } }, + svnsync_opt_disable_locking, svnsync_opt_steal_lock, + svnsync_opt_skip_unchanged, 'M' } }, { "info", info_cmd, { 0 }, N_("usage: svnsync info DEST_URL\n" "\n" @@ -179,6 +184,8 @@ static const apr_getopt_option_t svnsync_options[] = " 'HEAD' latest in repository") }, {"allow-non-empty", svnsync_opt_allow_non_empty, 0, N_("allow a non-empty destination repository") }, + {"skip-unchanged", svnsync_opt_skip_unchanged, 0, + N_("don't copy unchanged revision properties") }, {"non-interactive", svnsync_opt_non_interactive, 0, N_("do no interactive prompting (default is to prompt\n" " " @@ -303,6 +310,7 @@ typedef struct opt_baton_t { svn_boolean_t steal_lock; svn_boolean_t quiet; svn_boolean_t allow_non_empty; + svn_boolean_t skip_unchanged; svn_boolean_t version; svn_boolean_t help; svn_opt_revision_t start_rev; @@ -315,29 +323,8 @@ typedef struct opt_baton_t { /*** Helper functions ***/ -/* Global record of whether the user has requested cancellation. */ -static volatile sig_atomic_t cancelled = FALSE; - - -/* Callback function for apr_signal(). */ -static void -signal_handler(int signum) -{ - apr_signal(signum, SIG_IGN); - cancelled = TRUE; -} - - /* Cancellation callback function. */ -static svn_error_t * -check_cancel(void *baton) -{ - if (cancelled) - return svn_error_create(SVN_ERR_CANCELLED, NULL, _("Caught signal")); - else - return SVN_NO_ERROR; -} - +static svn_cancel_func_t check_cancel = 0; /* Check that the version of libraries in use match what we expect. */ static svn_error_t * @@ -422,6 +409,7 @@ typedef struct subcommand_baton_t { svn_ra_callbacks2_t sync_callbacks; svn_boolean_t quiet; svn_boolean_t allow_non_empty; + svn_boolean_t skip_unchanged; /* Enable optimization for revprop changes. */ const char *to_url; /* initialize, synchronize, and copy-revprops only */ @@ -592,6 +580,10 @@ filter_props(int *filtered_count, apr_hash_t *props, * and set *FILTERED_COUNT to the number of properties thus omitted. * REV_PROPS is a hash mapping (char *)propname to (svn_string_t *)propval. * + * If OLD_REV_PROPS is not NULL, skip all properties that did not change. + * Note that this implies that hook scripts won't be triggered anymore for + * those revprops that did not change. + * * All allocations will be done in a subpool of POOL. */ static svn_error_t * @@ -599,6 +591,7 @@ write_revprops(int *filtered_count, svn_ra_session_t *session, svn_revnum_t rev, apr_hash_t *rev_props, + apr_hash_t *old_rev_props, apr_pool_t *pool) { apr_pool_t *subpool = svn_pool_create(pool); @@ -616,6 +609,17 @@ write_revprops(int *filtered_count, if (strncmp(propname, SVNSYNC_PROP_PREFIX, sizeof(SVNSYNC_PROP_PREFIX) - 1) != 0) { + if (old_rev_props) + { + /* Skip the RA call for any no-op propset. */ + const svn_string_t *old_value = svn_hash_gets(old_rev_props, + propname); + if ((!old_value && !propval) + || (old_value && propval + && svn_string_compare(old_value, propval))) + continue; + } + SVN_ERR(svn_ra_change_rev_prop2(session, rev, propname, NULL, propval, subpool)); } @@ -677,6 +681,10 @@ log_properties_normalized(int normalized_rev_props_count, * If SYNC is TRUE, then properties on the destination revision that * do not exist on the source revision will be removed. * + * If SKIP_UNCHANGED is TRUE, skip any no-op revprop changes. This also + * prevents hook scripts from firing for those unchanged revprops. Has + * no effect if SYNC is FALSE. + * * If QUIET is FALSE, then log_properties_copied() is called to log that * properties were copied for revision REV. * @@ -689,6 +697,7 @@ copy_revprops(svn_ra_session_t *from_session, svn_ra_session_t *to_session, svn_revnum_t rev, svn_boolean_t sync, + svn_boolean_t skip_unchanged, svn_boolean_t quiet, const char *source_prop_encoding, int *normalized_count, @@ -714,7 +723,8 @@ copy_revprops(svn_ra_session_t *from_session, source_prop_encoding, pool)); /* Copy all but the svn:svnsync properties. */ - SVN_ERR(write_revprops(&filtered_count, to_session, rev, rev_props, pool)); + SVN_ERR(write_revprops(&filtered_count, to_session, rev, rev_props, + skip_unchanged ? existing_props : NULL, pool)); /* Delete those properties that were in TARGET but not in SOURCE */ if (sync) @@ -750,6 +760,7 @@ make_subcommand_baton(opt_baton_t *opt_baton, b->sync_callbacks.open_tmp_file = open_tmp_file; b->sync_callbacks.auth_baton = opt_baton->sync_auth_baton; b->quiet = opt_baton->quiet; + b->skip_unchanged = opt_baton->skip_unchanged; b->allow_non_empty = opt_baton->allow_non_empty; b->to_url = to_url; b->source_prop_encoding = opt_baton->source_prop_encoding; @@ -859,9 +870,9 @@ do_initialize(svn_ra_session_t *to_session, LATEST is not 0, this really serves merely aesthetic and informational purposes, keeping the output of this command consistent while allowing folks to see what the latest revision is. */ - SVN_ERR(copy_revprops(from_session, to_session, latest, FALSE, baton->quiet, - baton->source_prop_encoding, &normalized_rev_props_count, - pool)); + SVN_ERR(copy_revprops(from_session, to_session, latest, FALSE, FALSE, + baton->quiet, baton->source_prop_encoding, + &normalized_rev_props_count, pool)); SVN_ERR(log_properties_normalized(normalized_rev_props_count, 0, pool)); @@ -1372,7 +1383,7 @@ replay_rev_finished(svn_revnum_t revision, rb->normalized_rev_props_count += normalized_count; SVN_ERR(write_revprops(&filtered_count, rb->to_session, revision, filtered, - subpool)); + NULL, subpool)); /* Remove all extra properties in TARGET. */ SVN_ERR(remove_props_not_in_source(rb->to_session, revision, @@ -1478,7 +1489,8 @@ do_synchronize(svn_ra_session_t *to_session, if (copying > last_merged) { SVN_ERR(copy_revprops(from_session, to_session, to_latest, TRUE, - baton->quiet, baton->source_prop_encoding, + baton->skip_unchanged, baton->quiet, + baton->source_prop_encoding, &normalized_rev_props_count, pool)); last_merged = copying; last_merged_rev = svn_string_create @@ -1515,7 +1527,7 @@ do_synchronize(svn_ra_session_t *to_session, /* Now check to see if there are any revisions to copy. */ SVN_ERR(svn_ra_get_latest_revnum(from_session, &from_latest, pool)); - if (from_latest < last_merged) + if (from_latest <= last_merged) return SVN_NO_ERROR; /* Ok, so there are new revisions, iterate over them copying them @@ -1649,7 +1661,8 @@ do_copy_revprops(svn_ra_session_t *to_session, { int normalized_count; SVN_ERR(check_cancel(NULL)); - SVN_ERR(copy_revprops(from_session, to_session, i, TRUE, baton->quiet, + SVN_ERR(copy_revprops(from_session, to_session, i, TRUE, + baton->skip_unchanged, baton->quiet, baton->source_prop_encoding, &normalized_count, pool)); normalized_rev_props_count += normalized_count; @@ -1757,12 +1770,12 @@ copy_revprops_cmd(apr_getopt_t *os, void *b, apr_pool_t *pool) the source URL. */ if (os->argc - os->ind == 2) { - const char *arg_str = os->argv[os->argc - 1]; - const char *utf_arg_str; + const char *arg_str; - SVN_ERR(svn_utf_cstring_to_utf8(&utf_arg_str, arg_str, pool)); + SVN_ERR(svn_utf_cstring_to_utf8(&arg_str, os->argv[os->argc - 1], + pool)); - if (! svn_path_is_url(utf_arg_str)) + if (! svn_path_is_url(arg_str)) { /* This is the old "... TO_URL REV[:REV2]" syntax. Revisions come only from this argument. (We effectively @@ -2068,11 +2081,11 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) case svnsync_opt_config_dir: { - const char *path_utf8; - opt_err = svn_utf_cstring_to_utf8(&path_utf8, opt_arg, pool); + const char *path; + opt_err = svn_utf_cstring_to_utf8(&path, opt_arg, pool); if (!opt_err) - opt_baton.config_dir = svn_dirent_internal_style(path_utf8, pool); + opt_baton.config_dir = svn_dirent_internal_style(path, pool); } break; case svnsync_opt_config_options: @@ -2108,6 +2121,10 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) opt_baton.allow_non_empty = TRUE; break; + case svnsync_opt_skip_unchanged: + opt_baton.skip_unchanged = TRUE; + break; + case 'q': opt_baton.quiet = TRUE; break; @@ -2269,7 +2286,10 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) } else { - const char *first_arg = os->argv[os->ind++]; + const char *first_arg; + + SVN_ERR(svn_utf_cstring_to_utf8(&first_arg, os->argv[os->ind++], + pool)); subcommand = svn_opt_get_canonical_subcommand2(svnsync_cmd_table, first_arg); if (subcommand == NULL) @@ -2324,33 +2344,7 @@ sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool) opt_baton.source_prop_encoding = source_prop_encoding; - apr_signal(SIGINT, signal_handler); - -#ifdef SIGBREAK - /* SIGBREAK is a Win32 specific signal generated by ctrl-break. */ - apr_signal(SIGBREAK, signal_handler); -#endif - -#ifdef SIGHUP - apr_signal(SIGHUP, signal_handler); -#endif - -#ifdef SIGTERM - apr_signal(SIGTERM, signal_handler); -#endif - -#ifdef SIGPIPE - /* Disable SIGPIPE generation for the platforms that have it. */ - apr_signal(SIGPIPE, SIG_IGN); -#endif - -#ifdef SIGXFSZ - /* Disable SIGXFSZ generation for the platforms that have it, - otherwise working with large files when compiled against an APR - that doesn't have large file support will crash the program, - which is uncool. */ - apr_signal(SIGXFSZ, SIG_IGN); -#endif + check_cancel = svn_cmdline__setup_cancellation_handler(); err = svn_cmdline_create_auth_baton2( &opt_baton.source_auth_baton, @@ -2431,5 +2425,8 @@ main(int argc, const char *argv[]) } svn_pool_destroy(pool); + + svn_cmdline__cancellation_exit(); + return exit_code; } diff --git a/win-tests.py b/win-tests.py index 44ff110b15e7..5aaa37c80b40 100644 --- a/win-tests.py +++ b/win-tests.py @@ -24,14 +24,15 @@ Driver for running the tests on Windows. For a list of options, run this script with the --help option. """ -# $HeadURL: https://svn.apache.org/repos/asf/subversion/branches/1.9.x/win-tests.py $ -# $LastChangedRevision: 1718291 $ +# $HeadURL: https://svn.apache.org/repos/asf/subversion/branches/1.10.x/win-tests.py $ +# $LastChangedRevision: 1813897 $ import os, sys, subprocess import filecmp import shutil import traceback import logging +import re try: # Python >=3.0 import configparser @@ -83,6 +84,17 @@ def _usage_exit(): print(" --disable-http-v2 : Do not advertise support for HTTPv2 on server") print(" --disable-bulk-updates : Disable bulk updates on HTTP server") print(" --ssl-cert : Path to SSL server certificate to trust.") + print(" --https : Run Apache httpd with an https setup.") + print(" --http2 : Enable http2 in Apache Httpd (>= 2.4.17).") + print(" --mod-deflate : Enable mod_deflate in Apache Httpd.") + print(" --global-scheduler : Enable global scheduler.") + print(" --exclusive-wc-locks : Enable exclusive working copy locks") + print(" --memcached-dir=DIR : Run memcached from dir") + print(" --memcached-server= : Enable usage of the specified memcached server") + print(" ") + print(" --skip-c-tests : Skip all C tests") + print(" --dump-load-cross-check: Run the dump load cross check after every test") + print(" --javahl : Run the javahl tests instead of the normal tests") print(" --swig=language : Run the swig perl/python/ruby tests instead of") print(" the normal tests") @@ -101,6 +113,7 @@ def _usage_exit(): print(" --config-file : Configuration file for tests") print(" --fsfs-sharding : Specify shard size (for fsfs)") print(" --fsfs-packing : Run 'svnadmin pack' automatically") + print(" --fsfs-compression=VAL : Set compression type to VAL (for fsfs)") print(" -q, --quiet : Deprecated; this is the default.") print(" Use --set-log-level instead.") @@ -122,19 +135,24 @@ gen_obj = gen_win_dependencies.GenDependenciesBase('build.conf', version_header, opts, args = my_getopt(sys.argv[1:], 'hrdvqct:pu:f:', ['release', 'debug', 'verbose', 'quiet', 'cleanup', 'test=', 'url=', 'svnserve-args=', 'fs-type=', 'asp.net-hack', - 'httpd-dir=', 'httpd-port=', 'httpd-daemon', + 'httpd-dir=', 'httpd-port=', 'httpd-daemon', 'https', 'httpd-server', 'http-short-circuit', 'httpd-no-log', 'disable-http-v2', 'disable-bulk-updates', 'help', 'fsfs-packing', 'fsfs-sharding=', 'javahl', 'swig=', - 'list', 'enable-sasl', 'bin=', 'parallel', + 'list', 'enable-sasl', 'bin=', 'parallel', 'http2', + 'mod-deflate', 'global-scheduler', 'config-file=', 'server-minor-version=', 'log-level=', 'log-to-stdout', 'mode-filter=', 'milestone-filter=', - 'ssl-cert=']) + 'ssl-cert=', 'exclusive-wc-locks', 'memcached-server=', + 'skip-c-tests', 'dump-load-cross-check', 'memcached-dir=', + 'fsfs-compression=', + ]) if len(args) > 1: print('Warning: non-option arguments after the first one will be ignored') # Interpret the options and set parameters base_url, fs_type, verbose, cleanup = None, None, None, None +global_scheduler = None repo_loc = 'local repository.' objdir = 'Debug' log = 'tests.log' @@ -145,6 +163,9 @@ run_httpd = None httpd_port = None httpd_service = None httpd_no_log = None +use_ssl = False +use_http2 = False +use_mod_deflate = False http_short_circuit = False advertise_httpv2 = True http_bulk_updates = True @@ -164,6 +185,14 @@ mode_filter=None tests_to_run = [] log_level = None ssl_cert = None +exclusive_wc_locks = None +run_memcached = None +memcached_server = None +memcached_dir = None +skip_c_tests = None +dump_load_cross_check = None +fsfs_compression = None +fsfs_dir_deltification = None for opt, val in opts: if opt in ('-h', '--help'): @@ -199,6 +228,12 @@ for opt, val in opts: httpd_service = 1 elif opt == '--httpd-no-log': httpd_no_log = 1 + elif opt == '--https': + use_ssl = 1 + elif opt == '--http2': + use_http2 = 1 + elif opt == '--mod-deflate': + use_mod_deflate = 1 elif opt == '--http-short-circuit': http_short_circuit = True elif opt == '--disable-http-v2': @@ -211,6 +246,8 @@ for opt, val in opts: fsfs_packing = 1 elif opt == '--javahl': test_javahl = 1 + elif opt == '--global-scheduler': + global_scheduler = 1 elif opt == '--swig': if val not in ['perl', 'python', 'ruby']: sys.stderr.write('Running \'%s\' swig tests not supported (yet).\n' @@ -239,6 +276,21 @@ for opt, val in opts: log_level = getattr(logging, val, None) or int(val) elif opt == '--ssl-cert': ssl_cert = val + elif opt == '--exclusive-wc-locks': + exclusive_wc_locks = 1 + elif opt == '--memcached-server': + memcached_server = val + elif opt == '--skip-c-tests': + skip_c_tests = 1 + elif opt == '--dump-load-cross-check': + dump_load_cross_check = 1 + elif opt == '--memcached-dir': + memcached_dir = val + run_memcached = 1 + elif opt == '--fsfs-compression': + fsfs_compression = val + elif opt == '--fsfs-dir-deltification': + fsfs_dir_deltification = val # Calculate the source and test directory names abs_srcdir = os.path.abspath("") @@ -266,7 +318,12 @@ if run_httpd: if not httpd_port: httpd_port = random.randrange(1024, 30000) if not base_url: - base_url = 'http://localhost:' + str(httpd_port) + if use_ssl: + scheme = 'https' + else: + scheme = 'http' + + base_url = '%s://localhost:%d' % (scheme, httpd_port) if base_url: repo_loc = 'remote repository ' + base_url + '.' @@ -407,7 +464,9 @@ class Svnserve: args = [self.name] + self.args print('Starting %s %s' % (self.kind, self.name)) - self.proc = subprocess.Popen([self.path] + args[1:]) + env = os.environ.copy() + env['SVN_DBG_STACKTRACES_TO_STDERR'] = 'y' + self.proc = subprocess.Popen([self.path] + args[1:], env=env) def stop(self): if self.proc is not None: @@ -423,8 +482,9 @@ class Svnserve: class Httpd: "Run httpd for DAV tests" - def __init__(self, abs_httpd_dir, abs_objdir, abs_builddir, httpd_port, - service, no_log, httpv2, short_circuit, bulk_updates): + def __init__(self, abs_httpd_dir, abs_objdir, abs_builddir, abs_srcdir, + httpd_port, service, use_ssl, use_http2, use_mod_deflate, + no_log, httpv2, short_circuit, bulk_updates): self.name = 'apache.exe' self.httpd_port = httpd_port self.httpd_dir = abs_httpd_dir @@ -462,12 +522,19 @@ class Httpd: self.dontdothat_file = os.path.join(abs_builddir, CMDLINE_TEST_SCRIPT_NATIVE_PATH, 'svn-test-work', 'dontdothat') + self.certfile = os.path.join(abs_builddir, + CMDLINE_TEST_SCRIPT_NATIVE_PATH, + 'svn-test-work', 'cert.pem') + self.certkeyfile = os.path.join(abs_builddir, + CMDLINE_TEST_SCRIPT_NATIVE_PATH, + 'svn-test-work', 'cert-key.pem') self.httpd_config = os.path.join(self.root, 'httpd.conf') self.httpd_users = os.path.join(self.root, 'users') self.httpd_mime_types = os.path.join(self.root, 'mime.types') self.httpd_groups = os.path.join(self.root, 'groups') self.abs_builddir = abs_builddir self.abs_objdir = abs_objdir + self.abs_srcdir = abs_srcdir self.service_name = 'svn-test-httpd-' + str(httpd_port) if self.service: @@ -483,6 +550,9 @@ class Httpd: self._create_mime_types_file() self._create_dontdothat_file() + if use_ssl: + self._create_cert_files() + # Obtain version. version_vals = gen_obj._libraries['httpd'].version.split('.') self.httpd_ver = float('%s.%s' % (version_vals[0], version_vals[1])) @@ -491,9 +561,10 @@ class Httpd: fp = open(self.httpd_config, 'w') # Limit the number of threads (default = 64) - fp.write('\n') - fp.write('ThreadsPerChild 16\n') - fp.write('\n') + if not use_http2: + fp.write('\n') + fp.write('ThreadsPerChild 16\n') + fp.write('\n') # Global Environment fp.write('ServerRoot ' + self._quote(self.root) + '\n') @@ -511,6 +582,12 @@ class Httpd: fp.write('LogLevel Crit\n') # Write LoadModule for minimal system module + if use_ssl: + fp.write(self._sys_module('ssl_module', 'mod_ssl.so')) + if use_http2: + fp.write(self._sys_module('http2_module', 'mod_http2.so')) + if use_mod_deflate: + fp.write(self._sys_module('deflate_module', 'mod_deflate.so')) fp.write(self._sys_module('dav_module', 'mod_dav.so')) if self.httpd_ver >= 2.3: fp.write(self._sys_module('access_compat_module', 'mod_access_compat.so')) @@ -535,6 +612,21 @@ class Httpd: # And for mod_dontdothat fp.write(self._svn_module('dontdothat_module', 'mod_dontdothat.so')) + if use_ssl: + fp.write('SSLEngine on\n') + fp.write('SSLProtocol All -SSLv2 -SSLv3\n') + fp.write('SSLCertificateFile %s\n' % self._quote(self.certfile)) + fp.write('SSLCertificateKeyFile %s\n' % self._quote(self.certkeyfile)) + + if use_ssl and use_http2: + fp.write('Protocols h2 http/1.1\n') + elif use_http2: + fp.write('Protocols h2c http/1.1\n') + fp.write('H2Direct on\n') + + if use_mod_deflate: + fp.write('SetOutputFilter DEFLATE\n') + # Don't handle .htaccess, symlinks, etc. fp.write('\n') fp.write('AllowOverride None\n') @@ -575,6 +667,8 @@ class Httpd: 'jrandom', 'rayjandom']) os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp', self.httpd_users, 'jconstant', 'rayjandom']) + os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp', self.httpd_users, + '__dumpster__', '__loadster__']) os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp', self.httpd_users, 'JRANDOM', 'rayjandom']) os.spawnv(os.P_WAIT, htpasswd, ['htpasswd.exe', '-bp', self.httpd_users, @@ -605,6 +699,34 @@ class Httpd: fp.write('/ = deny\n') fp.close() + def _create_cert_files(self): + "Create certificate files" + # The unix build uses certificates encoded in davautocheck.sh + # Let's just read them from there + + sh_path = os.path.join(self.abs_srcdir, 'subversion', 'tests', 'cmdline', + 'davautocheck.sh') + sh = open(sh_path).readlines() + + def cert_extract(lines, what): + r = [] + pattern = r'cat\s*\>\s*' + re.escape(what) + r'\s*\<\<([A-Z_a-z0-9]+)' + exit_marker = None + for i in lines: + if exit_marker: + if i.startswith(exit_marker): + return r + r.append(i) + else: + m = re.match(pattern, i) + if m: + exit_marker = m.groups(1) + + cert_file = cert_extract(sh, '"$SSL_CERTIFICATE_FILE"') + cert_key = cert_extract(sh, '"$SSL_CERTIFICATE_KEY_FILE"') + open(self.certfile, 'w').write(''.join(cert_file)) + open(self.certkeyfile, 'w').write(''.join(cert_key)) + def _sys_module(self, name, path): full_path = os.path.join(self.httpd_dir, 'modules', path) return 'LoadModule ' + name + " " + self._quote(full_path) + '\n' @@ -786,9 +908,9 @@ class Httpd: ' AuthzSendForbiddenOnFailure On' + '\n' \ ' Satisfy All' + '\n' \ ' ' + '\n' \ - ' Require valid-user' + '\n' \ - ' Require expr req(\'ALLOW\') == \'1\'' + '\n' \ - '' + '\n' \ + ' Require valid-user' + '\n' \ + ' Require expr req(\'ALLOW\') == \'1\'' + '\n' \ + ' ' + '\n' \ ' SVNPathAuthz ' + self.path_authz_option + '\n' \ '' + '\n' \ '' + '\n' \ @@ -799,6 +921,10 @@ class Httpd: else: self._start_daemon() + # Avoid output from starting and preparing between test results + sys.stderr.flush() + sys.stdout.flush() + def stop(self): if self.service: self._stop_service() @@ -836,6 +962,45 @@ class Httpd: pass print('Httpd.stop_daemon not implemented') +class Memcached: + "Run memcached for tests" + def __init__(self, abs_memcached_dir, memcached_server): + self.name = 'memcached.exe' + + self.memcached_host, self.memcached_port = memcached_server.split(':') + self.memcached_dir = abs_memcached_dir + + self.proc = None + self.path = os.path.join(self.memcached_dir, self.name) + + self.memcached_args = [ + self.name, + '-p', self.memcached_port, + '-l', self.memcached_host + ] + + def __del__(self): + "Stop memcached when the object is deleted" + self.stop() + + def start(self): + "Start memcached as daemon" + print('Starting %s as daemon' % self.name) + print(self.memcached_args) + self.proc = subprocess.Popen([self.path] + self.memcached_args) + + def stop(self): + "Stop memcached" + if self.proc is not None: + try: + print('Stopping %s' % self.name) + self.proc.poll(); + if self.proc.returncode is None: + self.proc.kill(); + return + except AttributeError: + pass + # Move the binaries to the test directory create_target_dir(abs_builddir) locate_libs() @@ -855,19 +1020,28 @@ create_target_dir(CMDLINE_TEST_SCRIPT_NATIVE_PATH) # Ensure the tests directory is correctly cased abs_builddir = fix_case(abs_builddir) +failed = None daemon = None +memcached = None # Run the tests # No need to start any servers if we are only listing the tests. if not list_tests: + if run_memcached: + memcached = Memcached(memcached_dir, memcached_server) + memcached.start() + if run_svnserve: daemon = Svnserve(svnserve_args, objdir, abs_objdir, abs_builddir) if run_httpd: - daemon = Httpd(abs_httpd_dir, abs_objdir, abs_builddir, httpd_port, - httpd_service, httpd_no_log, - advertise_httpv2, http_short_circuit, - http_bulk_updates) + daemon = Httpd(abs_httpd_dir, abs_objdir, abs_builddir, abs_srcdir, + httpd_port, httpd_service, use_ssl, use_http2, + use_mod_deflate, httpd_no_log, advertise_httpv2, + http_short_circuit, http_bulk_updates) + + if use_ssl and not ssl_cert: + ssl_cert = daemon.certfile # Start service daemon, if any if daemon: @@ -922,6 +1096,7 @@ if not test_javahl and not test_swig: opts, args = run_tests.create_parser().parse_args([]) opts.url = base_url opts.fs_type = fs_type + opts.global_scheduler = global_scheduler opts.http_library = 'serf' opts.server_minor_version = server_minor_version opts.cleanup = cleanup @@ -937,6 +1112,12 @@ if not test_javahl and not test_swig: opts.httpd_version = httpd_version opts.set_log_level = log_level opts.ssl_cert = ssl_cert + opts.exclusive_wc_locks = exclusive_wc_locks + opts.memcached_server = memcached_server + opts.skip_c_tests = skip_c_tests + opts.dump_load_cross_check = dump_load_cross_check + opts.fsfs_compression = fsfs_compression + opts.fsfs_dir_deltification = fsfs_dir_deltification th = run_tests.TestHarness(abs_srcdir, abs_builddir, log_file, fail_log_file, opts) old_cwd = os.getcwd() @@ -971,6 +1152,9 @@ elif test_javahl: if (objdir == 'Debug'): args = args + ('-Xcheck:jni',) + if cleanup: + args = args + ('-Dtest.cleanup=1',) + args = args + ( '-Dtest.rootdir=' + os.path.join(abs_builddir, 'javahl'), '-Dtest.srcdir=' + os.path.join(abs_srcdir, @@ -1151,10 +1335,17 @@ elif test_swig == 'ruby': print('[Test runner reported failure]') failed = True +elif test_swig: + print('Unknown Swig binding type: ' + str(test_swig)) + failed = True + # Stop service daemon, if any if daemon: del daemon +if memcached: + del memcached + # Remove the execs again for tgt in copied_execs: try: