packages feed

hscdio (empty) → 0.1.0.0

raw patch · 143 files changed

+22222/−0 lines, 143 filesdep +HUnitdep +basedep +base-compatsetup-changedbinary-added

Dependencies added: HUnit, base, base-compat, bitwise, bytestring, containers, directory, hedgehog, hedgehog-classes, hscdio, mtl, optparse-applicative, text, vector

Files

+ CHANGELOG.md view
@@ -0,0 +1,34 @@+The Haskell bindings for libcdio follow the Haskell-standard [Package+Versioning Policy](https://pvp.haskell.org), where the first three numbers+indicate version (types/presence of exported symbols), the fourth number+indicates patch (underlying behaviour and/or backend code), and the fifth+indicates revision (docs, packaging, etc.)  This is in contrast to the C+libcdio itself, which (recently) uses Semantic Versioning; the only real+difference is that the first *two* numbers of the bindings signal a breaking+change, while the base library signals that with only *one*.+++## v/0.1.0.0.  Unreleased++Initial release with nearly all of 'cdio/cdio.h' translated, but not necessarily+tested, documented, or stabilized.+++### Added++* f/1.1.1.  Translate all core symbols brought in by simply using `#include "cdio/cdio.h`.+  For the full list of headers this includes, see `FEATURES`.+  Also note that several symbols were left untranslated; see the documentation of `Foreign.Libcdio` for the list.+	* f/1.1.3.1.  Translate `cdio/cd_types.h` as it's used in some bitmasks above.+	* f/1.1.3.2.  Integrate log messages with the monad rather than (impurely) printing output.+	* f/1.1.4.2.  Translate `cdio/util.h` as it provides the conversion functions for `Bcd` values.+* f/1.3.1. f/1.3.3.1. f/1.3.3.2. f/1.3.4.2.  Rewrite the documentation of the above to be more clear, more comprehensive, and (occasionally) more correct.+* (some of) f/1.4.1.  Just enough of the upstream tests to be sure the bindings are not going *completely* off the rails.+* f/3.1. f/3.3. i/008.  Provide a smoother means of accessing the library to Haskell users.+* i/002.  Close the low-hanging memory leaks from being returned allocated strings, without obfuscating the type system.+* i/003. i/009.  Enforce a bit more type safety by binding integral/string types with typesafe wrappers.++### Known issues++* i/011.  On some systems, opening a Cdio session stops the drive from recognizing a manual (push-button) request to open the drive.  This also occurs with other libraries, so it's not purely a libcdio problem, Haskell bindings or otherwise, but I come across it much more frequently with the bindings than anywhere else.+* i/021.  A `readLog` call will occasionally return unexpected entries.
+ FEATURES view
@@ -0,0 +1,111 @@+The numeric code may be used to search the version control log by prefixing it+with `f/`; for example, to find all of the documentation edits, `f/1.3.`++Lines prefixed with an asterisk (*) are considered complete -- though edits for+refactoring or bugfixes are always still possibilities -- while ones with an+exclamation point (!) are in progress.++  0.    Infrastructure and metadata for code structure, rather than program behaviour+  0.1.    Maintain a README with a high-level overview of the library+  0.2.    Explicit tracking of what has been and what will be done+  0.2.1.    FEATURES+  0.2.2.    CHANGELOG+  0.2.3.    ROADMAP+  0.3.    Track bug reports and feature requests++  1.    Provide a direct Haskell interface to libcdio and libcdio-paranoia+  1.1.    Export all symbols the libcdio public C headers do+* 1.1.1.    Translate the "primary" headers #included directly by `cdio/cdio.h`+* 1.1.1.1.    `cdio/version.h`+* 1.1.1.2.    `cdio/types.h`+* 1.1.1.3.    `cdio/sector.h`+* 1.1.1.4.    `cdio/device.h`+* 1.1.1.5.    `cdio/cdtext.h`+* 1.1.1.6.    `cdio/disc.h`+* 1.1.1.7.    `cdio/read.h`+* 1.1.1.8.    `cdio/track.h`+* 1.1.1.9.    `cdio/memory.h`+  1.1.2.    Translate the headers #included by `cdio/mmc_cmds.h`+  1.1.2.1.    `cdio/mmc.h`+  1.1.2.1.1.    `cdio/audio.h+  1.1.2.1.2.    `cdio/dvd.h`+  1.1.2.1.3.    `cdio/mmc_util.h`+  1.1.2.2.    `cdio/mmc_ll_cmds.h`+  1.1.2.3.    `cdio/mmc_hl_cmds.h`+  1.1.3.    Translate the remainder of those public headers+* 1.1.3.1.    `cdio/cd_types.h`+* 1.1.3.2.    `cdio/logging.h`+  1.1.3.3.    `cdio/utf8.h`+  1.1.3.4.    `cdio/posix.h`+  1.1.4.    Translate the deprecated headers for "backwards compatibility"+  1.1.4.1.    `cdio/ds.h`+* 1.1.4.2.    `cdio/util.h`+  1.1.5.    Translate the libcdio-paranoia headers+  1.1.5.1.    `cdio/paranoia/cdda.h`+  1.1.5.2.    `cdio/paranoia/paranoia.h`+  1.1.6.    Translate headers for handling non-audio data+  1.1.6.1.    `cdio/iso9660.h`+  1.1.6.1.1.    `cdio/rock.h`+  1.1.6.1.1.    `cdio/xa.h`+  1.1.6.2.    `cdio/udf.h`+  1.1.6.2.1.    `cdio/udf_file.h`+  1.1.6.2.2.    `cdio/udf_time.h`+  1.1.6.2.3.    `cdio/ecma_167.h`+  1.3.    Improve the documentation from that copied from the headers+* 1.3.1.    "Primary" headers #included directly by `cdio/cdio.h`+* 1.3.1.1.    `cdio/version.h`+* 1.3.1.2.    `cdio/types.h`+* 1.3.1.3.    `cdio/sector.h`+* 1.3.1.4.    `cdio/device.h`+* 1.3.1.5.    `cdio/cdtext.h`+* 1.3.1.6.    `cdio/disc.h`+* 1.3.1.7.    `cdio/read.h`+* 1.3.1.8.    `cdio/track.h`+* 1.3.1.9.    `cdio/memory.h`+  1.3.2.    Headers #included by `cdio/mmc_cmds.h`+  1.3.2.1.    `cdio/mmc.h`+  1.3.2.1.1.    `cdio/audio.h+  1.3.2.1.2.    `cdio/dvd.h`+  1.3.2.1.3.    `cdio/mmc_util.h`+  1.3.2.2.    `cdio/mmc_ll_cmds.h`+  1.3.2.3.    `cdio/mmc_hl_cmds.h`+  1.3.3.    Other public headers+* 1.3.3.1.    `cdio/cd_types.h`+* 1.3.3.2.    `cdio/logging.h`+  1.3.3.3.    `cdio/utf8.h`+  1.3.3.4.    `cdio/posix.h`+  1.3.4.    Deprecated headers for "backwards compatibility"+  1.3.4.1.    `cdio/ds.h`+* 1.3.4.2.    `cdio/util.h`+  1.3.5.    libcdio-paranoia headers+  1.3.5.1.    `cdio/paranoia/cdda.h`+  1.3.5.2.    `cdio/paranoia/paranoia.h`+  1.3.6.    Non-audio data+  1.3.6.1.    `cdio/iso9660.h`+  1.3.6.1.1.    `cdio/rock.h`+  1.3.6.1.1.    `cdio/xa.h`+  1.3.6.2.    `cdio/udf.h`+  1.3.6.2.1.    `cdio/udf_file.h`+  1.3.6.2.2.    `cdio/udf_time.h`+  1.3.6.2.3.    `cdio/ecma_167.h`+  1.4.    Copy and translate library tests+! 1.4.1.    libcdio tests+  1.4.2.    libcdio-paranoia tests++  2.    Provide Haskell reimplementations of the packaged binaries+  2.1.    `cd-drive`+  2.2.    `cd-info`+  2.3.    `cd-read`+  2.4.    `cdda-player`+  2.5.    `iso-info`+  2.6.    `iso-read`+  2.7.    `mmc-tool`+  2.8.    `libcdio-paranoia`++! 3.    Provide alternate idomatic (custom-Monad-based) interface for libcdio functions+* 3.1.    "Primary" headers #included directly by `cdio/cdio.h`+  3.2.    Headers #included by `cdio/mmc_cmds.h`+! 3.3.    Other public headers+  3.4.    Deprecated headers for "backwards compatibility"+  3.5.    libcdio-paranoia headers+  3.6.    Non-audio data file access
+ LICENSE view
@@ -0,0 +1,674 @@+                    GNU GENERAL PUBLIC LICENSE+                       Version 3, 29 June 2007++ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>+ Everyone is permitted to copy and distribute verbatim copies+ of this license document, but changing it is not allowed.++                            Preamble++  The GNU General Public License is a free, copyleft license for+software and other kinds of works.++  The licenses for most software and other practical works are designed+to take away your freedom to share and change the works.  By contrast,+the GNU General Public License is intended to guarantee your freedom to+share and change all versions of a program--to make sure it remains free+software for all its users.  We, the Free Software Foundation, use the+GNU General Public License for most of our software; it applies also to+any other work released this way by its authors.  You can apply it to+your programs, too.++  When we speak of free software, we are referring to freedom, not+price.  Our General Public Licenses are designed to make sure that you+have the freedom to distribute copies of free software (and charge for+them if you wish), that you receive source code or can get it if you+want it, that you can change the software or use pieces of it in new+free programs, and that you know you can do these things.++  To protect your rights, we need to prevent others from denying you+these rights or asking you to surrender the rights.  Therefore, you have+certain responsibilities if you distribute copies of the software, or if+you modify it: responsibilities to respect the freedom of others.++  For example, if you distribute copies of such a program, whether+gratis or for a fee, you must pass on to the recipients the same+freedoms that you received.  You must make sure that they, too, receive+or can get the source code.  And you must show them these terms so they+know their rights.++  Developers that use the GNU GPL protect your rights with two steps:+(1) assert copyright on the software, and (2) offer you this License+giving you legal permission to copy, distribute and/or modify it.++  For the developers' and authors' protection, the GPL clearly explains+that there is no warranty for this free software.  For both users' and+authors' sake, the GPL requires that modified versions be marked as+changed, so that their problems will not be attributed erroneously to+authors of previous versions.++  Some devices are designed to deny users access to install or run+modified versions of the software inside them, although the manufacturer+can do so.  This is fundamentally incompatible with the aim of+protecting users' freedom to change the software.  The systematic+pattern of such abuse occurs in the area of products for individuals to+use, which is precisely where it is most unacceptable.  Therefore, we+have designed this version of the GPL to prohibit the practice for those+products.  If such problems arise substantially in other domains, we+stand ready to extend this provision to those domains in future versions+of the GPL, as needed to protect the freedom of users.++  Finally, every program is threatened constantly by software patents.+States should not allow patents to restrict development and use of+software on general-purpose computers, but in those that do, we wish to+avoid the special danger that patents applied to a free program could+make it effectively proprietary.  To prevent this, the GPL assures that+patents cannot be used to render the program non-free.++  The precise terms and conditions for copying, distribution and+modification follow.++                       TERMS AND CONDITIONS++  0. Definitions.++  "This License" refers to version 3 of the GNU General Public License.++  "Copyright" also means copyright-like laws that apply to other kinds of+works, such as semiconductor masks.++  "The Program" refers to any copyrightable work licensed under this+License.  Each licensee is addressed as "you".  "Licensees" and+"recipients" may be individuals or organizations.++  To "modify" a work means to copy from or adapt all or part of the work+in a fashion requiring copyright permission, other than the making of an+exact copy.  The resulting work is called a "modified version" of the+earlier work or a work "based on" the earlier work.++  A "covered work" means either the unmodified Program or a work based+on the Program.++  To "propagate" a work means to do anything with it that, without+permission, would make you directly or secondarily liable for+infringement under applicable copyright law, except executing it on a+computer or modifying a private copy.  Propagation includes copying,+distribution (with or without modification), making available to the+public, and in some countries other activities as well.++  To "convey" a work means any kind of propagation that enables other+parties to make or receive copies.  Mere interaction with a user through+a computer network, with no transfer of a copy, is not conveying.++  An interactive user interface displays "Appropriate Legal Notices"+to the extent that it includes a convenient and prominently visible+feature that (1) displays an appropriate copyright notice, and (2)+tells the user that there is no warranty for the work (except to the+extent that warranties are provided), that licensees may convey the+work under this License, and how to view a copy of this License.  If+the interface presents a list of user commands or options, such as a+menu, a prominent item in the list meets this criterion.++  1. Source Code.++  The "source code" for a work means the preferred form of the work+for making modifications to it.  "Object code" means any non-source+form of a work.++  A "Standard Interface" means an interface that either is an official+standard defined by a recognized standards body, or, in the case of+interfaces specified for a particular programming language, one that+is widely used among developers working in that language.++  The "System Libraries" of an executable work include anything, other+than the work as a whole, that (a) is included in the normal form of+packaging a Major Component, but which is not part of that Major+Component, and (b) serves only to enable use of the work with that+Major Component, or to implement a Standard Interface for which an+implementation is available to the public in source code form.  A+"Major Component", in this context, means a major essential component+(kernel, window system, and so on) of the specific operating system+(if any) on which the executable work runs, or a compiler used to+produce the work, or an object code interpreter used to run it.++  The "Corresponding Source" for a work in object code form means all+the source code needed to generate, install, and (for an executable+work) run the object code and to modify the work, including scripts to+control those activities.  However, it does not include the work's+System Libraries, or general-purpose tools or generally available free+programs which are used unmodified in performing those activities but+which are not part of the work.  For example, Corresponding Source+includes interface definition files associated with source files for+the work, and the source code for shared libraries and dynamically+linked subprograms that the work is specifically designed to require,+such as by intimate data communication or control flow between those+subprograms and other parts of the work.++  The Corresponding Source need not include anything that users+can regenerate automatically from other parts of the Corresponding+Source.++  The Corresponding Source for a work in source code form is that+same work.++  2. Basic Permissions.++  All rights granted under this License are granted for the term of+copyright on the Program, and are irrevocable provided the stated+conditions are met.  This License explicitly affirms your unlimited+permission to run the unmodified Program.  The output from running a+covered work is covered by this License only if the output, given its+content, constitutes a covered work.  This License acknowledges your+rights of fair use or other equivalent, as provided by copyright law.++  You may make, run and propagate covered works that you do not+convey, without conditions so long as your license otherwise remains+in force.  You may convey covered works to others for the sole purpose+of having them make modifications exclusively for you, or provide you+with facilities for running those works, provided that you comply with+the terms of this License in conveying all material for which you do+not control copyright.  Those thus making or running the covered works+for you must do so exclusively on your behalf, under your direction+and control, on terms that prohibit them from making any copies of+your copyrighted material outside their relationship with you.++  Conveying under any other circumstances is permitted solely under+the conditions stated below.  Sublicensing is not allowed; section 10+makes it unnecessary.++  3. Protecting Users' Legal Rights From Anti-Circumvention Law.++  No covered work shall be deemed part of an effective technological+measure under any applicable law fulfilling obligations under article+11 of the WIPO copyright treaty adopted on 20 December 1996, or+similar laws prohibiting or restricting circumvention of such+measures.++  When you convey a covered work, you waive any legal power to forbid+circumvention of technological measures to the extent such circumvention+is effected by exercising rights under this License with respect to+the covered work, and you disclaim any intention to limit operation or+modification of the work as a means of enforcing, against the work's+users, your or third parties' legal rights to forbid circumvention of+technological measures.++  4. Conveying Verbatim Copies.++  You may convey verbatim copies of the Program's source code as you+receive it, in any medium, provided that you conspicuously and+appropriately publish on each copy an appropriate copyright notice;+keep intact all notices stating that this License and any+non-permissive terms added in accord with section 7 apply to the code;+keep intact all notices of the absence of any warranty; and give all+recipients a copy of this License along with the Program.++  You may charge any price or no price for each copy that you convey,+and you may offer support or warranty protection for a fee.++  5. Conveying Modified Source Versions.++  You may convey a work based on the Program, or the modifications to+produce it from the Program, in the form of source code under the+terms of section 4, provided that you also meet all of these conditions:++    a) The work must carry prominent notices stating that you modified+    it, and giving a relevant date.++    b) The work must carry prominent notices stating that it is+    released under this License and any conditions added under section+    7.  This requirement modifies the requirement in section 4 to+    "keep intact all notices".++    c) You must license the entire work, as a whole, under this+    License to anyone who comes into possession of a copy.  This+    License will therefore apply, along with any applicable section 7+    additional terms, to the whole of the work, and all its parts,+    regardless of how they are packaged.  This License gives no+    permission to license the work in any other way, but it does not+    invalidate such permission if you have separately received it.++    d) If the work has interactive user interfaces, each must display+    Appropriate Legal Notices; however, if the Program has interactive+    interfaces that do not display Appropriate Legal Notices, your+    work need not make them do so.++  A compilation of a covered work with other separate and independent+works, which are not by their nature extensions of the covered work,+and which are not combined with it such as to form a larger program,+in or on a volume of a storage or distribution medium, is called an+"aggregate" if the compilation and its resulting copyright are not+used to limit the access or legal rights of the compilation's users+beyond what the individual works permit.  Inclusion of a covered work+in an aggregate does not cause this License to apply to the other+parts of the aggregate.++  6. Conveying Non-Source Forms.++  You may convey a covered work in object code form under the terms+of sections 4 and 5, provided that you also convey the+machine-readable Corresponding Source under the terms of this License,+in one of these ways:++    a) Convey the object code in, or embodied in, a physical product+    (including a physical distribution medium), accompanied by the+    Corresponding Source fixed on a durable physical medium+    customarily used for software interchange.++    b) Convey the object code in, or embodied in, a physical product+    (including a physical distribution medium), accompanied by a+    written offer, valid for at least three years and valid for as+    long as you offer spare parts or customer support for that product+    model, to give anyone who possesses the object code either (1) a+    copy of the Corresponding Source for all the software in the+    product that is covered by this License, on a durable physical+    medium customarily used for software interchange, for a price no+    more than your reasonable cost of physically performing this+    conveying of source, or (2) access to copy the+    Corresponding Source from a network server at no charge.++    c) Convey individual copies of the object code with a copy of the+    written offer to provide the Corresponding Source.  This+    alternative is allowed only occasionally and noncommercially, and+    only if you received the object code with such an offer, in accord+    with subsection 6b.++    d) Convey the object code by offering access from a designated+    place (gratis or for a charge), and offer equivalent access to the+    Corresponding Source in the same way through the same place at no+    further charge.  You need not require recipients to copy the+    Corresponding Source along with the object code.  If the place to+    copy the object code is a network server, the Corresponding Source+    may be on a different server (operated by you or a third party)+    that supports equivalent copying facilities, provided you maintain+    clear directions next to the object code saying where to find the+    Corresponding Source.  Regardless of what server hosts the+    Corresponding Source, you remain obligated to ensure that it is+    available for as long as needed to satisfy these requirements.++    e) Convey the object code using peer-to-peer transmission, provided+    you inform other peers where the object code and Corresponding+    Source of the work are being offered to the general public at no+    charge under subsection 6d.++  A separable portion of the object code, whose source code is excluded+from the Corresponding Source as a System Library, need not be+included in conveying the object code work.++  A "User Product" is either (1) a "consumer product", which means any+tangible personal property which is normally used for personal, family,+or household purposes, or (2) anything designed or sold for incorporation+into a dwelling.  In determining whether a product is a consumer product,+doubtful cases shall be resolved in favor of coverage.  For a particular+product received by a particular user, "normally used" refers to a+typical or common use of that class of product, regardless of the status+of the particular user or of the way in which the particular user+actually uses, or expects or is expected to use, the product.  A product+is a consumer product regardless of whether the product has substantial+commercial, industrial or non-consumer uses, unless such uses represent+the only significant mode of use of the product.++  "Installation Information" for a User Product means any methods,+procedures, authorization keys, or other information required to install+and execute modified versions of a covered work in that User Product from+a modified version of its Corresponding Source.  The information must+suffice to ensure that the continued functioning of the modified object+code is in no case prevented or interfered with solely because+modification has been made.++  If you convey an object code work under this section in, or with, or+specifically for use in, a User Product, and the conveying occurs as+part of a transaction in which the right of possession and use of the+User Product is transferred to the recipient in perpetuity or for a+fixed term (regardless of how the transaction is characterized), the+Corresponding Source conveyed under this section must be accompanied+by the Installation Information.  But this requirement does not apply+if neither you nor any third party retains the ability to install+modified object code on the User Product (for example, the work has+been installed in ROM).++  The requirement to provide Installation Information does not include a+requirement to continue to provide support service, warranty, or updates+for a work that has been modified or installed by the recipient, or for+the User Product in which it has been modified or installed.  Access to a+network may be denied when the modification itself materially and+adversely affects the operation of the network or violates the rules and+protocols for communication across the network.++  Corresponding Source conveyed, and Installation Information provided,+in accord with this section must be in a format that is publicly+documented (and with an implementation available to the public in+source code form), and must require no special password or key for+unpacking, reading or copying.++  7. Additional Terms.++  "Additional permissions" are terms that supplement the terms of this+License by making exceptions from one or more of its conditions.+Additional permissions that are applicable to the entire Program shall+be treated as though they were included in this License, to the extent+that they are valid under applicable law.  If additional permissions+apply only to part of the Program, that part may be used separately+under those permissions, but the entire Program remains governed by+this License without regard to the additional permissions.++  When you convey a copy of a covered work, you may at your option+remove any additional permissions from that copy, or from any part of+it.  (Additional permissions may be written to require their own+removal in certain cases when you modify the work.)  You may place+additional permissions on material, added by you to a covered work,+for which you have or can give appropriate copyright permission.++  Notwithstanding any other provision of this License, for material you+add to a covered work, you may (if authorized by the copyright holders of+that material) supplement the terms of this License with terms:++    a) Disclaiming warranty or limiting liability differently from the+    terms of sections 15 and 16 of this License; or++    b) Requiring preservation of specified reasonable legal notices or+    author attributions in that material or in the Appropriate Legal+    Notices displayed by works containing it; or++    c) Prohibiting misrepresentation of the origin of that material, or+    requiring that modified versions of such material be marked in+    reasonable ways as different from the original version; or++    d) Limiting the use for publicity purposes of names of licensors or+    authors of the material; or++    e) Declining to grant rights under trademark law for use of some+    trade names, trademarks, or service marks; or++    f) Requiring indemnification of licensors and authors of that+    material by anyone who conveys the material (or modified versions of+    it) with contractual assumptions of liability to the recipient, for+    any liability that these contractual assumptions directly impose on+    those licensors and authors.++  All other non-permissive additional terms are considered "further+restrictions" within the meaning of section 10.  If the Program as you+received it, or any part of it, contains a notice stating that it is+governed by this License along with a term that is a further+restriction, you may remove that term.  If a license document contains+a further restriction but permits relicensing or conveying under this+License, you may add to a covered work material governed by the terms+of that license document, provided that the further restriction does+not survive such relicensing or conveying.++  If you add terms to a covered work in accord with this section, you+must place, in the relevant source files, a statement of the+additional terms that apply to those files, or a notice indicating+where to find the applicable terms.++  Additional terms, permissive or non-permissive, may be stated in the+form of a separately written license, or stated as exceptions;+the above requirements apply either way.++  8. Termination.++  You may not propagate or modify a covered work except as expressly+provided under this License.  Any attempt otherwise to propagate or+modify it is void, and will automatically terminate your rights under+this License (including any patent licenses granted under the third+paragraph of section 11).++  However, if you cease all violation of this License, then your+license from a particular copyright holder is reinstated (a)+provisionally, unless and until the copyright holder explicitly and+finally terminates your license, and (b) permanently, if the copyright+holder fails to notify you of the violation by some reasonable means+prior to 60 days after the cessation.++  Moreover, your license from a particular copyright holder is+reinstated permanently if the copyright holder notifies you of the+violation by some reasonable means, this is the first time you have+received notice of violation of this License (for any work) from that+copyright holder, and you cure the violation prior to 30 days after+your receipt of the notice.++  Termination of your rights under this section does not terminate the+licenses of parties who have received copies or rights from you under+this License.  If your rights have been terminated and not permanently+reinstated, you do not qualify to receive new licenses for the same+material under section 10.++  9. Acceptance Not Required for Having Copies.++  You are not required to accept this License in order to receive or+run a copy of the Program.  Ancillary propagation of a covered work+occurring solely as a consequence of using peer-to-peer transmission+to receive a copy likewise does not require acceptance.  However,+nothing other than this License grants you permission to propagate or+modify any covered work.  These actions infringe copyright if you do+not accept this License.  Therefore, by modifying or propagating a+covered work, you indicate your acceptance of this License to do so.++  10. Automatic Licensing of Downstream Recipients.++  Each time you convey a covered work, the recipient automatically+receives a license from the original licensors, to run, modify and+propagate that work, subject to this License.  You are not responsible+for enforcing compliance by third parties with this License.++  An "entity transaction" is a transaction transferring control of an+organization, or substantially all assets of one, or subdividing an+organization, or merging organizations.  If propagation of a covered+work results from an entity transaction, each party to that+transaction who receives a copy of the work also receives whatever+licenses to the work the party's predecessor in interest had or could+give under the previous paragraph, plus a right to possession of the+Corresponding Source of the work from the predecessor in interest, if+the predecessor has it or can get it with reasonable efforts.++  You may not impose any further restrictions on the exercise of the+rights granted or affirmed under this License.  For example, you may+not impose a license fee, royalty, or other charge for exercise of+rights granted under this License, and you may not initiate litigation+(including a cross-claim or counterclaim in a lawsuit) alleging that+any patent claim is infringed by making, using, selling, offering for+sale, or importing the Program or any portion of it.++  11. Patents.++  A "contributor" is a copyright holder who authorizes use under this+License of the Program or a work on which the Program is based.  The+work thus licensed is called the contributor's "contributor version".++  A contributor's "essential patent claims" are all patent claims+owned or controlled by the contributor, whether already acquired or+hereafter acquired, that would be infringed by some manner, permitted+by this License, of making, using, or selling its contributor version,+but do not include claims that would be infringed only as a+consequence of further modification of the contributor version.  For+purposes of this definition, "control" includes the right to grant+patent sublicenses in a manner consistent with the requirements of+this License.++  Each contributor grants you a non-exclusive, worldwide, royalty-free+patent license under the contributor's essential patent claims, to+make, use, sell, offer for sale, import and otherwise run, modify and+propagate the contents of its contributor version.++  In the following three paragraphs, a "patent license" is any express+agreement or commitment, however denominated, not to enforce a patent+(such as an express permission to practice a patent or covenant not to+sue for patent infringement).  To "grant" such a patent license to a+party means to make such an agreement or commitment not to enforce a+patent against the party.++  If you convey a covered work, knowingly relying on a patent license,+and the Corresponding Source of the work is not available for anyone+to copy, free of charge and under the terms of this License, through a+publicly available network server or other readily accessible means,+then you must either (1) cause the Corresponding Source to be so+available, or (2) arrange to deprive yourself of the benefit of the+patent license for this particular work, or (3) arrange, in a manner+consistent with the requirements of this License, to extend the patent+license to downstream recipients.  "Knowingly relying" means you have+actual knowledge that, but for the patent license, your conveying the+covered work in a country, or your recipient's use of the covered work+in a country, would infringe one or more identifiable patents in that+country that you have reason to believe are valid.++  If, pursuant to or in connection with a single transaction or+arrangement, you convey, or propagate by procuring conveyance of, a+covered work, and grant a patent license to some of the parties+receiving the covered work authorizing them to use, propagate, modify+or convey a specific copy of the covered work, then the patent license+you grant is automatically extended to all recipients of the covered+work and works based on it.++  A patent license is "discriminatory" if it does not include within+the scope of its coverage, prohibits the exercise of, or is+conditioned on the non-exercise of one or more of the rights that are+specifically granted under this License.  You may not convey a covered+work if you are a party to an arrangement with a third party that is+in the business of distributing software, under which you make payment+to the third party based on the extent of your activity of conveying+the work, and under which the third party grants, to any of the+parties who would receive the covered work from you, a discriminatory+patent license (a) in connection with copies of the covered work+conveyed by you (or copies made from those copies), or (b) primarily+for and in connection with specific products or compilations that+contain the covered work, unless you entered into that arrangement,+or that patent license was granted, prior to 28 March 2007.++  Nothing in this License shall be construed as excluding or limiting+any implied license or other defenses to infringement that may+otherwise be available to you under applicable patent law.++  12. No Surrender of Others' Freedom.++  If conditions are imposed on you (whether by court order, agreement or+otherwise) that contradict the conditions of this License, they do not+excuse you from the conditions of this License.  If you cannot convey a+covered work so as to satisfy simultaneously your obligations under this+License and any other pertinent obligations, then as a consequence you may+not convey it at all.  For example, if you agree to terms that obligate you+to collect a royalty for further conveying from those to whom you convey+the Program, the only way you could satisfy both those terms and this+License would be to refrain entirely from conveying the Program.++  13. Use with the GNU Affero General Public License.++  Notwithstanding any other provision of this License, you have+permission to link or combine any covered work with a work licensed+under version 3 of the GNU Affero General Public License into a single+combined work, and to convey the resulting work.  The terms of this+License will continue to apply to the part which is the covered work,+but the special requirements of the GNU Affero General Public License,+section 13, concerning interaction through a network will apply to the+combination as such.++  14. Revised Versions of this License.++  The Free Software Foundation may publish revised and/or new versions of+the GNU General Public License from time to time.  Such new versions will+be similar in spirit to the present version, but may differ in detail to+address new problems or concerns.++  Each version is given a distinguishing version number.  If the+Program specifies that a certain numbered version of the GNU General+Public License "or any later version" applies to it, you have the+option of following the terms and conditions either of that numbered+version or of any later version published by the Free Software+Foundation.  If the Program does not specify a version number of the+GNU General Public License, you may choose any version ever published+by the Free Software Foundation.++  If the Program specifies that a proxy can decide which future+versions of the GNU General Public License can be used, that proxy's+public statement of acceptance of a version permanently authorizes you+to choose that version for the Program.++  Later license versions may give you additional or different+permissions.  However, no additional obligations are imposed on any+author or copyright holder as a result of your choosing to follow a+later version.++  15. Disclaimer of Warranty.++  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.++  16. Limitation of Liability.++  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF+SUCH DAMAGES.++  17. Interpretation of Sections 15 and 16.++  If the disclaimer of warranty and limitation of liability provided+above cannot be given local legal effect according to their terms,+reviewing courts shall apply local law that most closely approximates+an absolute waiver of all civil liability in connection with the+Program, unless a warranty or assumption of liability accompanies a+copy of the Program in return for a fee.++                     END OF TERMS AND CONDITIONS++            How to Apply These Terms to Your New Programs++  If you develop a new program, and you want it to be of the greatest+possible use to the public, the best way to achieve this is to make it+free software which everyone can redistribute and change under these terms.++  To do so, attach the following notices to the program.  It is safest+to attach them to the start of each source file to most effectively+state the exclusion of warranty; and each file should have at least+the "copyright" line and a pointer to where the full notice is found.++    <one line to give the program's name and a brief idea of what it does.>+    Copyright (C) <year>  <name of author>++    This program is free software: you can redistribute it and/or modify+    it under the terms of the GNU General Public License as published by+    the Free Software Foundation, either version 3 of the License, or+    (at your option) any later version.++    This program is distributed in the hope that it will be useful,+    but WITHOUT ANY WARRANTY; without even the implied warranty of+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+    GNU General Public License for more details.++    You should have received a copy of the GNU General Public License+    along with this program.  If not, see <http://www.gnu.org/licenses/>.++Also add information on how to contact you by electronic and paper mail.++  If the program does terminal interaction, make it output a short+notice like this when it starts in an interactive mode:++    <program>  Copyright (C) <year>  <name of author>+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.+    This is free software, and you are welcome to redistribute it+    under certain conditions; type `show c' for details.++The hypothetical commands `show w' and `show c' should show the appropriate+parts of the General Public License.  Of course, your program's commands+might be different; for a GUI interface, you would use an "about box".++  You should also get your employer (if you work as a programmer) or school,+if any, to sign a "copyright disclaimer" for the program, if necessary.+For more information on this, and how to apply and follow the GNU GPL, see+<http://www.gnu.org/licenses/>.++  The GNU General Public License does not permit incorporating your program+into proprietary programs.  If your program is a subroutine library, you+may consider it more useful to permit linking proprietary applications with+the library.  If this is what you want to do, use the GNU Lesser General+Public License instead of this License.  But first, please read+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+ README.md view
@@ -0,0 +1,129 @@+# About+In C, [libcdio](https://www.gnu.org/software/libcdio/) provides a widely-ported +and highly-usable library for retrieving data from CDs (and disc images).  This +is an area which Haskell has thus far been lacking a solution for; while modern +technology has admittedly been moving away from discs in favour of downloading +files over the internet, there is still some utility in the medium for any +programmers whose projects might involve external storage (note, however, that +`libcdio` only allows /reading/ discs, and leaves /authoring/ to other +libraries).++While the majority of the core library has been translated, many supplemental +headers (MMC commands, CD-Paranoia, etc.) are not yet available; for the +current progress see the [FEATURES](./FEATURES) file and the +[ROADMAP](./ROADMAP.md) for the rough order in which those are planned to be +developed, and please do report any bugs you find (or even fix them yourself!)+++# License++The original `libcdio` is licensed under the GPL, and these bindings, of +course, follow suit.  If you do use this in your own project, therefore, you +are subject to the ambiguity of whether linking to a GPL library then requires +your own code to also be released under the GPL.  Look elsewhere for a full +discussion on what arguments are given in that debate, but in short, the GPL +says that "a work based on the Program" must *also* be released under the GPL.++To err on the side of caution, if you use this library, release your code under +the GPL.  To do otherwise is to take a firm stance against the linking argument +at best, violate the copyright at worst, and make GPL proponents angry at you +either way.+++# Installation++## Requirements++As with nearly every Haskell project, the `.cabal` file maintains the list of +dependencies, and that should be taken as authoritative over anywhere else +except Hackage revisions, and I'll try to keep the code up to date with those.++Notably, the actual core of this package is the C `libcdio` library.  All +bindings should fail gracefully for any version within the supported range, and +so should be safe to call blindly, but this is accomplished via preprocessor +commands, and so *this package must be recompiled whenever the base libcdio +version changes*.  Minor version bumps to the underlying library (and certainly +patch releases) should still run safely after being recompiled, but there may +be some unexpected behaviour: version 2.1 added a few meta-values to the +`Language` enum, for example, at values greater than 255, while the previous +maximum value was below that.  It is possible for a C compiler to have used a +byte representation for <2.1 and a larger one for >=2.1; something like that +could *possibly* result in things being set at/referenced from the wrong memory +offset.++	* libcdio: >= 0.93 && < 2.2+	* c2hs: >= 0.26+	* ghc: >= 8.0++## c2hs + ghc++Some parts of the bindings have been written for the `c2hs` preprocessor, and +while manual compilation is technically possible, it's much more involved than +necessary.  Instead, just use `cabal-install` or `stack` as usual.  If you +really do have to invoke `gcc` manually, however, run that preprocessor first:++	c2hs --cppopts=-E --cppopts=-Iinclude/ --include=.../ src/Foreign/Libcdio/Types/Enums.chs+	c2hs --cppopts=-E --cppopts=-Iinclude/ --include=.../ src/Foreign/Libcdio/Types/Offsets.chs+++# Usage++The original implementation revolves around a classically-C architecture of +threading a mutable (though opaque) pointer through through many function +calls.  For those used to that or who are following pre-existing guides, a +set of low-level bindings mirroring that architecture may be found under +the "Foreign.Libcdio" tree; for anyone used to Haskell, the monadic +bindings under "Sound.Libcdio" are recommended instead.  A lookup table for +translating existing code and/or knowledge into each progressively higher-level +interface is provided in the documentation of the `Foreign.Libcdio.*` modules.++As a general rule, any project should /only/ import modules from a single set +of bindings, not both, as while the datatypes can frequently be passed between +them, several function names have been reused and so may collide.+++# Contributing++I welcome any patches, whether for bug fixes, new features, or anything else.  +If you just want to point out a bug or ask for some yet-unmentioned feature, I +maintain that list in [ISSUES](./ISSUES/); see the [README](./ISSUES/README.md) +in that directory for the format if you want to submit something in a more +complete form or contribute to any ongoing discussion, but otherwise feel free +to simply [email me](mailto:ag@eitilt.life) and I'll wrangle it into the +right form.++If you decide to contribute yourself, please enable the `dev` build flag.  +For the moment, it just enables all warnings I want to enforce in the code, but +it might provide other aids in the future as well.  I've avoided enabling them +during everyday building as while an end user seeing a warning *might* feel +inclined to fix the program, chances are it's just going to be ignored as the +list of built files scrolls by.++	cabal configure -fdev++Depending on the size of your hack, I welcome either a diff file, or you can +bundle your complete darcs patches with `darcs send`.  Either way, attach the +changes to an email addressed to ag@eitilt.life and I'll see about adding it to +the codebase.++## Patch format++If you do send the latter, every patch should have a comment with a (at least +mildly) descriptive name prefixed with a tag indicating the general category +addressed by the patch: for fixing issues, that is an "i/" followed by the +issue number (padded with leading zeros to three digits); for general +development, "f/" followed by the best topic in the `FEATURES` key; for +completeness, version tags are "v/" followed by the package reference followed +by the version.  All are terminated with a final period.++Please do not squash patches.  Each patch should represent a minimal but +complete change: certainly enough context to successfully compile, hopefully +enough context to not break any previously-passing tests, and potentially +combining closely-related changes at your discretion, but if you wind up trying +to decide between multiple tags or you're adding all of your work over the +entire day, you should probably look closely at whether you can break the patch +apart any farther.++Additionally, make good use of the `--ask-deps` flag.  Until I get a CI +integration together, it's easy to miss a dependency, but do your best to +select anything which your patch may require to build successfully.
+ ROADMAP.md view
@@ -0,0 +1,58 @@+# Version roadmap++While the `FEATURES` file provides a checklist and rough progress indication,+it does not give any indication of priority.  This document, then, is a means+of sorting those features into a rough order of implementation.  Future version+numbers here are only a rough indication of expectations; intermediate breaking+changes and partial releases may require they be incremented.+++## Core library++* f/1.1.1.+* f/1.1.3.1.+* f/1.3.1.+* f/1.3.3.1.+* f/1.1.3.2.+* f/1.4.1.  *(those which may be implemented at this point)*+* f/3.1.+++## Re-implement binaries for testing++* f/2.1.+* f/2.2.+* f/2.3.+* f/2.5.+* f/2.6.+++## libcdio-paranoia++* f/1.1.5.+* f/1.3.5.+* f/1.4.2.+* f/2.8.+* f/3.5.+++## MMC commands++* f/1.1.2.+* f/1.3.2.+* f/1.4.1.  *(those which may be implemented at this point)*+* f/2.7.+* f/3.2.+++## Non-audio data++* f/1.1.3.3.+* f/1.1.3.4.+* f/1.1.4.1.+* f/1.1.6.+* f/1.3.3.3.+* f/1.3.3.4.+* f/1.3.4.1.+* f/1.3.6.+* f/3.6.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ bin/Sound/Libcdio/PackCdText.hs view
@@ -0,0 +1,73 @@+{-# LANGUAGE CPP #-}++module Main where+++import qualified Options.Applicative as O++import qualified Data.ByteString as BS++import qualified System.IO as IO++import Sound.Libcdio+import Sound.Libcdio.Read.CdText++#if MIN_VERSION_base(4,11,0)+#else+import Data.Monoid ( (<>) )+#endif++import Options.Applicative ( (<|>), (<**>) )+++data Options = Options+    { source :: FilePath+    , sink :: Maybe FilePath+    , help :: Bool+    }+  deriving ( Eq, Ord, Show, Read )+++options :: O.Parser Options+options = Options+    <$> O.strArgument (O.metavar "FILE")+    <*> output+    <*> O.switch+        (   O.long "help"+         <> O.short 'h'+         <> O.help "Print this help message"+        )++output :: O.Parser (Maybe FilePath)+output = O.flag' Nothing+        (   O.long "stdout"+         <> O.short 'O'+         <> O.help "Echo the resulting binary blob to stdout"+        )+    <|> Just <$> O.strOption+        (   O.long "output"+         <> O.short 'o'+         <> O.metavar "FILE"+         <> O.value "cdtext.dat"+         <> O.help "Where to save the resulting CDTEXT blob"+        )++description :: O.InfoMod a+description = O.fullDesc+     <> O.progDesc "Generate a binary CDTEXT file from readable data"+++main :: IO ()+main = do+    os <- O.execParser $ O.info (options <**> O.helper) description+    if help os+    then putStrLn "TODO: Print the help"+    else do+        let write p = case sink os of+                Just f -> IO.withBinaryFile f IO.WriteMode $ flip BS.hPut p+                Nothing -> BS.putStr p+        bs <- open (Just $ source os) False cdTextRaw+        case bs of+            Right (Just bs') -> write bs'+            Right Nothing -> IO.hPutStrLn IO.stderr "No CDTEXT on disc"+            _ -> IO.hPutStrLn IO.stderr "Unable to open device"
+ hscdio.cabal view
@@ -0,0 +1,277 @@+cabal-version:      2.4++name:               hscdio+author:             Sam May+category:           Sound+synopsis:           Haskell bindings to the libcdio disc-reading library.++version:            0.1.0.0+stability:          provisional+maintainer:         sam@eitilt.life++copyright:          (c) 2018-2021 Sam May+license:            GPL-3.0-or-later+license-file:       LICENSE+extra-source-files: CHANGELOG.md+                  , FEATURES+                  , README.md+                  , ROADMAP.md+                  , include/cdio/compat/*.h+                    -- The test suites will run relative to the source directory+                  , test/datafiles/**/*.bin+                  , test/datafiles/**/*.cdtext+                  , test/datafiles/**/*.cue+                  , test/datafiles/**/*.nrg+                  , test/datafiles/**/*.toc+                  , test/datafiles/**/*.txt++homepage:           https://ag.eitilt.life/hscdio+bug-reports:        mailto:ag@eitilt.life++description:+    The C library "libcdio" provides unified functions for reading data from+    CDs and disc images across an impressive range of operating sysems.  This+    package provides Haskell bindings for those functions, in both a format+    familiar to anyone who has used the original library, and a format more+    native to the Haskell ecosystem.++build-type:         Simple+tested-with:        GHC ==8.0.2, GHC ==8.2.2, GHC ==8.4.4, GHC ==8.6.5, GHC ==8.8.4, GHC ==8.10.4+++source-repository head+  type:             darcs+  location:         https://darcs.eitilt.life/hscdio++source-repository this+  type:             darcs+  location:         https://darcs.eitilt.life/hscdio+  tag:              v/0.1.0.0.+++source-repository head+  type:             darcs+  location:         https://hub.darcs.net/ag.eitilt/hscdio++source-repository this+  type:             darcs+  location:         https://hub.darcs.net/ag.eitilt/hscdio+  tag:              v/0.1.0.0.+++flag dev+  description:      Trigger stricter behaviour for development+  default:          False+  manual:           True++flag tools+  description:      Build developers' aids+  default:          False+  manual:           True+++common flags-ghc+  if flag(dev)+    ghc-options:    -Weverything+                    -Wno-unrecognised-pragmas+                    -Wno-implicit-prelude -Wno-missing-import-lists+                    -Wno-missing-exported-signatures -Wno-missing-local-signatures+                    -Wno-missed-specialisations -Wno-all-missed-specialisations+                    -Wno-safe -Wno-unsafe+                    -Wno-monomorphism-restriction+    if impl(ghc >= 8.4.1)+      ghc-options:  -Wno-missing-export-lists+    if impl(ghc >= 8.8.1)+      ghc-options:  -Wno-missing-deriving-strategies+    if impl(ghc >= 8.10.1)+      ghc-options:  -Wno-missing-safe-haskell-mode+                    -Wno-prepositive-qualified-module+  else+    ghc-options:    -Wno-unrecognised-pragmas+++library+  import:           flags-ghc+  hs-source-dirs:   src+  exposed-modules:  Data.Text.Encoding.MsJIS+                  , Foreign.Libcdio.CdText+                  , Foreign.Libcdio.CdTypes+                  , Foreign.Libcdio.Device+                  , Foreign.Libcdio.Disc+                  , Foreign.Libcdio.Logging+                  , Foreign.Libcdio.Read+                  , Foreign.Libcdio.Sector+                  , Foreign.Libcdio.Track+                  , Foreign.Libcdio.Types+                  , Foreign.Libcdio.Util+                  , Foreign.Libcdio.Version+                  , Foreign.Libcdio+                  , Sound.Libcdio+                  , Sound.Libcdio.Device+                  , Sound.Libcdio.Logging+                  , Sound.Libcdio.Read.CdText+                  , Sound.Libcdio.Read.Data+                  , Sound.Libcdio.Read.Filesystem+                  , Sound.Libcdio.Track+                  , Sound.Libcdio.Types+  other-modules:    Foreign.Libcdio.Marshal+                  , Foreign.Libcdio.CdText.Binary+                  , Foreign.Libcdio.Types.Enums+                  , Foreign.Libcdio.Types.Internal+                  , Foreign.Libcdio.Types.Offsets+                  , Sound.Libcdio.Common+                  , Sound.Libcdio.Types.Cdio+  -- Be sure to keep pkg/gentoo/dev-haskell/*.ebuild up to date+  build-depends:    base >=4.9 && <4.15+                  , bitwise >=0.1 && <1.1+                  , bytestring >=0.9 && <0.12+                  , containers <0.7+                  , mtl <2.3+                  , text >=0.3 && <1.3+                  , vector <0.13+  build-tool-depends: c2hs:c2hs >=0.26 && <0.29+  include-dirs:     include+  includes:         cdio/cdtext.h+                  , cdio/cdio.h+                  , cdio/cd_types.h+                  , cdio/device.h+                  , cdio/disc.h+                  , cdio/memory.h+                  , cdio/mmc.h+                  , cdio/track.h+                  , cdio/types.h+                  , cdio/sector.h+                  , cdio/util.h+                  , cdio/compat/cdtext.h+                  , cdio/compat/cd_types.h+                  , cdio/compat/cycle_break.h+                  , cdio/compat/device.h+                  , cdio/compat/disc.h+                  , cdio/compat/logging.h+                  , cdio/compat/mmc.h+                  , cdio/compat/read.h+                  , cdio/compat/sector.h+                  , cdio/compat/track.h+                  , cdio/compat/types.h+                  , cdio/compat/version.h+                  , stdint.h+                  , stdlib.h+                  , string.h+                  , unistd.h+  c-sources:        src/c/cdio/compat/cdtext.c+                  , src/c/cdio/compat/device.c+                  , src/c/cdio/compat/disc.c+                  , src/c/cdio/compat/logging.c+                  , src/c/cdio/compat/read.c+                  , src/c/cdio/compat/sector.c+                  , src/c/cdio/compat/track.c+                  , src/c/cdio/compat/types.c+                  , src/c/cdio/compat/version.c+  extra-libraries:  cdio+  default-language: Haskell2010+  other-extensions: CPP+                  , ForeignFunctionInterface+                  , MultiParamTypeClasses+                  , OverloadedStrings+                  , Trustworthy++test-suite property+  import:           flags-ghc+  type:             exitcode-stdio-1.0+  hs-source-dirs:   test+  if impl(ghc < 8.6.1)+    -- hedgehog-classes requires base>=4.12.0.0+    buildable:      False+  main-is:          Test/Libcdio/Property.hs+  other-modules:    Data.Text.Encoding.MsJIS.Test.Classes+                  , Foreign.Libcdio.CdText.Test.Classes+                  , Foreign.Libcdio.CdTypes.Test.Classes+                  , Foreign.Libcdio.Device.Test.Classes+                  , Foreign.Libcdio.Disc.Test.Classes+                  , Foreign.Libcdio.Logging.Test.Classes+                  , Foreign.Libcdio.Logging.Test.Property+                  , Foreign.Libcdio.Read.Test.Classes+                  , Foreign.Libcdio.Sector.Test.Classes+                  , Foreign.Libcdio.Track.Test.Classes+                  , Foreign.Libcdio.Util.Test.Classes+                  , Sound.Libcdio.Cdio.Test.Classes+                  , Sound.Libcdio.CdText.Test.Classes+                  , Test.Libcdio.Property.Common+  build-depends:    base+                  , hscdio+                  , hedgehog <1.1+                  , hedgehog-classes >=0.1.1.0 && <0.3+                  , text+  default-language: Haskell2010+  other-extensions: CPP+                  , OverloadedStrings++test-suite unit+  import:           flags-ghc+  type:             exitcode-stdio-1.0+  hs-source-dirs:   test+  main-is:          Test/Libcdio/Unit.hs+  other-modules:    Paths_hscdio+                  , Data.Text.Encoding.MsJIS.Test.Unit+                  , Test.Libcdio.Unit.Common+                  , Test.Libcdio.Unit.Foreign.CarolusRex+                  , Test.Libcdio.Unit.Foreign.DeeperDance+                  , Test.Libcdio.Unit.Foreign.RevolutionDays+                  , Test.Libcdio.Unit.Sound.Common+                  , Test.Libcdio.Unit.Sound.CarolusRex+                  , Test.Libcdio.Unit.Sound.DeeperDance+                  , Test.Libcdio.Unit.Sound.RevolutionDays+  autogen-modules:  Paths_hscdio+  build-depends:    base+                  , hscdio+                  , HUnit >=1.1 && <1.7+                  , base-compat >= 0.9.3 && <0.12+                  , bytestring+                  , text+  default-language: Haskell2010++test-suite upstream+  import:           flags-ghc+  type:             exitcode-stdio-1.0+  hs-source-dirs:   test+  main-is:          Test/Libcdio/Upstream.hs+  other-modules:    Paths_hscdio+                  , Test.Libcdio.Upstream.Foreign.Common+                  , Test.Libcdio.Upstream.Foreign.BinCue+                  , Test.Libcdio.Upstream.Foreign.CdrDao+                  , Test.Libcdio.Upstream.Foreign.FreeBsd+                  , Test.Libcdio.Upstream.Foreign.Linux+                  , Test.Libcdio.Upstream.Foreign.Nrg+                  , Test.Libcdio.Upstream.Foreign.OsX+                  , Test.Libcdio.Upstream.Foreign.Pregap+                  , Test.Libcdio.Upstream.Foreign.Solaris+                  , Test.Libcdio.Upstream.Foreign.SizeOf+                  , Test.Libcdio.Upstream.Foreign.Track+                  , Test.Libcdio.Upstream.Foreign.Win32+                  , Test.Libcdio.Upstream.Sound.Common+                  , Test.Libcdio.Upstream.Sound.Image+                  , Test.Libcdio.Upstream.Sound.System+                  , Test.Libcdio.Upstream.Sound.Track+  autogen-modules:  Paths_hscdio+  build-depends:    base+                  , hscdio+                  , HUnit >=1.1 && <1.7+                  , base-compat >= 0.9.3 && <0.12+                  , directory >=1.2.3 && <1.4+                  , text+  default-language: Haskell2010+  other-extensions: CPP+                  , OverloadedStrings++executable pack-cdtext+  import:           flags-ghc+  hs-source-dirs:   bin+  if !flag(tools)+    buildable:      False+  main-is:          Sound/Libcdio/PackCdText.hs+  build-depends:    base+                  , hscdio+                  , bytestring+                  , optparse-applicative+  default-language: Haskell2010+  other-extensions: CPP
+ include/cdio/compat/cd_types.h view
@@ -0,0 +1,29 @@+#ifndef __CDIO_COMPAT_CD_TYPES__+#define __CDIO_COMPAT_CD_TYPES__+++#include "cdio/compat/types.h"+#include "cdio/cd_types.h"++#include "stdint.h"+++// c2hs can't handle the `~` in CDIO_FS_MATCH_ALL+typedef enum {+    FS_ANAL_XA           = CDIO_FS_ANAL_XA,+    FS_ANAL_MULTISESSION = CDIO_FS_ANAL_MULTISESSION,+    FS_ANAL_PHOTO_CD     = CDIO_FS_ANAL_PHOTO_CD,+    FS_ANAL_HIDDEN_TRACK = CDIO_FS_ANAL_HIDDEN_TRACK,+    FS_ANAL_CDTV         = CDIO_FS_ANAL_CDTV,+    FS_ANAL_BOOTABLE     = CDIO_FS_ANAL_BOOTABLE,+    FS_ANAL_VIDEOCD      = CDIO_FS_ANAL_VIDEOCD,+    FS_ANAL_ROCKRIDGE    = CDIO_FS_ANAL_ROCKRIDGE,+    FS_ANAL_JOLIET       = CDIO_FS_ANAL_JOLIET,+    FS_ANAL_SVCD         = CDIO_FS_ANAL_SVCD,+    FS_ANAL_CVD          = CDIO_FS_ANAL_CVD,+    FS_ANAL_XISO         = CDIO_FS_ANAL_XISO,+    FS_ANAL_ISO9660_ANY  = CDIO_FS_ANAL_ISO9660_ANY+} fs_cap_t;+++#endif
+ include/cdio/compat/cdtext.h view
@@ -0,0 +1,36 @@+#ifndef __CDIO_COMPAT_CDTEXT__+#define __CDIO_COMPAT_CDTEXT__+++#include "cdio/cdtext.h"++#include "stdint.h"++// Required for 'DriverReturnCode' for some reason+#include "cdio/cdio.h"+++// Defined in a private header+#define CDTEXT_NUM_BLOCKS_MAX 8+++// FFI-compatible wrappers++cdtext_genre_t genre_unused();++cdtext_lang_t language_unknown();+cdtext_lang_t language_invalid();+cdtext_lang_t language_unused();+++// Symbol compatibility definitions++cdtext_lang_t cdtext_str2lang_safe(const char*);++int cdtext_data_init_safe(cdtext_t*, uint8_t*, size_t);++cdtext_lang_t* cdtext_list_languages_v2_safe(cdtext_t*);+bool cdtext_set_language_index_safe(cdtext_t*, int);+++#endif
+ include/cdio/compat/cycle_break.h view
@@ -0,0 +1,14 @@+#ifndef __CDIO_COMPAT_CYCLE_BREAK__+#define __CDIO_COMPAT_CYCLE_BREAK__+++// Several cdio headers don't support direct inclusion (they invoke cdio.h,+// which in turn brings in read.h before the device definitions that one needs)+// so short-circuit that loop by pretending cdio.h has already been processed.+#define __CDIO_H__++// That then requires the one symbol defined in cdio.h be created manually:+typedef struct _CdIo CdIo_t;+++#endif
+ include/cdio/compat/device.h view
@@ -0,0 +1,42 @@+#ifndef __CDIO_COMPAT_DEVICE__+#define __CDIO_COMPAT_DEVICE__+++#include "cdio/compat/cycle_break.h"+#include "cdio/device.h"+++// FFI-compatible wrappers++const unsigned int vendor_len();+const unsigned int model_len();+const unsigned int revision_len();++bitfield_t drive_cap_error();+bitfield_t drive_cap_unknown();++const driver_id_t* get_drivers();+const driver_id_t* get_device_drivers();+const driver_id_t get_os_driver();+++// Symbol compatibility definitions++#if LIBCDIO_SINCE_VERSION_1_0+// Keep the old enum values around, for broader compatibility.+#define DRIVER_BSDI (DRIVER_DEVICE+1)+#define DRIVER_OS2 (DRIVER_DEVICE+2)+#endif++CdIo_t* cdio_open_bsdi_safe(const char*);+CdIo_t* cdio_open_am_bsdi_safe(const char*, const char*);+char* cdio_get_default_device_bsdi_safe();+char** cdio_get_devices_bsdi_safe();++CdIo_t* cdio_open_os2_safe(const char*);+CdIo_t* cdio_open_am_os2_safe(const char*, const char*);+char* cdio_get_default_device_os2_safe();+char** cdio_get_devices_os2_safe();+++#endif
+ include/cdio/compat/disc.h view
@@ -0,0 +1,25 @@+#ifndef __CDIO_COMPAT_DISC__+#define __CDIO_COMPAT_DISC__+++#include "cdio/compat/cycle_break.h"+#include "cdio/compat/cdtext.h"+#include "cdio/disc.h"++#include "cdio/compat/track.h"+#include "cdio/compat/types.h"+++// FFI-compatible wrappers++const char* discmode_string(discmode_t);++discmode_t discmode_error();+++// Marshalling aids++void get_cdtext_raw_len(CdIo_t*, uint8_t**, unsigned int*);+++#endif
+ include/cdio/compat/logging.h view
@@ -0,0 +1,33 @@+#ifndef __CDIO_COMPAT_LOGGING__+#define __CDIO_COMPAT_LOGGING__++// Custom in-memory log management+++#include "cdio/compat/cycle_break.h"+#include "cdio/logging.h"+++// Combination log entry and linked list+typedef struct cdio_log_entry_s {+    cdio_log_level_t level;+    const char* message;+    struct cdio_log_entry_s* prev;+} cdio_log_entry_t;++// Root of the afore-mentioned linked list+cdio_log_entry_t* haskell_log;++// Register the custom handler with libcdio+void setup_cdio_logger();++// Control message filtering+cdio_log_level_t get_cdio_log_level();+void set_cdio_log_level(cdio_log_level_t);++// Access/clear the accumulated list+cdio_log_entry_t** read_cdio_log();+void free_cdio_log();+++#endif
+ include/cdio/compat/mmc.h view
@@ -0,0 +1,9 @@+#ifndef __CDIO_COMPAT_MMC__+#define __CDIO_COMPAT_MMC__+++#include "cdio/compat/device.h"+#include "cdio/mmc.h"+++#endif
+ include/cdio/compat/read.h view
@@ -0,0 +1,39 @@+#ifndef __CDIO_COMPAT_READ__+#define __CDIO_COMPAT_READ__+++#include "cdio/compat/device.h"+#include "cdio/read.h"++#include "unistd.h"+++// FFI-compatible wrappings++typedef enum {+    WHENCE_SEEK_START = SEEK_SET,+    WHENCE_SEEK_CURRENT = SEEK_CUR,+    WHENCE_SEEK_END = SEEK_END+} whence_t;+++// Marshalling aids++void read_bytes(const CdIo_t*, void**, ssize_t*, size_t);++driver_return_code_t read_sector(const CdIo_t*, void**, uint32_t*, lsn_t, cdio_read_mode_t);+driver_return_code_t read_sectors(const CdIo_t*, void**, uint32_t*, lsn_t, cdio_read_mode_t, uint32_t);++driver_return_code_t read_data_sectors(const CdIo_t*, void**, uint32_t*, lsn_t, uint16_t, uint32_t);++driver_return_code_t read_audio_sector(const CdIo_t*, void**, uint32_t*, lsn_t);+driver_return_code_t read_audio_sectors(const CdIo_t*, void**, uint32_t*, lsn_t, uint32_t);++driver_return_code_t read_mode1_sector(const CdIo_t*, void**, uint32_t*, lsn_t, bool);+driver_return_code_t read_mode1_sectors(const CdIo_t*, void**, uint32_t*, lsn_t, bool, uint32_t);++driver_return_code_t read_mode2_sector(const CdIo_t*, void**, uint32_t*, lsn_t, bool);+driver_return_code_t read_mode2_sectors(const CdIo_t*, void**, uint32_t*, lsn_t, bool, uint32_t);+++#endif
+ include/cdio/compat/sector.h view
@@ -0,0 +1,60 @@+#ifndef __CDIO_COMPAT_SECTOR__+#define __CDIO_COMPAT_SECTOR__+++#include "cdio/sector.h"++#include "stdint.h"+++// FFI-compatible wrappings++lsn_t min_lsn();+lsn_t max_lsn();++lba_t invalid_lba();+lsn_t invalid_lsn();++size_t sizeof_msf();++unsigned int pregap_sectors();+unsigned int postgap_sectors();++unsigned int cd_mins();+unsigned int secs_per_min();+unsigned int frames_per_min();+unsigned int frames_per_sec();+unsigned int chunks_per_frame();++unsigned int min_session();+unsigned int max_session();++unsigned int sync_size();+unsigned int chunk_size();+unsigned int framesize_sub();++unsigned int header_size();+unsigned int subheader_size();+unsigned int edc_size();+unsigned int mode1_pad_size();+unsigned int ecc_size();++unsigned int framesize();+unsigned int framesize_raw();+unsigned int framesize_rawer();+unsigned int framesize_raw0();+unsigned int framesize_raw1();++unsigned int header_size_xa();+unsigned int tail_size_xa();+unsigned int sync_size_xa();+unsigned int data_size_xa();+unsigned int tagged_size_xa();+++const uint8_t* sector_sync_header();++cdio_cd_minutes_sectors max_sectors();+++#endif
+ include/cdio/compat/track.h view
@@ -0,0 +1,21 @@+#ifndef __CDIO_COMPAT_TRACK__+#define __CDIO_COMPAT_TRACK__+++#include "cdio/compat/types.h"+#include "cdio/track.h"+++// FFI-compatible wrappings++const char* track_format_string(track_format_t);++track_t invalid_track();+track_t leadout_track();+track_t min_tracks();+track_t max_tracks();++track_format_t track_format_error();+++#endif
+ include/cdio/compat/types.h view
@@ -0,0 +1,13 @@+#ifndef __CDIO_COMPAT_TYPES__+#define __CDIO_COMPAT_TYPES__+++#include "cdio/compat/cycle_break.h"+#include "cdio/types.h"+++unsigned char mcn_length();+unsigned char isrc_length();+++#endif
+ include/cdio/compat/version.h view
@@ -0,0 +1,25 @@+#ifndef __CDIO_COMPAT_VERSION__+#define __CDIO_COMPAT_VERSION__+++#include "cdio/cdio.h"+#include "cdio/version.h"+++// FFI-compatible wrappings++const char* get_cdio_version_string();+const unsigned int get_cdio_version_num();+const unsigned int get_cdio_version_api();+++// Base library compatibility testing++#define LIBCDIO_SINCE_VERSION_0_94   (LIBCDIO_VERSION_NUM >= 94    || LIBCDIO_VERSION_NUM == 1)+#define LIBCDIO_SINCE_VERSION_1_0    (LIBCDIO_VERSION_NUM >= 10000 || LIBCDIO_VERSION_NUM == 1)+#define LIBCDIO_SINCE_VERSION_1_1    (LIBCDIO_VERSION_NUM >= 10100)+#define LIBCDIO_SINCE_VERSION_2_0    (LIBCDIO_VERSION_NUM >= 20000)+#define LIBCDIO_SINCE_VERSION_2_1    (LIBCDIO_VERSION_NUM >= 20100)+++#endif
+ src/Data/Text/Encoding/MsJIS.hs view
@@ -0,0 +1,1566 @@+{-# LANGUAGE Trustworthy #-}++{-|+Description:    Basic support for the Microsoft extension of Shift JIS.++Copyright:      (c) 2020-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      stable+Portability:    portable++The CdText standard technically allows for data encoded as Shift JIS; I am+unaware of any discs produced with such data as no member of the libcdio-dev+mailing list (or any of the very few other resources) have Japanese imports,+but for completion the ability to read that encoding is required.  This module+provides a light-weight implementation modeled on the "Data.Text.Encoding"+UTF-8 interface.+-}+module Data.Text.Encoding.MsJIS+    ( -- * Types+      JISChar ( .. )+    , JISDecodeError ( .. )+    , JISEncodeError ( .. )+      -- * Transformations+      -- ** Decode+    , decodeMsJIS'+    , decodeMsJISWith+      -- ** Encode+    , encodeMsJIS'+    , encodeMsJISWith+    ) where+++import qualified Data.ByteString as BS+import qualified Data.IntMap as M+import qualified Data.Maybe as Y+import qualified Data.Text as T+import qualified Data.Text.Encoding.Error as T+import qualified Data.Vector as V+import qualified Data.Word as W++import Data.Vector ( (!) )+++-- | A shorthand categorization scheme for representing the effect of a single+-- byte in the absence of existing context.+data First+    = None+        -- ^ The byte is invalid, perhaps unless preceded by a lead byte.+    | Lone Char+        -- ^ It represents the given character when not preceded by a lead+        -- byte.+    | Lead+        -- ^ The representation is dependant on the next byte in the stream.+  deriving ( Eq, Ord, Show, Read )++-- | The characters which may be represented under the Shift JIS encoding.+-- Note that this type is only exposed as part of error reporting or recovery+-- functions, and is not intended as a replacement of 'Char'.+data JISChar+    = Single W.Word8+    | Double W.Word8 W.Word8+  deriving ( Eq, Ord, Show, Read )+instance Bounded JISChar where+    minBound = Single minBound+    maxBound = Double 0xFC 0xFC+-- | Ignores the three invalid single-byte characters @"\xFD\xFE\xFF"@, and any+-- double-byte characters outside the primary range+-- @([0x81..0x9F]++[0xE0..0xFC], [0x40..0xFC])@.  'fromEnum' any such "invalid"+-- characters will overlap with the canonical characters, and the result should+-- not be relied upon to remain consistent between versions.+-- +-- >>> succ $ Single 0xFC+-- Double 0x81 0x40+-- +-- >>> succ $ Double 0x9F 0xFC+-- Double 0xE0 0x40+instance Enum JISChar where+    toEnum i+        | i <= 0xFC = Single $ fromIntegral i+        | otherwise = Double l t+      where (d, m) = divMod (i - 0xFD) 0xBC+            l = fromIntegral d + if d >= 0x1F+                -- First index of second table group (0xE0) minus first value of d here (0x1F)+                then 0xC1+                -- First index of first table group+                else 0x81+            -- First byte in trail tables+            t = fromIntegral m + 0x40+    fromEnum (Single c) = fromIntegral c+    -- Underlying: @s + (l' * x) + (t - y) + 1@+    -- +    -- s = Last single char (0xFC)+    -- l' = Table index (in [0x81..0x9F]++[0xE0..0xFC]): @l - w@+    -- l = Lead byte+    -- w = First byte of either first group (0x81) or second (0xE0)+    -- x = Length of tables (0xBC)+    -- t = Trail byte+    -- y = First byte in trail tables (0x40)+    -- +    -- s - y + 1 = 0xBD+    fromEnum (Double l t) = (l' * 0xBC) + fromIntegral t + 0xBD+      where l' = fromIntegral l - if l > 0x9F then 0xE0 else 0x81+++-- | The given one- or two- byte sequence was unable to be decoded; the error+-- may be described by the unstructured text.+data JISDecodeError = JISDecodeError String (Maybe JISChar)+  deriving ( Eq, Show, Read )++-- | The given character was unable to be serialized in binary form; this is+-- almost certainly due to it not being included in Shift JIS, but the error is+-- described by the unstructured text anyway.+data JISEncodeError = JISEncodeError String (Maybe Char)+  deriving ( Eq, Show, Read )+++-- | Lookup table for the broad category a byte falls into when not preceded+-- by a lead byte.+type FirstByteTable = V.Vector First++-- | The characters a two-byte sequence may decode to under the context of a+-- given lead byte.+type SecondByteTable = V.Vector (Maybe Char)+++-- | Transform a 'BS.ByteString' into unambiguous 'Char's according to+-- Microsoft's extension of the Shift JIS encoding scheme.+--+-- If the input contains any invalid sequences under that scheme, the first+-- byte(s) which triggered an error will be returned instead.+decodeMsJIS' :: BS.ByteString -> Either JISDecodeError T.Text+decodeMsJIS' = fmap T.pack . decodeMsJIS'' . BS.unpack++-- | Iterate through the byte stream, consuming one or two bytes each cycle as+-- required to decode a Shift JIS character.+--+-- If the input contains any invalid sequences under that scheme, the first+-- byte(s) which triggered an error will be returned instead.+decodeMsJIS'' :: [W.Word8] -> Either JISDecodeError String+decodeMsJIS'' [] = Right ""+decodeMsJIS'' (b1:bs) = case lookupJIS b1 $ Y.listToMaybe bs of+    (Left err, _) -> Left err+    (Right c, w) -> fmap (c :) . decodeMsJIS'' $ if w then drop 1 bs else bs+++-- | Transform a 'BS.ByteString' into unambiguous 'Char's according to+-- Microsoft's extension of the Shift JIS encoding scheme.+decodeMsJISWith :: T.OnError JISChar Char -> BS.ByteString -> T.Text+decodeMsJISWith e = T.pack . decodeMsJISWith' e . BS.unpack++-- | Iterate through the byte stream, consuming one or two bytes each cycle as+-- required to decode a Shift JIS character.+decodeMsJISWith' :: T.OnError JISChar Char -> [W.Word8] -> String+decodeMsJISWith' _ [] = ""+decodeMsJISWith' e (b1:bs) = case lookupJIS b1 $ Y.listToMaybe bs of+    (Left (JISDecodeError msg err), w) -> maybe (loop w) (: loop w) $ e msg err+    (Right c, w) -> c : loop w+  where loop _ | null bs = ""+        loop w = decodeMsJISWith' e $ if w then drop 1 bs else bs+++-- | Transform an unambiguous string into a binary stream according to+-- Microsoft's extension of the Shift JIS encoding scheme.+--+-- If the input contains any characters without an associated binary sequence+-- under that scheme, the first such character which triggers the error will be+-- returned instead.+encodeMsJIS' :: T.Text -> Either JISEncodeError BS.ByteString+encodeMsJIS' = T.foldl' (\bs -> throwEncode bs . flatten . lookupUnicode) (Right BS.empty)+  where throwEncode e@(Left _) _ = e+        throwEncode _ (Left c) = Left $ JISEncodeError (encodeErrorString "encodeMsJIS'") c+        throwEncode (Right bs) (Right bs') = Right $ mappend bs bs'++-- | Transform an unambiguous string into a binary stream according to+-- Microsoft's extension of the Shift JIS encoding scheme.+encodeMsJISWith :: T.OnError Char BS.ByteString -> T.Text -> BS.ByteString+encodeMsJISWith e = T.foldl' (\bs -> throwEncode bs . flatten . lookupUnicode) BS.empty+  where throwEncode bs (Left c) = Y.fromMaybe bs $ e (encodeErrorString "encodeMsJISWith") c+        throwEncode bs (Right bs') = mappend bs bs'++-- | There is only a single reason why encoding to Shift JIS may fail.+encodeErrorString :: String -> String+encodeErrorString func = func ++ ": Character not in MS JIS"++-- | Rewrap the result of a character-to-binary lookup into a form suitable for+-- 'JISEncodeError'.+flatten :: Either Char [BS.ByteString] -> Either (Maybe Char) BS.ByteString+flatten (Right []) = Left Nothing+flatten (Right (bs:_)) = Right bs+flatten (Left e) = Left $ Just e+++-- | The broad categories defining the behaviour of a byte in the Shift JIS+-- encoding scheme, in the absence of any existing context.  May be safely+-- indexed using any integer fitting into eight bits:+--+-- >>> length firstBytes+-- 255+firstBytes :: FirstByteTable+firstBytes = V.fromList $+    {-0x00..0x7F-}  map Lone ['\NUL'..'\DEL'] +++    {-0x80..0x9F-}  None : replicate 0x1F Lead +++    {-0xA0..0xDF-}  None : map Lone ['\xFF61'..'\xFF9F'] +++    {-0xE0..0xFC-}  replicate 0x1D Lead +++    {-0xFD..0xFF-}  replicate 3 None++-- | The lookup tables describing the representation of any valid two-byte+-- sequence in the Shift JIS encoding scheme.  As not every byte is a valid+-- lead byte (and thus may not have an indexed table), @lookupTrailTable@ is+-- recommended rather than direct indexing.  The presence or absence of a valid+-- character does not affect whether the subtable may be safely indexed:+--+-- >>> V.all ((==) 0xBC . length) secondBytes+-- True+secondBytes :: V.Vector SecondByteTable+secondBytes = V.fromList $+    [ second81, second82, second83, second84, second85, second86, second87 ] +++    [ second88, second89, second8A, second8B, second8C, second8D, second8E, second8F ] +++    [ second90, second91, second92, second93, second94, second95, second96, second97 ] +++    [ second98, second99, second9A, second9B, second9C, second9D, second9E, second9F ] +++    [ secondE0, secondE1, secondE2, secondE3, secondE4, secondE5, secondE6, secondE7 ] +++    [ secondE8, secondE9, secondEA, secondEB, secondEC, secondED, secondEE, secondEF ] +++    [ secondF0, secondF1, secondF2, secondF3, secondF4, secondF5, secondF6, secondF7 ] +++    [ secondF8, secondF9, secondFA, secondFB, secondFC ]++-- | Try to decode a one- or two-byte sequence to an unambiguous character+-- according to the Shift JIS encoding scheme.  Returns a 'Bool' indicating+-- whether the second byte was used in decoding the 'Char' (i.e., 'False'+-- indicates that the next character starts /on/ the second byte given rather+-- than /after/ it).+lookupJIS :: W.Word8 -> Maybe W.Word8 -> (Either JISDecodeError Char, Bool)+lookupJIS l t' = case (lookupLead l, t') of+    (SingleByte c, _) -> (Right c, False)+    (MultiByte _, Nothing) -> (err "Input ended without trail byte" $ Single l, False)+    (MultiByte ts, Just t) ->+        let found = ts ! (fromIntegral t - 0x40)+        in (maybe (err "Unassigned trail byte" $ Double l t) Right found, True)+    (NoChar e, _) -> (Left e, False)+  where err msg char = Left . JISDecodeError ("lookupJIS: " ++ msg) $ Just char++-- | Given the first byte in a (potentially multibyte) Shift JIS binary+-- representation, try to retrieve the associated character.+lookupLead :: W.Word8 -> LeadResult+lookupLead w = case firstBytes ! fromIntegral w of+    Lone c -> SingleByte c+    Lead -> maybe (err "Invalid lead byte") MultiByte $ lookupTrailTable w+    None -> err "Unassigned lead byte"+  where err msg = NoChar . JISDecodeError ("lookupJIS: " ++ msg) . Just $ Single w++-- | The potential values which may result from looking up a single byte in the+-- Shift JIS scheme without any preceding context.+data LeadResult+    = SingleByte Char+        -- ^ The byte represents a complete character.+    | MultiByte SecondByteTable+        -- ^ The byte indicates one of a set of characters which may only be+        -- disambiguated by the next byte in the stream.+    | NoChar JISDecodeError+        -- ^ The byte itself is invalid.++-- | Given the first byte in a multibyte Shift JIS binary representation, look+-- up what characters may be represented depending on the following byte in the+-- stream.  If the input is not a valid lead byte, 'Nothing' is returned+-- instead.  The presence or absence of a valid character does not affect+-- whether the subtable may be safely indexed (but note that position @0@ is+-- associated with byte @0x40@):+--+-- >>> maybe True ((==) 0xBC . length) $ lookupTrailTable b+-- True+lookupTrailTable :: W.Word8 -> Maybe SecondByteTable+lookupTrailTable l+    | l < 0x81 ||+        (l > 0x9F && l < 0xE0) ||+        l > 0xFC = Nothing+    | l <= 0x9F = Just $ secondBytes ! (fromIntegral l - 0x81)+    | otherwise = Just $ secondBytes ! (fromIntegral l - 0xC1)++++-- | The lookup table from Unicode character reference number to Shift JIS+-- binary representation.+unicodeMap :: M.IntMap [JISChar]+unicodeMap = M.fromListWith (++) . V.toList $+    V.imapMaybe keyFirsts firstBytes V.++ V.concat (V.toList $ V.imap keySeconds secondBytes)++-- | Transformation function to obtain a lookup-tuple from a single-byte Shift+-- JIS representation.+keyFirsts+    :: Int+        -- ^ The index (i.e., the byte itself) in the list of single- and+        -- lead-byte categories.+    -> First+        -- ^ The category associated with that byte; everything /except/ @Lone@+        -- bytes will be ignored.+    -> Maybe (M.Key, [JISChar])+keyFirsts l (Lone j) = Just (fromEnum j, [Single $ fromIntegral l])+keyFirsts _ _ = Nothing++-- | Transformation function to obtain all lookup-tuples of double-byte Shift+-- JIS representations beginning with the given byte.+keySeconds+    :: Int+        -- ^ The index (i.e., the byte itself) in the list of single- and+        -- lead-byte categories.+    -> SecondByteTable+        -- ^ The trailing-byte lookup table associated with that lead byte.+    -> V.Vector (M.Key, [JISChar])+keySeconds l = V.imapMaybe (\t j -> m (Double l' $ fromIntegral t + 0x40) <$> j)+  where l' = fromIntegral $ l + if l < 0x1F then 0x81 else 0xC1+        m t' j' = (fromEnum j', [t'])+++-- | Given a particular character, retrieve all its potential binary+-- representations in the Shift JIS encoding scheme.+lookupUnicode :: Char -> Either Char [BS.ByteString]+lookupUnicode c = case M.lookup (fromEnum c) unicodeMap of+    Just js -> Right $ map pack js+    Nothing -> Left c+  where pack (Single w) = BS.singleton w+        pack (Double l t) = BS.pack [l, t]+++-- * Multi-byte lookup tables++-- | A continuous sequence of valid multibyte characters.+chars :: String -> [Maybe Char]+chars = map Just++-- | A continuous sequence of unassigned multibyte characters.+nothings :: Int -> [Maybe Char]+nothings = flip replicate Nothing++-- | Generate an entire table of "valid" multibyte characters, without any+-- actual assigned characters.+nothingSecond :: SecondByteTable+nothingSecond = V.replicate 0xC0 Nothing++-- | Generate an entire table of multibyte characters which map to a portion of+-- the Private Use Area (i.e., are reserved for program- or company-internal+-- use).+privateUseSecond :: W.Word16 -> SecondByteTable+privateUseSecond b = V.fromList $+    {-0x40..0x7F-}  map (Just . toEnum . fromIntegral) [b..b + 0x3E] ++ Nothing :+    {-0x80..0xFC-}  map (Just . toEnum . fromIntegral) [b + 0x3F..b + 0xBB]+++-- | The multibyte characters with a lead byte of @0x81@.+second81 :: SecondByteTable+second81 = V.fromList $+    {-0x40-}  chars "\x3000\x3001\x3002\xFF0C\xFF0E\x30FB\xFF1A\xFF1B" +++    {-0x48-}  chars "\xFF1F\xFF01\x309B\x309C\x00B4\xFF40\x00A8\xFF3E" +++    {-0x50-}  chars "\xFFE3\xFF3F\x30FD\x30FE\x309D\x309E\x3003\x4EDD" +++    {-0x58-}  chars "\x3005\x3006\x3007\x30FC\x2015\x2010\xFF0F\xFF3C" +++    {-0x60-}  chars "\xFF5E\x2225\xFF5C\x2026\x2025\x2018\x2019\x201C" +++    {-0x68-}  chars "\x201D\xFF08\xFF09\x3014\x3015\xFF3B\xFF3D\xFF5B" +++    {-0x70-}  chars "\xFF5D\x3008\x3009\x300A\x300B\x300C\x300D\x300E" +++    {-0x78-}  chars "\x300F\x3010\x3011\xFF0B\xFF0D\x00B1\x00D7" ++ Nothing :+    {-0x80-}  chars "\x00F7\xFF1D\x2260\xFF1C\xFF1E\x2266\x2267\x221E" +++    {-0x88-}  chars "\x2234\x2642\x2640\x00B0\x2032\x2033\x2103\xFFE5" +++    {-0x90-}  chars "\xFF04\xFFE0\xFFE1\xFF05\xFF03\xFF06\xFF0A\xFF20" +++    {-0x98-}  chars "\x00A7\x2606\x2605\x25CB\x25CF\x25CE\x25C7\x25C6" +++    {-0xA0-}  chars "\x25A1\x25A0\x25B3\x25B2\x25BD\x25BC\x203B\x3012" +++    {-0xA8-}  chars "\x2192\x2190\x2191\x2193\x3013" ++ nothings 3 +++    {-0xB0-}  nothings 8 +++    {-0xB8-}  chars "\x2208\x220B\x2286\x2287\x2282\x2283\x222A\x2229" +++    {-0xC0-}  nothings 8 +++    {-0xC8-}  chars "\x2227\x2228\xFFE2\x21D2\x21D4\x2200\x2203" ++ Nothing :+    {-0xD0-}  nothings 8 +++    {-0xD8-}  nothings 2 ++ chars "\x2220\x22A5\x2312\x2202\x2207\x2261" +++    {-0xE0-}  chars "\x2252\x226A\x226B\x221A\x223D\x221D\x2235\x222B" +++    {-0xE8-}  Just '\x222C' : nothings 7 +++    {-0xF0-}  chars "\x212B\x2030\x266F\x266D\x266A\x2020\x2021\x00B6" +++    {-0xF8-}  nothings 4 ++ [Just '\x25EF']++-- | The multibyte characters with a lead byte of @0x82@.+second82 :: SecondByteTable+second82 = V.fromList $+    {-0x40..0x4E-}  nothings 15 +++    {-0x4F..0x58-}  chars ['\xFF10'..'\xFF19'] +++    {-0x59..0x5F-}  nothings 7 +++    {-0x60..0x79-}  chars ['\xFF21'..'\xFF3A'] +++    {-0x7A..0x80-}  nothings 7 +++    {-0x81..0x9A-}  chars ['\xFF41'..'\xFF5A'] +++    {-0x9B..0x9E-}  nothings 4 +++    {-0x9F..0xF1-}  chars ['\x3041'..'\x3093'] +++    {-0xF2..0xFC-}  nothings 11++-- | The multibyte characters with a lead byte of @0x83@.+second83 :: SecondByteTable+second83 = V.fromList $+    {-0x40..0x7F-}  chars ['\x30A1'..'\x30DF'] ++ Nothing :+    {-0x80..0x96-}  chars ['\x30E0'..'\x30F6'] +++    {-0x97..0x9E-}  nothings 8 +++    {-0x9F..0xAF-}  chars ['\x0391'..'\x03A1'] +++    {-0xB0..0xB6-}  chars ['\x03A3'..'\x03A9'] +++    {-0xB7..0xBE-}  nothings 8 +++    {-0xBF..0xCF-}  chars ['\x03B1'..'\x03C1'] +++    {-0xD0..0xD6-}  chars ['\x03C3'..'\x03C9'] +++    {-0xD7..0xFC-}  nothings 0x26++-- | The multibyte characters with a lead byte of @0x84@.+second84 :: SecondByteTable+second84 = V.fromList $+    {-0x40..0x46-}  chars ['\x0410'..'\x0415'] ++ Just '\x0401' :+    {-0x47..0x60-}  chars ['\x0416'..'\x042F'] +++    {-0x61..0x6F-}  nothings 15 +++    {-0x60..0x66-}  chars ['\x0430'..'\x0435'] ++ Just '\x0451' :+    {-0x67..0x7F-}  chars ['\x0436'..'\x043D'] ++ Nothing :+    {-0x80..0x91-}  chars ['\x043E'..'\x044F'] +++    {-0x92..0x9F-}  nothings 13 ++ Just '\x2500' :+    {-0xA0-}  chars "\x2502\x250C\x2510\x2518\x2514\x251C\x252C\x2524" +++    {-0xA8-}  chars "\x2534\x253C\x2501\x2503\x250F\x2513\x251B\x2517" +++    {-0xB0-}  chars "\x2523\x2533\x252B\x253B\x254B\x2520\x252F\x2528" +++    {-0xB8-}  chars "\x2537\x253F\x251D\x2530\x2525\x2538\x2542" +++    {-0xBF..0xFC-}  nothings 0x3E++-- | The multibyte characters with a lead byte of @0x85@.+second85 :: SecondByteTable+second85 = nothingSecond++-- | The multibyte characters with a lead byte of @0x86@.+second86 :: SecondByteTable+second86 = nothingSecond++-- | The multibyte characters with a lead byte of @0x87@.+second87 :: SecondByteTable+second87 = V.fromList $+    {-0x40..0x53-}  chars ['\x2460'..'\x2473'] +++    {-0x54..0x5F-}  chars ['\x2160'..'\x2169'] ++ Nothing : Just '\x3349' :+    {-0x60-}  chars "\x3314\x3322\x334D\x3318\x3327\x3303\x3336\x3351" +++    {-0x68-}  chars "\x3357\x330D\x3326\x3323\x332B\x334A\x333B\x339C" +++    {-0x70-}  chars "\x339D\x339E\x338E\x338F\x33C4\x33A1" +++    {-0x76..0x7F-}  nothings 8 ++ Just '\x337B' : Nothing :+    {-0x80-}  chars "\x301D\x301F\x2116\x33CD\x2121\x32A4\x32A5\x32A6" +++    {-0x88-}  chars "\x32A7\x32A8\x3231\x3232\x3239\x337E\x337D\x337C" +++    {-0x90-}  chars "\x2252\x2261\x222B\x222E\x2211\x221A\x22A5\x2220" +++    {-0x98-}  chars "\x221F\x22BF\x2235\x2229\x222A" +++    {-0x9D..0xFC-}  nothings 0x60++-- | The multibyte characters with a lead byte of @0x88@.+second88 :: SecondByteTable+second88 = V.fromList $+    {-0x40..0x9F-}  nothings 0x5F ++ Just '\x4E9C' :+    {-0xA0-}  chars "\x5516\x5A03\x963F\x54C0\x611B\x6328\x59F6\x9022" +++    {-0xA8-}  chars "\x8475\x831C\x7A50\x60AA\x63E1\x6E25\x65ED\x8466" +++    {-0xB0-}  chars "\x82A6\x9BF5\x6893\x5727\x65A1\x6271\x5B9B\x59D0" +++    {-0xB8-}  chars "\x867B\x98F4\x7D62\x7DBE\x9B8E\x6216\x7C9F\x88B7" +++    {-0xC0-}  chars "\x5B89\x5EB5\x6309\x6697\x6848\x95C7\x978D\x674F" +++    {-0xC8-}  chars "\x4EE5\x4F0A\x4F4D\x4F9D\x5049\x56F2\x5937\x59D4" +++    {-0xD0-}  chars "\x5A01\x5C09\x60DF\x610F\x6170\x6613\x6905\x70BA" +++    {-0xD8-}  chars "\x754F\x7570\x79FB\x7DAD\x7DEF\x80C3\x840E\x8863" +++    {-0xE0-}  chars "\x8B02\x9055\x907A\x533B\x4E95\x4EA5\x57DF\x80B2" +++    {-0xE8-}  chars "\x90C1\x78EF\x4E00\x58F1\x6EA2\x9038\x7A32\x8328" +++    {-0xF0-}  chars "\x828B\x9C2F\x5141\x5370\x54BD\x54E1\x56E0\x59FB" +++    {-0xF8-}  chars "\x5F15\x98F2\x6DEB\x80E4\x852D"++-- | The multibyte characters with a lead byte of @0x89@.+second89 :: SecondByteTable+second89 = V.fromList $+    {-0x40-}  chars "\x9662\x9670\x96A0\x97FB\x540B\x53F3\x5B87\x70CF" +++    {-0x48-}  chars "\x7FBD\x8FC2\x96E8\x536F\x9D5C\x7ABA\x4E11\x7893" +++    {-0x50-}  chars "\x81FC\x6E26\x5618\x5504\x6B1D\x851A\x9C3B\x59E5" +++    {-0x58-}  chars "\x53A9\x6D66\x74DC\x958F\x5642\x4E91\x904B\x96F2" +++    {-0x60-}  chars "\x834F\x990C\x53E1\x55B6\x5B30\x5F71\x6620\x66F3" +++    {-0x68-}  chars "\x6804\x6C38\x6CF3\x6D29\x745B\x76C8\x7A4E\x9834" +++    {-0x70-}  chars "\x82F1\x885B\x8A60\x92ED\x6DB2\x75AB\x76CA\x99C5" +++    {-0x78-}  chars "\x60A6\x8B01\x8D8A\x95B2\x698E\x53AD\x5186" ++ Nothing :+    {-0x80-}  chars "\x5712\x5830\x5944\x5BB4\x5EF6\x6028\x63A9\x63F4" +++    {-0x88-}  chars "\x6CBF\x6F14\x708E\x7114\x7159\x71D5\x733F\x7E01" +++    {-0x90-}  chars "\x8276\x82D1\x8597\x9060\x925B\x9D1B\x5869\x65BC" +++    {-0x98-}  chars "\x6C5A\x7525\x51F9\x592E\x5965\x5F80\x5FDC\x62BC" +++    {-0xA0-}  chars "\x65FA\x6A2A\x6B27\x6BB4\x738B\x7FC1\x8956\x9D2C" +++    {-0xA8-}  chars "\x9D0E\x9EC4\x5CA1\x6C96\x837B\x5104\x5C4B\x61B6" +++    {-0xB0-}  chars "\x81C6\x6876\x7261\x4E59\x4FFA\x5378\x6069\x6E29" +++    {-0xB8-}  chars "\x7A4F\x97F3\x4E0B\x5316\x4EEE\x4F55\x4F3D\x4FA1" +++    {-0xC0-}  chars "\x4F73\x52A0\x53EF\x5609\x590F\x5AC1\x5BB6\x5BE1" +++    {-0xC8-}  chars "\x79D1\x6687\x679C\x67B6\x6B4C\x6CB3\x706B\x73C2" +++    {-0xD0-}  chars "\x798D\x79BE\x7A3C\x7B87\x82B1\x82DB\x8304\x8377" +++    {-0xD8-}  chars "\x83EF\x83D3\x8766\x8AB2\x5629\x8CA8\x8FE6\x904E" +++    {-0xE0-}  chars "\x971E\x868A\x4FC4\x5CE8\x6211\x7259\x753B\x81E5" +++    {-0xE8-}  chars "\x82BD\x86FE\x8CC0\x96C5\x9913\x99D5\x4ECB\x4F1A" +++    {-0xF0-}  chars "\x89E3\x56DE\x584A\x58CA\x5EFB\x5FEB\x602A\x6094" +++    {-0xF8-}  chars "\x6062\x61D0\x6212\x62D0\x6539"++-- | The multibyte characters with a lead byte of @0x8A@.+second8A :: SecondByteTable+second8A = V.fromList $+    {-0x40-}  chars "\x9B41\x6666\x68B0\x6D77\x7070\x754C\x7686\x7D75" +++    {-0x48-}  chars "\x82A5\x87F9\x958B\x968E\x8C9D\x51F1\x52BE\x5916" +++    {-0x50-}  chars "\x54B3\x5BB3\x5D16\x6168\x6982\x6DAF\x788D\x84CB" +++    {-0x58-}  chars "\x8857\x8A72\x93A7\x9AB8\x6D6C\x99A8\x86D9\x57A3" +++    {-0x60-}  chars "\x67FF\x86CE\x920E\x5283\x5687\x5404\x5ED3\x62E1" +++    {-0x68-}  chars "\x64B9\x683C\x6838\x6BBB\x7372\x78BA\x7A6B\x899A" +++    {-0x70-}  chars "\x89D2\x8D6B\x8F03\x90ED\x95A3\x9694\x9769\x5B66" +++    {-0x78-}  chars "\x5CB3\x697D\x984D\x984E\x639B\x7B20\x6A2B" ++ Nothing :+    {-0x80-}  chars "\x6A7F\x68B6\x9C0D\x6F5F\x5272\x559D\x6070\x62EC" +++    {-0x88-}  chars "\x6D3B\x6E07\x6ED1\x845B\x8910\x8F44\x4E14\x9C39" +++    {-0x90-}  chars "\x53F6\x691B\x6A3A\x9784\x682A\x515C\x7AC3\x84B2" +++    {-0x98-}  chars "\x91DC\x938C\x565B\x9D28\x6822\x8305\x8431\x7CA5" +++    {-0xA0-}  chars "\x5208\x82C5\x74E6\x4E7E\x4F83\x51A0\x5BD2\x520A" +++    {-0xA8-}  chars "\x52D8\x52E7\x5DFB\x559A\x582A\x59E6\x5B8C\x5B98" +++    {-0xB0-}  chars "\x5BDB\x5E72\x5E79\x60A3\x611F\x6163\x61BE\x63DB" +++    {-0xB8-}  chars "\x6562\x67D1\x6853\x68FA\x6B3E\x6B53\x6C57\x6F22" +++    {-0xC0-}  chars "\x6F97\x6F45\x74B0\x7518\x76E3\x770B\x7AFF\x7BA1" +++    {-0xC8-}  chars "\x7C21\x7DE9\x7F36\x7FF0\x809D\x8266\x839E\x89B3" +++    {-0xD0-}  chars "\x8ACC\x8CAB\x9084\x9451\x9593\x9591\x95A2\x9665" +++    {-0xD8-}  chars "\x97D3\x9928\x8218\x4E38\x542B\x5CB8\x5DCC\x73A9" +++    {-0xE0-}  chars "\x764C\x773C\x5CA9\x7FEB\x8D0B\x96C1\x9811\x9854" +++    {-0xE8-}  chars "\x9858\x4F01\x4F0E\x5371\x559C\x5668\x57FA\x5947" +++    {-0xF0-}  chars "\x5B09\x5BC4\x5C90\x5E0C\x5E7E\x5FCC\x63EE\x673A" +++    {-0xF8-}  chars "\x65D7\x65E2\x671F\x68CB\x68C4"++-- | The multibyte characters with a lead byte of @0x8B@.+second8B :: SecondByteTable+second8B = V.fromList $+    {-0x40-}  chars "\x6A5F\x5E30\x6BC5\x6C17\x6C7D\x757F\x7948\x5B63" +++    {-0x48-}  chars "\x7A00\x7D00\x5FBD\x898F\x8A18\x8CB4\x8D77\x8ECC" +++    {-0x50-}  chars "\x8F1D\x98E2\x9A0E\x9B3C\x4E80\x507D\x5100\x5993" +++    {-0x58-}  chars "\x5B9C\x622F\x6280\x64EC\x6B3A\x72A0\x7591\x7947" +++    {-0x60-}  chars "\x7FA9\x87FB\x8ABC\x8B70\x63AC\x83CA\x97A0\x5409" +++    {-0x68-}  chars "\x5403\x55AB\x6854\x6A58\x8A70\x7827\x6775\x9ECD" +++    {-0x70-}  chars "\x5374\x5BA2\x811A\x8650\x9006\x4E18\x4E45\x4EC7" +++    {-0x78-}  chars "\x4F11\x53CA\x5438\x5BAE\x5F13\x6025\x6551" ++ Nothing :+    {-0x80-}  chars "\x673D\x6C42\x6C72\x6CE3\x7078\x7403\x7A76\x7AAE" +++    {-0x88-}  chars "\x7B08\x7D1A\x7CFE\x7D66\x65E7\x725B\x53BB\x5C45" +++    {-0x90-}  chars "\x5DE8\x62D2\x62E0\x6319\x6E20\x865A\x8A31\x8DDD" +++    {-0x98-}  chars "\x92F8\x6F01\x79A6\x9B5A\x4EA8\x4EAB\x4EAC\x4F9B" +++    {-0xA0-}  chars "\x4FA0\x50D1\x5147\x7AF6\x5171\x51F6\x5354\x5321" +++    {-0xA8-}  chars "\x537F\x53EB\x55AC\x5883\x5CE1\x5F37\x5F4A\x602F" +++    {-0xB0-}  chars "\x6050\x606D\x631F\x6559\x6A4B\x6CC1\x72C2\x72ED" +++    {-0xB8-}  chars "\x77EF\x80F8\x8105\x8208\x854E\x90F7\x93E1\x97FF" +++    {-0xC0-}  chars "\x9957\x9A5A\x4EF0\x51DD\x5C2D\x6681\x696D\x5C40" +++    {-0xC8-}  chars "\x66F2\x6975\x7389\x6850\x7C81\x50C5\x52E4\x5747" +++    {-0xD0-}  chars "\x5DFE\x9326\x65A4\x6B23\x6B3D\x7434\x7981\x79BD" +++    {-0xD8-}  chars "\x7B4B\x7DCA\x82B9\x83CC\x887F\x895F\x8B39\x8FD1" +++    {-0xE0-}  chars "\x91D1\x541F\x9280\x4E5D\x5036\x53E5\x533A\x72D7" +++    {-0xE8-}  chars "\x7396\x77E9\x82E6\x8EAF\x99C6\x99C8\x99D2\x5177" +++    {-0xF0-}  chars "\x611A\x865E\x55B0\x7A7A\x5076\x5BD3\x9047\x9685" +++    {-0xF8-}  chars "\x4E32\x6ADB\x91E7\x5C51\x5C48"++-- | The multibyte characters with a lead byte of @0x8C@.+second8C :: SecondByteTable+second8C = V.fromList $+    {-0x40-}  chars "\x6398\x7A9F\x6C93\x9774\x8F61\x7AAA\x718A\x9688" +++    {-0x48-}  chars "\x7C82\x6817\x7E70\x6851\x936C\x52F2\x541B\x85AB" +++    {-0x50-}  chars "\x8A13\x7FA4\x8ECD\x90E1\x5366\x8888\x7941\x4FC2" +++    {-0x58-}  chars "\x50BE\x5211\x5144\x5553\x572D\x73EA\x578B\x5951" +++    {-0x60-}  chars "\x5F62\x5F84\x6075\x6176\x6167\x61A9\x63B2\x643A" +++    {-0x68-}  chars "\x656C\x666F\x6842\x6E13\x7566\x7A3D\x7CFB\x7D4C" +++    {-0x70-}  chars "\x7D99\x7E4B\x7F6B\x830E\x834A\x86CD\x8A08\x8A63" +++    {-0x78-}  chars "\x8B66\x8EFD\x981A\x9D8F\x82B8\x8FCE\x9BE8" ++ Nothing :+    {-0x80-}  chars "\x5287\x621F\x6483\x6FC0\x9699\x6841\x5091\x6B20" +++    {-0x88-}  chars "\x6C7A\x6F54\x7A74\x7D50\x8840\x8A23\x6708\x4EF6" +++    {-0x90-}  chars "\x5039\x5026\x5065\x517C\x5238\x5263\x55A7\x570F" +++    {-0x98-}  chars "\x5805\x5ACC\x5EFA\x61B2\x61F8\x62F3\x6372\x691C" +++    {-0xA0-}  chars "\x6A29\x727D\x72AC\x732E\x7814\x786F\x7D79\x770C" +++    {-0xA8-}  chars "\x80A9\x898B\x8B19\x8CE2\x8ED2\x9063\x9375\x967A" +++    {-0xB0-}  chars "\x9855\x9A13\x9E78\x5143\x539F\x53B3\x5E7B\x5F26" +++    {-0xB8-}  chars "\x6E1B\x6E90\x7384\x73FE\x7D43\x8237\x8A00\x8AFA" +++    {-0xC0-}  chars "\x9650\x4E4E\x500B\x53E4\x547C\x56FA\x59D1\x5B64" +++    {-0xC8-}  chars "\x5DF1\x5EAB\x5F27\x6238\x6545\x67AF\x6E56\x72D0" +++    {-0xD0-}  chars "\x7CCA\x88B4\x80A1\x80E1\x83F0\x864E\x8A87\x8DE8" +++    {-0xD8-}  chars "\x9237\x96C7\x9867\x9F13\x4E94\x4E92\x4F0D\x5348" +++    {-0xE0-}  chars "\x5449\x543E\x5A2F\x5F8C\x5FA1\x609F\x68A7\x6A8E" +++    {-0xE8-}  chars "\x745A\x7881\x8A9E\x8AA4\x8B77\x9190\x4E5E\x9BC9" +++    {-0xF0-}  chars "\x4EA4\x4F7C\x4FAF\x5019\x5016\x5149\x516C\x529F" +++    {-0xF8-}  chars "\x52B9\x52FE\x539A\x53E3\x5411"++-- | The multibyte characters with a lead byte of @0x8D@.+second8D :: SecondByteTable+second8D = V.fromList $+    {-0x40-}  chars "\x540E\x5589\x5751\x57A2\x597D\x5B54\x5B5D\x5B8F" +++    {-0x48-}  chars "\x5DE5\x5DE7\x5DF7\x5E78\x5E83\x5E9A\x5EB7\x5F18" +++    {-0x50-}  chars "\x6052\x614C\x6297\x62D8\x63A7\x653B\x6602\x6643" +++    {-0x58-}  chars "\x66F4\x676D\x6821\x6897\x69CB\x6C5F\x6D2A\x6D69" +++    {-0x60-}  chars "\x6E2F\x6E9D\x7532\x7687\x786C\x7A3F\x7CE0\x7D05" +++    {-0x68-}  chars "\x7D18\x7D5E\x7DB1\x8015\x8003\x80AF\x80B1\x8154" +++    {-0x70-}  chars "\x818F\x822A\x8352\x884C\x8861\x8B1B\x8CA2\x8CFC" +++    {-0x78-}  chars "\x90CA\x9175\x9271\x783F\x92FC\x95A4\x964D" ++ Nothing :+    {-0x80-}  chars "\x9805\x9999\x9AD8\x9D3B\x525B\x52AB\x53F7\x5408" +++    {-0x88-}  chars "\x58D5\x62F7\x6FE0\x8C6A\x8F5F\x9EB9\x514B\x523B" +++    {-0x90-}  chars "\x544A\x56FD\x7A40\x9177\x9D60\x9ED2\x7344\x6F09" +++    {-0x98-}  chars "\x8170\x7511\x5FFD\x60DA\x9AA8\x72DB\x8FBC\x6B64" +++    {-0xA0-}  chars "\x9803\x4ECA\x56F0\x5764\x58BE\x5A5A\x6068\x61C7" +++    {-0xA8-}  chars "\x660F\x6606\x6839\x68B1\x6DF7\x75D5\x7D3A\x826E" +++    {-0xB0-}  chars "\x9B42\x4E9B\x4F50\x53C9\x5506\x5D6F\x5DE6\x5DEE" +++    {-0xB8-}  chars "\x67FB\x6C99\x7473\x7802\x8A50\x9396\x88DF\x5750" +++    {-0xC0-}  chars "\x5EA7\x632B\x50B5\x50AC\x518D\x6700\x54C9\x585E" +++    {-0xC8-}  chars "\x59BB\x5BB0\x5F69\x624D\x63A1\x683D\x6B73\x6E08" +++    {-0xD0-}  chars "\x707D\x91C7\x7280\x7815\x7826\x796D\x658E\x7D30" +++    {-0xD8-}  chars "\x83DC\x88C1\x8F09\x969B\x5264\x5728\x6750\x7F6A" +++    {-0xE0-}  chars "\x8CA1\x51B4\x5742\x962A\x583A\x698A\x80B4\x54B2" +++    {-0xE8-}  chars "\x5D0E\x57FC\x7895\x9DFA\x4F5C\x524A\x548B\x643E" +++    {-0xF0-}  chars "\x6628\x6714\x67F5\x7A84\x7B56\x7D22\x932F\x685C" +++    {-0xF8-}  chars "\x9BAD\x7B39\x5319\x518A\x5237"++-- | The multibyte characters with a lead byte of @0x8E@.+second8E :: SecondByteTable+second8E = V.fromList $+    {-0x40-}  chars "\x5BDF\x62F6\x64AE\x64E6\x672D\x6BBA\x85A9\x96D1" +++    {-0x48-}  chars "\x7690\x9BD6\x634C\x9306\x9BAB\x76BF\x6652\x4E09" +++    {-0x50-}  chars "\x5098\x53C2\x5C71\x60E8\x6492\x6563\x685F\x71E6" +++    {-0x58-}  chars "\x73CA\x7523\x7B97\x7E82\x8695\x8B83\x8CDB\x9178" +++    {-0x60-}  chars "\x9910\x65AC\x66AB\x6B8B\x4ED5\x4ED4\x4F3A\x4F7F" +++    {-0x68-}  chars "\x523A\x53F8\x53F2\x55E3\x56DB\x58EB\x59CB\x59C9" +++    {-0x70-}  chars "\x59FF\x5B50\x5C4D\x5E02\x5E2B\x5FD7\x601D\x6307" +++    {-0x78-}  chars "\x652F\x5B5C\x65AF\x65BD\x65E8\x679D\x6B62" ++ Nothing :+    {-0x80-}  chars "\x6B7B\x6C0F\x7345\x7949\x79C1\x7CF8\x7D19\x7D2B" +++    {-0x88-}  chars "\x80A2\x8102\x81F3\x8996\x8A5E\x8A69\x8A66\x8A8C" +++    {-0x90-}  chars "\x8AEE\x8CC7\x8CDC\x96CC\x98FC\x6B6F\x4E8B\x4F3C" +++    {-0x98-}  chars "\x4F8D\x5150\x5B57\x5BFA\x6148\x6301\x6642\x6B21" +++    {-0xA0-}  chars "\x6ECB\x6CBB\x723E\x74BD\x75D4\x78C1\x793A\x800C" +++    {-0xA8-}  chars "\x8033\x81EA\x8494\x8F9E\x6C50\x9E7F\x5F0F\x8B58" +++    {-0xB0-}  chars "\x9D2B\x7AFA\x8EF8\x5B8D\x96EB\x4E03\x53F1\x57F7" +++    {-0xB8-}  chars "\x5931\x5AC9\x5BA4\x6089\x6E7F\x6F06\x75BE\x8CEA" +++    {-0xC0-}  chars "\x5B9F\x8500\x7BE0\x5072\x67F4\x829D\x5C61\x854A" +++    {-0xC8-}  chars "\x7E1E\x820E\x5199\x5C04\x6368\x8D66\x659C\x716E" +++    {-0xD0-}  chars "\x793E\x7D17\x8005\x8B1D\x8ECA\x906E\x86C7\x90AA" +++    {-0xD8-}  chars "\x501F\x52FA\x5C3A\x6753\x707C\x7235\x914C\x91C8" +++    {-0xE0-}  chars "\x932B\x82E5\x5BC2\x5F31\x60F9\x4E3B\x53D6\x5B88" +++    {-0xE8-}  chars "\x624B\x6731\x6B8A\x72E9\x73E0\x7A2E\x816B\x8DA3" +++    {-0xF0-}  chars "\x9152\x9996\x5112\x53D7\x546A\x5BFF\x6388\x6A39" +++    {-0xF8-}  chars "\x7DAC\x9700\x56DA\x53CE\x5468"++-- | The multibyte characters with a lead byte of @0x8F@.+second8F :: SecondByteTable+second8F = V.fromList $+    {-0x40-}  chars "\x5B97\x5C31\x5DDE\x4FEE\x6101\x62FE\x6D32\x79C0" +++    {-0x48-}  chars "\x79CB\x7D42\x7E4D\x7FD2\x81ED\x821F\x8490\x8846" +++    {-0x50-}  chars "\x8972\x8B90\x8E74\x8F2F\x9031\x914B\x916C\x96C6" +++    {-0x58-}  chars "\x919C\x4EC0\x4F4F\x5145\x5341\x5F93\x620E\x67D4" +++    {-0x60-}  chars "\x6C41\x6E0B\x7363\x7E26\x91CD\x9283\x53D4\x5919" +++    {-0x68-}  chars "\x5BBF\x6DD1\x795D\x7E2E\x7C9B\x587E\x719F\x51FA" +++    {-0x70-}  chars "\x8853\x8FF0\x4FCA\x5CFB\x6625\x77AC\x7AE3\x821C" +++    {-0x78-}  chars "\x99FF\x51C6\x5FAA\x65EC\x696F\x6B89\x6DF3" ++ Nothing :+    {-0x80-}  chars "\x6E96\x6F64\x76FE\x7D14\x5DE1\x9075\x9187\x9806" +++    {-0x88-}  chars "\x51E6\x521D\x6240\x6691\x66D9\x6E1A\x5EB6\x7DD2" +++    {-0x90-}  chars "\x7F72\x66F8\x85AF\x85F7\x8AF8\x52A9\x53D9\x5973" +++    {-0x98-}  chars "\x5E8F\x5F90\x6055\x92E4\x9664\x50B7\x511F\x52DD" +++    {-0xA0-}  chars "\x5320\x5347\x53EC\x54E8\x5546\x5531\x5617\x5968" +++    {-0xA8-}  chars "\x59BE\x5A3C\x5BB5\x5C06\x5C0F\x5C11\x5C1A\x5E84" +++    {-0xB0-}  chars "\x5E8A\x5EE0\x5F70\x627F\x6284\x62DB\x638C\x6377" +++    {-0xB8-}  chars "\x6607\x660C\x662D\x6676\x677E\x68A2\x6A1F\x6A35" +++    {-0xC0-}  chars "\x6CBC\x6D88\x6E09\x6E58\x713C\x7126\x7167\x75C7" +++    {-0xC8-}  chars "\x7701\x785D\x7901\x7965\x79F0\x7AE0\x7B11\x7CA7" +++    {-0xD0-}  chars "\x7D39\x8096\x83D6\x848B\x8549\x885D\x88F3\x8A1F" +++    {-0xD8-}  chars "\x8A3C\x8A54\x8A73\x8C61\x8CDE\x91A4\x9266\x937E" +++    {-0xE0-}  chars "\x9418\x969C\x9798\x4E0A\x4E08\x4E1E\x4E57\x5197" +++    {-0xE8-}  chars "\x5270\x57CE\x5834\x58CC\x5B22\x5E38\x60C5\x64FE" +++    {-0xF0-}  chars "\x6761\x6756\x6D44\x72B6\x7573\x7A63\x84B8\x8B72" +++    {-0xF8-}  chars "\x91B8\x9320\x5631\x57F4\x98FE"++-- | The multibyte characters with a lead byte of @0x90@.+second90 :: SecondByteTable+second90 = V.fromList $+    {-0x40-}  chars "\x62ED\x690D\x6B96\x71ED\x7E54\x8077\x8272\x89E6" +++    {-0x48-}  chars "\x98DF\x8755\x8FB1\x5C3B\x4F38\x4FE1\x4FB5\x5507" +++    {-0x50-}  chars "\x5A20\x5BDD\x5BE9\x5FC3\x614E\x632F\x65B0\x664B" +++    {-0x58-}  chars "\x68EE\x699B\x6D78\x6DF1\x7533\x75B9\x771F\x795E" +++    {-0x60-}  chars "\x79E6\x7D33\x81E3\x82AF\x85AA\x89AA\x8A3A\x8EAB" +++    {-0x68-}  chars "\x8F9B\x9032\x91DD\x9707\x4EBA\x4EC1\x5203\x5875" +++    {-0x70-}  chars "\x58EC\x5C0B\x751A\x5C3D\x814E\x8A0A\x8FC5\x9663" +++    {-0x78-}  chars "\x976D\x7B25\x8ACF\x9808\x9162\x56F3\x53A8" ++ Nothing :+    {-0x80-}  chars "\x9017\x5439\x5782\x5E25\x63A8\x6C34\x708A\x7761" +++    {-0x88-}  chars "\x7C8B\x7FE0\x8870\x9042\x9154\x9310\x9318\x968F" +++    {-0x90-}  chars "\x745E\x9AC4\x5D07\x5D69\x6570\x67A2\x8DA8\x96DB" +++    {-0x98-}  chars "\x636E\x6749\x6919\x83C5\x9817\x96C0\x88FE\x6F84" +++    {-0xA0-}  chars "\x647A\x5BF8\x4E16\x702C\x755D\x662F\x51C4\x5236" +++    {-0xA8-}  chars "\x52E2\x59D3\x5F81\x6027\x6210\x653F\x6574\x661F" +++    {-0xB0-}  chars "\x6674\x68F2\x6816\x6B63\x6E05\x7272\x751F\x76DB" +++    {-0xB8-}  chars "\x7CBE\x8056\x58F0\x88FD\x897F\x8AA0\x8A93\x8ACB" +++    {-0xC0-}  chars "\x901D\x9192\x9752\x9759\x6589\x7A0E\x8106\x96BB" +++    {-0xC8-}  chars "\x5E2D\x60DC\x621A\x65A5\x6614\x6790\x77F3\x7A4D" +++    {-0xD0-}  chars "\x7C4D\x7E3E\x810A\x8CAC\x8D64\x8DE1\x8E5F\x78A9" +++    {-0xD8-}  chars "\x5207\x62D9\x63A5\x6442\x6298\x8A2D\x7A83\x7BC0" +++    {-0xE0-}  chars "\x8AAC\x96EA\x7D76\x820C\x8749\x4ED9\x5148\x5343" +++    {-0xE8-}  chars "\x5360\x5BA3\x5C02\x5C16\x5DDD\x6226\x6247\x64B0" +++    {-0xF0-}  chars "\x6813\x6834\x6CC9\x6D45\x6D17\x67D3\x6F5C\x714E" +++    {-0xF8-}  chars "\x717D\x65CB\x7A7F\x7BAD\x7DDA"++-- | The multibyte characters with a lead byte of @0x91@.+second91 :: SecondByteTable+second91 = V.fromList $+    {-0x40-}  chars "\x7E4A\x7FA8\x817A\x821B\x8239\x85A6\x8A6E\x8CCE" +++    {-0x48-}  chars "\x8DF5\x9078\x9077\x92AD\x9291\x9583\x9BAE\x524D" +++    {-0x50-}  chars "\x5584\x6F38\x7136\x5168\x7985\x7E55\x81B3\x7CCE" +++    {-0x58-}  chars "\x564C\x5851\x5CA8\x63AA\x66FE\x66FD\x695A\x72D9" +++    {-0x60-}  chars "\x758F\x758E\x790E\x7956\x79DF\x7C97\x7D20\x7D44" +++    {-0x68-}  chars "\x8607\x8A34\x963B\x9061\x9F20\x50E7\x5275\x53CC" +++    {-0x70-}  chars "\x53E2\x5009\x55AA\x58EE\x594F\x723D\x5B8B\x5C64" +++    {-0x78-}  chars "\x531D\x60E3\x60F3\x635C\x6383\x633F\x63BB" ++ Nothing :+    {-0x80-}  chars "\x64CD\x65E9\x66F9\x5DE3\x69CD\x69FD\x6F15\x71E5" +++    {-0x88-}  chars "\x4E89\x75E9\x76F8\x7A93\x7CDF\x7DCF\x7D9C\x8061" +++    {-0x90-}  chars "\x8349\x8358\x846C\x84BC\x85FB\x88C5\x8D70\x9001" +++    {-0x98-}  chars "\x906D\x9397\x971C\x9A12\x50CF\x5897\x618E\x81D3" +++    {-0xA0-}  chars "\x8535\x8D08\x9020\x4FC3\x5074\x5247\x5373\x606F" +++    {-0xA8-}  chars "\x6349\x675F\x6E2C\x8DB3\x901F\x4FD7\x5C5E\x8CCA" +++    {-0xB0-}  chars "\x65CF\x7D9A\x5352\x8896\x5176\x63C3\x5B58\x5B6B" +++    {-0xB8-}  chars "\x5C0A\x640D\x6751\x905C\x4ED6\x591A\x592A\x6C70" +++    {-0xC0-}  chars "\x8A51\x553E\x5815\x59A5\x60F0\x6253\x67C1\x8235" +++    {-0xC8-}  chars "\x6955\x9640\x99C4\x9A28\x4F53\x5806\x5BFE\x8010" +++    {-0xD0-}  chars "\x5CB1\x5E2F\x5F85\x6020\x614B\x6234\x66FF\x6CF0" +++    {-0xD8-}  chars "\x6EDE\x80CE\x817F\x82D4\x888B\x8CB8\x9000\x902E" +++    {-0xE0-}  chars "\x968A\x9EDB\x9BDB\x4EE3\x53F0\x5927\x7B2C\x918D" +++    {-0xE8-}  chars "\x984C\x9DF9\x6EDD\x7027\x5353\x5544\x5B85\x6258" +++    {-0xF0-}  chars "\x629E\x62D3\x6CA2\x6FEF\x7422\x8A17\x9438\x6FC1" +++    {-0xF8-}  chars "\x8AFE\x8338\x51E7\x86F8\x53EA"++-- | The multibyte characters with a lead byte of @0x92@.+second92 :: SecondByteTable+second92 = V.fromList $+    {-0x40-}  chars "\x53E9\x4F46\x9054\x8FB0\x596A\x8131\x5DFD\x7AEA" +++    {-0x48-}  chars "\x8FBF\x68DA\x8C37\x72F8\x9C48\x6A3D\x8AB0\x4E39" +++    {-0x50-}  chars "\x5358\x5606\x5766\x62C5\x63A2\x65E6\x6B4E\x6DE1" +++    {-0x58-}  chars "\x6E5B\x70AD\x77ED\x7AEF\x7BAA\x7DBB\x803D\x80C6" +++    {-0x60-}  chars "\x86CB\x8A95\x935B\x56E3\x58C7\x5F3E\x65AD\x6696" +++    {-0x68-}  chars "\x6A80\x6BB5\x7537\x8AC7\x5024\x77E5\x5730\x5F1B" +++    {-0x70-}  chars "\x6065\x667A\x6C60\x75F4\x7A1A\x7F6E\x81F4\x8718" +++    {-0x78-}  chars "\x9045\x99B3\x7BC9\x755C\x7AF9\x7B51\x84C4" ++ Nothing :+    {-0x80-}  chars "\x9010\x79E9\x7A92\x8336\x5AE1\x7740\x4E2D\x4EF2" +++    {-0x88-}  chars "\x5B99\x5FE0\x62BD\x663C\x67F1\x6CE8\x866B\x8877" +++    {-0x90-}  chars "\x8A3B\x914E\x92F3\x99D0\x6A17\x7026\x732A\x82E7" +++    {-0x98-}  chars "\x8457\x8CAF\x4E01\x5146\x51CB\x558B\x5BF5\x5E16" +++    {-0xA0-}  chars "\x5E33\x5E81\x5F14\x5F35\x5F6B\x5FB4\x61F2\x6311" +++    {-0xA8-}  chars "\x66A2\x671D\x6F6E\x7252\x753A\x773A\x8074\x8139" +++    {-0xB0-}  chars "\x8178\x8776\x8ABF\x8ADC\x8D85\x8DF3\x929A\x9577" +++    {-0xB8-}  chars "\x9802\x9CE5\x52C5\x6357\x76F4\x6715\x6C88\x73CD" +++    {-0xC0-}  chars "\x8CC3\x93AE\x9673\x6D25\x589C\x690E\x69CC\x8FFD" +++    {-0xC8-}  chars "\x939A\x75DB\x901A\x585A\x6802\x63B4\x69FB\x4F43" +++    {-0xD0-}  chars "\x6F2C\x67D8\x8FBB\x8526\x7DB4\x9354\x693F\x6F70" +++    {-0xD8-}  chars "\x576A\x58F7\x5B2C\x7D2C\x722A\x540A\x91E3\x9DB4" +++    {-0xE0-}  chars "\x4EAD\x4F4E\x505C\x5075\x5243\x8C9E\x5448\x5824" +++    {-0xE8-}  chars "\x5B9A\x5E1D\x5E95\x5EAD\x5EF7\x5F1F\x608C\x62B5" +++    {-0xF0-}  chars "\x633A\x63D0\x68AF\x6C40\x7887\x798E\x7A0B\x7DE0" +++    {-0xF8-}  chars "\x8247\x8A02\x8AE6\x8E44\x9013"++-- | The multibyte characters with a lead byte of @0x93@.+second93 :: SecondByteTable+second93 = V.fromList $+    {-0x40-}  chars "\x90B8\x912D\x91D8\x9F0E\x6CE5\x6458\x64E2\x6575" +++    {-0x48-}  chars "\x6EF4\x7684\x7B1B\x9069\x93D1\x6EBA\x54F2\x5FB9" +++    {-0x50-}  chars "\x64A4\x8F4D\x8FED\x9244\x5178\x586B\x5929\x5C55" +++    {-0x58-}  chars "\x5E97\x6DFB\x7E8F\x751C\x8CBC\x8EE2\x985B\x70B9" +++    {-0x60-}  chars "\x4F1D\x6BBF\x6FB1\x7530\x96FB\x514E\x5410\x5835" +++    {-0x68-}  chars "\x5857\x59AC\x5C60\x5F92\x6597\x675C\x6E21\x767B" +++    {-0x70-}  chars "\x83DF\x8CED\x9014\x90FD\x934D\x7825\x783A\x52AA" +++    {-0x78-}  chars "\x5EA6\x571F\x5974\x6012\x5012\x515A\x51AC" ++ Nothing :+    {-0x80-}  chars "\x51CD\x5200\x5510\x5854\x5858\x5957\x5B95\x5CF6" +++    {-0x88-}  chars "\x5D8B\x60BC\x6295\x642D\x6771\x6843\x68BC\x68DF" +++    {-0x90-}  chars "\x76D7\x6DD8\x6E6F\x6D9B\x706F\x71C8\x5F53\x75D8" +++    {-0x98-}  chars "\x7977\x7B49\x7B54\x7B52\x7CD6\x7D71\x5230\x8463" +++    {-0xA0-}  chars "\x8569\x85E4\x8A0E\x8B04\x8C46\x8E0F\x9003\x900F" +++    {-0xA8-}  chars "\x9419\x9676\x982D\x9A30\x95D8\x50CD\x52D5\x540C" +++    {-0xB0-}  chars "\x5802\x5C0E\x61A7\x649E\x6D1E\x77B3\x7AE5\x80F4" +++    {-0xB8-}  chars "\x8404\x9053\x9285\x5CE0\x9D07\x533F\x5F97\x5FB3" +++    {-0xC0-}  chars "\x6D9C\x7279\x7763\x79BF\x7BE4\x6BD2\x72EC\x8AAD" +++    {-0xC8-}  chars "\x6803\x6A61\x51F8\x7A81\x6934\x5C4A\x9CF6\x82EB" +++    {-0xD0-}  chars "\x5BC5\x9149\x701E\x5678\x5C6F\x60C7\x6566\x6C8C" +++    {-0xD8-}  chars "\x8C5A\x9041\x9813\x5451\x66C7\x920D\x5948\x90A3" +++    {-0xE0-}  chars "\x5185\x4E4D\x51EA\x8599\x8B0E\x7058\x637A\x934B" +++    {-0xE8-}  chars "\x6962\x99B4\x7E04\x7577\x5357\x6960\x8EDF\x96E3" +++    {-0xF0-}  chars "\x6C5D\x4E8C\x5C3C\x5F10\x8FE9\x5302\x8CD1\x8089" +++    {-0xF8-}  chars "\x8679\x5EFF\x65E5\x4E73\x5165"++-- | The multibyte characters with a lead byte of @0x94@.+second94 :: SecondByteTable+second94 = V.fromList $+    {-0x40-}  chars "\x5982\x5C3F\x97EE\x4EFB\x598A\x5FCD\x8A8D\x6FE1" +++    {-0x48-}  chars "\x79B0\x7962\x5BE7\x8471\x732B\x71B1\x5E74\x5FF5" +++    {-0x50-}  chars "\x637B\x649A\x71C3\x7C98\x4E43\x5EFC\x4E4B\x57DC" +++    {-0x58-}  chars "\x56A2\x60A9\x6FC3\x7D0D\x80FD\x8133\x81BF\x8FB2" +++    {-0x60-}  chars "\x8997\x86A4\x5DF4\x628A\x64AD\x8987\x6777\x6CE2" +++    {-0x68-}  chars "\x6D3E\x7436\x7834\x5A46\x7F75\x82AD\x99AC\x4FF3" +++    {-0x70-}  chars "\x5EC3\x62DD\x6392\x6557\x676F\x76C3\x724C\x80CC" +++    {-0x78-}  chars "\x80BA\x8F29\x914D\x500D\x57F9\x5A92\x6885" ++ Nothing :+    {-0x80-}  chars "\x6973\x7164\x72FD\x8CB7\x58F2\x8CE0\x966A\x9019" +++    {-0x88-}  chars "\x877F\x79E4\x77E7\x8429\x4F2F\x5265\x535A\x62CD" +++    {-0x90-}  chars "\x67CF\x6CCA\x767D\x7B94\x7C95\x8236\x8584\x8FEB" +++    {-0x98-}  chars "\x66DD\x6F20\x7206\x7E1B\x83AB\x99C1\x9EA6\x51FD" +++    {-0xA0-}  chars "\x7BB1\x7872\x7BB8\x8087\x7B48\x6AE8\x5E61\x808C" +++    {-0xA8-}  chars "\x7551\x7560\x516B\x9262\x6E8C\x767A\x9197\x9AEA" +++    {-0xB0-}  chars "\x4F10\x7F70\x629C\x7B4F\x95A5\x9CE9\x567A\x5859" +++    {-0xB8-}  chars "\x86E4\x96BC\x4F34\x5224\x534A\x53CD\x53DB\x5E06" +++    {-0xC0-}  chars "\x642C\x6591\x677F\x6C3E\x6C4E\x7248\x72AF\x73ED" +++    {-0xC8-}  chars "\x7554\x7E41\x822C\x85E9\x8CA9\x7BC4\x91C6\x7169" +++    {-0xD0-}  chars "\x9812\x98EF\x633D\x6669\x756A\x76E4\x78D0\x8543" +++    {-0xD8-}  chars "\x86EE\x532A\x5351\x5426\x5983\x5E87\x5F7C\x60B2" +++    {-0xE0-}  chars "\x6249\x6279\x62AB\x6590\x6BD4\x6CCC\x75B2\x76AE" +++    {-0xE8-}  chars "\x7891\x79D8\x7DCB\x7F77\x80A5\x88AB\x8AB9\x8CBB" +++    {-0xF0-}  chars "\x907F\x975E\x98DB\x6A0B\x7C38\x5099\x5C3E\x5FAE" +++    {-0xF8-}  chars "\x6787\x6BD8\x7435\x7709\x7F8E"++-- | The multibyte characters with a lead byte of @0x95@.+second95 :: SecondByteTable+second95 = V.fromList $+    {-0x40-}  chars "\x9F3B\x67CA\x7A17\x5339\x758B\x9AED\x5F66\x819D" +++    {-0x48-}  chars "\x83F1\x8098\x5F3C\x5FC5\x7562\x7B46\x903C\x6867" +++    {-0x50-}  chars "\x59EB\x5A9B\x7D10\x767E\x8B2C\x4FF5\x5F6A\x6A19" +++    {-0x58-}  chars "\x6C37\x6F02\x74E2\x7968\x8868\x8A55\x8C79\x5EDF" +++    {-0x60-}  chars "\x63CF\x75C5\x79D2\x82D7\x9328\x92F2\x849C\x86ED" +++    {-0x68-}  chars "\x9C2D\x54C1\x5F6C\x658C\x6D5C\x7015\x8CA7\x8CD3" +++    {-0x70-}  chars "\x983B\x654F\x74F6\x4E0D\x4ED8\x57E0\x592B\x5A66" +++    {-0x78-}  chars "\x5BCC\x51A8\x5E03\x5E9C\x6016\x6276\x6577" ++ Nothing :+    {-0x80-}  chars "\x65A7\x666E\x6D6E\x7236\x7B26\x8150\x819A\x8299" +++    {-0x88-}  chars "\x8B5C\x8CA0\x8CE6\x8D74\x961C\x9644\x4FAE\x64AB" +++    {-0x90-}  chars "\x6B66\x821E\x8461\x856A\x90E8\x5C01\x6953\x98A8" +++    {-0x98-}  chars "\x847A\x8557\x4F0F\x526F\x5FA9\x5E45\x670D\x798F" +++    {-0xA0-}  chars "\x8179\x8907\x8986\x6DF5\x5F17\x6255\x6CB8\x4ECF" +++    {-0xA8-}  chars "\x7269\x9B92\x5206\x543B\x5674\x58B3\x61A4\x626E" +++    {-0xB0-}  chars "\x711A\x596E\x7C89\x7CDE\x7D1B\x96F0\x6587\x805E" +++    {-0xB8-}  chars "\x4E19\x4F75\x5175\x5840\x5E63\x5E73\x5F0A\x67C4" +++    {-0xC0-}  chars "\x4E26\x853D\x9589\x965B\x7C73\x9801\x50FB\x58C1" +++    {-0xC8-}  chars "\x7656\x78A7\x5225\x77A5\x8511\x7B86\x504F\x5909" +++    {-0xD0-}  chars "\x7247\x7BC7\x7DE8\x8FBA\x8FD4\x904D\x4FBF\x52C9" +++    {-0xD8-}  chars "\x5A29\x5F01\x97AD\x4FDD\x8217\x92EA\x5703\x6355" +++    {-0xE0-}  chars "\x6B69\x752B\x88DC\x8F14\x7A42\x52DF\x5893\x6155" +++    {-0xE8-}  chars "\x620A\x66AE\x6BCD\x7C3F\x83E9\x5023\x4FF8\x5305" +++    {-0xF0-}  chars "\x5446\x5831\x5949\x5B9D\x5CF0\x5CEF\x5D29\x5E96" +++    {-0xF8-}  chars "\x62B1\x6367\x653E\x65B9\x670B"++-- | The multibyte characters with a lead byte of @0x96@.+second96 :: SecondByteTable+second96 = V.fromList $+    {-0x40-}  chars "\x6CD5\x6CE1\x70F9\x7832\x7E2B\x80DE\x82B3\x840C" +++    {-0x48-}  chars "\x84EC\x8702\x8912\x8A2A\x8C4A\x90A6\x92D2\x98FD" +++    {-0x50-}  chars "\x9CF3\x9D6C\x4E4F\x4EA1\x508D\x5256\x574A\x59A8" +++    {-0x58-}  chars "\x5E3D\x5FD8\x5FD9\x623F\x66B4\x671B\x67D0\x68D2" +++    {-0x60-}  chars "\x5192\x7D21\x80AA\x81A8\x8B00\x8C8C\x8CBF\x927E" +++    {-0x68-}  chars "\x9632\x5420\x982C\x5317\x50D5\x535C\x58A8\x64B2" +++    {-0x70-}  chars "\x6734\x7267\x7766\x7A46\x91E6\x52C3\x6CA1\x6B86" +++    {-0x78-}  chars "\x5800\x5E4C\x5954\x672C\x7FFB\x51E1\x76C6" ++ Nothing :+    {-0x80-}  chars "\x6469\x78E8\x9B54\x9EBB\x57CB\x59B9\x6627\x679A" +++    {-0x88-}  chars "\x6BCE\x54E9\x69D9\x5E55\x819C\x6795\x9BAA\x67FE" +++    {-0x90-}  chars "\x9C52\x685D\x4EA6\x4FE3\x53C8\x62B9\x672B\x6CAB" +++    {-0x98-}  chars "\x8FC4\x4FAD\x7E6D\x9EBF\x4E07\x6162\x6E80\x6F2B" +++    {-0xA0-}  chars "\x8513\x5473\x672A\x9B45\x5DF3\x7B95\x5CAC\x5BC6" +++    {-0xA8-}  chars "\x871C\x6E4A\x84D1\x7A14\x8108\x5999\x7C8D\x6C11" +++    {-0xB0-}  chars "\x7720\x52D9\x5922\x7121\x725F\x77DB\x9727\x9D61" +++    {-0xB8-}  chars "\x690B\x5A7F\x5A18\x51A5\x540D\x547D\x660E\x76DF" +++    {-0xC0-}  chars "\x8FF7\x9298\x9CF4\x59EA\x725D\x6EC5\x514D\x68C9" +++    {-0xC8-}  chars "\x7DBF\x7DEC\x9762\x9EBA\x6478\x6A21\x8302\x5984" +++    {-0xD0-}  chars "\x5B5F\x6BDB\x731B\x76F2\x7DB2\x8017\x8499\x5132" +++    {-0xD8-}  chars "\x6728\x9ED9\x76EE\x6762\x52FF\x9905\x5C24\x623B" +++    {-0xE0-}  chars "\x7C7E\x8CB0\x554F\x60B6\x7D0B\x9580\x5301\x4E5F" +++    {-0xE8-}  chars "\x51B6\x591C\x723A\x8036\x91CE\x5F25\x77E2\x5384" +++    {-0xF0-}  chars "\x5F79\x7D04\x85AC\x8A33\x8E8D\x9756\x67F3\x85AE" +++    {-0xF8-}  chars "\x9453\x6109\x6108\x6CB9\x7652"++-- | The multibyte characters with a lead byte of @0x97@.+second97 :: SecondByteTable+second97 = V.fromList $+    {-0x40-}  chars "\x8AED\x8F38\x552F\x4F51\x512A\x52C7\x53CB\x5BA5" +++    {-0x48-}  chars "\x5E7D\x60A0\x6182\x63D6\x6709\x67DA\x6E67\x6D8C" +++    {-0x50-}  chars "\x7336\x7337\x7531\x7950\x88D5\x8A98\x904A\x9091" +++    {-0x58-}  chars "\x90F5\x96C4\x878D\x5915\x4E88\x4F59\x4E0E\x8A89" +++    {-0x60-}  chars "\x8F3F\x9810\x50AD\x5E7C\x5996\x5BB9\x5EB8\x63DA" +++    {-0x68-}  chars "\x63FA\x64C1\x66DC\x694A\x69D8\x6D0B\x6EB6\x7194" +++    {-0x70-}  chars "\x7528\x7AAF\x7F8A\x8000\x8449\x84C9\x8981\x8B21" +++    {-0x78-}  chars "\x8E0A\x9065\x967D\x990A\x617E\x6291\x6B32" ++ Nothing :+    {-0x80-}  chars "\x6C83\x6D74\x7FCC\x7FFC\x6DC0\x7F85\x87BA\x88F8" +++    {-0x88-}  chars "\x6765\x83B1\x983C\x96F7\x6D1B\x7D61\x843D\x916A" +++    {-0x90-}  chars "\x4E71\x5375\x5D50\x6B04\x6FEB\x85CD\x862D\x89A7" +++    {-0x98-}  chars "\x5229\x540F\x5C65\x674E\x68A8\x7406\x7483\x75E2" +++    {-0xA0-}  chars "\x88CF\x88E1\x91CC\x96E2\x9678\x5F8B\x7387\x7ACB" +++    {-0xA8-}  chars "\x844E\x63A0\x7565\x5289\x6D41\x6E9C\x7409\x7559" +++    {-0xB0-}  chars "\x786B\x7C92\x9686\x7ADC\x9F8D\x4FB6\x616E\x65C5" +++    {-0xB8-}  chars "\x865C\x4E86\x4EAE\x50DA\x4E21\x51CC\x5BEE\x6599" +++    {-0xC0-}  chars "\x6881\x6DBC\x731F\x7642\x77AD\x7A1C\x7CE7\x826F" +++    {-0xC8-}  chars "\x8AD2\x907C\x91CF\x9675\x9818\x529B\x7DD1\x502B" +++    {-0xD0-}  chars "\x5398\x6797\x6DCB\x71D0\x7433\x81E8\x8F2A\x96A3" +++    {-0xD8-}  chars "\x9C57\x9E9F\x7460\x5841\x6D99\x7D2F\x985E\x4EE4" +++    {-0xE0-}  chars "\x4F36\x4F8B\x51B7\x52B1\x5DBA\x601C\x73B2\x793C" +++    {-0xE8-}  chars "\x82D3\x9234\x96B7\x96F6\x970A\x9E97\x9F62\x66A6" +++    {-0xF0-}  chars "\x6B74\x5217\x52A3\x70C8\x88C2\x5EC9\x604B\x6190" +++    {-0xF8-}  chars "\x6F23\x7149\x7C3E\x7DF4\x806F"++-- | The multibyte characters with a lead byte of @0x98@.+second98 :: SecondByteTable+second98 = V.fromList $+    {-0x40-}  chars "\x84EE\x9023\x932C\x5442\x9B6F\x6AD3\x7089\x8CC2" +++    {-0x48-}  chars "\x8DEF\x9732\x52B4\x5A41\x5ECA\x5F04\x6717\x697C" +++    {-0x50-}  chars "\x6994\x6D6A\x6F0F\x7262\x72FC\x7BED\x8001\x807E" +++    {-0x58-}  chars "\x874B\x90CE\x516D\x9E93\x7984\x808B\x9332\x8AD6" +++    {-0x60-}  chars "\x502D\x548C\x8A71\x6B6A\x8CC4\x8107\x60D1\x67A0" +++    {-0x68-}  chars "\x9DF2\x4E99\x4E98\x9C10\x8A6B\x85C1\x8568\x6900" +++    {-0x70-}  chars "\x6E7E\x7897\x8155" +++    {-0x73..0x9F-} nothings 0x2C ++ Just '\x5F0C' :+    {-0xA0-}  chars "\x4E10\x4E15\x4E2A\x4E31\x4E36\x4E3C\x4E3F\x4E42" +++    {-0xA8-}  chars "\x4E56\x4E58\x4E82\x4E85\x8C6B\x4E8A\x8212\x5F0D" +++    {-0xB0-}  chars "\x4E8E\x4E9E\x4E9F\x4EA0\x4EA2\x4EB0\x4EB3\x4EB6" +++    {-0xB8-}  chars "\x4ECE\x4ECD\x4EC4\x4EC6\x4EC2\x4ED7\x4EDE\x4EED" +++    {-0xC0-}  chars "\x4EDF\x4EF7\x4F09\x4F5A\x4F30\x4F5B\x4F5D\x4F57" +++    {-0xC8-}  chars "\x4F47\x4F76\x4F88\x4F8F\x4F98\x4F7B\x4F69\x4F70" +++    {-0xD0-}  chars "\x4F91\x4F6F\x4F86\x4F96\x5118\x4FD4\x4FDF\x4FCE" +++    {-0xD8-}  chars "\x4FD8\x4FDB\x4FD1\x4FDA\x4FD0\x4FE4\x4FE5\x501A" +++    {-0xE0-}  chars "\x5028\x5014\x502A\x5025\x5005\x4F1C\x4FF6\x5021" +++    {-0xE8-}  chars "\x5029\x502C\x4FFE\x4FEF\x5011\x5006\x5043\x5047" +++    {-0xF0-}  chars "\x6703\x5055\x5050\x5048\x505A\x5056\x506C\x5078" +++    {-0xF8-}  chars "\x5080\x509A\x5085\x50B4\x50B2"++-- | The multibyte characters with a lead byte of @0x99@.+second99 :: SecondByteTable+second99 = V.fromList $+    {-0x40-}  chars "\x50C9\x50CA\x50B3\x50C2\x50D6\x50DE\x50E5\x50ED" +++    {-0x48-}  chars "\x50E3\x50EE\x50F9\x50F5\x5109\x5101\x5102\x5116" +++    {-0x50-}  chars "\x5115\x5114\x511A\x5121\x513A\x5137\x513C\x513B" +++    {-0x58-}  chars "\x513F\x5140\x5152\x514C\x5154\x5162\x7AF8\x5169" +++    {-0x60-}  chars "\x516A\x516E\x5180\x5182\x56D8\x518C\x5189\x518F" +++    {-0x68-}  chars "\x5191\x5193\x5195\x5196\x51A4\x51A6\x51A2\x51A9" +++    {-0x70-}  chars "\x51AA\x51AB\x51B3\x51B1\x51B2\x51B0\x51B5\x51BD" +++    {-0x78-}  chars "\x51C5\x51C9\x51DB\x51E0\x8655\x51E9\x51ED" ++ Nothing :+    {-0x80-}  chars "\x51F0\x51F5\x51FE\x5204\x520B\x5214\x520E\x5227" +++    {-0x88-}  chars "\x522A\x522E\x5233\x5239\x524F\x5244\x524B\x524C" +++    {-0x90-}  chars "\x525E\x5254\x526A\x5274\x5269\x5273\x527F\x527D" +++    {-0x98-}  chars "\x528D\x5294\x5292\x5271\x5288\x5291\x8FA8\x8FA7" +++    {-0xA0-}  chars "\x52AC\x52AD\x52BC\x52B5\x52C1\x52CD\x52D7\x52DE" +++    {-0xA8-}  chars "\x52E3\x52E6\x98ED\x52E0\x52F3\x52F5\x52F8\x52F9" +++    {-0xB0-}  chars "\x5306\x5308\x7538\x530D\x5310\x530F\x5315\x531A" +++    {-0xB8-}  chars "\x5323\x532F\x5331\x5333\x5338\x5340\x5346\x5345" +++    {-0xC0-}  chars "\x4E17\x5349\x534D\x51D6\x535E\x5369\x536E\x5918" +++    {-0xC8-}  chars "\x537B\x5377\x5382\x5396\x53A0\x53A6\x53A5\x53AE" +++    {-0xD0-}  chars "\x53B0\x53B6\x53C3\x7C12\x96D9\x53DF\x66FC\x71EE" +++    {-0xD8-}  chars "\x53EE\x53E8\x53ED\x53FA\x5401\x543D\x5440\x542C" +++    {-0xE0-}  chars "\x542D\x543C\x542E\x5436\x5429\x541D\x544E\x548F" +++    {-0xE8-}  chars "\x5475\x548E\x545F\x5471\x5477\x5470\x5492\x547B" +++    {-0xF0-}  chars "\x5480\x5476\x5484\x5490\x5486\x54C7\x54A2\x54B8" +++    {-0xF8-}  chars "\x54A5\x54AC\x54C4\x54C8\x54A8"++-- | The multibyte characters with a lead byte of @0x9A@.+second9A :: SecondByteTable+second9A = V.fromList $+    {-0x40-}  chars "\x54AB\x54C2\x54A4\x54BE\x54BC\x54D8\x54E5\x54E6" +++    {-0x48-}  chars "\x550F\x5514\x54FD\x54EE\x54ED\x54FA\x54E2\x5539" +++    {-0x50-}  chars "\x5540\x5563\x554C\x552E\x555C\x5545\x5556\x5557" +++    {-0x58-}  chars "\x5538\x5533\x555D\x5599\x5580\x54AF\x558A\x559F" +++    {-0x60-}  chars "\x557B\x557E\x5598\x559E\x55AE\x557C\x5583\x55A9" +++    {-0x68-}  chars "\x5587\x55A8\x55DA\x55C5\x55DF\x55C4\x55DC\x55E4" +++    {-0x70-}  chars "\x55D4\x5614\x55F7\x5616\x55FE\x55FD\x561B\x55F9" +++    {-0x78-}  chars "\x564E\x5650\x71DF\x5634\x5636\x5632\x5638" ++ Nothing :+    {-0x80-}  chars "\x566B\x5664\x562F\x566C\x566A\x5686\x5680\x568A" +++    {-0x88-}  chars "\x56A0\x5694\x568F\x56A5\x56AE\x56B6\x56B4\x56C2" +++    {-0x90-}  chars "\x56BC\x56C1\x56C3\x56C0\x56C8\x56CE\x56D1\x56D3" +++    {-0x98-}  chars "\x56D7\x56EE\x56F9\x5700\x56FF\x5704\x5709\x5708" +++    {-0xA0-}  chars "\x570B\x570D\x5713\x5718\x5716\x55C7\x571C\x5726" +++    {-0xA8-}  chars "\x5737\x5738\x574E\x573B\x5740\x574F\x5769\x57C0" +++    {-0xB0-}  chars "\x5788\x5761\x577F\x5789\x5793\x57A0\x57B3\x57A4" +++    {-0xB8-}  chars "\x57AA\x57B0\x57C3\x57C6\x57D4\x57D2\x57D3\x580A" +++    {-0xC0-}  chars "\x57D6\x57E3\x580B\x5819\x581D\x5872\x5821\x5862" +++    {-0xC8-}  chars "\x584B\x5870\x6BC0\x5852\x583D\x5879\x5885\x58B9" +++    {-0xD0-}  chars "\x589F\x58AB\x58BA\x58DE\x58BB\x58B8\x58AE\x58C5" +++    {-0xD8-}  chars "\x58D3\x58D1\x58D7\x58D9\x58D8\x58E5\x58DC\x58E4" +++    {-0xE0-}  chars "\x58DF\x58EF\x58FA\x58F9\x58FB\x58FC\x58FD\x5902" +++    {-0xE8-}  chars "\x590A\x5910\x591B\x68A6\x5925\x592C\x592D\x5932" +++    {-0xF0-}  chars "\x5938\x593E\x7AD2\x5955\x5950\x594E\x595A\x5958" +++    {-0xF8-}  chars "\x5962\x5960\x5967\x596C\x5969"++-- | The multibyte characters with a lead byte of @0x9B@.+second9B :: SecondByteTable+second9B = V.fromList $+    {-0x40-}  chars "\x5978\x5981\x599D\x4F5E\x4FAB\x59A3\x59B2\x59C6" +++    {-0x48-}  chars "\x59E8\x59DC\x598D\x59D9\x59DA\x5A25\x5A1F\x5A11" +++    {-0x50-}  chars "\x5A1C\x5A09\x5A1A\x5A40\x5A6C\x5A49\x5A35\x5A36" +++    {-0x58-}  chars "\x5A62\x5A6A\x5A9A\x5ABC\x5ABE\x5ACB\x5AC2\x5ABD" +++    {-0x60-}  chars "\x5AE3\x5AD7\x5AE6\x5AE9\x5AD6\x5AFA\x5AFB\x5B0C" +++    {-0x68-}  chars "\x5B0B\x5B16\x5B32\x5AD0\x5B2A\x5B36\x5B3E\x5B43" +++    {-0x70-}  chars "\x5B45\x5B40\x5B51\x5B55\x5B5A\x5B5B\x5B65\x5B69" +++    {-0x78-}  chars "\x5B70\x5B73\x5B75\x5B78\x6588\x5B7A\x5B80" ++ Nothing :+    {-0x80-}  chars "\x5B83\x5BA6\x5BB8\x5BC3\x5BC7\x5BC9\x5BD4\x5BD0" +++    {-0x88-}  chars "\x5BE4\x5BE6\x5BE2\x5BDE\x5BE5\x5BEB\x5BF0\x5BF6" +++    {-0x90-}  chars "\x5BF3\x5C05\x5C07\x5C08\x5C0D\x5C13\x5C20\x5C22" +++    {-0x98-}  chars "\x5C28\x5C38\x5C39\x5C41\x5C46\x5C4E\x5C53\x5C50" +++    {-0xA0-}  chars "\x5C4F\x5B71\x5C6C\x5C6E\x4E62\x5C76\x5C79\x5C8C" +++    {-0xA8-}  chars "\x5C91\x5C94\x599B\x5CAB\x5CBB\x5CB6\x5CBC\x5CB7" +++    {-0xB0-}  chars "\x5CC5\x5CBE\x5CC7\x5CD9\x5CE9\x5CFD\x5CFA\x5CED" +++    {-0xB8-}  chars "\x5D8C\x5CEA\x5D0B\x5D15\x5D17\x5D5C\x5D1F\x5D1B" +++    {-0xC0-}  chars "\x5D11\x5D14\x5D22\x5D1A\x5D19\x5D18\x5D4C\x5D52" +++    {-0xC8-}  chars "\x5D4E\x5D4B\x5D6C\x5D73\x5D76\x5D87\x5D84\x5D82" +++    {-0xD0-}  chars "\x5DA2\x5D9D\x5DAC\x5DAE\x5DBD\x5D90\x5DB7\x5DBC" +++    {-0xD8-}  chars "\x5DC9\x5DCD\x5DD3\x5DD2\x5DD6\x5DDB\x5DEB\x5DF2" +++    {-0xE0-}  chars "\x5DF5\x5E0B\x5E1A\x5E19\x5E11\x5E1B\x5E36\x5E37" +++    {-0xE8-}  chars "\x5E44\x5E43\x5E40\x5E4E\x5E57\x5E54\x5E5F\x5E62" +++    {-0xF0-}  chars "\x5E64\x5E47\x5E75\x5E76\x5E7A\x9EBC\x5E7F\x5EA0" +++    {-0xF8-}  chars "\x5EC1\x5EC2\x5EC8\x5ED0\x5ECF"++-- | The multibyte characters with a lead byte of @0x9C@.+second9C :: SecondByteTable+second9C = V.fromList $+    {-0x40-}  chars "\x5ED6\x5EE3\x5EDD\x5EDA\x5EDB\x5EE2\x5EE1\x5EE8" +++    {-0x48-}  chars "\x5EE9\x5EEC\x5EF1\x5EF3\x5EF0\x5EF4\x5EF8\x5EFE" +++    {-0x50-}  chars "\x5F03\x5F09\x5F5D\x5F5C\x5F0B\x5F11\x5F16\x5F29" +++    {-0x58-}  chars "\x5F2D\x5F38\x5F41\x5F48\x5F4C\x5F4E\x5F2F\x5F51" +++    {-0x60-}  chars "\x5F56\x5F57\x5F59\x5F61\x5F6D\x5F73\x5F77\x5F83" +++    {-0x68-}  chars "\x5F82\x5F7F\x5F8A\x5F88\x5F91\x5F87\x5F9E\x5F99" +++    {-0x70-}  chars "\x5F98\x5FA0\x5FA8\x5FAD\x5FBC\x5FD6\x5FFB\x5FE4" +++    {-0x78-}  chars "\x5FF8\x5FF1\x5FDD\x60B3\x5FFF\x6021\x6060" ++ Nothing :+    {-0x80-}  chars "\x6019\x6010\x6029\x600E\x6031\x601B\x6015\x602B" +++    {-0x88-}  chars "\x6026\x600F\x603A\x605A\x6041\x606A\x6077\x605F" +++    {-0x90-}  chars "\x604A\x6046\x604D\x6063\x6043\x6064\x6042\x606C" +++    {-0x98-}  chars "\x606B\x6059\x6081\x608D\x60E7\x6083\x609A\x6084" +++    {-0xA0-}  chars "\x609B\x6096\x6097\x6092\x60A7\x608B\x60E1\x60B8" +++    {-0xA8-}  chars "\x60E0\x60D3\x60B4\x5FF0\x60BD\x60C6\x60B5\x60D8" +++    {-0xB0-}  chars "\x614D\x6115\x6106\x60F6\x60F7\x6100\x60F4\x60FA" +++    {-0xB8-}  chars "\x6103\x6121\x60FB\x60F1\x610D\x610E\x6147\x613E" +++    {-0xC0-}  chars "\x6128\x6127\x614A\x613F\x613C\x612C\x6134\x613D" +++    {-0xC8-}  chars "\x6142\x6144\x6173\x6177\x6158\x6159\x615A\x616B" +++    {-0xD0-}  chars "\x6174\x616F\x6165\x6171\x615F\x615D\x6153\x6175" +++    {-0xD8-}  chars "\x6199\x6196\x6187\x61AC\x6194\x619A\x618A\x6191" +++    {-0xE0-}  chars "\x61AB\x61AE\x61CC\x61CA\x61C9\x61F7\x61C8\x61C3" +++    {-0xE8-}  chars "\x61C6\x61BA\x61CB\x7F79\x61CD\x61E6\x61E3\x61F6" +++    {-0xF0-}  chars "\x61FA\x61F4\x61FF\x61FD\x61FC\x61FE\x6200\x6208" +++    {-0xF8-}  chars "\x6209\x620D\x620C\x6214\x621B"++-- | The multibyte characters with a lead byte of @0x9D@.+second9D :: SecondByteTable+second9D = V.fromList $+    {-0x40-}  chars "\x621E\x6221\x622A\x622E\x6230\x6232\x6233\x6241" +++    {-0x48-}  chars "\x624E\x625E\x6263\x625B\x6260\x6268\x627C\x6282" +++    {-0x50-}  chars "\x6289\x627E\x6292\x6293\x6296\x62D4\x6283\x6294" +++    {-0x58-}  chars "\x62D7\x62D1\x62BB\x62CF\x62FF\x62C6\x64D4\x62C8" +++    {-0x60-}  chars "\x62DC\x62CC\x62CA\x62C2\x62C7\x629B\x62C9\x630C" +++    {-0x68-}  chars "\x62EE\x62F1\x6327\x6302\x6308\x62EF\x62F5\x6350" +++    {-0x70-}  chars "\x633E\x634D\x641C\x634F\x6396\x638E\x6380\x63AB" +++    {-0x78-}  chars "\x6376\x63A3\x638F\x6389\x639F\x63B5\x636B" ++ Nothing :+    {-0x80-}  chars "\x6369\x63BE\x63E9\x63C0\x63C6\x63E3\x63C9\x63D2" +++    {-0x88-}  chars "\x63F6\x63C4\x6416\x6434\x6406\x6413\x6426\x6436" +++    {-0x90-}  chars "\x651D\x6417\x6428\x640F\x6467\x646F\x6476\x644E" +++    {-0x98-}  chars "\x652A\x6495\x6493\x64A5\x64A9\x6488\x64BC\x64DA" +++    {-0xA0-}  chars "\x64D2\x64C5\x64C7\x64BB\x64D8\x64C2\x64F1\x64E7" +++    {-0xA8-}  chars "\x8209\x64E0\x64E1\x62AC\x64E3\x64EF\x652C\x64F6" +++    {-0xB0-}  chars "\x64F4\x64F2\x64FA\x6500\x64FD\x6518\x651C\x6505" +++    {-0xB8-}  chars "\x6524\x6523\x652B\x6534\x6535\x6537\x6536\x6538" +++    {-0xC0-}  chars "\x754B\x6548\x6556\x6555\x654D\x6558\x655E\x655D" +++    {-0xC8-}  chars "\x6572\x6578\x6582\x6583\x8B8A\x659B\x659F\x65AB" +++    {-0xD0-}  chars "\x65B7\x65C3\x65C6\x65C1\x65C4\x65CC\x65D2\x65DB" +++    {-0xD8-}  chars "\x65D9\x65E0\x65E1\x65F1\x6772\x660A\x6603\x65FB" +++    {-0xE0-}  chars "\x6773\x6635\x6636\x6634\x661C\x664F\x6644\x6649" +++    {-0xE8-}  chars "\x6641\x665E\x665D\x6664\x6667\x6668\x665F\x6662" +++    {-0xF0-}  chars "\x6670\x6683\x6688\x668E\x6689\x6684\x6698\x669D" +++    {-0xF8-}  chars "\x66C1\x66B9\x66C9\x66BE\x66BC"++-- | The multibyte characters with a lead byte of @0x9E@.+second9E :: SecondByteTable+second9E = V.fromList $+    {-0x40-}  chars "\x66C4\x66B8\x66D6\x66DA\x66E0\x663F\x66E6\x66E9" +++    {-0x48-}  chars "\x66F0\x66F5\x66F7\x670F\x6716\x671E\x6726\x6727" +++    {-0x50-}  chars "\x9738\x672E\x673F\x6736\x6741\x6738\x6737\x6746" +++    {-0x58-}  chars "\x675E\x6760\x6759\x6763\x6764\x6789\x6770\x67A9" +++    {-0x60-}  chars "\x677C\x676A\x678C\x678B\x67A6\x67A1\x6785\x67B7" +++    {-0x68-}  chars "\x67EF\x67B4\x67EC\x67B3\x67E9\x67B8\x67E4\x67DE" +++    {-0x70-}  chars "\x67DD\x67E2\x67EE\x67B9\x67CE\x67C6\x67E7\x6A9C" +++    {-0x78-}  chars "\x681E\x6846\x6829\x6840\x684D\x6832\x684E" ++ Nothing :+    {-0x80-}  chars "\x68B3\x682B\x6859\x6863\x6877\x687F\x689F\x688F" +++    {-0x88-}  chars "\x68AD\x6894\x689D\x689B\x6883\x6AAE\x68B9\x6874" +++    {-0x90-}  chars "\x68B5\x68A0\x68BA\x690F\x688D\x687E\x6901\x68CA" +++    {-0x98-}  chars "\x6908\x68D8\x6922\x6926\x68E1\x690C\x68CD\x68D4" +++    {-0xA0-}  chars "\x68E7\x68D5\x6936\x6912\x6904\x68D7\x68E3\x6925" +++    {-0xA8-}  chars "\x68F9\x68E0\x68EF\x6928\x692A\x691A\x6923\x6921" +++    {-0xB0-}  chars "\x68C6\x6979\x6977\x695C\x6978\x696B\x6954\x697E" +++    {-0xB8-}  chars "\x696E\x6939\x6974\x693D\x6959\x6930\x6961\x695E" +++    {-0xC0-}  chars "\x695D\x6981\x696A\x69B2\x69AE\x69D0\x69BF\x69C1" +++    {-0xC8-}  chars "\x69D3\x69BE\x69CE\x5BE8\x69CA\x69DD\x69BB\x69C3" +++    {-0xD0-}  chars "\x69A7\x6A2E\x6991\x69A0\x699C\x6995\x69B4\x69DE" +++    {-0xD8-}  chars "\x69E8\x6A02\x6A1B\x69FF\x6B0A\x69F9\x69F2\x69E7" +++    {-0xE0-}  chars "\x6A05\x69B1\x6A1E\x69ED\x6A14\x69EB\x6A0A\x6A12" +++    {-0xE8-}  chars "\x6AC1\x6A23\x6A13\x6A44\x6A0C\x6A72\x6A36\x6A78" +++    {-0xF0-}  chars "\x6A47\x6A62\x6A59\x6A66\x6A48\x6A38\x6A22\x6A90" +++    {-0xF8-}  chars "\x6A8D\x6AA0\x6A84\x6AA2\x6AA3"++-- | The multibyte characters with a lead byte of @0x9F@.+second9F :: SecondByteTable+second9F = V.fromList $+    {-0x40-}  chars "\x6A97\x8617\x6ABB\x6AC3\x6AC2\x6AB8\x6AB3\x6AAC" +++    {-0x48-}  chars "\x6ADE\x6AD1\x6ADF\x6AAA\x6ADA\x6AEA\x6AFB\x6B05" +++    {-0x50-}  chars "\x8616\x6AFA\x6B12\x6B16\x9B31\x6B1F\x6B38\x6B37" +++    {-0x58-}  chars "\x76DC\x6B39\x98EE\x6B47\x6B43\x6B49\x6B50\x6B59" +++    {-0x60-}  chars "\x6B54\x6B5B\x6B5F\x6B61\x6B78\x6B79\x6B7F\x6B80" +++    {-0x68-}  chars "\x6B84\x6B83\x6B8D\x6B98\x6B95\x6B9E\x6BA4\x6BAA" +++    {-0x70-}  chars "\x6BAB\x6BAF\x6BB2\x6BB1\x6BB3\x6BB7\x6BBC\x6BC6" +++    {-0x78-}  chars "\x6BCB\x6BD3\x6BDF\x6BEC\x6BEB\x6BF3\x6BEF" ++ Nothing :+    {-0x80-}  chars "\x9EBE\x6C08\x6C13\x6C14\x6C1B\x6C24\x6C23\x6C5E" +++    {-0x88-}  chars "\x6C55\x6C62\x6C6A\x6C82\x6C8D\x6C9A\x6C81\x6C9B" +++    {-0x90-}  chars "\x6C7E\x6C68\x6C73\x6C92\x6C90\x6CC4\x6CF1\x6CD3" +++    {-0x98-}  chars "\x6CBD\x6CD7\x6CC5\x6CDD\x6CAE\x6CB1\x6CBE\x6CBA" +++    {-0xA0-}  chars "\x6CDB\x6CEF\x6CD9\x6CEA\x6D1F\x884D\x6D36\x6D2B" +++    {-0xA8-}  chars "\x6D3D\x6D38\x6D19\x6D35\x6D33\x6D12\x6D0C\x6D63" +++    {-0xB0-}  chars "\x6D93\x6D64\x6D5A\x6D79\x6D59\x6D8E\x6D95\x6FE4" +++    {-0xB8-}  chars "\x6D85\x6DF9\x6E15\x6E0A\x6DB5\x6DC7\x6DE6\x6DB8" +++    {-0xC0-}  chars "\x6DC6\x6DEC\x6DDE\x6DCC\x6DE8\x6DD2\x6DC5\x6DFA" +++    {-0xC8-}  chars "\x6DD9\x6DE4\x6DD5\x6DEA\x6DEE\x6E2D\x6E6E\x6E2E" +++    {-0xD0-}  chars "\x6E19\x6E72\x6E5F\x6E3E\x6E23\x6E6B\x6E2B\x6E76" +++    {-0xD8-}  chars "\x6E4D\x6E1F\x6E43\x6E3A\x6E4E\x6E24\x6EFF\x6E1D" +++    {-0xE0-}  chars "\x6E38\x6E82\x6EAA\x6E98\x6EC9\x6EB7\x6ED3\x6EBD" +++    {-0xE8-}  chars "\x6EAF\x6EC4\x6EB2\x6ED4\x6ED5\x6E8F\x6EA5\x6EC2" +++    {-0xF0-}  chars "\x6E9F\x6F41\x6F11\x704C\x6EEC\x6EF8\x6EFE\x6F3F" +++    {-0xF8-}  chars "\x6EF2\x6F31\x6EEF\x6F32\x6ECC"++-- | The multibyte characters with a lead byte of @0xE0@.+secondE0 :: SecondByteTable+secondE0 = V.fromList $+    {-0x40-}  chars "\x6F3E\x6F13\x6EF7\x6F86\x6F7A\x6F78\x6F81\x6F80" +++    {-0x48-}  chars "\x6F6F\x6F5B\x6FF3\x6F6D\x6F82\x6F7C\x6F58\x6F8E" +++    {-0x50-}  chars "\x6F91\x6FC2\x6F66\x6FB3\x6FA3\x6FA1\x6FA4\x6FB9" +++    {-0x58-}  chars "\x6FC6\x6FAA\x6FDF\x6FD5\x6FEC\x6FD4\x6FD8\x6FF1" +++    {-0x60-}  chars "\x6FEE\x6FDB\x7009\x700B\x6FFA\x7011\x7001\x700F" +++    {-0x68-}  chars "\x6FFE\x701B\x701A\x6F74\x701D\x7018\x701F\x7030" +++    {-0x70-}  chars "\x703E\x7032\x7051\x7063\x7099\x7092\x70AF\x70F1" +++    {-0x78-}  chars "\x70AC\x70B8\x70B3\x70AE\x70DF\x70CB\x70DD" ++ Nothing :+    {-0x80-}  chars "\x70D9\x7109\x70FD\x711C\x7119\x7165\x7155\x7188" +++    {-0x88-}  chars "\x7166\x7162\x714C\x7156\x716C\x718F\x71FB\x7184" +++    {-0x90-}  chars "\x7195\x71A8\x71AC\x71D7\x71B9\x71BE\x71D2\x71C9" +++    {-0x98-}  chars "\x71D4\x71CE\x71E0\x71EC\x71E7\x71F5\x71FC\x71F9" +++    {-0xA0-}  chars "\x71FF\x720D\x7210\x721B\x7228\x722D\x722C\x7230" +++    {-0xA8-}  chars "\x7232\x723B\x723C\x723F\x7240\x7246\x724B\x7258" +++    {-0xB0-}  chars "\x7274\x727E\x7282\x7281\x7287\x7292\x7296\x72A2" +++    {-0xB8-}  chars "\x72A7\x72B9\x72B2\x72C3\x72C6\x72C4\x72CE\x72D2" +++    {-0xC0-}  chars "\x72E2\x72E0\x72E1\x72F9\x72F7\x500F\x7317\x730A" +++    {-0xC8-}  chars "\x731C\x7316\x731D\x7334\x732F\x7329\x7325\x733E" +++    {-0xD0-}  chars "\x734E\x734F\x9ED8\x7357\x736A\x7368\x7370\x7378" +++    {-0xD8-}  chars "\x7375\x737B\x737A\x73C8\x73B3\x73CE\x73BB\x73C0" +++    {-0xE0-}  chars "\x73E5\x73EE\x73DE\x74A2\x7405\x746F\x7425\x73F8" +++    {-0xE8-}  chars "\x7432\x743A\x7455\x743F\x745F\x7459\x7441\x745C" +++    {-0xF0-}  chars "\x7469\x7470\x7463\x746A\x7476\x747E\x748B\x749E" +++    {-0xF8-}  chars "\x74A7\x74CA\x74CF\x74D4\x73F1"++-- | The multibyte characters with a lead byte of @0xE1@.+secondE1 :: SecondByteTable+secondE1 = V.fromList $+    {-0x40-}  chars "\x74E0\x74E3\x74E7\x74E9\x74EE\x74F2\x74F0\x74F1" +++    {-0x48-}  chars "\x74F8\x74F7\x7504\x7503\x7505\x750C\x750E\x750D" +++    {-0x50-}  chars "\x7515\x7513\x751E\x7526\x752C\x753C\x7544\x754D" +++    {-0x58-}  chars "\x754A\x7549\x755B\x7546\x755A\x7569\x7564\x7567" +++    {-0x60-}  chars "\x756B\x756D\x7578\x7576\x7586\x7587\x7574\x758A" +++    {-0x68-}  chars "\x7589\x7582\x7594\x759A\x759D\x75A5\x75A3\x75C2" +++    {-0x70-}  chars "\x75B3\x75C3\x75B5\x75BD\x75B8\x75BC\x75B1\x75CD" +++    {-0x78-}  chars "\x75CA\x75D2\x75D9\x75E3\x75DE\x75FE\x75FF" ++ Nothing :+    {-0x80-}  chars "\x75FC\x7601\x75F0\x75FA\x75F2\x75F3\x760B\x760D" +++    {-0x88-}  chars "\x7609\x761F\x7627\x7620\x7621\x7622\x7624\x7634" +++    {-0x90-}  chars "\x7630\x763B\x7647\x7648\x7646\x765C\x7658\x7661" +++    {-0x98-}  chars "\x7662\x7668\x7669\x766A\x7667\x766C\x7670\x7672" +++    {-0xA0-}  chars "\x7676\x7678\x767C\x7680\x7683\x7688\x768B\x768E" +++    {-0xA8-}  chars "\x7696\x7693\x7699\x769A\x76B0\x76B4\x76B8\x76B9" +++    {-0xB0-}  chars "\x76BA\x76C2\x76CD\x76D6\x76D2\x76DE\x76E1\x76E5" +++    {-0xB8-}  chars "\x76E7\x76EA\x862F\x76FB\x7708\x7707\x7704\x7729" +++    {-0xC0-}  chars "\x7724\x771E\x7725\x7726\x771B\x7737\x7738\x7747" +++    {-0xC8-}  chars "\x775A\x7768\x776B\x775B\x7765\x777F\x777E\x7779" +++    {-0xD0-}  chars "\x778E\x778B\x7791\x77A0\x779E\x77B0\x77B6\x77B9" +++    {-0xD8-}  chars "\x77BF\x77BC\x77BD\x77BB\x77C7\x77CD\x77D7\x77DA" +++    {-0xE0-}  chars "\x77DC\x77E3\x77EE\x77FC\x780C\x7812\x7926\x7820" +++    {-0xE8-}  chars "\x792A\x7845\x788E\x7874\x7886\x787C\x789A\x788C" +++    {-0xF0-}  chars "\x78A3\x78B5\x78AA\x78AF\x78D1\x78C6\x78CB\x78D4" +++    {-0xF8-}  chars "\x78BE\x78BC\x78C5\x78CA\x78EC"++-- | The multibyte characters with a lead byte of @0xE2@.+secondE2 :: SecondByteTable+secondE2 = V.fromList $+    {-0x40-}  chars "\x78E7\x78DA\x78FD\x78F4\x7907\x7912\x7911\x7919" +++    {-0x48-}  chars "\x792C\x792B\x7940\x7960\x7957\x795F\x795A\x7955" +++    {-0x50-}  chars "\x7953\x797A\x797F\x798A\x799D\x79A7\x9F4B\x79AA" +++    {-0x58-}  chars "\x79AE\x79B3\x79B9\x79BA\x79C9\x79D5\x79E7\x79EC" +++    {-0x60-}  chars "\x79E1\x79E3\x7A08\x7A0D\x7A18\x7A19\x7A20\x7A1F" +++    {-0x68-}  chars "\x7980\x7A31\x7A3B\x7A3E\x7A37\x7A43\x7A57\x7A49" +++    {-0x70-}  chars "\x7A61\x7A62\x7A69\x9F9D\x7A70\x7A79\x7A7D\x7A88" +++    {-0x78-}  chars "\x7A97\x7A95\x7A98\x7A96\x7AA9\x7AC8\x7AB0" ++ Nothing :+    {-0x80-}  chars "\x7AB6\x7AC5\x7AC4\x7ABF\x9083\x7AC7\x7ACA\x7ACD" +++    {-0x88-}  chars "\x7ACF\x7AD5\x7AD3\x7AD9\x7ADA\x7ADD\x7AE1\x7AE2" +++    {-0x90-}  chars "\x7AE6\x7AED\x7AF0\x7B02\x7B0F\x7B0A\x7B06\x7B33" +++    {-0x98-}  chars "\x7B18\x7B19\x7B1E\x7B35\x7B28\x7B36\x7B50\x7B7A" +++    {-0xA0-}  chars "\x7B04\x7B4D\x7B0B\x7B4C\x7B45\x7B75\x7B65\x7B74" +++    {-0xA8-}  chars "\x7B67\x7B70\x7B71\x7B6C\x7B6E\x7B9D\x7B98\x7B9F" +++    {-0xB0-}  chars "\x7B8D\x7B9C\x7B9A\x7B8B\x7B92\x7B8F\x7B5D\x7B99" +++    {-0xB8-}  chars "\x7BCB\x7BC1\x7BCC\x7BCF\x7BB4\x7BC6\x7BDD\x7BE9" +++    {-0xC0-}  chars "\x7C11\x7C14\x7BE6\x7BE5\x7C60\x7C00\x7C07\x7C13" +++    {-0xC8-}  chars "\x7BF3\x7BF7\x7C17\x7C0D\x7BF6\x7C23\x7C27\x7C2A" +++    {-0xD0-}  chars "\x7C1F\x7C37\x7C2B\x7C3D\x7C4C\x7C43\x7C54\x7C4F" +++    {-0xD8-}  chars "\x7C40\x7C50\x7C58\x7C5F\x7C64\x7C56\x7C65\x7C6C" +++    {-0xE0-}  chars "\x7C75\x7C83\x7C90\x7CA4\x7CAD\x7CA2\x7CAB\x7CA1" +++    {-0xE8-}  chars "\x7CA8\x7CB3\x7CB2\x7CB1\x7CAE\x7CB9\x7CBD\x7CC0" +++    {-0xF0-}  chars "\x7CC5\x7CC2\x7CD8\x7CD2\x7CDC\x7CE2\x9B3B\x7CEF" +++    {-0xF8-}  chars "\x7CF2\x7CF4\x7CF6\x7CFA\x7D06"++-- | The multibyte characters with a lead byte of @0xE3@.+secondE3 :: SecondByteTable+secondE3 = V.fromList $+    {-0x40-}  chars "\x7D02\x7D1C\x7D15\x7D0A\x7D45\x7D4B\x7D2E\x7D32" +++    {-0x48-}  chars "\x7D3F\x7D35\x7D46\x7D73\x7D56\x7D4E\x7D72\x7D68" +++    {-0x50-}  chars "\x7D6E\x7D4F\x7D63\x7D93\x7D89\x7D5B\x7D8F\x7D7D" +++    {-0x58-}  chars "\x7D9B\x7DBA\x7DAE\x7DA3\x7DB5\x7DC7\x7DBD\x7DAB" +++    {-0x60-}  chars "\x7E3D\x7DA2\x7DAF\x7DDC\x7DB8\x7D9F\x7DB0\x7DD8" +++    {-0x68-}  chars "\x7DDD\x7DE4\x7DDE\x7DFB\x7DF2\x7DE1\x7E05\x7E0A" +++    {-0x70-}  chars "\x7E23\x7E21\x7E12\x7E31\x7E1F\x7E09\x7E0B\x7E22" +++    {-0x78-}  chars "\x7E46\x7E66\x7E3B\x7E35\x7E39\x7E43\x7E37" ++ Nothing :+    {-0x80-}  chars "\x7E32\x7E3A\x7E67\x7E5D\x7E56\x7E5E\x7E59\x7E5A" +++    {-0x88-}  chars "\x7E79\x7E6A\x7E69\x7E7C\x7E7B\x7E83\x7DD5\x7E7D" +++    {-0x90-}  chars "\x8FAE\x7E7F\x7E88\x7E89\x7E8C\x7E92\x7E90\x7E93" +++    {-0x98-}  chars "\x7E94\x7E96\x7E8E\x7E9B\x7E9C\x7F38\x7F3A\x7F45" +++    {-0xA0-}  chars "\x7F4C\x7F4D\x7F4E\x7F50\x7F51\x7F55\x7F54\x7F58" +++    {-0xA8-}  chars "\x7F5F\x7F60\x7F68\x7F69\x7F67\x7F78\x7F82\x7F86" +++    {-0xB0-}  chars "\x7F83\x7F88\x7F87\x7F8C\x7F94\x7F9E\x7F9D\x7F9A" +++    {-0xB8-}  chars "\x7FA3\x7FAF\x7FB2\x7FB9\x7FAE\x7FB6\x7FB8\x8B71" +++    {-0xC0-}  chars "\x7FC5\x7FC6\x7FCA\x7FD5\x7FD4\x7FE1\x7FE6\x7FE9" +++    {-0xC8-}  chars "\x7FF3\x7FF9\x98DC\x8006\x8004\x800B\x8012\x8018" +++    {-0xD0-}  chars "\x8019\x801C\x8021\x8028\x803F\x803B\x804A\x8046" +++    {-0xD8-}  chars "\x8052\x8058\x805A\x805F\x8062\x8068\x8073\x8072" +++    {-0xE0-}  chars "\x8070\x8076\x8079\x807D\x807F\x8084\x8086\x8085" +++    {-0xE8-}  chars "\x809B\x8093\x809A\x80AD\x5190\x80AC\x80DB\x80E5" +++    {-0xF0-}  chars "\x80D9\x80DD\x80C4\x80DA\x80D6\x8109\x80EF\x80F1" +++    {-0xF8-}  chars "\x811B\x8129\x8123\x812F\x814B"++-- | The multibyte characters with a lead byte of @0xE4@.+secondE4 :: SecondByteTable+secondE4 = V.fromList $+    {-0x40-}  chars "\x968B\x8146\x813E\x8153\x8151\x80FC\x8171\x816E" +++    {-0x48-}  chars "\x8165\x8166\x8174\x8183\x8188\x818A\x8180\x8182" +++    {-0x50-}  chars "\x81A0\x8195\x81A4\x81A3\x815F\x8193\x81A9\x81B0" +++    {-0x58-}  chars "\x81B5\x81BE\x81B8\x81BD\x81C0\x81C2\x81BA\x81C9" +++    {-0x60-}  chars "\x81CD\x81D1\x81D9\x81D8\x81C8\x81DA\x81DF\x81E0" +++    {-0x68-}  chars "\x81E7\x81FA\x81FB\x81FE\x8201\x8202\x8205\x8207" +++    {-0x70-}  chars "\x820A\x820D\x8210\x8216\x8229\x822B\x8238\x8233" +++    {-0x78-}  chars "\x8240\x8259\x8258\x825D\x825A\x825F\x8264" ++ Nothing :+    {-0x80-}  chars "\x8262\x8268\x826A\x826B\x822E\x8271\x8277\x8278" +++    {-0x88-}  chars "\x827E\x828D\x8292\x82AB\x829F\x82BB\x82AC\x82E1" +++    {-0x90-}  chars "\x82E3\x82DF\x82D2\x82F4\x82F3\x82FA\x8393\x8303" +++    {-0x98-}  chars "\x82FB\x82F9\x82DE\x8306\x82DC\x8309\x82D9\x8335" +++    {-0xA0-}  chars "\x8334\x8316\x8332\x8331\x8340\x8339\x8350\x8345" +++    {-0xA8-}  chars "\x832F\x832B\x8317\x8318\x8385\x839A\x83AA\x839F" +++    {-0xB0-}  chars "\x83A2\x8396\x8323\x838E\x8387\x838A\x837C\x83B5" +++    {-0xB8-}  chars "\x8373\x8375\x83A0\x8389\x83A8\x83F4\x8413\x83EB" +++    {-0xC0-}  chars "\x83CE\x83FD\x8403\x83D8\x840B\x83C1\x83F7\x8407" +++    {-0xC8-}  chars "\x83E0\x83F2\x840D\x8422\x8420\x83BD\x8438\x8506" +++    {-0xD0-}  chars "\x83FB\x846D\x842A\x843C\x855A\x8484\x8477\x846B" +++    {-0xD8-}  chars "\x84AD\x846E\x8482\x8469\x8446\x842C\x846F\x8479" +++    {-0xE0-}  chars "\x8435\x84CA\x8462\x84B9\x84BF\x849F\x84D9\x84CD" +++    {-0xE8-}  chars "\x84BB\x84DA\x84D0\x84C1\x84C6\x84D6\x84A1\x8521" +++    {-0xF0-}  chars "\x84FF\x84F4\x8517\x8518\x852C\x851F\x8515\x8514" +++    {-0xF8-}  chars "\x84FC\x8540\x8563\x8558\x8548"++-- | The multibyte characters with a lead byte of @0xE5@.+secondE5 :: SecondByteTable+secondE5 = V.fromList $+    {-0x40-}  chars "\x8541\x8602\x854B\x8555\x8580\x85A4\x8588\x8591" +++    {-0x48-}  chars "\x858A\x85A8\x856D\x8594\x859B\x85EA\x8587\x859C" +++    {-0x50-}  chars "\x8577\x857E\x8590\x85C9\x85BA\x85CF\x85B9\x85D0" +++    {-0x58-}  chars "\x85D5\x85DD\x85E5\x85DC\x85F9\x860A\x8613\x860B" +++    {-0x60-}  chars "\x85FE\x85FA\x8606\x8622\x861A\x8630\x863F\x864D" +++    {-0x68-}  chars "\x4E55\x8654\x865F\x8667\x8671\x8693\x86A3\x86A9" +++    {-0x70-}  chars "\x86AA\x868B\x868C\x86B6\x86AF\x86C4\x86C6\x86B0" +++    {-0x78-}  chars "\x86C9\x8823\x86AB\x86D4\x86DE\x86E9\x86EC" ++ Nothing :+    {-0x80-}  chars "\x86DF\x86DB\x86EF\x8712\x8706\x8708\x8700\x8703" +++    {-0x88-}  chars "\x86FB\x8711\x8709\x870D\x86F9\x870A\x8734\x873F" +++    {-0x90-}  chars "\x8737\x873B\x8725\x8729\x871A\x8760\x875F\x8778" +++    {-0x98-}  chars "\x874C\x874E\x8774\x8757\x8768\x876E\x8759\x8753" +++    {-0xA0-}  chars "\x8763\x876A\x8805\x87A2\x879F\x8782\x87AF\x87CB" +++    {-0xA8-}  chars "\x87BD\x87C0\x87D0\x96D6\x87AB\x87C4\x87B3\x87C7" +++    {-0xB0-}  chars "\x87C6\x87BB\x87EF\x87F2\x87E0\x880F\x880D\x87FE" +++    {-0xB8-}  chars "\x87F6\x87F7\x880E\x87D2\x8811\x8816\x8815\x8822" +++    {-0xC0-}  chars "\x8821\x8831\x8836\x8839\x8827\x883B\x8844\x8842" +++    {-0xC8-}  chars "\x8852\x8859\x885E\x8862\x886B\x8881\x887E\x889E" +++    {-0xD0-}  chars "\x8875\x887D\x88B5\x8872\x8882\x8897\x8892\x88AE" +++    {-0xD8-}  chars "\x8899\x88A2\x888D\x88A4\x88B0\x88BF\x88B1\x88C3" +++    {-0xE0-}  chars "\x88C4\x88D4\x88D8\x88D9\x88DD\x88F9\x8902\x88FC" +++    {-0xE8-}  chars "\x88F4\x88E8\x88F2\x8904\x890C\x890A\x8913\x8943" +++    {-0xF0-}  chars "\x891E\x8925\x892A\x892B\x8941\x8944\x893B\x8936" +++    {-0xF8-}  chars "\x8938\x894C\x891D\x8960\x895E"++-- | The multibyte characters with a lead byte of @0xE6@.+secondE6 :: SecondByteTable+secondE6 = V.fromList $+    {-0x40-}  chars "\x8966\x8964\x896D\x896A\x896F\x8974\x8977\x897E" +++    {-0x48-}  chars "\x8983\x8988\x898A\x8993\x8998\x89A1\x89A9\x89A6" +++    {-0x50-}  chars "\x89AC\x89AF\x89B2\x89BA\x89BD\x89BF\x89C0\x89DA" +++    {-0x58-}  chars "\x89DC\x89DD\x89E7\x89F4\x89F8\x8A03\x8A16\x8A10" +++    {-0x60-}  chars "\x8A0C\x8A1B\x8A1D\x8A25\x8A36\x8A41\x8A5B\x8A52" +++    {-0x68-}  chars "\x8A46\x8A48\x8A7C\x8A6D\x8A6C\x8A62\x8A85\x8A82" +++    {-0x70-}  chars "\x8A84\x8AA8\x8AA1\x8A91\x8AA5\x8AA6\x8A9A\x8AA3" +++    {-0x78-}  chars "\x8AC4\x8ACD\x8AC2\x8ADA\x8AEB\x8AF3\x8AE7" ++ Nothing :+    {-0x80-}  chars "\x8AE4\x8AF1\x8B14\x8AE0\x8AE2\x8AF7\x8ADE\x8ADB" +++    {-0x88-}  chars "\x8B0C\x8B07\x8B1A\x8AE1\x8B16\x8B10\x8B17\x8B20" +++    {-0x90-}  chars "\x8B33\x97AB\x8B26\x8B2B\x8B3E\x8B28\x8B41\x8B4C" +++    {-0x98-}  chars "\x8B4F\x8B4E\x8B49\x8B56\x8B5B\x8B5A\x8B6B\x8B5F" +++    {-0xA0-}  chars "\x8B6C\x8B6F\x8B74\x8B7D\x8B80\x8B8C\x8B8E\x8B92" +++    {-0xA8-}  chars "\x8B93\x8B96\x8B99\x8B9A\x8C3A\x8C41\x8C3F\x8C48" +++    {-0xB0-}  chars "\x8C4C\x8C4E\x8C50\x8C55\x8C62\x8C6C\x8C78\x8C7A" +++    {-0xB8-}  chars "\x8C82\x8C89\x8C85\x8C8A\x8C8D\x8C8E\x8C94\x8C7C" +++    {-0xC0-}  chars "\x8C98\x621D\x8CAD\x8CAA\x8CBD\x8CB2\x8CB3\x8CAE" +++    {-0xC8-}  chars "\x8CB6\x8CC8\x8CC1\x8CE4\x8CE3\x8CDA\x8CFD\x8CFA" +++    {-0xD0-}  chars "\x8CFB\x8D04\x8D05\x8D0A\x8D07\x8D0F\x8D0D\x8D10" +++    {-0xD8-}  chars "\x9F4E\x8D13\x8CCD\x8D14\x8D16\x8D67\x8D6D\x8D71" +++    {-0xE0-}  chars "\x8D73\x8D81\x8D99\x8DC2\x8DBE\x8DBA\x8DCF\x8DDA" +++    {-0xE8-}  chars "\x8DD6\x8DCC\x8DDB\x8DCB\x8DEA\x8DEB\x8DDF\x8DE3" +++    {-0xF0-}  chars "\x8DFC\x8E08\x8E09\x8DFF\x8E1D\x8E1E\x8E10\x8E1F" +++    {-0xF8-}  chars "\x8E42\x8E35\x8E30\x8E34\x8E4A"++-- | The multibyte characters with a lead byte of @0xE7@.+secondE7 :: SecondByteTable+secondE7 = V.fromList $+    {-0x40-}  chars "\x8E47\x8E49\x8E4C\x8E50\x8E48\x8E59\x8E64\x8E60" +++    {-0x48-}  chars "\x8E2A\x8E63\x8E55\x8E76\x8E72\x8E7C\x8E81\x8E87" +++    {-0x50-}  chars "\x8E85\x8E84\x8E8B\x8E8A\x8E93\x8E91\x8E94\x8E99" +++    {-0x58-}  chars "\x8EAA\x8EA1\x8EAC\x8EB0\x8EC6\x8EB1\x8EBE\x8EC5" +++    {-0x60-}  chars "\x8EC8\x8ECB\x8EDB\x8EE3\x8EFC\x8EFB\x8EEB\x8EFE" +++    {-0x68-}  chars "\x8F0A\x8F05\x8F15\x8F12\x8F19\x8F13\x8F1C\x8F1F" +++    {-0x70-}  chars "\x8F1B\x8F0C\x8F26\x8F33\x8F3B\x8F39\x8F45\x8F42" +++    {-0x78-}  chars "\x8F3E\x8F4C\x8F49\x8F46\x8F4E\x8F57\x8F5C" ++ Nothing :+    {-0x80-}  chars "\x8F62\x8F63\x8F64\x8F9C\x8F9F\x8FA3\x8FAD\x8FAF" +++    {-0x88-}  chars "\x8FB7\x8FDA\x8FE5\x8FE2\x8FEA\x8FEF\x9087\x8FF4" +++    {-0x90-}  chars "\x9005\x8FF9\x8FFA\x9011\x9015\x9021\x900D\x901E" +++    {-0x98-}  chars "\x9016\x900B\x9027\x9036\x9035\x9039\x8FF8\x904F" +++    {-0xA0-}  chars "\x9050\x9051\x9052\x900E\x9049\x903E\x9056\x9058" +++    {-0xA8-}  chars "\x905E\x9068\x906F\x9076\x96A8\x9072\x9082\x907D" +++    {-0xB0-}  chars "\x9081\x9080\x908A\x9089\x908F\x90A8\x90AF\x90B1" +++    {-0xB8-}  chars "\x90B5\x90E2\x90E4\x6248\x90DB\x9102\x9112\x9119" +++    {-0xC0-}  chars "\x9132\x9130\x914A\x9156\x9158\x9163\x9165\x9169" +++    {-0xC8-}  chars "\x9173\x9172\x918B\x9189\x9182\x91A2\x91AB\x91AF" +++    {-0xD0-}  chars "\x91AA\x91B5\x91B4\x91BA\x91C0\x91C1\x91C9\x91CB" +++    {-0xD8-}  chars "\x91D0\x91D6\x91DF\x91E1\x91DB\x91FC\x91F5\x91F6" +++    {-0xE0-}  chars "\x921E\x91FF\x9214\x922C\x9215\x9211\x925E\x9257" +++    {-0xE8-}  chars "\x9245\x9249\x9264\x9248\x9295\x923F\x924B\x9250" +++    {-0xF0-}  chars "\x929C\x9296\x9293\x929B\x925A\x92CF\x92B9\x92B7" +++    {-0xF8-}  chars "\x92E9\x930F\x92FA\x9344\x932E"++-- | The multibyte characters with a lead byte of @0xE8@.+secondE8 :: SecondByteTable+secondE8 = V.fromList $+    {-0x40-}  chars "\x9319\x9322\x931A\x9323\x933A\x9335\x933B\x935C" +++    {-0x48-}  chars "\x9360\x937C\x936E\x9356\x93B0\x93AC\x93AD\x9394" +++    {-0x50-}  chars "\x93B9\x93D6\x93D7\x93E8\x93E5\x93D8\x93C3\x93DD" +++    {-0x58-}  chars "\x93D0\x93C8\x93E4\x941A\x9414\x9413\x9403\x9407" +++    {-0x60-}  chars "\x9410\x9436\x942B\x9435\x9421\x943A\x9441\x9452" +++    {-0x68-}  chars "\x9444\x945B\x9460\x9462\x945E\x946A\x9229\x9470" +++    {-0x70-}  chars "\x9475\x9477\x947D\x945A\x947C\x947E\x9481\x947F" +++    {-0x78-}  chars "\x9582\x9587\x958A\x9594\x9596\x9598\x9599" ++ Nothing :+    {-0x80-}  chars "\x95A0\x95A8\x95A7\x95AD\x95BC\x95BB\x95B9\x95BE" +++    {-0x88-}  chars "\x95CA\x6FF6\x95C3\x95CD\x95CC\x95D5\x95D4\x95D6" +++    {-0x90-}  chars "\x95DC\x95E1\x95E5\x95E2\x9621\x9628\x962E\x962F" +++    {-0x98-}  chars "\x9642\x964C\x964F\x964B\x9677\x965C\x965E\x965D" +++    {-0xA0-}  chars "\x965F\x9666\x9672\x966C\x968D\x9698\x9695\x9697" +++    {-0xA8-}  chars "\x96AA\x96A7\x96B1\x96B2\x96B0\x96B4\x96B6\x96B8" +++    {-0xB0-}  chars "\x96B9\x96CE\x96CB\x96C9\x96CD\x894D\x96DC\x970D" +++    {-0xB8-}  chars "\x96D5\x96F9\x9704\x9706\x9708\x9713\x970E\x9711" +++    {-0xC0-}  chars "\x970F\x9716\x9719\x9724\x972A\x9730\x9739\x973D" +++    {-0xC8-}  chars "\x973E\x9744\x9746\x9748\x9742\x9749\x975C\x9760" +++    {-0xD0-}  chars "\x9764\x9766\x9768\x52D2\x976B\x9771\x9779\x9785" +++    {-0xD8-}  chars "\x977C\x9781\x977A\x9786\x978B\x978F\x9790\x979C" +++    {-0xE0-}  chars "\x97A8\x97A6\x97A3\x97B3\x97B4\x97C3\x97C6\x97C8" +++    {-0xE8-}  chars "\x97CB\x97DC\x97ED\x9F4F\x97F2\x7ADF\x97F6\x97F5" +++    {-0xF0-}  chars "\x980F\x980C\x9838\x9824\x9821\x9837\x983D\x9846" +++    {-0xF8-}  chars "\x984F\x984B\x986B\x986F\x9870"++-- | The multibyte characters with a lead byte of @0xE9@.+secondE9 :: SecondByteTable+secondE9 = V.fromList $+    {-0x40-}  chars "\x9871\x9874\x9873\x98AA\x98AF\x98B1\x98B6\x98C4" +++    {-0x48-}  chars "\x98C3\x98C6\x98E9\x98EB\x9903\x9909\x9912\x9914" +++    {-0x50-}  chars "\x9918\x9921\x991D\x991E\x9924\x9920\x992C\x992E" +++    {-0x58-}  chars "\x993D\x993E\x9942\x9949\x9945\x9950\x994B\x9951" +++    {-0x60-}  chars "\x9952\x994C\x9955\x9997\x9998\x99A5\x99AD\x99AE" +++    {-0x68-}  chars "\x99BC\x99DF\x99DB\x99DD\x99D8\x99D1\x99ED\x99EE" +++    {-0x70-}  chars "\x99F1\x99F2\x99FB\x99F8\x9A01\x9A0F\x9A05\x99E2" +++    {-0x78-}  chars "\x9A19\x9A2B\x9A37\x9A45\x9A42\x9A40\x9A43" ++ Nothing :+    {-0x80-}  chars "\x9A3E\x9A55\x9A4D\x9A5B\x9A57\x9A5F\x9A62\x9A65" +++    {-0x88-}  chars "\x9A64\x9A69\x9A6B\x9A6A\x9AAD\x9AB0\x9ABC\x9AC0" +++    {-0x90-}  chars "\x9ACF\x9AD1\x9AD3\x9AD4\x9ADE\x9ADF\x9AE2\x9AE3" +++    {-0x98-}  chars "\x9AE6\x9AEF\x9AEB\x9AEE\x9AF4\x9AF1\x9AF7\x9AFB" +++    {-0xA0-}  chars "\x9B06\x9B18\x9B1A\x9B1F\x9B22\x9B23\x9B25\x9B27" +++    {-0xA8-}  chars "\x9B28\x9B29\x9B2A\x9B2E\x9B2F\x9B32\x9B44\x9B43" +++    {-0xB0-}  chars "\x9B4F\x9B4D\x9B4E\x9B51\x9B58\x9B74\x9B93\x9B83" +++    {-0xB8-}  chars "\x9B91\x9B96\x9B97\x9B9F\x9BA0\x9BA8\x9BB4\x9BC0" +++    {-0xC0-}  chars "\x9BCA\x9BB9\x9BC6\x9BCF\x9BD1\x9BD2\x9BE3\x9BE2" +++    {-0xC8-}  chars "\x9BE4\x9BD4\x9BE1\x9C3A\x9BF2\x9BF1\x9BF0\x9C15" +++    {-0xD0-}  chars "\x9C14\x9C09\x9C13\x9C0C\x9C06\x9C08\x9C12\x9C0A" +++    {-0xD8-}  chars "\x9C04\x9C2E\x9C1B\x9C25\x9C24\x9C21\x9C30\x9C47" +++    {-0xE0-}  chars "\x9C32\x9C46\x9C3E\x9C5A\x9C60\x9C67\x9C76\x9C78" +++    {-0xE8-}  chars "\x9CE7\x9CEC\x9CF0\x9D09\x9D08\x9CEB\x9D03\x9D06" +++    {-0xF0-}  chars "\x9D2A\x9D26\x9DAF\x9D23\x9D1F\x9D44\x9D15\x9D12" +++    {-0xF8-}  chars "\x9D41\x9D3F\x9D3E\x9D46\x9D48"++-- | The multibyte characters with a lead byte of @0xEA@.+secondEA :: SecondByteTable+secondEA = V.fromList $+    {-0x40-}  chars "\x9D5D\x9D5E\x9D64\x9D51\x9D50\x9D59\x9D72\x9D89" +++    {-0x48-}  chars "\x9D87\x9DAB\x9D6F\x9D7A\x9D9A\x9DA4\x9DA9\x9DB2" +++    {-0x50-}  chars "\x9DC4\x9DC1\x9DBB\x9DB8\x9DBA\x9DC6\x9DCF\x9DC2" +++    {-0x58-}  chars "\x9DD9\x9DD3\x9DF8\x9DE6\x9DED\x9DEF\x9DFD\x9E1A" +++    {-0x60-}  chars "\x9E1B\x9E1E\x9E75\x9E79\x9E7D\x9E81\x9E88\x9E8B" +++    {-0x68-}  chars "\x9E8C\x9E92\x9E95\x9E91\x9E9D\x9EA5\x9EA9\x9EB8" +++    {-0x70-}  chars "\x9EAA\x9EAD\x9761\x9ECC\x9ECE\x9ECF\x9ED0\x9ED4" +++    {-0x78-}  chars "\x9EDC\x9EDE\x9EDD\x9EE0\x9EE5\x9EE8\x9EEF" ++ Nothing :+    {-0x80-}  chars "\x9EF4\x9EF6\x9EF7\x9EF9\x9EFB\x9EFC\x9EFD\x9F07" +++    {-0x88-}  chars "\x9F08\x76B7\x9F15\x9F21\x9F2C\x9F3E\x9F4A\x9F52" +++    {-0x90-}  chars "\x9F54\x9F63\x9F5F\x9F60\x9F61\x9F66\x9F67\x9F6C" +++    {-0x98-}  chars "\x9F6A\x9F77\x9F72\x9F76\x9F95\x9F9C\x9FA0\x582F" +++    {-0xA0-}  chars "\x69C7\x9059\x7464\x51DC\x7199" +++    {-0xA5..0xFC-} nothings 0x58++-- | The multibyte characters with a lead byte of @0xEB@.+secondEB :: SecondByteTable+secondEB = nothingSecond++-- | The multibyte characters with a lead byte of @0xEC@.+secondEC :: SecondByteTable+secondEC = nothingSecond++-- | The multibyte characters with a lead byte of @0xED@.+secondED :: SecondByteTable+secondED = V.fromList $+    {-0x40-}  chars "\x7E8A\x891C\x9348\x9288\x84DC\x4FC9\x70BB\x6631" +++    {-0x48-}  chars "\x68C8\x92F9\x66FB\x5F45\x4E28\x4EE1\x4EFC\x4F00" +++    {-0x50-}  chars "\x4F03\x4F39\x4F56\x4F92\x4F8A\x4F9A\x4F94\x4FCD" +++    {-0x58-}  chars "\x5040\x5022\x4FFF\x501E\x5046\x5070\x5042\x5094" +++    {-0x60-}  chars "\x50F4\x50D8\x514A\x5164\x519D\x51BE\x51EC\x5215" +++    {-0x68-}  chars "\x529C\x52A6\x52C0\x52DB\x5300\x5307\x5324\x5372" +++    {-0x70-}  chars "\x5393\x53B2\x53DD\xFA0E\x549C\x548A\x54A9\x54FF" +++    {-0x78-}  chars "\x5586\x5759\x5765\x57AC\x57C8\x57C7\xFA0F" ++ Nothing :+    {-0x80-}  chars "\xFA10\x589E\x58B2\x590B\x5953\x595B\x595D\x5963" +++    {-0x88-}  chars "\x59A4\x59BA\x5B56\x5BC0\x752F\x5BD8\x5BEC\x5C1E" +++    {-0x90-}  chars "\x5CA6\x5CBA\x5CF5\x5D27\x5D53\xFA11\x5D42\x5D6D" +++    {-0x98-}  chars "\x5DB8\x5DB9\x5DD0\x5F21\x5F34\x5F67\x5FB7\x5FDE" +++    {-0xA0-}  chars "\x605D\x6085\x608A\x60DE\x60D5\x6120\x60F2\x6111" +++    {-0xA8-}  chars "\x6137\x6130\x6198\x6213\x62A6\x63F5\x6460\x649D" +++    {-0xB0-}  chars "\x64CE\x654E\x6600\x6615\x663B\x6609\x662E\x661E" +++    {-0xB8-}  chars "\x6624\x6665\x6657\x6659\xFA12\x6673\x6699\x66A0" +++    {-0xC0-}  chars "\x66B2\x66BF\x66FA\x670E\xF929\x6766\x67BB\x6852" +++    {-0xC8-}  chars "\x67C0\x6801\x6844\x68CF\xFA13\x6968\xFA14\x6998" +++    {-0xD0-}  chars "\x69E2\x6A30\x6A6B\x6A46\x6A73\x6A7E\x6AE2\x6AE4" +++    {-0xD8-}  chars "\x6BD6\x6C3F\x6C5C\x6C86\x6C6F\x6CDA\x6D04\x6D87" +++    {-0xE0-}  chars "\x6D6F\x6D96\x6DAC\x6DCF\x6DF8\x6DF2\x6DFC\x6E39" +++    {-0xE8-}  chars "\x6E5C\x6E27\x6E3C\x6EBF\x6F88\x6FB5\x6FF5\x7005" +++    {-0xF0-}  chars "\x7007\x7028\x7085\x70AB\x710F\x7104\x715C\x7146" +++    {-0xF8-}  chars "\x7147\xFA15\x71C1\x71FE\x72B1"++-- | The multibyte characters with a lead byte of @0xEE@.+secondEE :: SecondByteTable+secondEE = V.fromList $+    {-0x40-}  chars "\x72BE\x7324\xFA16\x7377\x73BD\x73C9\x73D6\x73E3" +++    {-0x48-}  chars "\x73D2\x7407\x73F5\x7426\x742A\x7429\x742E\x7462" +++    {-0x50-}  chars "\x7489\x749F\x7501\x756F\x7682\x769C\x769E\x769B" +++    {-0x58-}  chars "\x76A6\xFA17\x7746\x52AF\x7821\x784E\x7864\x787A" +++    {-0x40-}  chars "\x7930\xFA18\xFA19\xFA1A\x7994\xFA1B\x799B\x7AD1" +++    {-0x68-}  chars "\x7AE7\xFA1C\x7AEB\x7B9E\xFA1D\x7D48\x7D5C\x7DB7" +++    {-0x70-}  chars "\x7DA0\x7DD6\x7E52\x7F47\x7FA1\xFA1E\x8301\x8362" +++    {-0x78-}  chars "\x837F\x83C7\x83F6\x8448\x84B4\x8553\x8559" ++ Nothing :+    {-0x80-}  chars "\x856B\xFA1F\x85B0\xFA20\xFA21\x8807\x88F5\x8A12" +++    {-0x88-}  chars "\x8A37\x8A79\x8AA7\x8ABE\x8ADF\xFA22\x8AF6\x8B53" +++    {-0x90-}  chars "\x8B7F\x8CF0\x8CF4\x8D12\x8D76\xFA23\x8ECF\xFA24" +++    {-0x98-}  chars "\xFA25\x9067\x90DE\xFA26\x9115\x9127\x91DA\x91D7" +++    {-0xA0-}  chars "\x91DE\x91ED\x91EE\x91E4\x91E5\x9206\x9210\x920A" +++    {-0xA8-}  chars "\x923A\x9240\x923C\x924E\x9259\x9251\x9239\x9267" +++    {-0xB0-}  chars "\x92A7\x9277\x9278\x92E7\x92D7\x92D9\x92D0\xFA27" +++    {-0xB8-}  chars "\x92D5\x92E0\x92D3\x9325\x9321\x92FB\xFA28\x931E" +++    {-0xC0-}  chars "\x92FF\x931D\x9302\x9370\x9357\x93A4\x93C6\x93DE" +++    {-0xC8-}  chars "\x93F8\x9431\x9445\x9448\x9592\xF9DC\xFA29\x969D" +++    {-0xD0-}  chars "\x96AF\x9733\x973B\x9743\x974D\x974F\x9751\x9755" +++    {-0xD8-}  chars "\x9857\x9865\xFA2A\xFA2B\x9927\xFA2C\x999E\x9A4E" +++    {-0xE0-}  chars "\x9AD9\x9ADC\x9B75\x9B72\x9B8F\x9BB1\x9BBB\x9C00" +++    {-0xE8-}  chars "\x9D70\x9D6B\xFA2D\x9E19\x9ED1" ++ nothings 2 +++    {-0xEF..0xF8-}  chars ['\x2170'..'\x2179'] +++    {-0xF9-}  chars "\xFFE2\xFFE4\xFF07\xFF02"++-- | The multibyte characters with a lead byte of @0xEF@.+secondEF :: SecondByteTable+secondEF = nothingSecond++-- | The multibyte characters with a lead byte of @0xF0@.+secondF0 :: SecondByteTable+secondF0 = privateUseSecond 0xE000++-- | The multibyte characters with a lead byte of @0xF1@.+secondF1 :: SecondByteTable+secondF1 = privateUseSecond 0xE0BC++-- | The multibyte characters with a lead byte of @0xF2@.+secondF2 :: SecondByteTable+secondF2 = privateUseSecond 0xE178++-- | The multibyte characters with a lead byte of @0xF3@.+secondF3 :: SecondByteTable+secondF3 = privateUseSecond 0xE234++-- | The multibyte characters with a lead byte of @0xF4@.+secondF4 :: SecondByteTable+secondF4 = privateUseSecond 0xE2F0++-- | The multibyte characters with a lead byte of @0xF5@.+secondF5 :: SecondByteTable+secondF5 = privateUseSecond 0xE3AC++-- | The multibyte characters with a lead byte of @0xF6@.+secondF6 :: SecondByteTable+secondF6 = privateUseSecond 0xE468++-- | The multibyte characters with a lead byte of @0xF7@.+secondF7 :: SecondByteTable+secondF7 = privateUseSecond 0xE524++-- | The multibyte characters with a lead byte of @0xF8@.+secondF8 :: SecondByteTable+secondF8 = privateUseSecond 0xE5E0++-- | The multibyte characters with a lead byte of @0xF9@.+secondF9 :: SecondByteTable+secondF9 = privateUseSecond 0xE69C++-- | The multibyte characters with a lead byte of @0xFA@.+secondFA :: SecondByteTable+secondFA = V.fromList $+    {-0x40..0x49-}  chars ['\x2170'..'\x2179'] +++    {-0x4A..0x53-}  chars ['\x2160'..'\x2169'] +++    {-0x54-}  chars "\xFFE2\xFFE4\xFF07\xFF02" +++    {-0x58-}  chars "\x3231\x2116\x2121\x2235\x7E8A\x891C\x9348\x9288" +++    {-0x60-}  chars "\x84DC\x4FC9\x70BB\x6631\x68C8\x92F9\x66FB\x5F45" +++    {-0x68-}  chars "\x4E28\x4EE1\x4EFC\x4F00\x4F03\x4F39\x4F56\x4F92" +++    {-0x70-}  chars "\x4F8A\x4F9A\x4F94\x4FCD\x5040\x5022\x4FFF\x501E" +++    {-0x78-}  chars "\x5046\x5070\x5042\x5094\x50F4\x50D8\x514A" ++ Nothing :+    {-0x80-}  chars "\x5164\x519D\x51BE\x51EC\x5215\x529C\x52A6\x52C0" +++    {-0x88-}  chars "\x52DB\x5300\x5307\x5324\x5372\x5393\x53B2\x53DD" +++    {-0x90-}  chars "\xFA0E\x549C\x548A\x54A9\x54FF\x5586\x5759\x5765" +++    {-0x98-}  chars "\x57AC\x57C8\x57C7\xFA0F\xFA10\x589E\x58B2\x590B" +++    {-0xA0-}  chars "\x5953\x595B\x595D\x5963\x59A4\x59BA\x5B56\x5BC0" +++    {-0xA8-}  chars "\x752F\x5BD8\x5BEC\x5C1E\x5CA6\x5CBA\x5CF5\x5D27" +++    {-0xB0-}  chars "\x5D53\xFA11\x5D42\x5D6D\x5DB8\x5DB9\x5DD0\x5F21" +++    {-0xB8-}  chars "\x5F34\x5F67\x5FB7\x5FDE\x605D\x6085\x608A\x60DE" +++    {-0xC0-}  chars "\x60D5\x6120\x60F2\x6111\x6137\x6130\x6198\x6213" +++    {-0xC8-}  chars "\x62A6\x63F5\x6460\x649D\x64CE\x654E\x6600\x6615" +++    {-0xD0-}  chars "\x663B\x6609\x662E\x661E\x6624\x6665\x6657\x6659" +++    {-0xD8-}  chars "\xFA12\x6673\x6699\x66A0\x66B2\x66BF\x66FA\x670E" +++    {-0xE0-}  chars "\xF929\x6766\x67BB\x6852\x67C0\x6801\x6844\x68CF" +++    {-0xE8-}  chars "\xFA13\x6968\xFA14\x6998\x69E2\x6A30\x6A6B\x6A46" +++    {-0xF0-}  chars "\x6A73\x6A7E\x6AE2\x6AE4\x6BD6\x6C3F\x6C5C\x6C86" +++    {-0xF8-}  chars "\x6C6F\x6CDA\x6D04\x6D87\x6D6F"++-- | The multibyte characters with a lead byte of @0xFB@.+secondFB :: SecondByteTable+secondFB = V.fromList $+    {-0x40-}  chars "\x6D96\x6DAC\x6DCF\x6DF8\x6DF2\x6DFC\x6E39\x6E5C" +++    {-0x48-}  chars "\x6E27\x6E3C\x6EBF\x6F88\x6FB5\x6FF5\x7005\x7007" +++    {-0x50-}  chars "\x7028\x7085\x70AB\x710F\x7104\x715C\x7146\x7147" +++    {-0x58-}  chars "\xFA15\x71C1\x71FE\x72B1\x72BE\x7324\xFA16\x7377" +++    {-0x60-}  chars "\x73BD\x73C9\x73D6\x73E3\x73D2\x7407\x73F5\x7426" +++    {-0x68-}  chars "\x742A\x7429\x742E\x7462\x7489\x749F\x7501\x756F" +++    {-0x70-}  chars "\x7682\x769C\x769E\x769B\x76A6\xFA17\x7746\x52AF" +++    {-0x78-}  chars "\x7821\x784E\x7864\x787A\x7930\xFA18\xFA19" ++ Nothing :+    {-0x80-}  chars "\xFA1A\x7994\xFA1B\x799B\x7AD1\x7AE7\xFA1C\x7AEB" +++    {-0x88-}  chars "\x7B9E\xFA1D\x7D48\x7D5C\x7DB7\x7DA0\x7DD6\x7E52" +++    {-0x90-}  chars "\x7F47\x7FA1\xFA1E\x8301\x8362\x837F\x83C7\x83F6" +++    {-0x98-}  chars "\x8448\x84B4\x8553\x8559\x856B\xFA1F\x85B0\xFA20" +++    {-0xA0-}  chars "\xFA21\x8807\x88F5\x8A12\x8A37\x8A79\x8AA7\x8ABE" +++    {-0xA8-}  chars "\x8ADF\xFA22\x8AF6\x8B53\x8B7F\x8CF0\x8CF4\x8D12" +++    {-0xB0-}  chars "\x8D76\xFA23\x8ECF\xFA24\xFA25\x9067\x90DE\xFA26" +++    {-0xB8-}  chars "\x9115\x9127\x91DA\x91D7\x91DE\x91ED\x91EE\x91E4" +++    {-0xC0-}  chars "\x91E5\x9206\x9210\x920A\x923A\x9240\x923C\x924E" +++    {-0xC8-}  chars "\x9259\x9251\x9239\x9267\x92A7\x9277\x9278\x92E7" +++    {-0xD0-}  chars "\x92D7\x92D9\x92D0\xFA27\x92D5\x92E0\x92D3\x9325" +++    {-0xD8-}  chars "\x9321\x92FB\xFA28\x931E\x92FF\x931D\x9302\x9370" +++    {-0xE0-}  chars "\x9357\x93A4\x93C6\x93DE\x93F8\x9431\x9445\x9448" +++    {-0xE8-}  chars "\x9592\xF9DC\xFA29\x969D\x96AF\x9733\x973B\x9743" +++    {-0xF0-}  chars "\x974D\x974F\x9751\x9755\x9857\x9865\xFA2A\xFA2B" +++    {-0xF8-}  chars "\x9927\xFA2C\x999E\x9A4E\x9AD9"++-- | The multibyte characters with a lead byte of @0xFC@.+secondFC :: SecondByteTable+secondFC = V.fromList $+    {-0x40-}  chars "\x9ADC\x9B75\x9B72\x9B8F\x9BB1\x9BBB\x9C00\x9D70" +++    {-0x48-}  chars "\x9D6B\xFA2D\x9E19\x9ED1" +++    {-0x4C..0xFC-} nothings 0xB1
+ src/Foreign/Libcdio.hs view
@@ -0,0 +1,74 @@+{-|+Description:    Bindings directly mirroring the C interface of libcdio.++Copyright:      (c) 2018-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      stable+Portability:    non-portable (requires libcdio)++Modules in this tree are designed so users familiar with working with the+original libcdio should be able to write essentially the same code they're+used to, in the 'IO' monad.  There have, however, been some changes made (beyond+mapping the types to ones more native to Haskell), mostly to take advantage of+the type safety.  These have then been adapted further into the modules under+"Sound.Libcdio", which aim to provide much of the same functionality but in a+form the library might have taken if it had been originally written for+Haskell.++As /this/ interface does mirror the structure of the C library, each header+file is translated into a separate module, as follows.  Any changes from those+original headers which might not be easily guessed are noted in the+documentation for each module, along with similar equivalencies to the+higher-level interface.++* @cdio.h@ -> "Foreign.Libcdio"+* @cd_types.h@ -> "Foreign.Libcdio.CdTypes" (not reexported by @cdio.h@, or this module)+* @cdtext.h@ -> "Foreign.Libcdio.CdText"+* @device.h@ -> "Foreign.Libcdio.Device"+* @disc.h@ -> "Foreign.Libcdio.Disc"+* @logging.h@ -> "Foreign.Libcdio.Logging" (not reexported by @cdio.h@, or this module)+* @memory.h@ (removed; the only exported symbol @cdio_free@ is encapsulated+  into the Haskell garbage collection)+* @read.h@ -> "Foreign.Libcdio.Read"+* @sector.h@ -> "Foreign.Libcdio.Sector"+* @track.h@ -> "Foreign.Libcdio.Track"+* @types.h@ -> "Foreign.Libcdio.Types"++    * The original header was an interesting collection of some (but not all)+      types used by the library.  The module is both more universal by+      exporting all types in the interface, and less required as each relevant+      type is exported by the various modules themselves.++* @util.h@ -> "Foreign.Libcdio.Util" (not reexported by @cdio.h@, or this module)+* @version.h@ -> "Foreign.Libcdio.Version"+++= @cdio.h@++== Defines+* @CDIO_API_VERSION@                -> 'apiVersion' (primarily exported from "Foreign.Libcdio.Version")++== Types+* @CdIo_t@                          -> 'Cdio' (primarily exported from "Foreign.Libcdio.Device")+-}+module Foreign.Libcdio+    ( module Foreign.Libcdio.CdText+    , module Foreign.Libcdio.Device+    , module Foreign.Libcdio.Disc+    , module Foreign.Libcdio.Read+    , module Foreign.Libcdio.Sector+    , module Foreign.Libcdio.Track+    , module Foreign.Libcdio.Version+    ) where+++import Foreign.Libcdio.Version+import Foreign.Libcdio.Sector++import Foreign.Libcdio.Device+import Foreign.Libcdio.CdText+import Foreign.Libcdio.Disc+import Foreign.Libcdio.Read+import Foreign.Libcdio.Track
+ src/Foreign/Libcdio/CdText.hs view
@@ -0,0 +1,310 @@+{-# LANGUAGE ForeignFunctionInterface #-}++{-|+Description:    Functions and types providing metadata about the disc contents.++Copyright:      (c) 2018-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      stable+Portability:    non-portable (requires libcdio)++Metadata is stored in a binary format both library-internally and on the disc.+Most audio archivists will recognize it as "those information fields in a CUE+file" (though there are [other+formats](https://www.gnu.org/software/libcdio/cd-text-format.html#Sony-Text-File-Format-_0028Input-Sheet-Version-0_002e7T_0029)+as well), and casual listeners will recognize it as the scrolling text that+you're always happy to see, on the rare times your music player shows it.+Little-used and even-less-known, however, is that a single disc can+theoretically contain metadata in up to eight different languages; because of+the complexity that introduces, no unifying datatype is provided in favour of a+function-based interface.+++= @cdtext.h@++== Defines+* @MIN_CDTEXT_FIELD@                (removed; identical to @'minBound' :: 'Field'@)+* @MAX_CDTEXT_FIELD@                (removed; identical to @'maxBound' :: 'Field'@)++== Types+* @cdtext_field_t@                  -> 'Field'++    - @CDTEXT_FIELD_INVALID@        (removed; handled via 'Nothing')++* @cdtext_genre_t@                  -> 'Genre'++    - @CDTEXT_GENRE_UNUSED@         (removed; handled via 'Nothing')++* @cdtext_lang_t@                   -> 'Language'++    - @CDTEXT_LANGUAGE_UNKNOWN@     -> 'UnknownLanguage'++        - /Before libcdio 2.1.0:  (often effectively removed; handled via 'Nothing')/++    - @CDTEXT_LANGUAGE_INVALID@     (removed; handled via 'Nothing')+    - @CDTEXT_LANGUAGE_BLOCK_UNUSED@ (removed; handled via 'Nothing')++* @cdtext_t@                        (removed; merged into 'Cdio' objects)++== Symbols+* @cdtext_data_init@                -> 'cdTextDataInit'+* @cdtext_destroy@                  (removed; handled via the garbage collector)+* @cdtext_field2str@                -> 'fieldString'+* @cdtext_genre2str@                -> 'genreString'+* @cdtext_get@                      (removed; type conversion makes it identical to @cdtext_get_const@)+* @cdtext_get_const@                -> 'cdTextGet'+* @cdtext_get_first_track@          -> 'firstTrack'+* @cdtext_get_genre@                -> 'genre'+* @cdtext_get_language@             -> 'language'+* @cdtext_get_last_track@           -> 'lastTrack'+* @cdtext_init@                     (removed; internal function without much external occasion)+* @cdtext_lang2str@                 -> 'languageString'+* @cdtext_list_languages@           -> 'listLanguages'+* @cdtext_list_languages_v2@        -> 'listAllLanguages'+* @cdtext_select_language@          -> 'selectLanguage'+* @cdtext_set@                      (removed; primarily intended for internal use, and is more limited than would be expected)+* @cdtext_set_language_index@       -> 'selectLanguageIndex'+* @cdtext_str2lang@                 -> 'parseLanguage'+++= "Sound.Libcdio.Read.CdText"+While similar functionality is provided, the+@"Sound.Libcdio.Read".'Sound.Libcdio.Read.CdText'@ is written as a separate+monadic interface rather than in the 'Cdio'-bound style used here.++* 'cdTextDataInit'                  -> 'Sound.Libcdio.Read.CdText.parseCdText'+* 'cdTextGet'                       -> 'Sound.Libcdio.Read.CdText.discId', @'snd' 'Sound.Libcdio.Read.CdText.genre'@, and 'Sound.Libcdio.Read.CdText.info'+* 'genre'                           -> @'fst' 'Sound.Libcdio.Read.CdText.genre'@+* 'listAllLanguages'                -> 'Sound.Libcdio.Read.CdText.languages'+* 'listLanguages'                   (removed; obsolete and imprecise)+* 'selectLanguage'                  -> 'Sound.Libcdio.Read.CdText.withLanguage'+* 'selectLanguageIndex'             -> 'Sound.Libcdio.Read.CdText.withIndex'+-}+module Foreign.Libcdio.CdText+    ( -- * Types+      Cdio+    , Field ( .. )+    , Genre ( .. )+    , Language ( .. )+      -- * Description+    , fieldString+    , languageString+    , parseLanguage+    , genreString+      -- * Management+    , cdTextDataInit+    , listLanguages+    , listAllLanguages+    , selectLanguage+    , selectLanguageIndex+      -- * Access+    , cdTextGet+    , genre+    , language+    , firstTrack+    , lastTrack+    ) where+++import qualified Data.List as L+import qualified Data.Maybe as Y++import qualified Foreign.C.String as C+import qualified Foreign.C.Types as C+import qualified Foreign.Ptr as C++import qualified Foreign.Marshal.Array as M+import qualified Foreign.Marshal.Utils as M++import qualified System.IO.Unsafe as IO.Unsafe++import Foreign.Libcdio.Device+import Foreign.Libcdio.Marshal+import Foreign.Libcdio.Track+import Foreign.Libcdio.Types.Enums+import Foreign.Libcdio.Types.Internal+import Foreign.Libcdio.Version++import Sound.Libcdio.Common+++-- | Return a canonical English name of the given genre, as opposed to the+-- machine representation returned by the 'Show' instance.+genreString :: Genre -> String+genreString = IO.Unsafe.unsafePerformIO .+    C.peekCString . genreString' . fromIntegral . fromEnum++foreign import ccall safe "cdio/compat/cdtext.h cdtext_genre2str"+  genreString' :: CGenre -> C.CString++-- | Return a canonical English name of the given language, as opposed to the+-- machine representation returned by the 'Show' instance.+languageString :: Language -> String+languageString = IO.Unsafe.unsafePerformIO .+    C.peekCString . languageString' . fromIntegral . fromEnum++foreign import ccall safe "cdio/compat/cdtext.h cdtext_lang2str"+  languageString' :: CLanguage -> C.CString++-- | Transform a string returned by 'languageString' back into its+-- 'Language' representation.+-- +-- /Before libcdio 2.1.0:  Always returns 'Nothing'/+parseLanguage :: String -> Maybe Language+parseLanguage s+    | libcdioVersionNum >= makeVersion [2,1] = IO.Unsafe.unsafePerformIO $ do+        i <- C.withCString s parseLanguage'+        return . fmap (toEnum . fromIntegral) $ maybeError [languageInvalid, languageUnused] i+    | otherwise = Nothing++foreign import ccall safe "cdio/compat/cdtext.h cdtext_str2lang_safe"+  parseLanguage' :: C.CString -> IO CLanguage++foreign import ccall safe "cdio/compat/cdtext.h language_unknown"+  languageUnknown :: CLanguage++foreign import ccall safe "cdio/compat/cdtext.h language_invalid"+  languageInvalid :: CLanguage++foreign import ccall safe "cdio/compat/cdtext.h language_unused"+  languageUnused :: CLanguage++-- | Describe the type of data in a human-readable manner, as opposed to the+-- machine representation returned by the 'Show' instance.+fieldString :: Field -> String+fieldString = IO.Unsafe.unsafePerformIO .+    C.peekCString . fieldString' . fromIntegral . fromEnum++foreign import ccall safe "cdio/compat/cdtext.h cdtext_field2str"+  fieldString' :: CField -> C.CString+++-- | Attempt to retrieve the value of a given field from the disc (if+-- 'Nothing') or track (if 'Just') metadata, in the currently-active language.+-- Note that 'GenreName' and 'DiscId' will /always/ refer to the disc-level+-- data.+cdTextGet :: Cdio -> Field -> Maybe Track -> IO (Maybe String)+cdTextGet _ _ (Just DiscPregap) = return Nothing+cdTextGet _ _ (Just DiscLeadout) = return Nothing+cdTextGet c GenreName _ = cdTextGet_ c GenreName 0+cdTextGet c DiscId _ = cdTextGet_ c DiscId 0+cdTextGet c f Nothing = cdTextGet_ c f 0+cdTextGet c f (Just t) = cdTextGet_ c f t++cdTextGet_ :: Cdio -> Field -> Track -> IO (Maybe String)+cdTextGet_ c f t = withCdText' Nothing c $ \x ->+    cdTextGet' x (fromIntegral $ fromEnum f) (fromIntegral $ fromEnum t) >>= M.maybePeek C.peekCString++foreign import ccall safe "cdio/compat/cdtext.h cdtext_get_const"+  cdTextGet' :: C.Ptr CdText -> CField -> CTrack -> IO C.CString+++-- | The machine-readable genre describing the music on this disc.  For any+-- associated human-readable name or subgenre, use @'cdTextGet' c 'GenreName'+-- 'Nothing'@.+genre :: Cdio -> IO (Maybe Genre)+genre c = do+    g <- withCdText c genre'+    return $ if g == Just 0 then Nothing else toEnum . fromIntegral <$> g++foreign import ccall safe "cdio/compat/cdtext.h cdtext_get_genre"+  genre' :: C.Ptr CdText -> IO CGenre++-- | Indicate which language results will (currently) be returned in.  See+-- 'selectLanguage' to change this.+language :: Cdio -> IO (Maybe Language)+language c = fmap (toEnum . fromIntegral) <$> withCdText c language'++foreign import ccall safe "cdio/compat/cdtext.h cdtext_get_language"+  language' :: C.Ptr CdText -> IO CLanguage+++-- | The earliest track with any associated metadata in the current language.+-- Note that this may differ from 'minTrack'.+firstTrack :: Cdio -> IO (Maybe Track)+firstTrack c = fmap (toEnum . fromIntegral) . maybeError [0] <$> withCdText' 0 c firstTrack'++foreign import ccall safe "cdio/compat/cdtext.h cdtext_get_first_track"+  firstTrack' :: C.Ptr CdText -> IO CTrack++-- | The final track with any associated metadata in the current language.+-- Note that this may differ from 'maxTrack'.+lastTrack :: Cdio -> IO (Maybe Track)+lastTrack c = fmap (toEnum . fromIntegral) . maybeError [0] <$> withCdText' 0 c lastTrack'++foreign import ccall safe "cdio/compat/cdtext.h cdtext_get_last_track"+  lastTrack' :: C.Ptr CdText -> IO CTrack+++-- | Try to set the data associated with the given language as active for+-- future calls to 'cdTextGet' and similar.  If passed 'UnknownLanguage' or the+-- CDTEXT does not provide the one requested, selects the first (default) data+-- set instead, and returns 'False'.+selectLanguage :: Cdio -> Language -> IO Bool+selectLanguage c l = fmap M.toBool . withCdText' 0 c $ \x ->+    selectLanguage' x . fromIntegral $ fromEnum l++foreign import ccall safe "cdio/compat/cdtext.h cdtext_select_language"+  selectLanguage' :: C.Ptr CdText -> CLanguage -> IO CBool++-- | Retrieve the languages included in the disc metadata.  Note that this does+-- not save the index position or any duplicate language blocks (if that is+-- desired, see 'listAllLanguages' instead).+listLanguages :: Cdio -> IO [Language]+listLanguages c = withCdText' [] c $ \x -> do+    l' <- listLanguages' x+    ls <- peekLanguages l' [languageUnknown, languageInvalid, languageUnused]+    return . L.nub $ Y.catMaybes ls++foreign import ccall safe "cdio/compat/cdtext.h cdtext_list_languages"+  listLanguages' :: C.Ptr CdText -> IO (C.Ptr CLanguage)++-- | Retrieve the languages included in the disc metadata, in the order they+-- occur, and respecting any empty language blocks if there's a valid language+-- after them (empty blocks at the end are cleaned away).+-- +-- /Before libcdio 2.1.0:  Acts as 'listLanguages'/+listAllLanguages :: Cdio -> IO [Maybe Language]+listAllLanguages c = withCdText' [] c $ \x -> do+    l' <- listAllLanguages' x+    ls <- peekLanguages l' [languageInvalid, languageUnused]+    return $ case L.dropWhileEnd Y.isNothing ls of+        [] -> [Just UnknownLanguage]+        ls' -> ls'++foreign import ccall safe "cdio/compat/cdtext.h cdtext_list_languages_v2_safe"+  listAllLanguages' :: C.Ptr CdText -> IO (C.Ptr CLanguage)++peekLanguages :: C.Ptr CLanguage -> [CLanguage] -> IO [Maybe Language]+peekLanguages p es+    | p == C.nullPtr = return []+    | otherwise = map (fmap (toEnum . fromIntegral) . maybeError es) <$> M.peekArray 8 p++-- | Select the language at the given index of 'listAllLanguages' for future+-- data retrieval.  If the index is out of bounds or corresponds to a 'Nothing'+-- in 'listAllLanguages', the first (default) data set is selected instead and+-- 'False is returned.+selectLanguageIndex :: Cdio -> Word -> IO Bool+selectLanguageIndex c i = M.toBool <$> withCdText' 0 c (flip selectLanguageIndex' $ fromIntegral i)++foreign import ccall safe "cdio/compat/cdtext.h cdtext_set_language_index_safe"+  selectLanguageIndex' :: C.Ptr CdText -> C.CInt -> IO CBool+++{- Primarily intended as an internal function+-- | Set the given field at the given track to the given value.+cdTextSet :: Cdio -> Field -> Maybe String -> Maybe Track -> IO ()+cdTextSet _ _ _ (Just DiscPregap) = mempty+cdTextSet _ _ _ (Just DiscLeadout) = mempty+cdTextSet c f v Nothing = cdTextSet_ c f v 0+cdTextSet c f v (Just t) = cdTextSet_ c f v t++cdTextSet_ :: Cdio -> Field -> Maybe String -> Track -> IO ()+cdTextSet_ c f v t = withCdText_ c $ \x -> M.maybeWith C.withCString v $ \s ->+    cdTextSet' x (toCEnum f) s (withTrack t) C.nullPtr++foreign import ccall safe "cdio/compat/cdtext.h cdtext_set"+  cdTextSet' :: C.Ptr CdText -> CField -> C.CString -> CTrack -> C.CString -> IO ()+-}
+ src/Foreign/Libcdio/CdText/Binary.hs view
@@ -0,0 +1,409 @@+{-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}+{-# OPTIONS_GHC -Wno-unused-imports #-}++{-|+Description:    ++Copyright:      (c) 2020-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      stable+Portability:    non-portable (requires libcdio)+-}+module Foreign.Libcdio.CdText.Binary+    ( Info ( .. )+    , emptyCdTextRaw+    , packCdTextBlock+    , joinBlockInfo+    , checksum+    ) where+++import qualified Data.Bits as B+import qualified Data.Bifunctor as F.B+import qualified Data.ByteString as BS+import qualified Data.ByteString.Char8 as BS.C+import qualified Data.Char as C+import qualified Data.List as L+import qualified Data.Maybe as Y+import qualified Data.Word as W++import qualified Data.Text as T+import qualified Data.Text.Encoding.Error as T+import qualified Data.Text.Encoding.MsJIS as T++import Data.Bits ( (.&.), (.|.) )++import Foreign.Libcdio.Track+import Foreign.Libcdio.Types.Enums++import Sound.Libcdio.Common+++type TrackId = W.Word8+type PackType = W.Word8+type BlockId = Word+type BlockSize = W.Word8+++-- | Textual data used for describing tracks on a disc (as well as the disc+-- itself).+data Info = Info+    { title      :: Maybe String+    , performer  :: Maybe String+    , songwriter :: Maybe String+    , composer   :: Maybe String+    , arranger   :: Maybe String+    , message    :: Maybe String+    , code       :: Maybe String+    }+  deriving ( Eq, Show, Read )+++emptyCdTextRaw :: [Maybe Language] -> BS.ByteString+emptyCdTextRaw [] = emptyCdTextRaw [Nothing]+emptyCdTextRaw ls =+    BS.concat . concat . flip map (zip [0..] ls) $ \(i, _) -> map checksum .+    joinBlockInfo ls [3 | _ <- ls] .+    generateBlockInfo i Iso8859_1 0 0 $+    replicate 15 0 ++ [3]+++data Encoding+    = Iso8859_1+    | ASCII+    | MS_JIS+  deriving ( Eq, Ord, Bounded, Show, Read )+instance Enum Encoding where+    toEnum 0x00 = Iso8859_1+    toEnum 0x01 = ASCII+    toEnum 0x80 = MS_JIS+    toEnum _ = ASCII+    fromEnum Iso8859_1 = 0x00+    fromEnum ASCII = 0x01+    fromEnum MS_JIS = 0x80++data Pack+    = TitlePack+    | PerformerPack+    | SongwriterPack+    | ComposerPack+    | ArrangerPack+    | MessagePack+    | DiscIdPack+    | GenrePack+    | TocPack+    | Toc2Pack+    | ClosedPack+    | CodePack+    | InfoPack+  deriving ( Eq, Ord, Bounded, Enum, Show, Read )+++-- | Generate the binary data representing a CDTEXT language block.+packCdTextBlock+    :: BlockId+    -> Maybe String+    -> Track+    -> Maybe Genre+    -> Maybe String+    -> Info+    -> [Info]+    -> [BS.ByteString]+packCdTextBlock blockIndex catalogue startTrack@(Track _) genreCode genreName disc tracks =+    allPacks <> generateBlockInfo blockIndex encoding startTrackId endTrackId allLengths+  where (titles, tt) = text title TitlePack (0 :: Int)+        (performers, tp) = text performer PerformerPack ip+        (songwriters, ts) = text songwriter SongwriterPack is+        (composers, tc) = text composer ComposerPack ic+        (arrangers, ta) = text arranger ArrangerPack ia+        (messages, tm) = text message MessagePack im+        (catalogueB, _) = pack' DiscIdPack False il (prepareSingleText ASCII catalogue, 0 :: Int)+        (genreB, _) = pack' GenrePack False ig (prepareGenre genreCode genreName, 0 :: Int)+     -- (tocB, _) = pack' TocPack False it _+     -- (toc2B, ) = pack' Toc2Pack False i2 _+     -- (closedB, ) = pack' ClosedPack False ix $ prepareSingleText Iso8859_1 _+        (codes, to) = pack' CodePack False io $ prepareText' ASCII code+        lt = length titles+        (ip, lp) = (     lt, length performers)+        (is, ls) = (ip + lp, length songwriters)+        (ic, lc) = (is + ls, length composers)+        (ia, la) = (ic + lc, length arrangers)+        (im, lm) = (ia + la, length messages)+        (il, ll) = (im + lm, length catalogueB)+        (ig, lg) = (il + ll, length genreB)+        (io, lo) = (ig + lg, length codes)+        allLengths = reverse . (3 :) . snd $ L.foldl'+            (\(acc, as) a -> if acc + a > 0xFC then (0xFC, (0xFC - acc) : as) else (acc + a, a : as))+            (0, [])+            [lt, lp, ls, lc, la, lm, ll, lg, 0, 0, 0, 0, 0, 0, lo]+        allPacks = take 0xFC+             $ titles+            <> performers+            <> songwriters+            <> composers+            <> arrangers+            <> messages+            <> catalogueB+            <> genreB+            <> codes+        encoding = guessEncoding . Y.catMaybes . concat $ infoList disc : map infoList tracks+        wideChars = encoding == MS_JIS+        infoList i = [f i | f <- [title, performer, songwriter, composer, arranger, message, code]]+        startTrackId = fromIntegral $ fromEnum startTrack+        endTrackId = foldr max 0 [tt, tp, ts, tc, ta, tm, to]+        text f p i = F.B.first (pack p wideChars blockIndex $ fromIntegral i) $+            prepareText' encoding f+        prepareSingleText _ Nothing = []+        prepareSingleText e (Just t) = (\t' -> [(0, t')]) $ encodeText e t+        prepareText' e f = (t', foldr (max . fst) 0 t')+          where t' = prepareText e startTrackId (f disc) (map f tracks)+        pack' p w i = F.B.first . pack p w blockIndex $ fromIntegral i+packCdTextBlock blockIndex catalogue DiscPregap genreCode genreName _ tracks =+    packCdTextBlock blockIndex catalogue 1 genreCode genreName disc tracks'+  where (disc, tracks') = case tracks of+            [] -> (Info Nothing Nothing Nothing Nothing Nothing Nothing Nothing, [])+            (t:ts) -> (t, ts)+packCdTextBlock blockIndex catalogue DiscLeadout genreCode genreName disc _ =+    packCdTextBlock blockIndex catalogue 1 genreCode genreName disc []++-- | Generate the local block info.  Note that this does /not/ result in full+-- payloads for the last two packs; @packInfo@ adds them automatically.+generateBlockInfo :: BlockId -> Encoding -> TrackId -> TrackId -> [Int] -> [BS.ByteString]+generateBlockInfo blockIndex encoding startTrack endTrack lengths =+    pack InfoPack False blockIndex (fromIntegral $ sum lengths - 3) . packTuple $+        [fromIntegral $ fromEnum encoding, startTrack, endTrack, 0x00] +++        take 16 (map fromIntegral lengths ++ repeat 0)+  where packTuple bs = [(0, BS.pack bs)]+++-- | Use the minimal encoding based on the characters used by the strings.  If+-- any character outside ISO 8859-1 ("Latin-1") is found, 'MS_JIS' is used as a+-- fallback; this isn't strictly comprehensive, but it is a lot harder to test+-- for (i.e. I'd have to write a function for it).+guessEncoding :: [String] -> Encoding+guessEncoding [] = Iso8859_1+guessEncoding ts+    | all (all C.isAscii) ts = ASCII+    | all (all C.isLatin1) ts = Iso8859_1+    | otherwise = MS_JIS+++-- | Collapse the track texts to their minimal size if allowed (if present for+-- disc-level info, all tracks must be represented).+prepareText :: Encoding -> TrackId -> Maybe String -> [Maybe String] -> [(TrackId, BS.ByteString)]+prepareText e _ (Just d) [] = [(0, encodeText e d)]+prepareText e i d'@(Just d) ta@(t:_)+    | d' == t = case prepareTrackTexts e i' $ d' : trim ta of+        [] -> []+        ((_, bs):bss) -> (0, bs) : bss+    | otherwise = (0, encodeText e d) : uncurry (prepareTrackTexts e) (trimTexts i ta)+  where trim = L.dropWhileEnd Y.isNothing . dropWhile Y.isNothing+        i' = i - 1 + fromIntegral (length $ takeWhile Y.isNothing ta)+{- This block forces track info if it's present for the disc, as required by+ - the libcdio docs.  It doesn't look like that's actually required in these+ - references, but I don't trust them enough to take it out entirely.+prepareText e i d'@(Just d) ta@(t:_)+    | d' == t = case prepareTrackTexts e (i - 1) $ d' : ta of+        [] -> []+        ((_, bs):bss) -> (0, bs) : bss+    | otherwise = (0, encodeText e d) : prepareTrackTexts e i ta+-}+prepareText e i Nothing ts = uncurry (prepareTrackTexts e) $ trimTexts i ts++trimTexts :: TrackId -> [Maybe String] -> (TrackId, [Maybe String])+trimTexts i' [] = (i', [])+trimTexts i' (Nothing:ts') = trimTexts (i' + 1) ts'+trimTexts i' ts' = (i', L.dropWhileEnd Y.isNothing ts')++-- | Collapse the texts further by making use of the tab-replacement shortcut+-- for repeated values.+prepareTrackTexts :: Encoding -> TrackId -> [Maybe String] -> [(TrackId, BS.ByteString)]+prepareTrackTexts _ _ [] = []+prepareTrackTexts e i ts = encodeTrackTexts e i . reverse $ L.foldl' deduplicate [] ts+  where deduplicate [] (Just s) = [s]+        deduplicate ts' Nothing = "" : ts'+        deduplicate ts' (Just s) =+            let ss = takeWhile (== s) ts'+            in  s : map (const "\t") ss ++ deduplicate' (drop (length ss) ts')+        deduplicate' [] = []+        deduplicate' (t':ts') = deduplicate ts' $ Just t'++-- | Combine the genre code and description into a single bytestring.+prepareGenre :: Maybe Genre -> Maybe String -> [(TrackId, BS.ByteString)]+prepareGenre Nothing Nothing = []+prepareGenre gc gt = [(0, encodeGenre gc <> encodeText ASCII (Y.fromMaybe "" gt))]+++-- | Conduct text to the proper encoder and append the proper terminator.+encodeText :: Encoding -> String -> BS.ByteString+encodeText MS_JIS "\t" = BS.pack [0x09,0x09,0x00,0x00]+encodeText ASCII t = BS.map (.&. 0x7F) $ encodeText Iso8859_1 t+encodeText Iso8859_1 t = BS.C.pack $ t ++ ['\NUL']+encodeText MS_JIS t = T.encodeMsJISWith T.ignore (T.pack t) <> BS.C.pack ['\NUL', '\NUL']++-- | Encode all members of a given textual category, pairing them with their+-- track index or 0 if one applies to the disc as a whole.+encodeTrackTexts :: Encoding -> TrackId -> [String] -> [(TrackId, BS.ByteString)]+encodeTrackTexts e i ts = zip [i ..] $ map (encodeText e) ts++-- | Store the genre code in a two-byte string.+encodeGenre :: Maybe Genre -> BS.ByteString+encodeGenre g = BS.pack [gh, gc]+  where gc = maybe 0x00 (fromIntegral . fromEnum) g+        -- Futureproofing decades-old technology+        gh = if gc <= 0xFF then 0x00 else B.shiftR gc 8+++-- | Prevent index overflow for any single pack type.+pack :: Pack -> Bool -> BlockId -> BlockSize -> [(TrackId, BS.ByteString)] -> [BS.ByteString]+pack p w b i bss = take 0xFF $ pack_ p w b i bss++-- | Conduct binary data and starting track to the proper packers.+pack_ :: Pack -> Bool -> BlockId -> BlockSize -> [(TrackId, BS.ByteString)] -> [BS.ByteString]+pack_ TitlePack = packText 0x80+pack_ PerformerPack = packText 0x81+pack_ SongwriterPack = packText 0x82+pack_ ComposerPack = packText 0x83+pack_ ArrangerPack = packText 0x84+pack_ MessagePack = packText 0x85+pack_ DiscIdPack = packText 0x86+pack_ GenrePack = packGenre+pack_ ClosedPack = packText 0x8D+pack_ TocPack = const4 []+pack_ Toc2Pack = const4 []+pack_ CodePack = packText 0x8E+pack_ InfoPack = packBlockInfo++const4 :: a -> b -> c -> d -> e -> a+const4 a _ _ _ _ = a++packText+    :: PackType+    -> Bool+    -> BlockId+    -> BlockSize+    -> [(TrackId, BS.ByteString)] -> [BS.ByteString]+packText p w b i bss = zipWith (curry $ addHeader p w b) [i ..] .+    reverse $ L.foldl' splitText [] bss++packGenre :: Bool -> BlockId -> BlockSize -> [(TrackId, BS.ByteString)] -> [BS.ByteString]+packGenre _ _ _ [] = []+packGenre w b i ((_, bs):_) = zipWith (curry $ addHeader 0x87 w b) [i ..] $ splitGenre bs++-- | Create the skeleton block info packs, leaving out counts and languages.+packBlockInfo :: Bool -> BlockId -> BlockSize -> [(TrackId, BS.ByteString)] -> [BS.ByteString]+packBlockInfo w b i [] =+    [ addHeader 0x8F w b (i + p, (p, 0, BS.empty))+    | p <- [0 .. 2]+    ]+packBlockInfo w b i ((_, bs):_) =+    [ addHeader 0x8F w b (i, (0, 0, p1))+    , addHeader 0x8F w b (i + 1, (1, 0, p2))+    , addHeader 0x8F w b (i + 2, (2, 0, BS.empty))+    ]+  where (p1, p2) = BS.splitAt 12 bs++-- | Generate the four-byte identifying and metadata-carrying header.+-- +-- NOTE: While the libcdio documentation on the CDTEXT format says that byte 3+-- (@l'@) is 15 if the text starts at any point before the previous pack,+-- that's not the case in any of my (admittedly limited and unverified)+-- reference blobs: it's capped at 15, yes, but if one pack has two characters,+-- the next has the full twelve, and the text still continues into a third,+-- that third will have a third byte of 14.+addHeader+    :: PackType+        -- ^ Pack type+    -> Bool+        -- ^ Two-byte characters?+    -> BlockId+        -- ^ Language index+    -> (BlockSize, (TrackId, Word, BS.ByteString))+                        -- ^ Starting pack index, track number, characters in previous block, and payload+    -> BS.ByteString+addHeader p w b (i, (t, l, bs)) = BS.pack [p, t, i, f] <> bs+  where l' = if l > 15 then 0x0F else 0x0F .&. fromIntegral l+        b' = 0x70 .&. B.shiftL (fromIntegral b) 4+        w' = if w then 0x80 else 0x00+        f = w' .|. b' .|. l'++-- | Takes tuples of (track index, track data) and adds them (initial track,+-- initial length in previous packs, packed data), where the packed data is+-- /no more than/ 12 bytes long.  Note that the final list will have to be+-- 'reverse'd.+splitText :: [(TrackId, Word, BS.ByteString)] -> (TrackId, BS.ByteString) -> [(TrackId, Word, BS.ByteString)]+splitText [] bst@(t, _) = splitText [(t, 0, BS.empty)] bst+splitText csa@((u, l, cs):css) (t, bs)+    | cl == 12 =+        [ (t, l', bs')+        | (l', bs') <- reverse . zip [0, 12 ..] $ splitAtEvery 12 bs+        ] ++ csa+    -- Will have incorrect t, l' if @BS.length cs > 12@, but as that shouldn't+    -- happen anyway, it's not an issue.+    | otherwise =+        let (cs':bss) = splitAtEvery 12 $ cs <> bs+        in  [ (t, l', bs')+            | (l', bs') <- reverse $ zip [(12 - cl), (24 - cl) ..] bss+            ] ++ (u, l, cs') : css+  where cl = fromIntegral $ BS.length cs++-- | Takes the genre string prefixed by a single, two-byte genre code+-- identifier, splits the string, and prepends the code to every pack.+splitGenre :: BS.ByteString -> [(TrackId, Word, BS.ByteString)]+splitGenre bs =+    [ (0, l', gc <> bs')+    | (l', bs') <- zip [0, 10 ..] . splitAtEvery 10 $ BS.drop 2 bs+    ]+  where gc = BS.take 2 bs++-- | Extend the builtin 'BS.splitAt' to return an entire list of substrings.+splitAtEvery :: Int -> BS.ByteString -> [BS.ByteString]+splitAtEvery i bs+    | i <= 0 = []+    | i >= BS.length bs = [bs]+    | otherwise = recurse $ BS.splitAt i bs+  where recurse (h, t) = h : splitAtEvery i t+++-- | Now that we have the languages and sizes of all blocks, update the info+-- packs to include them.  Note that this requires that the info packs are+-- located at the end of the block.+joinBlockInfo :: [Maybe Language] -> [BlockSize] -> [BS.ByteString] -> [BS.ByteString]+joinBlockInfo _ _ [] = []+joinBlockInfo _ _ [b] = [b]+joinBlockInfo ls ss bss = h ++ [p2, p3]+  where (h, t) = splitAt (length bss - 2) bss+        ls' = take 8 $ map (maybe 0 $ fromIntegral . fromEnum) ls ++ repeat 0+        ss' = take 8 $ ss ++ repeat 0+        p2 = head t <> BS.pack (take 4 ss')+        p3 = head (tail t) <> BS.pack (drop 4 ss' ++ ls')+++-- | Generate a checksum over the first 16 (including header) bytes of a data+-- pack, zero-padding /or truncating/ as necessary.+checksum :: BS.ByteString -> BS.ByteString+checksum bs = checksum' $ case compare 16 $ BS.length bs of+    GT -> BS.take 16 $ bs <> BS.replicate 16 0+    EQ -> bs+    LT -> BS.take 16 bs++-- | Actually run the checksum function on all the bytes of the input.  Note+-- that this doesn't verify that the length is actually the proper 16.+checksum' :: BS.ByteString -> BS.ByteString+checksum' bs = bs <> (BS.pack . split . finalize . BS.foldl' checksumBytes h' $ t <> BS.singleton 0)+  where split i = map fromIntegral [B.shiftR i 8, i]+        finalize i = B.xor i 0xFFFF+        (h, t) = Y.fromMaybe (0, BS.empty) $ BS.uncons bs+        h' = B.shiftL (fromIntegral h) 8++checksumBytes :: W.Word16 -> W.Word8 -> W.Word16+checksumBytes acc a = checksumBits 8 . B.xor acc $ fromIntegral a++checksumBits :: Word -> W.Word16 -> W.Word16+checksumBits 0 i = i+checksumBits c i = checksumBits (c - 1) i'+  where i'  | B.testBit i 15 = B.xor 0x1021 $ B.shiftL i 1+            | otherwise = B.shiftL i 1
+ src/Foreign/Libcdio/CdTypes.hs view
@@ -0,0 +1,193 @@+{-# LANGUAGE ForeignFunctionInterface #-}++{-|+Description:    Objects used to describe the CD and filesystem format.++Copyright:      (c) 2019-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      stable+Portability:    non-portable (requires libcdio)++Like any drive, discs may store their data according to many different+filesystem structures.  These are abstracted to a degree in libcdio, but as+each track may store its data differently, and at the very least 'Audio' is+handled differently than any of the file-oriented layouts, it is still helpful+to know the underlying structure.+++= @cd_types.h@++== Defines+* CDIO_FSTYPE                       (removed; cdio_fs_anal_t represented differently in Haskell)+* CDIO_FS_UNKNOWN                   (removed; handled via 'Nothing')++== Types+* @cdio_fs_t@                       -> 'Foreign.Libcdio.CdTypes.Filesystem'++    - @CDIO_FS_INTERACTIVE@         -> 'Foreign.Libcdio.CdTypes.CdI'+    - @CDIO_FS_ISO_HFS@             -> 'Foreign.Libcdio.CdTypes.Hfs' with a 'Just' 'Foreign.Libcdio.CdTypes.IsoAnalysis'+    - @CDIO_FS_ISO_9660_INTERACTIVE@ -> 'Foreign.Libcdio.CdTypes.CdI' with a 'Just' 'Foreign.Libcdio.CdTypes.IsoAnalysis'+    - @CDIO_FS_ISO_UDF@             -> 'Foreign.Libcdio.CdTypes.Udf' with a 'Just' 'Foreign.Libcdio.CdTypes.IsoAnalysis'+    - @CDIO_FS_ISO_XISO@            -> 'Foreign.Libcdio.CdTypes.XboxIso'+    - @CDIO_FS_ISO_UDFX@            -> 'Foreign.Libcdio.CdTypes.XboxUdf'++* @cdio_fs_cap_t@                   -> 'Foreign.Libcdio.CdTypes.FilesystemClass'++    Note that some values are not included in the Haskell type, as the indexing+    implementation is stricter than the equivalent bit operations in C.++    - @CDIO_FS_MASK@                (removed; cdio_fs_anal_t represented differently in Haskell)+    - @CDIO_FS_ANAL_VCD_ANY@        -> 'Foreign.Libcdio.CdTypes.fsAnyVcd'+    - @CDIO_FS_MATCH_ALL@           -> 'Foreign.Libcdio.CdTypes.fsAny'+    - @CDIO_FS_ANAL_CDTV@           -> 'Foreign.Libcdio.CdTypes.CommodoreCdtv'+    - @CDIO_FS_ANAL_SVCD@           -> 'Foreign.Libcdio.CdTypes.SuperVideoCd'+    - @CDIO_FS_ANAL_CVD@            -> 'Foreign.Libcdio.CdTypes.ChoijiVideoCd'+    - @CDIO_FS_ANAL_XISO@           -> 'Foreign.Libcdio.CdTypes.XboxIsoClass'++* @cdio_iso_analysis_t@             -> 'Foreign.Libcdio.CdTypes.IsoAnalysis'++    - @joliet_level@                -> 'Foreign.Libcdio.CdTypes.jolietLevel'+    - @iso_label@                   -> 'Foreign.Libcdio.CdTypes.label'+    - @isofs_size@                  -> 'Foreign.Libcdio.CdTypes.fsSize'+    - @UDFVerMajor@                 -> 'fst' 'Foreign.Libcdio.CdTypes.udfVersion'+    - @UDFVerMinor@                 -> 'snd' 'Foreign.Libcdio.CdTypes.udfVersion'++== Symbols+* @cdio_guess_cd_type@              -> 'Foreign.Libcdio.CdTypes.trackType'+++= "Sound.Libcdio.Read.Filesystem"++* 'trackType'                       -> 'Sound.Libcdio.Read.Filesystem.filesystemType'+-}+module Foreign.Libcdio.CdTypes+    ( -- * Types+      Filesystem ( .. )+    , FilesystemClass ( .. )+    , FilesystemClasses+    , fsAny, fsAnyVcd+    , IsoAnalysis ( .. )+      -- * Access+    , trackType+    ) where+++import qualified Data.Maybe as Y+import qualified Data.Word as W++import qualified Data.Array.BitArray as A++import qualified Foreign.C.String as C+import qualified Foreign.C.Types as C+import qualified Foreign.Ptr as C++import qualified Foreign.Marshal.Alloc as M+import qualified Foreign.Storable as S++import Foreign.Libcdio.Marshal+import Foreign.Libcdio.Track+import Foreign.Libcdio.Types.Enums+import Foreign.Libcdio.Types.Offsets+import Foreign.Libcdio.Types.Internal+++-- | Types of filesystem which may be read from a disc.+data Filesystem+    = Audio+    | HighSierra+    | Iso9660+    | CdI+    | Cd3do+    | Ext2+    | Hfs+    | Ufs+    | Udf+    | XboxIso+    | XboxUdf+  deriving ( Eq, Show, Read, Ord, Enum, Bounded )+++-- | A collection of disc/filesystem descriptions.+type FilesystemClasses = A.BitArray FilesystemClass++-- | Any sort of Video CD.+fsAnyVcd :: FilesystemClasses+fsAnyVcd = genBitArray+    [ VideoCd+    , SuperVideoCd+    , ChoijiVideoCd+    ]++-- | The set of every 'FilesystemClass'.+fsAny :: FilesystemClasses+fsAny = genBitArray [minBound .. maxBound]+++-- | A collection of data describing a disc using the ISO 9660 standard.+data IsoAnalysis = IsoAnalysis+    { jolietLevel :: Maybe Word+    , label       :: String+    , fsSize      :: Word+    , udfVersion  :: Maybe (W.Word8, W.Word8)+    }+  deriving ( Eq, Show, Read )+instance S.Storable IsoAnalysis where+    sizeOf _    = iaSizeOf+    alignment _ = iaAlign+    peek c = do+        j <- S.peekByteOff c iaJolietLevel :: IO C.CUInt+        l <- C.peekCString $ C.plusPtr c iaLabel+        s <- S.peekByteOff c iaIsoSize :: IO C.CUInt+        a <- S.peekByteOff c iaUDFMajor+        i <- S.peekByteOff c iaUDFMinor+        return $ IsoAnalysis+            { jolietLevel = if j == 0 then Nothing else Just $ fromIntegral j+            , label = l+            , fsSize = fromIntegral s+            , udfVersion = if a == 0 then Nothing else Just (a, i)+            }+    poke c hs = do+        let (a, i) = Y.fromMaybe (0, 0) $ udfVersion hs+        S.pokeByteOff c iaJolietLevel . maybe (0 :: C.CUInt) fromIntegral $ jolietLevel hs+        pokeCString (label hs) 33 $ C.plusPtr c iaLabel+        S.pokeByteOff c iaIsoSize (fromIntegral $ fsSize hs :: C.CUInt)+        S.pokeByteOff c iaUDFMajor a+        S.pokeByteOff c iaUDFMinor i+++-- | Determine what type of file system is stored in the given track of a disc.+trackType :: Cdio -> Track -> IO (Maybe Filesystem, FilesystemClasses, Maybe IsoAnalysis)+trackType c t = do+    l' <- trackLsn c t+    (fs, iso') <- case l' of+        Just l -> withCdio' defaultCdType $ \c' -> M.alloca $ \i' -> do+            e' <- cdType_ c' l (withTrack t) i'+            iso <- S.peek i'+            return (modEnumFlags e', iso)+        Nothing -> return defaultCdType+    let fc = snd fs+        iso = Just iso' { udfVersion = Nothing }+        isoUdf = Just iso'+    return $ case fst fs of+        Nothing -> (Nothing, fc, isoUdf)+        Just Fs3do -> (Just Cd3do, fc, iso)+        Just FsAudio -> (Just Audio, fc, Nothing)+        Just FsExt2 -> (Just Ext2, fc, iso)+        Just FsHfs -> (Just Hfs, fc, Nothing)+        Just FsIsoHfs -> (Just Hfs, fc, iso)+        Just FsHighSierra -> (Just HighSierra, fc, iso)+        Just FsInteractive -> (Just CdI, fc, Nothing)+        Just FsIso9660Interactive -> (Just CdI, fc, iso)+        Just FsIso9660 -> (Just Iso9660, fc, iso)+        Just FsUdf -> (Just Udf, fc, Nothing)+        Just FsIsoUdf -> (Just Udf, fc, isoUdf)+        Just FsUdfx -> (Just Udf, fc, isoUdf)+        Just FsUfs -> (Just Ufs, fc, iso)+        Just FsXiso -> (Just XboxIso, fc, iso)+  where defaultCdType = ((Nothing, genBitArray []), IsoAnalysis Nothing "" 0 Nothing)+        withCdio' b = fmap (Y.fromMaybe b) . withCdio c++foreign import ccall safe "cdio/compat/cd_types.h cdio_guess_cd_type"+  cdType_ :: C.Ptr Cdio -> Lsn -> CTrack -> C.Ptr IsoAnalysis -> IO C.CInt
+ src/Foreign/Libcdio/Device.hs view
@@ -0,0 +1,1380 @@+{-# LANGUAGE ForeignFunctionInterface #-}++{-|+Description:    Various device-management functions, including session initialization.++Copyright:      (c) 2018-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      stable+Portability:    non-portable (requires libcdio)++The entire library architecture revolves around the concept of a device—not the+disc, but the drive containing it.  A function to read a segment of data is not+just a lookup from memory, but an instruction to the device to move the read+arm into position and begin interpreting the pits and ridges.  With that+understanding, it makes sense that this module provides not just the means to+determine what any particular drive is capable of, but also the only means to+obtain the 'Cdio' object the everything else revolves around.+++= @device.h@++== Types+* @cdio_drive_cap_misc_t@           -> 'DriveCapabilityMisc'++    - @CDIO_DRIVE_CAP_ERROR@        (removed; handled via 'Nothing')+    - @CDIO_DRIVE_CAP_UNKNOWN@      (removed; handled via 'Nothing')++* @cdio_drive_cap_read_t@           -> 'DriveCapabilityRead'++    - @CDIO_DRIVE_CAP_READ_AUDIO@   -> 'ReadAnalogAudio'+    - @CDIO_DRIVE_CAP_READ_CD_DA@   -> 'ReadDigitalAudio'+    - @CDIO_DRIVE_CAP_READ_CD_R@    -> 'ReadCdRecordable'+    - @CDIO_DRIVE_CAP_READ_CD_RW@   -> 'ReadCdReWritable'+    - @CDIO_DRIVE_CAP_READ_DVD_R@   -> 'ReadDvdRecordable'+    - @CDIO_DRIVE_CAP_READ_DVD_PR@  -> 'ReadDvdPlusRecordable'+    - @CDIO_DRIVE_CAP_READ_DVD_RW@   -> 'ReadDvdReWritable'+    - @CDIO_DRIVE_CAP_READ_DVD_PRW@  -> 'ReadDvdPlusReWritable'+    - @CDIO_DRIVE_CAP_READ_C2_ERRS@ -> 'ReadC2ErrorCorrection'++* @cdio_drive_cap_write_t@          -> 'DriveCapabilityWrite'++    Note that some values are not included in the Haskell type, as the indexing+    implementation is stricter than the equivalent bit operations in C.++    - @CDIO_DRIVE_CAP_WRITE_CD_R@    -> 'WriteCdRecordable'+    - @CDIO_DRIVE_CAP_WRITE_CD_RW@   -> 'WriteCdReWritable'+    - @CDIO_DRIVE_CAP_WRITE_DVD_R@   -> 'WriteDvdRecordable'+    - @CDIO_DRIVE_CAP_WRITE_DVD_PR@  -> 'WriteDvdPlusRecordable'+    - @CDIO_DRIVE_CAP_WRITE_DVD_RW@   -> 'WriteDvdReWritable'+    - @CDIO_DRIVE_CAP_WRITE_DVD_PRW@  -> 'WriteDvdPlusReWritable'+    - @CDIO_DRIVE_CAP_WRITE_CD@     -> 'capsWriteCd'+    - @CDIO_DRIVE_CAP_WRITE_DVD@    -> 'capsWriteDvd'+    - @CDIO_DRIVE_CAP_WRITE@        -> 'capsWrite'++* @cdio_drive_misc_cap_t@           -> 'DriveMiscCaps'+* @cdio_drive_read_cap_t@           -> 'DriveReadCaps'+* @cdio_drive_write_cap_t@          -> 'DriveWriteCaps'+* @cdio_hwinfo_t@                   -> 'HardwareInfo'++    - @psz_vendor@                  -> 'vendor'+    - @psz_model@                   -> 'model'+    - @psz_revision@                -> 'revision'++* @cdio_mmc_hw_len_t@               (type removed; values are structural constants rather than an actual enum)++    - @CDIO_MMC_HW_VENDOR_LEN@      -> 'vendorLength'+    - @CDIO_MMC_HW_MODEL_LEN@       -> 'modelLength'+    - @CDIO_MMC_HW_REVISION_LEN@    -> 'revisionLength'++* @cdio_src_category_mask_t@        (removed; never used in the public interface)+* @driver_id_t@                     -> 'DriverId'+* @driver_return_code_t@            -> 'DriverReturnCode'++== Symbols+* @cdio_close_tray@                 -> 'closeTray'+* @cdio_destroy@                    (removed; handled via garbage collector)+* @cdio_device_drivers@             -> 'deviceDrivers'+* @cdio_driver_describe@            -> 'driverDescribe'+* @cdio_driver_errmsg@              -> 'driverErrmsg'+* @cdio_drivers@                    -> 'drivers'+* @cdio_eject_media@                -> 'ejectMedia'+* @cdio_eject_media_drive@          -> 'ejectDrive'+* @cdio_free_device_list@           (removed; handled via garbage collector)+* @cdio_get_arg@                    -> 'getArg' and 'getAccessMode'+* @cdio_get_default_device@         -> 'defaultDevice' (@CdIo_t*@ argument dropped as no non-redundant path to get one exists)+* @cdio_get_default_device_*@       -> @defaultDevice*@ (eg. 'defaultDeviceLinux')+* @cdio_get_devices@                -> 'devices'+* @cdio_get_devices_*@              -> @devices*@ (eg. 'devicesLinux')+* @cdio_get_devices_with_cap@       -> 'devicesWithFilesystem'+* @cdio_get_devices_with_cap_ret@   -> 'devicesWithFilesystemRet'+* @cdio_get_drive_cap@              -> 'driveCap'+* @cdio_get_drive_cap_dev@          -> 'driveCapDevice'+* @cdio_get_driver_id@              -> 'driverId'+* @cdio_get_driver_name@            -> 'driverName'+* @cdio_get_hwinfo@                 -> 'hwinfo'+* @cdio_get_last_session@           -> 'lastSession'+* @cdio_get_media_changed@          -> 'isMediaChanged'+* @cdio_have_atapi@                 -> 'haveAtapi'+* @cdio_have_driver@                -> 'haveDriver'+* @cdio_init@                       (removed; internal function without much external occasion for use)+* @cdio_is_binfile@                 -> 'cueFromBin'+* @cdio_is_cuefile@                 -> 'binFromCue'+* @cdio_is_device@                  -> 'isDevice'+* @cdio_is_nrg@                     -> 'isNrg'+* @cdio_is_tocfile@                 -> 'isToc'+* @cdio_open@                       -> 'cdioOpen'+* @cdio_open_*@                     -> @cdioOpen*@ (eg. 'cdioOpenLinux')+* @cdio_open_am@                    -> 'cdioOpenAm'+* @cdio_open_am_*@                  -> @cdioOpenAm*@ (eg. 'cdioOpenAmLinux')+* @cdio_os_driver@                  -> 'osDriver'+* @cdio_set_arg@                    (removed; primarily intended for internal use, and is more limited than would be expected)+* @cdio_set_blocksize@              -> 'setBlocksize'+* @cdio_set_speed@                  -> 'setSpeed'+++= "Sound.Libcdio.Device"++* 'Cdio'                            -> @"Sound.Libcdio".'Sound.Libcdio.Cdio'@ (note, however, that the latter is a more abstracted 'Monad')++* 'binFromCue'                      -> 'Sound.Libcdio.Device.isCue'+* 'cdioOpen'                        -> @"Sound.Libcdio".'Sound.Libcdio.open'@ and 'Sound.Libcdio.openDefault'+* 'cdioOpenAm'                      -> @"Sound.Libcdio".'Sound.Libcdio.openMode'@ and 'Sound.Libcdio.openModeDefault'+* @cdioOpen*@                       (removed; @"Sound.Libcdio".'Sound.Libcdio.open'@ handles the auto-detection)+* 'closeTray'                       -> 'Sound.Libcdio.Device.closeDeviceTray' and 'Sound.Libcdio.Device.closeDeviceTray''+* 'cueFromBin'                      (removed; this and 'Foreign.binFromCue' just replace the file extension after validation, they don't go searching)+* @defaultDevice*@                  (removed; driver type isn't a public part of device opening)+* 'deviceDrivers'                   -> @'not' 'Sound.Libcdio.Device.isImageDriver'@+* 'devicesRet'                      (removed; @"Sound.Libcdio".'Sound.Libcdio.open'@ doesn't require a specific 'Foreign.DriverId' to be passed)+* 'devicesWithFilesystem'           (removed; can't think of a use case for searching for discs of a specific data layout)+* 'devicesWithFilesystemRet'        (removed; can't think of a use case for searching for discs of a specific data layout)+* @devices*@                        (removed; 'Sound.Libcdio.Device.devices' delegates via the 'Foreign.DriverId' parameter)+* 'driveCap'                        -> 'Sound.Libcdio.Device.capabilities'+* 'driveCapDevice'                  -> 'Sound.Libcdio.Device.deviceCapabilities'+* 'driverId'                        -> 'Sound.Libcdio.Device.driver'+* 'ejectDrive'                      -> 'Sound.Libcdio.Device.ejectDevice'+* 'ejectMedia'                      (removed; argument to e.g. @"Sound.Libcdio".'Sound.Libcdio.open'@)+* 'getArg'                          -> @"Sound.Libcdio".'Sound.Libcdio.getArg'@+* 'getAccessMode'                   -> @"Sound.Libcdio".'Sound.Libcdio.getAccessMode'@+* 'haveDriver'                      (removed; use @`'elem'` 'Sound.Libcdio.Device.drivers'@)+* 'hwinfo'                          -> 'Sound.Libcdio.Device.hardware'+* 'lastSession'                     -> @"Sound.Libcdio.Read.Data".'Sound.Libcdio.Read.Data.lastSessionOffset'@+* 'modelLength'                     (removed; unnecessary low-level detail)+* 'revisionLength'                  (removed; unnecessary low-level detail)+* 'vendorLength'                    (removed; unnecessary low-level detail)+-}+module Foreign.Libcdio.Device+    ( -- * Types+      Cdio+    , HardwareInfo ( .. )+    , vendorLength+    , modelLength+    , revisionLength+    , emptyHardwareInfo+    , DriverId ( .. )+    , DriverReturnCode ( .. )+    , SessionArg ( .. )+    , AccessMode ( .. )+      -- ** Capabilities+    , DriveCapabilityRead ( .. )+    , DriveReadCaps+    , DriveCapabilityWrite ( .. )+    , DriveWriteCaps+    , capsWriteCd+    , capsWriteDvd+    , capsWrite+    , DriveCapabilityMisc ( .. )+    , DriveMiscCaps+    , DriveCaps+      -- * Drivers+    , drivers+    , deviceDrivers+    , osDriver+    , driverName+    , driverId+    , driverDescribe+    , driverErrmsg+    , haveDriver+      -- * Devices+    , devices+    , devicesRet+    , devicesWithFilesystem+    , devicesWithFilesystemRet+    , defaultDevice+    , defaultDeviceDriver+    , hwinfo+    , driveCap+    , driveCapDevice+    , haveAtapi+    , ejectMedia+    , ejectDrive+    , closeTray+      -- * Session+    , getArg+    , getAccessMode+    , isMediaChanged+    , setBlocksize+    , setSpeed+    , lastSession+      -- * Device paths+    , cdioOpen+    , cdioOpenAm+      -- ** Hardware+    , isDevice+    , cdioOpenCd+    , cdioOpenAmCd+      -- ** Images+    , cueFromBin+    , binFromCue+    , isNrg+    , isToc+    {-+      -- *** BIN/CUE+    , cdioOpenBinCue+    , cdioOpenCue+    , cdioOpenAmBinCue+    , defaultDeviceBinCue+    , devicesBinCue+      -- *** cdrdao+    , cdioOpenCdrDao+    , cdioOpenAmCdrDao+    , defaultDeviceCdrDao+    , devicesCdrDao+      -- *** Nero+    , cdioOpenNero+    , cdioOpenAmNero+    , defaultDeviceNero+    , devicesNero+      -- ** Hardware+      -- *** BSDI+    , cdioOpenBsdi+    , cdioOpenAmBsdi+    , defaultDeviceBsdi+    , devicesBsdi+      -- *** FreeBSD+    , cdioOpenFreeBsd+    , cdioOpenAmFreeBsd+    , defaultDeviceFreeBsd+    , devicesFreeBsd+      -- *** Linux+    , cdioOpenLinux+    , cdioOpenAmLinux+    , defaultDeviceLinux+    , devicesLinux+      -- *** OS/2+    , cdioOpenOs2+    , cdioOpenAmOs2+    , defaultDeviceOs2+    , devicesOs2+      -- *** Solaris+    , cdioOpenSolaris+    , cdioOpenAmSolaris+    , defaultDeviceSolaris+    , devicesSolaris+      -- *** Windows+    , cdioOpenWin32+    , cdioOpenAmWin32+    , defaultDeviceWin32+    , devicesWin32+    -}+    ) where+++import qualified Control.Monad as N++import qualified Data.Array.BitArray as A+import qualified Data.Maybe as Y++import qualified Foreign.C.String as C+import qualified Foreign.C.Types as C+import qualified Foreign.Ptr as C++import qualified Foreign.Marshal.Alloc as M+import qualified Foreign.Marshal.Array as M+import qualified Foreign.Marshal.Utils as M+import qualified Foreign.Storable as S++import qualified System.IO.Unsafe as IO.Unsafe++import Data.Ix ( Ix )+import Data.Bits ( (.&.) )++import Foreign.Libcdio.CdTypes+import Foreign.Libcdio.Marshal+import Foreign.Libcdio.Types.Enums+import Foreign.Libcdio.Types.Internal+import Foreign.Libcdio.Types.Offsets++import Sound.Libcdio.Common+++toDriverReturnCode :: Maybe CDriverReturnCode -> DriverReturnCode+toDriverReturnCode = maybe Uninitialized $ toEnum . fromIntegral+++-- | The collection of features for reading discs a device provides.+type DriveReadCaps = A.BitArray DriveCapabilityRead+-- | The collection of features for writing discs a device provides.+type DriveWriteCaps = A.BitArray DriveCapabilityWrite+-- | The collection of hardware features a device was built with.+type DriveMiscCaps = A.BitArray DriveCapabilityMisc++-- | The three types are usually passed around together, so we can simplify the+-- type signatures using them.+type DriveCaps = (DriveReadCaps, DriveWriteCaps, DriveMiscCaps)+++-- | Capabilites indicating a device has some sort of CD-writing ability.+capsWriteCd :: DriveWriteCaps+capsWriteCd = genBitArray+    [ WriteCdRecordable+    , WriteCdReWritable+    ]++-- | Capabilites indicating a device has some sort of DVD-writing ability.+capsWriteDvd :: DriveWriteCaps+capsWriteDvd = genBitArray+    [ WriteDvdRecordable+    , WriteDvdPlusRecordable+    , WriteDvdRam+    , WriteDvdReWritable+    , WriteDvdPlusReWritable+    ]++-- | Capabilites indicating a device has some sort of disc-writing ability.+capsWrite :: DriveWriteCaps+capsWrite = A.zipWith (||) capsWriteCd capsWriteDvd+++-- | Length of the drive vendor name in returned in a 'HardwareInfo' query.+vendorLength :: Word+vendorLength = fromIntegral vendorLength'++foreign import ccall safe "cdio/compat/device.h vendor_len"+  vendorLength' :: C.CUInt+++-- | Length of the drive model name in returned in a 'HardwareInfo' query.+modelLength :: Word+modelLength = fromIntegral modelLength'++foreign import ccall safe "cdio/compat/device.h model_len"+  modelLength' :: C.CUInt++-- | Length of the drive revision number in returned in a 'HardwareInfo' query.+revisionLength :: Word+revisionLength = fromIntegral revisionLength'++foreign import ccall safe "cdio/compat/device.h revision_len"+  revisionLength' :: C.CUInt+++-- | Information defining the make and model of a (typically physical) device.+data HardwareInfo = HardwareInfo+    { vendor    :: String+        -- ^ The company who designed and/or built the drive.+    , model     :: String+        -- ^ The name of the specific drive design.+    , revision  :: String+        -- ^ The version number for hardware/firmware following a series.+    }+  deriving ( Eq, Show, Read )+instance S.Storable HardwareInfo where+    sizeOf _    = hiSizeOf+    alignment _ = hiAlign+    peek c = do+        v <- decode vendorLength hiVendor+        m <- decode modelLength hiModel+        r <- decode revisionLength hiRevision+        return $ HardwareInfo v m r+      where decode l o = C.peekCStringLen (C.plusPtr c o, fromIntegral l)+    poke c hs = do+        pokeCString (vendor hs) (fromIntegral vendorLength + 1) (C.plusPtr c hiVendor)+        pokeCString (model hs) (fromIntegral modelLength + 1) (C.plusPtr c hiModel)+        pokeCString (revision hs) (fromIntegral revisionLength + 1) (C.plusPtr c hiRevision)++-- | A 'HardwareInfo' object with values suitable as defaults.+emptyHardwareInfo :: HardwareInfo+emptyHardwareInfo = HardwareInfo+    { vendor = replicate (fromIntegral vendorLength) '\NUL'+    , model = replicate (fromIntegral modelLength) '\NUL'+    , revision = replicate (fromIntegral revisionLength) '\NUL'+    }+++{- Barely even used internally.+-- | Which type(s) of device describe a particular drive.+type SrcCategories = A.BitArray SrcCategoryMask+-}+++-- | Unmarshall a C-style list of drivers.+peekDriverIdArray :: (Integral a, S.Storable a) => C.Ptr a -> IO [DriverId]+peekDriverIdArray is' = do+    is <- M.peekArray0 (fromIntegral $ fromEnum DriverUnknown) is'+    return $ map (toEnum . fromIntegral) is+++-- | All supported drivers, listed in order of preference.+drivers :: [DriverId]+drivers = filter haveDriver <$> IO.Unsafe.unsafePerformIO $ peekDriverIdArray drivers'++foreign import ccall safe "cdio/compat/device.h get_drivers"+  drivers' :: C.Ptr CDriverId++-- | All supported drivers for physical devices, listed in order of preference.+deviceDrivers :: [DriverId]+deviceDrivers = IO.Unsafe.unsafePerformIO $ peekDriverIdArray deviceDrivers'++foreign import ccall safe "cdio/compat/device.h get_device_drivers"+  deviceDrivers' :: C.Ptr CDriverId++-- | The particular driver for the current operating system, or 'DriverUnknown'+-- if no device driver exists.+osDriver :: DriverId+osDriver = toEnum $ fromIntegral osDriver'++foreign import ccall safe "cdio/compat/device.h get_os_driver"+  osDriver' :: CDriverId+++-- | Close a CD drive, if the device supports doing so.+closeTray+    :: Maybe FilePath+        -- ^ The name of the drive to use, or 'Nothing' to use 'defaultDeviceDriver'.+    -> DriverId+    -> IO (DriverReturnCode, DriverId)+        -- ^ Any errors, along with the actual driver used if passed+        -- 'DriverUnknown' or 'DriverDevice'.+closeTray f d = M.maybeWith C.withCString f $ \f' -> M.with (fromIntegral $ fromEnum d) $ \d' -> do+    r <- closeTray' f' d'+    d'' <- S.peek d'+    return (toEnum $ fromIntegral r, toEnum $ fromIntegral d'')++foreign import ccall safe "cdio/compat/device.h cdio_close_tray"+  closeTray' :: C.CString -> C.Ptr CDriverId -> IO CDriverReturnCode+++-- | Describe the driver-level error in a human-readable manner, as opposed to+-- the machine representation returned by the 'Show' instance.+driverErrmsg :: DriverReturnCode -> String+driverErrmsg = IO.Unsafe.unsafePerformIO .+    C.peekCString . driverErrmsg' . fromIntegral . fromEnum++foreign import ccall safe "cdio/compat/device.h cdio_driver_errmsg"+  driverErrmsg' :: CDriverReturnCode -> C.CString+++-- | Eject the media represented by the session identifier, if the device+-- supports doing so.+-- +-- __Warning:__  Assuming this succeeds, the 'Cdio' object is destroyed and any+-- further operations on it will fail!+ejectMedia :: Cdio -> IO DriverReturnCode+ejectMedia = fmap toDriverReturnCode . flip withCdioPtr ejectMedia'++foreign import ccall safe "cdio/compat/device.h cdio_eject_media"+  ejectMedia' :: C.Ptr (C.Ptr Cdio) -> IO CDriverReturnCode++-- | Eject media in a CD drive, if the device supports doing so.  If a 'Cdio'+-- session has already been opened on the drive, 'ejectMedia' is strongly+-- recommended instead.+ejectDrive+    :: Maybe FilePath+        -- ^ The name of the device to eject, or 'Nothing' to use the default+        -- drive for the machine.+    -> IO DriverReturnCode+ejectDrive = fmap (toEnum . fromIntegral) . flip (M.maybeWith C.withCString) ejectDrive'++foreign import ccall safe "cdio/compat/device.h cdio_eject_media_drive"+  ejectDrive' :: C.CString -> IO CDriverReturnCode+++-- | Find the default disc device for the system, if one exists.+-- +-- The C library allows getting the default device from a 'Cdio' object, but+-- since that seems to only be initialized from either the default device+-- itself or with an explicit path, doing so seems rather redundant.+defaultDevice :: IO (Maybe FilePath)+defaultDevice = defaultDevice' C.nullPtr >>= M.maybePeek C.peekCString++foreign import ccall safe "cdio/compat/device.h cdio_get_default_device"+  defaultDevice' :: C.Ptr Cdio -> IO C.CString++-- | Find the default disc device for a given driver, if one exists.+defaultDeviceDriver+    :: DriverId+    -> IO (Maybe FilePath, DriverId)+        -- ^ The name of the device, along with the associated driver if+        -- passed 'DriverUnknown' or 'DriverDevice'.+defaultDeviceDriver d = M.with (fromIntegral $ fromEnum d) $ \d' -> do+    f <- defaultDeviceDriver' d' >>= M.maybePeek C.peekCString+    d'' <- S.peek d'+    return (f, toEnum $ fromIntegral d'')++foreign import ccall safe "cdio/compat/device.h cdio_get_default_device_driver"+  defaultDeviceDriver' :: C.Ptr CDriverId -> IO C.CString+++-- | List (static) available devices on the system which can be accessed with a+-- particular driver; some file devices (e.g.  with 'DriverBinCue') might be+-- returned, but an exhaustive list should not be expected in that case.+-- +-- If passed 'DriverDevice', the returned value will list any type of hardware+-- device, but no image files.  Likewise, if passed 'DriverUnknown', all+-- hardware devices will be returned along with any already-known images.+devices :: DriverId -> IO [FilePath]+devices d = devices' (fromIntegral $ fromEnum d) >>= peekFStringArray++foreign import ccall safe "cdio/compat/device.h cdio_get_devices"+  devices' :: CDriverId -> IO (C.Ptr C.CString)++-- | Like 'devices', but if 'DriverDevice' or 'DriverUnknown' is passed, the+-- second return value reflects the driver the library would use by default.+-- If any other 'DriverId' is passed, that value is returned unchanged.+devicesRet :: DriverId -> IO ([FilePath], DriverId)+devicesRet d = M.with (fromIntegral $ fromEnum d) $ \d' -> do+    fs <- devicesRet' d' >>= peekFStringArray+    d'' <- S.peek d'+    return (fs, toEnum $ fromIntegral d'')++foreign import ccall safe "cdio/compat/device.h cdio_get_devices_ret"+  devicesRet' :: C.Ptr CDriverId -> IO (C.Ptr C.CString)++-- | Determine which of the devices may read discs fitting the given+-- description.+devicesWithFilesystem+    :: [FilePath]+        -- ^ If empty, then search all possible drives.+    -> Maybe Filesystem+    -> FilesystemClasses+    -> Bool+        -- ^ If 'True', then a device matching any of the capabilities+        -- succeeds; if 'False' then it must match every capability given+        -- (empty capabilities always match).+    -> IO [FilePath]+devicesWithFilesystem ps fs fc b = allocaStringArray ps $ \ps' ->+    devicesWithFilesystem' ps' (joinEnumFlags fs' fc) (M.fromBool b) >>= peekFStringArray+  where fs' = maybe 0 fromEnum fs++foreign import ccall safe "cdio/compat/device.h cdio_get_devices_with_cap"+  devicesWithFilesystem' :: C.Ptr C.CString -> C.CInt -> CBool -> IO (C.Ptr C.CString)++-- | Like 'devicesWithFilesystem', but returning the type of driver found as with+-- 'devicesRet'.  This is only helpful if the device list is empty; otherwise+-- it simply returns 'DriverDevice'.+devicesWithFilesystemRet+    :: [FilePath]+        -- ^ If empty, then search all possible drives.+    -> Maybe Filesystem+    -> FilesystemClasses+    -> Bool+        -- ^ If 'True', then a device matching any of the capabilities+        -- succeeds; if 'False' then it must match every capability given+        -- (empty capabilities always match).+    -> IO ([FilePath], DriverId)+devicesWithFilesystemRet ps fs fc b = M.alloca $ \d -> allocaStringArray ps $ \ps' -> do+    ds <- devicesWithFilesystemRet' ps' (joinEnumFlags fs' fc) (M.fromBool b) d+    ds' <- peekFStringArray ds+    d' <- S.peek d+    return (ds', toEnum $ fromIntegral d')+  where fs' = maybe 0 fromEnum fs++foreign import ccall safe "cdio/compat/device.h cdio_get_devices_with_cap_ret"+  devicesWithFilesystemRet' :: C.Ptr C.CString -> C.CInt -> CBool -> C.Ptr CDriverId -> IO (C.Ptr C.CString)+++-- | Get the drive capabilities for the default device.+driveCap :: Cdio -> IO DriveCaps+driveCap c = M.alloca $ \x -> M.alloca $ \y -> M.alloca $ \z -> do+    withCdio_ c $ \c' -> driveCap' c' x y z+    peekDriveCaps x y z++foreign import ccall safe "cdio/compat/device.h cdio_get_drive_cap"+  driveCap' :: C.Ptr Cdio -> C.Ptr CBitfield -> C.Ptr CBitfield -> C.Ptr CBitfield -> IO ()++-- | Get the drive capabilities for a specified device.+driveCapDevice :: FilePath -> IO DriveCaps+driveCapDevice f = C.withCString f $ \f' -> M.alloca $ \x -> M.alloca $ \y -> M.alloca $ \z -> do+    driveCapDevice' f' x y z+    peekDriveCaps x y z++foreign import ccall safe "cdio/compat/device.h cdio_get_drive_cap_dev"+  driveCapDevice' :: C.CString -> C.Ptr CBitfield -> C.Ptr CBitfield -> C.Ptr CBitfield -> IO ()++-- | The value indicating an error occurring during the retrieval of drive+-- capabilities.+foreign import ccall safe "cdio/compat/device.h drive_cap_error"+  capError :: CBitfield++-- | The value used for initializing drive capabilities.+foreign import ccall safe "cdio/compat/device.h drive_cap_unknown"+  capUnknown :: CBitfield++peekDriveCaps :: C.Ptr CBitfield -> C.Ptr CBitfield -> C.Ptr CBitfield -> IO DriveCaps+peekDriveCaps x y z = do+    x' <- S.peek x+    y' <- S.peek y+    z' <- S.peek z+    return $ extractCapError x' y' z'++-- | Process each capability collection, and if all are+-- @CDIO_DRIVE_CAP_UNKNOWN@ (uninitialized) or @CDIO_DRIVE_CAP_ERROR@, then+-- collapse them.+extractCapError :: CBitfield -> CBitfield -> CBitfield -> DriveCaps+extractCapError rs ws ms = case (packMay rs, packMay ws, packMay ms) of+    (Nothing, Nothing, Nothing) -> (pack empty, pack empty, pack empty)+    (rs', ws', ms') -> (orEmpty rs', orEmpty ws', orEmpty ms')+  where testEnumBit :: (Integral c, Enum i) => c -> i -> (i, Bool)+        testEnumBit c i = (i, (fromIntegral c .&. fromEnum i) /= 0)+        pack bs = A.array (minBound, maxBound) $ map (testEnumBit bs) [minBound .. maxBound]+        packMay bs+            | bs .&. capError == 0 = Nothing+            | bs .&. capUnknown == 0 = Nothing+            | otherwise = Just $ pack bs+        orEmpty :: (Bounded a, Enum a, Ix a) => Maybe (A.BitArray a) -> A.BitArray a+        orEmpty = Y.fromMaybe $ pack empty+        empty = 0x0 :: CBitfield+++-- | Describe the driver used by the session in a human-readable (English)+-- manner.  See also 'driverId'.+driverName :: Cdio -> IO (Maybe String)+driverName c = withCdio c driverName' >>= maybe (return Nothing) (M.maybePeek C.peekCString)++foreign import ccall safe "cdio/compat/device.h cdio_get_driver_name"+  driverName' :: C.Ptr Cdio -> IO C.CString++{- Not exported+-- | Describe the IO driver in a human-readable manner, as opposed to the+-- machine representation returned by the 'Show' instance.+driverNameFromId :: DriverId -> String+driverNameFromId d = IO.Unsafe.unsafePerformIO $ driverNameFromId d >>= C.peekCString++foreign import ccall safe "cdio/compat/device.h cdio_get_driver_name_from_id"+  driverNameFromId' :: DriverId -> C.CString+-}++-- | The machine-readable identifier of the driver used by the session.  This+-- should be preferred to 'driverName' wherever possible.+-- +-- Returns 'Nothing' if the 'Cdio' object has already been closed.+driverId :: Cdio -> IO (Maybe DriverId)+driverId c = fmap (toEnum . fromIntegral) <$> withCdio c driverId'++foreign import ccall safe "cdio/compat/device.h cdio_get_driver_id"+  driverId' :: C.Ptr Cdio -> IO CDriverId++-- | Get a description of the hardware associated with a particular session.+-- +-- Returns 'Nothing' if the 'Cdio' object has already been closed, or if an+-- error occurred in retrieval.+hwinfo :: Cdio -> IO (Maybe HardwareInfo)+hwinfo c = M.alloca $ \h -> do+    b <- withCdio c $ flip hwinfo' h+    case M.toBool <$> b of+        Just True -> M.maybePeek S.peek h+        _ -> return Nothing++foreign import ccall safe "cdio/compat/device.h cdio_get_hwinfo"+  hwinfo' :: C.Ptr Cdio -> C.Ptr HardwareInfo -> IO CBool+++-- | Get the starting address of the last write session of a disc.+lastSession :: Cdio -> IO (Either DriverReturnCode Lsn)+lastSession c = M.alloca $ \l -> do+    r <- withCdio c $ flip lastSession' l+    l' <- S.peek l+    return $ case toEnum . fromIntegral <$> r of+        Just Success -> Right l'+        Just e -> Left e+        Nothing -> Left Uninitialized++foreign import ccall safe "cdio/compat/device.h cdio_get_last_session"+  lastSession' :: C.Ptr Cdio -> C.Ptr Lsn -> IO CDriverReturnCode+++-- | Find out if the media has changed since the last call.+isMediaChanged :: Cdio -> IO (Either DriverReturnCode Bool)+isMediaChanged c = maybe (Left Uninitialized) errorOrBool <$> withCdio c isMediaChanged'++foreign import ccall safe "cdio/compat/device.h cdio_get_media_changed"+  isMediaChanged' :: C.Ptr Cdio -> IO CDriverReturnCode+++-- | Determine if the device understands ATAPI commands.+-- +-- Returns 'Nothing' if the 'Cdio' object has already been closed, or if the+-- capability can't be determined.+haveAtapi :: Cdio -> IO (Maybe Bool)+haveAtapi c = fmap N.join . withCdio c $ fmap bool3 . haveAtapi'++foreign import ccall safe "cdio/compat/device.h cdio_have_atapi"+  haveAtapi' :: C.Ptr Cdio -> IO C.CInt+++-- | Determine whether the system provides a particular driver.+haveDriver :: DriverId -> Bool+haveDriver = M.toBool . haveDriver' . fromIntegral . fromEnum++foreign import ccall safe "cdio/compat/device.h cdio_have_driver"+  haveDriver' :: CDriverId -> CBool+++{- Encapsulated into the 'ForeignPtr Cdio'.+-- | Free any resources associated with a reading session.+cdioDestroy :: Cdio -> IO ()+cdioDestroy = flip withCdio cdioDestroy'++foreign import ccall safe "cdio/compat/device.h cdio_destroy"+  cdioDestroy' :: C.Ptr Cdio -> IO ()+-}+++-- | Describe the IO driver in a human-readable manner, as opposed to the+-- machine representation returned by the 'Show' instance.+driverDescribe :: DriverId -> String+driverDescribe = IO.Unsafe.unsafePerformIO .+    C.peekCString . driverDescribe' . fromIntegral . fromEnum++foreign import ccall safe "cdio/compat/device.h cdio_driver_describe"+  driverDescribe' :: CDriverId -> C.CString+++-- | Open a session referencing the given location, or the default device if+-- passed 'Nothing'.+cdioOpen :: Maybe FilePath -> DriverId -> IO (Maybe Cdio)+cdioOpen f d = M.maybeWith C.withCString f $ \f' -> do+    setupLogger+    c' <- cdioOpen' f' (fromIntegral $ fromEnum d)+    M.maybePeek peekCdio c'++foreign import ccall safe "cdio/compat/device.h cdio_open"+  cdioOpen' :: C.CString -> CDriverId -> IO (C.Ptr Cdio)++-- | Open a session referencing the given location, or the default device if+-- passed 'Nothing', with the desired access mode.+cdioOpenAm :: Maybe FilePath -> DriverId -> AccessMode -> IO (Maybe Cdio)+cdioOpenAm f d m = M.maybeWith C.withCString f $ \f' -> C.withCString (serializeAccessMode m) $ \m' -> do+    setupLogger+    c' <- cdioOpenAm' f' (fromIntegral $ fromEnum d) m'+    M.maybePeek peekCdio c'++foreign import ccall safe "cdio/compat/device.h cdio_open_am"+  cdioOpenAm' :: C.CString -> CDriverId -> C.CString -> IO (C.Ptr Cdio)+++open'+    :: (C.CString -> IO (C.Ptr Cdio))+    -> Maybe FilePath+    -> IO (Maybe Cdio)+open' f p = withCStringNull p $ \p' -> do+    setupLogger+    f p' >>= M.maybePeek peekCdio++openAm'+    :: (C.CString -> C.CString -> IO (C.Ptr Cdio))+    -> Maybe FilePath+    -> AccessMode+    -> IO (Maybe Cdio)+openAm' f p m = withCStringNull p $ \p' -> C.withCString (serializeAccessMode m) $ \m' -> do+    setupLogger+    f p' m' >>= M.maybePeek peekCdio++withCStringNull :: Maybe String -> (C.CString -> IO a) -> IO a+withCStringNull Nothing f = f C.nullPtr+withCStringNull (Just str) f = C.withCString str f+++-- | Set up the specified CD-ROM device for reading.+cdioOpenCd :: Maybe FilePath -> IO (Maybe Cdio)+cdioOpenCd = open' cdioOpenCd'++foreign import ccall safe "cdio/compat/device.h cdio_open_cd"+  cdioOpenCd' :: C.CString -> IO (C.Ptr Cdio)++-- | Set up the specified CD-ROM device for reading, with the desired access+-- mode.+cdioOpenAmCd :: Maybe FilePath -> AccessMode -> IO (Maybe Cdio)+cdioOpenAmCd = openAm' cdioOpenAmCd'++foreign import ccall safe "cdio/compat/device.h cdio_open_am_cd"+  cdioOpenAmCd' :: C.CString -> C.CString -> IO (C.Ptr Cdio)+++{- All the official bindings hide these, which makes me think they're not as reliable.+defaultPath' :: IO C.CString -> IO (Maybe FilePath)+defaultPath' p = p >>= M.maybePeek C.peekCString++deviceList' :: IO (C.Ptr C.CString) -> IO [FilePath]+deviceList' ps = ps >>= peekFStringArray+++-- | Set up a BIN/CUE disc image for reading.+cdioOpenBinCue+    :: Maybe FilePath+        -- ^ The path to either the @*.bin@ or the @*.cue@ file.+    -> IO (Maybe Cdio)+cdioOpenBinCue = open' cdioOpenBinCue'++foreign import ccall safe "cdio/compat/device.h cdio_open_bincue"+  cdioOpenBinCue' :: C.CString -> IO (C.Ptr Cdio)++-- | Set up a BIN/CUE disc image for reading, with the desired access mode.+cdioOpenAmBinCue+    :: Maybe FilePath+        -- ^ The path to either the @*.bin@ or the @*.cue@ file.+    -> AccessMode+    -> IO (Maybe Cdio)+cdioOpenAmBinCue = openAm' cdioOpenAmBinCue'++foreign import ccall safe "cdio/compat/device.h cdio_open_am_bincue"+  cdioOpenAmBinCue' :: C.CString -> C.CString -> IO (C.Ptr Cdio)++-- | The default CUE file that would be used if none is specified.+defaultDeviceBinCue :: IO (Maybe FilePath)+defaultDeviceBinCue = defaultPath' defaultDeviceBinCue'++foreign import ccall safe "cdio/compat/device.h cdio_get_default_device_bincue"+  defaultDeviceBinCue' :: IO C.CString++-- | The CUE files contained in the current directory.+devicesBinCue :: IO [FilePath]+devicesBinCue = deviceList' devicesBinCue'++foreign import ccall safe "cdio/compat/device.h cdio_get_devices_bincue"+  devicesBinCue' :: IO (C.Ptr C.CString)+++-- | Set up a cdrdao disc image for reading.+cdioOpenCdrDao+    :: Maybe FilePath+        -- ^ The path to the @*.toc@ file.+    -> IO (Maybe Cdio)+cdioOpenCdrDao = open' cdioOpenCdrDao'++foreign import ccall safe "cdio/compat/device.h cdio_open_cdrdao"+  cdioOpenCdrDao' :: C.CString -> IO (C.Ptr Cdio)++-- | Set up a cdrdao disc image for reading, with the desired access mode.+cdioOpenAmCdrDao+    :: Maybe FilePath+        -- ^ The path to the @*.toc@ file.+    -> AccessMode+    -> IO (Maybe Cdio)+cdioOpenAmCdrDao = openAm' cdioOpenAmCdrDao'++foreign import ccall safe "cdio/compat/device.h cdio_open_am_cdrdao"+  cdioOpenAmCdrDao' :: C.CString -> C.CString -> IO (C.Ptr Cdio)++-- | The default TOC file that would be used if none is specified.+defaultDeviceCdrDao :: IO (Maybe FilePath)+defaultDeviceCdrDao = defaultPath' defaultDeviceCdrDao'++foreign import ccall safe "cdio/compat/device.h cdio_get_default_device_cdrdao"+  defaultDeviceCdrDao' :: IO C.CString++-- | Paths to potential TOC disc images.+devicesCdrDao :: IO [FilePath]+devicesCdrDao = deviceList' devicesCdrDao'++foreign import ccall safe "cdio/compat/device.h cdio_get_devices_cdrdao"+  devicesCdrDao' :: IO (C.Ptr C.CString)+++-- | Set up a BIN/CUE disc image for reading.  Unlike 'cdioOpenBinCue' which+-- may reference either, this path /must/ point to the @*.cue@ file.+cdioOpenCue :: Maybe FilePath -> IO (Maybe Cdio)+cdioOpenCue = open' cdioOpenCue'++foreign import ccall safe "cdio/compat/device.h cdio_open_cue"+  cdioOpenCue' :: C.CString -> IO (C.Ptr Cdio)+++-- | Set up a device for reading using the AIX driver.+cdioOpenAix :: Maybe FilePath -> IO (Maybe Cdio)+cdioOpenAix = open' cdioOpenAix'++foreign import ccall safe "cdio/compat/device.h cdio_open_aix"+  cdioOpenAix' :: C.CString -> IO (C.Ptr Cdio)++-- | Set up a device for reading using the AIX driver, with the desired access+-- mode.+cdioOpenAmAix :: Maybe FilePath -> AccessMode -> IO (Maybe Cdio)+cdioOpenAmAix = openAm' cdioOpenAmAix'++foreign import ccall safe "cdio/compat/device.h cdio_open_am_aix"+  cdioOpenAmAix' :: C.CString -> C.CString -> IO (C.Ptr Cdio)++-- | The default device name that the AIX driver would use if none is+-- specified.+defaultDeviceAix :: IO (Maybe FilePath)+defaultDeviceAix = defaultPath' defaultDeviceAix'++foreign import ccall safe "cdio/compat/device.h cdio_get_default_device_aix"+  defaultDeviceAix' :: IO C.CString++-- | All of the devices that the AIX driver can find.  This may require a disc+-- to be inserted in order for the system to recognize the drive.+devicesAix :: IO [FilePath]+devicesAix = deviceList' devicesAix'++foreign import ccall safe "cdio/compat/device.h cdio_get_devices_aix"+  devicesAix' :: IO (C.Ptr C.CString)+++-- | Set up a device for reading using the FreeBSD driver.+cdioOpenFreeBsd :: Maybe FilePath -> IO (Maybe Cdio)+cdioOpenFreeBsd = open' cdioOpenFreeBsd'++foreign import ccall safe "cdio/compat/device.h cdio_open_freebsd"+  cdioOpenFreeBsd' :: C.CString -> IO (C.Ptr Cdio)++-- | Set up a device for reading using the FreeBSD driver, with the desired+-- access mode.+cdioOpenAmFreeBsd :: Maybe FilePath -> AccessMode -> IO (Maybe Cdio)+cdioOpenAmFreeBsd = openAm' cdioOpenAmFreeBsd'++foreign import ccall safe "cdio/compat/device.h cdio_open_am_freebsd"+  cdioOpenAmFreeBsd' :: C.CString -> C.CString -> IO (C.Ptr Cdio)++-- | The default device name that the FreeBSD driver would use if none is+-- specified.+defaultDeviceFreeBsd :: IO (Maybe FilePath)+defaultDeviceFreeBsd = defaultPath' defaultDeviceFreeBsd'++foreign import ccall safe "cdio/compat/device.h cdio_get_default_device_freebsd"+  defaultDeviceFreeBsd' :: IO C.CString++-- | All of the devices that the FreeBSD driver can find.  This may require a+-- disc to be inserted in order for the system to recognize the drive.+devicesFreeBsd :: IO [FilePath]+devicesFreeBsd = deviceList' devicesFreeBsd'++foreign import ccall safe "cdio/compat/device.h cdio_get_devices_freebsd"+  devicesFreeBsd' :: IO (C.Ptr C.CString)+++-- | Set up a device for reading using the BSDI driver.+-- +-- /Since libcdio 1.0:  Always returns 'Nothing'/+cdioOpenBsdi :: Maybe FilePath -> IO (Maybe Cdio)+cdioOpenBsdi = open' cdioOpenBsdi'++foreign import ccall safe "cdio/compat/device.h cdio_open_bsdi_safe"+  cdioOpenBsdi' :: C.CString -> IO (C.Ptr Cdio)++-- | Set up a device for reading using the BSDI driver, with the desired access+-- mode.+-- +-- /Since libcdio 1.0:  Always returns 'Nothing'/+cdioOpenAmBsdi :: Maybe FilePath -> AccessMode -> IO (Maybe Cdio)+cdioOpenAmBsdi = openAm' cdioOpenAmBsdi'++foreign import ccall safe "cdio/compat/device.h cdio_open_am_bsdi_safe"+  cdioOpenAmBsdi' :: C.CString -> C.CString -> IO (C.Ptr Cdio)++-- | The default device name that the BSDI driver would use if none is+-- specified.+-- +-- /Since libcdio 1.0:  Always returns 'Nothing'/+defaultDeviceBsdi :: IO (Maybe FilePath)+defaultDeviceBsdi = defaultPath' defaultDeviceBsdi'++foreign import ccall safe "cdio/compat/device.h cdio_get_default_device_bsdi_safe"+  defaultDeviceBsdi' :: IO C.CString++-- | All of the devices that the BSDI driver can find.  This may require a disc+-- to be inserted in order for the system to recognize the drive.+-- +-- /Since libcdio 1.0:  Always returns @[]@/+devicesBsdi :: IO [FilePath]+devicesBsdi = deviceList' devicesBsdi'++foreign import ccall safe "cdio/compat/device.h cdio_get_devices_bsdi_safe"+  devicesBsdi' :: IO (C.Ptr C.CString)+++-- | Set up a device for reading using the GNU/Linux driver.  This may require+-- a disc to be inserted in order for the system to recognize the drive.+cdioOpenLinux :: Maybe FilePath -> IO (Maybe Cdio)+cdioOpenLinux = open' cdioOpenLinux'++foreign import ccall safe "cdio/compat/device.h cdio_open_linux"+  cdioOpenLinux' :: C.CString -> IO (C.Ptr Cdio)++-- | Set up a device for reading using the GNU/Linux driver, with the desired+-- access mode.+cdioOpenAmLinux :: Maybe FilePath -> AccessMode -> IO (Maybe Cdio)+cdioOpenAmLinux = openAm' cdioOpenAmLinux'++foreign import ccall safe "cdio/compat/device.h cdio_open_am_linux"+  cdioOpenAmLinux' :: C.CString -> C.CString -> IO (C.Ptr Cdio)++-- | The default device name that the GNU/Linux driver would use if none is+-- specified.  This may require a disc to be inserted in order for the system to+-- recognize the drive.+defaultDeviceLinux :: IO (Maybe FilePath)+defaultDeviceLinux = defaultPath' defaultDeviceLinux'++foreign import ccall safe "cdio/compat/device.h cdio_get_default_device_linux"+  defaultDeviceLinux' :: IO C.CString++-- | All of the devices that the GNU/Linux driver can find.+devicesLinux :: IO [FilePath]+devicesLinux = deviceList' devicesLinux'++foreign import ccall safe "cdio/compat/device.h cdio_get_devices_linux"+  devicesLinux' :: IO (C.Ptr C.CString)+++-- | Set up a device for reading using the Sun Solaris driver.  This may+-- require a disc to be inserted in order for the system to recognize the+-- drive.+cdioOpenSolaris :: Maybe FilePath -> IO (Maybe Cdio)+cdioOpenSolaris = open' cdioOpenSolaris'++foreign import ccall safe "cdio/compat/device.h cdio_open_solaris"+  cdioOpenSolaris' :: C.CString -> IO (C.Ptr Cdio)++-- | Set up a device for reading using the Sun Solaris driver, with the desired+-- access mode.+cdioOpenAmSolaris :: Maybe FilePath -> AccessMode -> IO (Maybe Cdio)+cdioOpenAmSolaris = openAm' cdioOpenAmSolaris'++foreign import ccall safe "cdio/compat/device.h cdio_open_am_solaris"+  cdioOpenAmSolaris' :: C.CString -> C.CString -> IO (C.Ptr Cdio)++-- | The default device name that the Solaris driver would use if none is+-- specified.  This may require a disc to be inserted in order for the system+-- to recognize the drive.+defaultDeviceSolaris :: IO (Maybe FilePath)+defaultDeviceSolaris = defaultPath' defaultDeviceSolaris'++foreign import ccall safe "cdio/compat/device.h cdio_get_default_device_solaris"+  defaultDeviceSolaris' :: IO C.CString++-- | All of the devices that the Solaris driver can find.+devicesSolaris :: IO [FilePath]+devicesSolaris = deviceList' devicesSolaris'++foreign import ccall safe "cdio/compat/device.h cdio_get_devices_solaris"+  devicesSolaris' :: IO (C.Ptr C.CString)+++-- | Set up a device for reading using the Apple OSX driver.  This may require+-- a disc to be inserted in order for the system to recognize the drive.+cdioOpenOsX :: Maybe FilePath -> IO (Maybe Cdio)+cdioOpenOsX = open' cdioOpenOsX'++foreign import ccall safe "cdio/compat/device.h cdio_open_osx"+  cdioOpenOsX' :: C.CString -> IO (C.Ptr Cdio)++-- | Set up a device for reading using the Apple OSX driver, with the desired+-- access mode.+cdioOpenAmOsX :: Maybe FilePath -> AccessMode -> IO (Maybe Cdio)+cdioOpenAmOsX = openAm' cdioOpenAmOsX'++foreign import ccall safe "cdio/compat/device.h cdio_open_am_osx"+  cdioOpenAmOsX' :: C.CString -> C.CString -> IO (C.Ptr Cdio)++-- | The default device name that the OSX driver would use if none is+-- specified.  This may require a disc to be inserted in order for the system+-- to recognize the drive.+defaultDeviceOsX :: IO (Maybe FilePath)+defaultDeviceOsX = defaultPath' defaultDeviceOsX'++foreign import ccall safe "cdio/compat/device.h cdio_get_default_device_osx"+  defaultDeviceOsX' :: IO C.CString++-- | All of the devices that the OSX driver can find.+devicesOsX :: IO [FilePath]+devicesOsX = deviceList' devicesOsX'++foreign import ccall safe "cdio/compat/device.h cdio_get_devices_osx"+  devicesOsX' :: IO (C.Ptr C.CString)+++-- | Set up a device for reading using the Microsoft Windows driver.  This may+-- require a disc to be inserted in order for the system to recognize the+-- drive.+cdioOpenWin32 :: Maybe FilePath -> IO (Maybe Cdio)+cdioOpenWin32 = open' cdioOpenWin32'++foreign import ccall safe "cdio/compat/device.h cdio_open_win32"+  cdioOpenWin32' :: C.CString -> IO (C.Ptr Cdio)++-- | Set up a device for reading using the Microsoft Windows driver, with the+-- desired access mode.+cdioOpenAmWin32 :: Maybe FilePath -> AccessMode -> IO (Maybe Cdio)+cdioOpenAmWin32 = openAm' cdioOpenAmWin32'++foreign import ccall safe "cdio/compat/device.h cdio_open_am_win32"+  cdioOpenAmWin32' :: C.CString -> C.CString -> IO (C.Ptr Cdio)++-- | The default device name that the Microsoft Windows driver would use if+-- none is specified.  This may require a disc to be inserted in order for the+-- system to recognize the drive.+defaultDeviceWin32 :: IO (Maybe FilePath)+defaultDeviceWin32 = defaultPath' defaultDeviceWin32'++foreign import ccall safe "cdio/compat/device.h cdio_get_default_device_win32"+  defaultDeviceWin32' :: IO C.CString++-- | All of the devices that the Microsoft Windows driver can find.+devicesWin32 :: IO [FilePath]+devicesWin32 = deviceList' devicesWin32'++foreign import ccall safe "cdio/compat/device.h cdio_get_devices_win32"+  devicesWin32' :: IO (C.Ptr C.CString)+++-- | Set up a device for reading using the IBM OS/2 driver.  This may require a+-- disc to be inserted in order for the system to recognize the drive.+-- +-- /Since libcdio 1.0:  Always returns 'Nothing'/+cdioOpenOs2 :: Maybe FilePath -> IO (Maybe Cdio)+cdioOpenOs2 = open' cdioOpenOs2'++foreign import ccall safe "cdio/compat/device.h cdio_open_os2_safe"+  cdioOpenOs2' :: C.CString -> IO (C.Ptr Cdio)++-- | Set up a device for reading using the IBM OS/2 driver, with the desired+-- access mode.+-- +-- /Since libcdio 1.0:  Always returns 'Nothing'/+cdioOpenAmOs2 :: Maybe FilePath -> AccessMode -> IO (Maybe Cdio)+cdioOpenAmOs2 = openAm' cdioOpenAmOs2'++foreign import ccall safe "cdio/compat/device.h cdio_open_am_os2_safe"+  cdioOpenAmOs2' :: C.CString -> C.CString -> IO (C.Ptr Cdio)++-- | The default device name that the OS/2 driver would use if none is+-- specified.  This may require a disc to be inserted in order for the system+-- to recognize the drive.+-- +-- /Since libcdio 1.0:  Always returns 'Nothing'/+defaultDeviceOs2 :: IO (Maybe FilePath)+defaultDeviceOs2 = defaultPath' defaultDeviceOs2'++foreign import ccall safe "cdio/compat/device.h cdio_get_default_device_os2_safe"+  defaultDeviceOs2' :: IO C.CString++-- | All of the devices that the OS/2 driver can find.+-- +-- /Since libcdio 1.0:  Always returns @[]@/+devicesOs2 :: IO [FilePath]+devicesOs2 = deviceList' devicesOs2'++foreign import ccall safe "cdio/compat/device.h cdio_get_devices_os2_safe"+  devicesOs2' :: IO (C.Ptr C.CString)+++-- | Set up a Nero disc image for reading.+cdioOpenNero :: Maybe FilePath -> IO (Maybe Cdio)+cdioOpenNero = open' cdioOpenNero'++foreign import ccall safe "cdio/compat/device.h cdio_open_nrg"+  cdioOpenNero' :: C.CString -> IO (C.Ptr Cdio)++-- | Set up a Nero disc image for reading, with the desired access mode.+cdioOpenAmNero :: Maybe FilePath -> AccessMode -> IO (Maybe Cdio)+cdioOpenAmNero = openAm' cdioOpenAmNero'++foreign import ccall safe "cdio/compat/device.h cdio_open_am_nrg"+  cdioOpenAmNero' :: C.CString -> C.CString -> IO (C.Ptr Cdio)++-- | The default image file that the Nero driver would use if none is+-- specified.+defaultDeviceNero :: IO (Maybe FilePath)+defaultDeviceNero = defaultPath' defaultDeviceNero'++foreign import ccall safe "cdio/compat/device.h cdio_get_default_device_nrg"+  defaultDeviceNero' :: IO C.CString++-- | Paths to potential Nero disc images.+devicesNero :: IO [FilePath]+devicesNero = deviceList' devicesNero'++foreign import ccall safe "cdio/compat/device.h cdio_get_devices_nrg"+  devicesNero' :: IO (C.Ptr C.CString)+-}+++-- | If the given file is a BIN disc image (determined by file extension),+-- return the corresponding CUE file.  Note that this simply replaces the+-- extension to obtain the new file name.+cueFromBin :: FilePath -> IO (Maybe FilePath)+cueFromBin f = C.withCString f cueFromBin' >>= M.maybePeek C.peekCString++foreign import ccall safe "cdio/compat/device.h cdio_is_binfile"+  cueFromBin' :: C.CString -> IO C.CString++-- | If the given file is a valid CUE disc description, return the+-- corresponding BIN file.  Note that this simply replaces the file extension+-- to obtain the new file name.+binFromCue :: FilePath -> IO (Maybe FilePath)+binFromCue f = C.withCString f binFromCue' >>= M.maybePeek C.peekCString++foreign import ccall safe "cdio/compat/device.h cdio_is_cuefile"+  binFromCue' :: C.CString -> IO C.CString++-- | Check that a Nero disc image file is valid.+isNrg :: FilePath -> IO Bool+isNrg = fmap M.toBool . flip C.withCString isNrg'++foreign import ccall safe "cdio/compat/device.h cdio_is_nrg"+  isNrg' :: C.CString -> IO CBool++-- | Check that a cdrdao-style TOC description file is valid.+isToc :: FilePath -> IO Bool+isToc = fmap M.toBool . flip C.withCString isToc'++foreign import ccall safe "cdio/compat/device.h cdio_is_tocfile"+  isToc' :: C.CString -> IO CBool++-- | Determine whether the given path refers to a hardware device, according to+-- the given driver.  'DriverUnknown' or 'DriverDevice' may be passed if the+-- system is unknown.+isDevice :: FilePath -> DriverId -> IO Bool+isDevice f d = M.toBool <$> C.withCString f (flip isDevice' . fromIntegral $ fromEnum d)++foreign import ccall safe "cdio/compat/device.h cdio_is_device"+  isDevice' :: C.CString -> CDriverId -> IO CBool+++-- | Set the blocksize for subsequent reads.+setBlocksize+    :: Cdio+        -- ^ The CdText object is mutated as a result of the function.+    -> Int+    -> IO DriverReturnCode+setBlocksize c s = toDriverReturnCode <$> withCdio c (flip setBlocksize' $ fromIntegral s)++foreign import ccall safe "cdio/compat/device.h cdio_set_blocksize"+  setBlocksize' :: C.Ptr Cdio -> C.CInt -> IO CDriverReturnCode++-- | Set the drive speed.  With many devices, if a value above their maximum+-- speed is given, it will be silently capped.+--+-- Note that, unlike 'MMC.setSpeed', this uses a unit unique to disc drives,+-- which depends on the type of disc; to convert to or from Kb/s, use the+-- formula @dt * cds = kbs@ where @dt@ is either @176@ for raw data or @150@+-- for filesystem data, and @cds@ is the 'Int' passed to this function.+setSpeed+    :: Cdio+        -- ^ The CdText object is mutated as a result of the function.+    -> Int+    -> IO DriverReturnCode+setSpeed c v = toDriverReturnCode <$> withCdio c (flip setSpeed' $ fromIntegral v)++foreign import ccall safe "cdio/compat/device.h cdio_set_speed"+  setSpeed' :: C.Ptr Cdio -> C.CInt -> IO CDriverReturnCode+++-- | Retrieve the session value associated with the given key.  The particular+-- case of @"access-mode"@ is instead handled by 'getAccessMode'.+getArg :: Cdio -> SessionArg -> IO (Maybe String)+getArg c k = C.withCString (serializeSessionArg k) $ \k' ->+    withCdio c (`getArg'` k') >>= maybe (return Nothing) (M.maybePeek C.peekCString)++-- | Check what instruction set is in use for reading the disc.  Other session+-- values are handled by 'getArg'.+getAccessMode :: Cdio -> IO (Maybe AccessMode)+getAccessMode c = C.withCString "access-mode" $ \k' -> do+    str <- withCdio c (`getArg'` k') >>= maybe (return Nothing) (M.maybePeek C.peekCString)+    return $ fmap unserializeAccessMode str++foreign import ccall safe "cdio/compat/device.h cdio_get_arg"+  getArg' :: C.Ptr Cdio -> C.CString -> IO C.CString++{- This is very likely intended for internal use only+-- | Change the session value associated with the given key.+setArg+    :: Cdio+        -- ^ The CdText object is mutated as a result of the function.+    -> SessionArg+    -> String+        -- ^ The new property value.+    -> IO DriverReturnCode+setArg c k v = C.withCString (serializeSessionArg k) $ \k' -> C.withCString v $ \v' ->+    toDriverReturnCode <$> withCdio c (\c' -> setArg' c' k' v')++foreign import ccall safe "cdio/compat/device.h cdio_set_arg"+  setArg' :: C.Ptr Cdio -> C.CString -> C.CString -> IO CDriverReturnCode+-}++-- | Metadata about the session in the form of (often freeform) text, providing+-- a type-safe index to 'getArg'.  Note that not every driver type supports+-- every item.+--+-- The key @"access-mode"@ is handled separately by 'getAccessMode', to better+-- reflect its restricted outputs.+data SessionArg+    = Source+    | Cue+    | ScsiTuple+    | MmcSupported+  deriving ( Eq, Ord, Bounded, Enum, Show, Read )+instance S.Storable SessionArg where+    sizeOf _ = S.sizeOf (undefined :: C.CString)+    alignment _ = S.alignment (undefined :: C.CString)+    peek p = do+        p' <- S.peek $ C.castPtr p+        if p' == C.nullPtr+            then error "Storable(SessionArg).peek: NULL reference"+            else do+                str <- C.peekCString p'+                return $ case str of+                    "source" -> Source+                    "cue" -> Cue+                    "scsi-tuple" -> ScsiTuple+                    "mmc-supported?" -> MmcSupported+                    _ -> error $ "Storable(SessionArg).peek: unknown key '" ++ str ++ "'"+    poke p hs = C.newCString (serializeSessionArg hs) >>= S.poke (C.castPtr p)++serializeSessionArg :: SessionArg -> String+serializeSessionArg Source = "source"+serializeSessionArg Cue = "cue"+serializeSessionArg ScsiTuple = "scsi-tuple"+serializeSessionArg MmcSupported = "mmc-supported?"+++-- | Which instruction set should be used to communicate with the driver,+-- providing a type-safe input for session initialization.  Note that not every+-- driver type supports every item.+data AccessMode+    = Image+    | Ioctl+        -- ^ The 'DriverLinux' and 'DriverBsdi' drivers use a different+        -- internal representation for 'Ioctl_'.+    | Ioctl_+        -- ^ The 'DriverFreeBsd' and 'DriverWin32' drivers use a different+        -- internal representation for 'Ioctl'.+    | Aspi+    | Atapi+    | Cam+    | Scsi+    | ReadCd+    | Read10+    | MmcReadWrite+    | MmcReadWriteExclusive+  deriving ( Eq, Ord, Bounded, Enum, Show, Read )+instance S.Storable AccessMode where+    sizeOf _ = S.sizeOf (undefined :: C.CString)+    alignment _ = S.alignment (undefined :: C.CString)+    peek p = do+        p' <- S.peek $ C.castPtr p+        if p' == C.nullPtr+            then error "Storable(AccessMode).peek: NULL reference"+            else unserializeAccessMode <$> C.peekCString p'+    poke p hs = C.newCString (serializeAccessMode hs) >>= S.poke (C.castPtr p)++serializeAccessMode :: AccessMode -> String+serializeAccessMode Image = "image"+serializeAccessMode Ioctl = "IOCTL"+serializeAccessMode Ioctl_ = "ioctl"+serializeAccessMode Aspi = "ASPI"+serializeAccessMode Atapi = "ATAPI"+serializeAccessMode Cam = "CAM"+serializeAccessMode Scsi = "SCSI"+serializeAccessMode ReadCd = "READ_CD"+serializeAccessMode Read10 = "READ_10"+serializeAccessMode MmcReadWrite = "MMC_RDWR"+serializeAccessMode MmcReadWriteExclusive = "MMC_RDWR_EXCL"++unserializeAccessMode :: String -> AccessMode+unserializeAccessMode "image" = Image+unserializeAccessMode "IOCTL" = Ioctl+unserializeAccessMode "ioctl" = Ioctl_+unserializeAccessMode "ASPI" = Aspi+unserializeAccessMode "ATAPI" = Atapi+unserializeAccessMode "CAM" = Cam+unserializeAccessMode "SCSI" = Scsi+unserializeAccessMode "READ_CD" = ReadCd+unserializeAccessMode "READ_10" = Read10+unserializeAccessMode "MMC_RDRW" = MmcReadWrite+unserializeAccessMode "MMC_RDRW_EXCL" = MmcReadWriteExclusive+unserializeAccessMode str = error $ "Storable(AccessMode).peek: unknown key '" ++ str ++ "'"
+ src/Foreign/Libcdio/Disc.hs view
@@ -0,0 +1,256 @@+{-# LANGUAGE ForeignFunctionInterface #-}++{-|+Description:    The top-level header for disc-related libcdio calls.++Copyright:      (c) 2018-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      stable+Portability:    non-portable (requires libcdio)++This module provides informational and metadata functions primarily related to+the layout of data on a physical disc.  While both "Foreign.Libcdio.Read" and+"Foreign.Libcdio.CdText" provide more exciting access to the actual data, this+still provides a critical intermediate step between those and the physical+hardware of "Foreign.Libcdio.Device".+++= @disc.h@++== Types+* @discmode_t@                      -> 'DiscMode'++    - @CDIO_DISC_MODE_CD_DA@        -> 'AudioCdMode'+    - @CDIO_DISC_MODE_CD_DATA@      -> 'DataCdMode'+    - @CDIO_DISC_MODE_CD_XA@        -> 'XaCdMode'+    - @CDIO_DISC_MODE_CD_MIXED@     -> 'MixedCdMode'+    - @CDIO_DISC_MODE_DVD_ROM@      -> 'DvdRomMode'+    - @CDIO_DISC_MODE_DVD_RAM@      -> 'DvdRamMode'+    - @CDIO_DISC_MODE_DVD_R@        -> 'DvdRecordableMode'+    - @CDIO_DISC_MODE_DVD_RW@       -> 'DvdReWritableMode'+    - @CDIO_DISC_MODE_HD_DVD_ROM@   -> 'HighDefinitionDvdRomMode'+    - @CDIO_DISC_MODE_HD_DVD_RAM@   -> 'HighDefinitionDvdRamMode'+    - @CDIO_DISC_MODE_HD_DVD_R@     -> 'HighDefinitionDvdRecordableMode'+    - @CDIO_DISC_MODE_DVD_PR@       -> 'DvdPlusRecordableMode'+    - @CDIO_DISC_MODE_DVD_PRW@      -> 'DvdPlusReWritableMode'+    - @CDIO_DISC_MODE_DVD_PR_DL@    -> 'DoubleLayerDvdPlusRecordableMode'+    - @CDIO_DISC_MODE_DVD_PRW_DL@   -> 'DoubleLayerDvdPlusReWritableMode'+    - @CDIO_DISC_MODE_DVD_OTHER@    -> 'OtherDvdMode'+    - @CDIO_DISC_MODE_NO_INFO@      -> 'NoModeInfo'+    - @CDIO_DISC_MODE_CD_I@         -> 'CdIMode'+    - @CDIO_DISC_MODE_ERROR@        (removed; handled via 'Nothing')++== Symbols+* @cdio_get_cdtext@                 (removed; merged into 'Cdio' objects due to pointer lifespan issues)+* @cdio_get_cdtext_raw@             -> 'cdTextRaw'+* @cdio_get_disc_last_lsn@          -> 'lastLsn'+* @cdio_get_discmode@               -> 'discMode'+* @cdio_get_joliet_level@           -> 'discJolietLevel'+* @cdio_get_mcn@                    -> 'cdMcn'+* @cdio_get_num_tracks@             -> 'numTracks'+* @cdio_is_discmode_cdrom@          -> 'isCdRom'+* @cdio_is_discmode_dvd@            -> 'isDvd'+* @discmode2str@                    -> 'discModeString'+++= "Sound.Libcdio.Read.Data"++* @cdio_get_cdtext@                 -> @"Sound.Libcdio.Read.CdText".'Sound.Libcdio.Read.Data.cdText'@+* 'cdMcn'                           -> 'Sound.Libcdio.Read.Data.catalogue'+* 'cdTextRaw'                       -> @"Sound.Libcdio.Read.CdText".'Sound.Libcdio.Read.Data.cdTextRaw'@+* 'lastLsn'                         -> 'Sound.Libcdio.Read.Data.lastAddress'+* 'mcnLength'                       (removed; unnecessary low-level detail)+* 'numTracks'                       -> @"Sound.Libcdio.Track".'Sound.Libcdio.Track.tracks'@+-}+module Foreign.Libcdio.Disc+    ( -- * Types+      DiscMode ( .. )+    , discModeString+    , isCdRom, isDvd+      -- * Data+    , discMode+    , numTracks+    , lastLsn+    , discJolietLevel+    , hasCdText+    , cdTextRaw+    , cdMcn+    , mcnLength+    ) where+++import qualified Control.Monad as N++import qualified Data.ByteString as BS+import qualified Data.Maybe as Y+import qualified Data.Word as W++import qualified Foreign.C.String as C+import qualified Foreign.C.Types as C+import qualified Foreign.Ptr as C++import qualified Foreign.Marshal.Alloc as M+import qualified Foreign.Marshal.Utils as M+import qualified Foreign.Storable as S++import qualified System.IO.Unsafe as IO.Unsafe++import Foreign.Libcdio.CdText+import Foreign.Libcdio.CdText.Binary+import Foreign.Libcdio.Marshal+import Foreign.Libcdio.Track+import Foreign.Libcdio.Types.Enums+import Foreign.Libcdio.Types.Internal+++-- | Filter out @CDIO_DISC_MODE_ERROR@ values to fit the 'Enum'.+invalidDiscMode :: CDiscMode -> Maybe DiscMode+invalidDiscMode = fmap (toEnum . fromIntegral) . maybeError [invalidDiscMode']++foreign import ccall safe "cdio/compat/disc.h discmode_error"+  invalidDiscMode' :: CDiscMode+++-- | Describe a type a disc according to its official name, as opposed to the+-- machine representation returned by the 'Show' instance.+discModeString :: DiscMode -> String+discModeString = IO.Unsafe.unsafePerformIO .+    C.peekCString . discModeString' . fromIntegral . fromEnum++foreign import ccall safe "cdio/compat/disc.h discmode_string"+  discModeString' :: CDiscMode -> C.CString+++-- | Get the raw CD-Text binary data contained on a disc.+cdTextRaw :: Cdio -> IO (Maybe BS.ByteString)+cdTextRaw c = withCdTextBlob c cdTextRaw' >>= maybe (serialize c) (return . Just)++foreign import ccall safe "cdio/compat/disc.h get_cdtext_raw_len"+  cdTextRaw' :: C.Ptr Cdio -> C.Ptr (C.Ptr C.CChar) -> C.Ptr C.CInt -> IO ()++-- | Allocate a dummy pointer to have somewhere to store the return value.+withCdTextBlob :: Cdio -> (C.Ptr Cdio -> C.Ptr (C.Ptr C.CChar) -> C.Ptr C.CInt -> IO ()) -> IO (Maybe BS.ByteString)+withCdTextBlob c f = M.alloca $ \p' -> M.alloca $ \i' -> do+    y <- withCdio c $ \c' -> f c' p' i'+    if Y.isNothing y+    then return Nothing+    else do+        p <- S.peek p'+        i <- S.peek i'+        if p == C.nullPtr+        then return Nothing+        else do+            bs <- BS.packCStringLen (C.plusPtr p 4, fromIntegral i)+            M.free p+            return $ Just bs++-- | If the @cdio_get_cdtext_raw@ call fails to provide a valid+-- 'BS.ByteString', but we can access the stringified CDTEXT, generate one+-- ourselves.  This is necessary as, if the CDTEXT wasn't binary to begin with+-- (i.e. in an image file), libcdio is a bit lazy and doesn't return anything.+serialize :: Cdio -> IO (Maybe BS.ByteString)+serialize x = do+    ls <- listAllLanguages x+    ps <- N.forM [0 .. fromIntegral (length ls) - 1] $ \i -> do+        b <- selectLanguageIndex x i+        if b then serializeLanguage x i else return (0, [])+    let (ss, bss) = unzip ps+    return $ case map checksum $ concatMap (joinBlockInfo ls ss) bss of+        [] -> Nothing+        bs -> Just $ BS.concat bs++-- | Retrieve all data from the current CDTEXT block and render it to the pack+-- format used by the binary representation.  For convenience, the highest+-- sequence number used by this block is also returned.+serializeLanguage :: Cdio -> Word -> IO (W.Word8, [BS.ByteString])+serializeLanguage x i = do+    t1 <- Y.fromMaybe 1 <$> firstTrack x+    tl <- Y.fromMaybe 0 <$> lastTrack x+    di <- serializeInfo x Nothing+    tis <- mapM (serializeInfo x . Just) [t1..tl]+    c <- cdTextGet x DiscId Nothing+    g <- genre x+    gs <- cdTextGet x GenreName Nothing+    let ps = packCdTextBlock i c t1 g gs di tis+    return (fromIntegral . max 0 $ length ps - 1, ps)++-- | Retrieve all text packs defined in the current block for the given track,+-- and pack them into an easy-to-pass-around datatype.+serializeInfo :: Cdio -> Maybe Track -> IO Info+serializeInfo x t = do+    n <- cdTextGet x Title t+    p <- cdTextGet x Performer t+    s <- cdTextGet x Songwriter t+    c <- cdTextGet x Composer t+    a <- cdTextGet x Arranger t+    m <- cdTextGet x Message t+    o <- cdTextGet x (if Y.isNothing t then UpcEan else Isrc) t+    return $ Info n p s c a m o+++-- | Determine which type of disc is being accessed.  Note that while this+-- provides a general direction, it shouldn't be relied upon for actual reading+-- of data; use 'Foreign.Libcdio.Track.trackFormat' for more granular info.+discMode :: Cdio -> IO (Maybe DiscMode)+discMode c = (>>= invalidDiscMode) <$> withCdio c discMode'++foreign import ccall safe "cdio/compat/disc.h cdio_get_discmode"+  discMode' :: C.Ptr Cdio -> IO CDiscMode+++-- | Get the size of a disc in blocks, or equivalently the address of the end+-- of the readable data.+lastLsn :: Cdio -> IO (Maybe Lsn)+lastLsn c = (>>= invalidZeroLsn) <$> withCdio c lastLsn'++foreign import ccall safe "cdio/compat/disc.h cdio_get_disc_last_lsn"+  lastLsn' :: C.Ptr Cdio -> IO C.CInt+++-- | The original ISO 9660 (data) filesystem specification was rather+-- restrictive in what files could be named; the Joliet extensions allow such+-- exciting features as lowercase letters, not to mention full Unicode support.+discJolietLevel :: Cdio -> IO (Maybe Word)+discJolietLevel c = (>>= maybeError [0] . fromIntegral) <$> withCdio c discJolietLevel'++foreign import ccall safe "cdio/compat/disc.h cdio_get_joliet_level"+  discJolietLevel' :: C.Ptr Cdio -> IO C.CUChar+++-- | Get the media catalog number from a disc.  This may also be retrieved+-- by @'Foreign.Libcdio.CdText.getField' 'Foreign.Libcdio.CdText.UpcEan'+-- 'Nothing'@, though that references a different source and thus may not have+-- the same return value.+cdMcn :: Cdio -> IO (Maybe String)+cdMcn c = withCdio c cdMcn' >>= maybe (return Nothing) (M.maybePeek peekFString)++foreign import ccall safe "cdio/compat/disc.h cdio_get_mcn"+  cdMcn' :: C.Ptr Cdio -> IO C.CString+++-- | Get the number of tracks on a CD.+-- +-- Returns 'Nothing' if the 'Cdio' object has already been closed, or if the+-- disc table of contents can't be read.+numTracks :: Cdio -> IO (Maybe Track)+numTracks c = (>>= invalidTrack) <$> withCdio c numTracks'++foreign import ccall safe "cdio/compat/disc.h cdio_get_num_tracks"+  numTracks' :: C.Ptr Cdio -> IO C.CUChar+++-- | Return true if a 'DiscMode' refers to some sort of CD.+isCdRom :: DiscMode -> Bool+isCdRom = M.toBool . isCdRom' . fromIntegral . fromEnum++foreign import ccall safe "cdio/compat/disc.h cdio_is_discmode_cdrom"+  isCdRom' :: CDiscMode -> C.CUChar++-- | Return true if a 'DiscMode' refers to some sort of DVD.+isDvd :: DiscMode -> Bool+isDvd = M.toBool . isDvd' . fromIntegral . fromEnum++foreign import ccall safe "cdio/compat/disc.h cdio_is_discmode_dvd"+  isDvd' :: CDiscMode -> C.CUChar
+ src/Foreign/Libcdio/Logging.hs view
@@ -0,0 +1,166 @@+{-# LANGUAGE ForeignFunctionInterface #-}++{-|+Description:    Control over and access to library log output.++Copyright:      (c) 2020-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      stable+Portability:    non-portable (requires libcdio)++The underlying library is rather loud in its error and warning messages,+potentially emitting a lot of impure terminal clutter even on some+otherwise-pure functions.  Very helpfully, it also provides a mechanism for+integrating the logs with whatever framework is in place for the larger+project; that mechanism can be leveraged to cache the logs in memory until+specifically asked for, at which point they can be packaged into Haskell types.+Some of the immediacy—and therefore user ability to match note to source—is+unfortunately lost, but the apparent purity is worth it.+++= @logging.h@++== Types+* @cdio_log_level_t@                -> 'Foreign.Libcdio.Logging.LogLevel'++== Symbols+* @cdio_default_log_handler@        (removed; always handled through 'Foreign.Libcdio.Logging.readLog')+* @cdio_assert@                     -> @'Foreign.Libcdio.Logging.putLog' 'Forign.Libcdio.Logging.LogAssert'@+* @cdio_debug@                      -> @'Foreign.Libcdio.Logging.putLog' 'Forign.Libcdio.Logging.LogDebug'@+* @cdio_error@                      -> @'Foreign.Libcdio.Logging.putLog' 'Forign.Libcdio.Logging.LogError'@+* @cdio_info@                       -> @'Foreign.Libcdio.Logging.putLog' 'Forign.Libcdio.Logging.LogInfo'@+* @cdio_log@                        -> 'Foreign.Libcdio.Logging.putLog'+* @cdio_log_set_handler@            (removed; always handled through 'Foreign.Libcdio.Logging.readLog')+* @cdio_loglevel_default@           -> 'Foreign.Libcdio.Logging.logCutoff' and 'Foreign.Libcdio.Logging.setLogCutoff'+* @cdio_warn@                       -> @'Foreign.Libcdio.Logging.putLog' 'Forign.Libcdio.Logging.LogWarn'@+++= "Sound.Libcdio.Logging"+Most functions have been re-contextulized as being provided through a+'Sound.Libcdio.Logging.LibcdioLogger' instance, but the interface is otherwise+unchanged.+-}+module Foreign.Libcdio.Logging+    ( -- * Types+      LogEntry ( .. )+    , LogLevel ( .. )+      -- * Message interaction+    , putLog+    , readLog+    , clearLog+      -- * Management+    , logCutoff+    , setLogCutoff+    , setupLogger+    ) where+++import qualified Control.Monad as N++import qualified Data.Maybe as Y++import qualified Foreign.C.String as C+import qualified Foreign.C.Types as C+import qualified Foreign.Ptr as C++import qualified Foreign.Marshal.Array as M+import qualified Foreign.Marshal.Utils as M+import qualified Foreign.Storable as S++import Foreign.Libcdio.Marshal+import Foreign.Libcdio.Types.Enums+import Foreign.Libcdio.Types.Offsets+++-- | Check the current minimum severity which will be recorded in the logs.+--+-- See 'setLogCutoff'.+logCutoff :: IO LogLevel+logCutoff = toEnum . fromIntegral <$> logCutoff'++foreign import ccall safe "cdio/compat/logging.h get_cdio_log_level"+  logCutoff' :: IO CLogLevel+++-- | Set the minimum severity required for a message to be recorded in the+-- logs.+--+-- See 'logCutoff'.+setLogCutoff :: LogLevel -> IO ()+setLogCutoff = setLogCutoff' . fromIntegral . fromEnum++foreign import ccall safe "cdio/compat/logging.h set_cdio_log_level"+  setLogCutoff' :: CLogLevel -> IO ()+++-- | An unstructured message emitted from the library to let the user know+-- what's going on behind the scenes.+data LogEntry = LogEntry+    { logLevel :: LogLevel+        -- ^ How critical it is that the user receive this particular message.+    , logMessage :: String+        -- ^ The text of the message itself.+    }+  deriving ( Eq, Show, Read )+instance S.Storable LogEntry where+    sizeOf _    = leSizeOf+    alignment _ = leAlign+    peek c = do+        l <- S.peekByteOff c leLevel :: IO CLogLevel+        m' <- S.peekByteOff c leMessage+        m <- if m' == C.nullPtr+            then return ""+            else C.peekCString m'+        return $ LogEntry+            { logLevel = toEnum $ fromIntegral l+            , logMessage = m+            }+    poke c hs = do+        S.pokeByteOff c leLevel (fromIntegral . fromEnum $ logLevel hs :: CLogLevel)+        m <- C.newCString $ logMessage hs+        S.pokeByteOff c leMessage m+        S.pokeByteOff c lePrevious C.nullPtr+++-- | Retrieve all messages currently in the log for further processing.  Note+-- that this retains the contents of the log for future calls; to remove them,+-- a separate call to 'clearLog' must be made.+--+-- >>> setupLogger+-- >>> putLog $ LogEntry LogWarn "Testing log reading"+-- >>> readLog+-- [LogEntry LogWarn "Testing log reading"]+-- >>> readLog+-- [LogEntry LogWarn "Testing log reading"]+-- >>> clearLog+-- >>> readLog+-- []+readLog :: IO [LogEntry]+readLog = do+    es' <- readLog'+    es <- Y.fromMaybe [] <$> M.maybePeek (M.peekArray0 C.nullPtr) es'+    N.forM es S.peek++foreign import ccall safe "cdio/compat/logging.h read_cdio_log"+  readLog' :: IO (C.Ptr (C.Ptr LogEntry))+++-- | Empty all messages currently in the log.  There is no way to selectively+-- remove only some messages; if that is desired, call 'readLog' first:+--+-- >>> setupLogger+-- >>> msgs <- readLog+-- >>> clearLog+-- >>> mapM_ putLog $ filter p msgs+foreign import ccall safe "cdio/compat/logging.h free_cdio_log"+  clearLog :: IO ()+++-- | Append a message to the logs.+putLog :: LogEntry -> IO ()+putLog e = C.withCString (logMessage e) $ putLog' (fromIntegral . fromEnum $ logLevel e)++foreign import ccall safe "cdio/compat/logging.h cdio_log"+  putLog' :: CLogLevel -> C.CString -> IO ()
+ src/Foreign/Libcdio/Marshal.hs view
@@ -0,0 +1,295 @@+{-# LANGUAGE ForeignFunctionInterface #-}++{-|+Description:    Utility functions for the libcdio FFI.++Copyright:      (c) 2018-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      provisional+Portability:    portable+-}+module Foreign.Libcdio.Marshal+    ( -- * Types+      -- ** Cdio+      Cdio+    , withCdio+    , withCdio_+    , withCdioPtr+    , peekCdio+      -- ** CdText+    , CdText+    , withCdText+    , withCdText'+    , withCdText_+    , hasCdText+    , cdTextDataInit+      -- * Management+    , setupLogger+    , genBitArray+      -- * Marshalling+      -- ** Bool+    , errorOrBool+    , bool3+      -- ** Int+    , errorOrInt+    , maybeError+      -- ** Enum a+    , joinEnumFlags+    , modEnumFlags+      -- ** ByteString+    , peekByteStringLen+      -- ** String+    , allocaStringArray+      -- ** FString+    , peekFString+    , peekFStringArray+    ) where+++import qualified Data.Array.BitArray as A+import qualified Data.Bits as B+import qualified Data.ByteString as BS+import qualified Data.Ix as I+import qualified Data.Maybe as Y++import qualified Foreign.C.String as C+import qualified Foreign.C.Types as C+import qualified Foreign.ForeignPtr as C+import qualified Foreign.Ptr as C++import qualified Foreign.Marshal.Alloc as M+import qualified Foreign.Marshal.Array as M+import qualified Foreign.Marshal.Utils as M++import qualified Foreign.Storable as S+++-- | Helper to convert device capabilities to a bitfield.+genBitArray :: (Bounded a, I.Ix a) => [a] -> A.BitArray a+genBitArray [] = A.false (minBound, maxBound)+genBitArray cs = A.array (minBound, maxBound) $ map (\i -> (i, True)) cs+++-- | A particular disc reading/writing device, along with the data contained+-- on the loaded disc.  Note well that this is always a mutable object, and is+-- not thread-safe; moreover, any function this is passed to may wind up+-- silently modifying the data.+data Cdio = Cdio (Maybe (C.ForeignPtr Cdio)) (Maybe (C.ForeignPtr CdText))++-- | Free all memory used by a reference to a device.+foreign import ccall "cdio/compat/device.h &cdio_destroy"+  cdioDestroy :: C.FinalizerPtr Cdio++-- | Convert the (foreign) reference to a device to something the FFI can use.+withCdio :: Cdio -> (C.Ptr Cdio -> IO b) -> IO (Maybe b)+withCdio (Cdio Nothing _) = const $ return Nothing+withCdio (Cdio (Just c) _) = fmap Just . C.withForeignPtr c++withCdio_ :: Cdio -> (C.Ptr Cdio -> IO ()) -> IO ()+withCdio_ c f = withCdio c f >> mempty++-- | Marshall a device reference with an extra layer of indirection.+withCdioPtr :: Cdio -> (C.Ptr (C.Ptr Cdio) -> IO b) -> IO (Maybe b)+withCdioPtr (Cdio Nothing _) _ = return Nothing+withCdioPtr (Cdio (Just c) _) f = M.alloca $ \p ->+    C.withForeignPtr c $ \c' -> do+        S.poke p c'+        Just <$> f p++-- | Un-marshall a newly-allocated pointer to a drive.+peekCdio :: C.Ptr Cdio -> IO Cdio+peekCdio c = do+    -- All public methods of opening 'Cdio' objects already have this earlier to+    -- catch any logs from opening the disc, but add it again just to be safe.+    setupLogger+    x <- M.maybePeek getCdText' c+    x' <- case x of+        Just x' -> Just <$> C.newForeignPtr_ x'+        Nothing -> return Nothing+    p' <- C.newForeignPtr cdioDestroy c+    return $ Cdio (Just p') x'++foreign import ccall "cdio/compat/disc.h cdio_get_cdtext"+  getCdText' :: C.Ptr Cdio -> IO (C.Ptr CdText)+++-- | Initialize the log-management backend to use the mechanisms provided by+-- this library instead of just printing to standard output.  While this will+-- usually be taken care of automatically, it may still be necessary to call+-- this explicitly if messages are being recorded before any disc session is+-- opened.+foreign import ccall "cdio/compat/logging.h setup_cdio_logger"+  setupLogger :: IO ()+++-- | The metadata describing the contents of a disc.+-- +-- This type is not exported, and is mainly here to catch copy-paste errors on+-- my end.+data CdText++-- | Free all memory used by a reference to a device.+foreign import ccall "cdio/compat/cdtext.h &cdtext_destroy"+  cdTextDestroy :: C.FinalizerPtr CdText++-- | Convert the (foreign) reference to a device to something the FFI can use.+withCdText :: Cdio -> (C.Ptr CdText -> IO b) -> IO (Maybe b)+withCdText (Cdio _ Nothing) = const $ return Nothing+withCdText (Cdio _ (Just x)) = fmap Just <$> C.withForeignPtr x++withCdText' :: b -> Cdio -> (C.Ptr CdText -> IO b) -> IO b+withCdText' b c = fmap (Y.fromMaybe b) . withCdText c++withCdText_ :: Cdio -> (C.Ptr CdText -> IO ()) -> IO ()+withCdText_ c f = withCdText c f >> mempty++-- | Whether the various functions in "Foreign.Libcdio.CdText" will have any+-- effect, or simply return 'mempty'.+hasCdText :: Cdio -> Bool+hasCdText (Cdio _ x) = Y.isJust x+++-- | Read binary CD-TEXT data into a structured datatype.+--+-- Note that binary CdText dumps will frequently include four bytes at the+-- beginning indicating the size of the file; this implementation expects that+-- those bytes /are not/ included.  If your dump does include them, @'BS.drop'+-- 4@ before passing the 'BS.ByteString' to this function.+-- +-- /Before libcdio 0.94:  Always returns 'Nothing'/+cdTextDataInit :: BS.ByteString -> IO (Maybe Cdio)+cdTextDataInit bs = do+    setupLogger+    x <- cdTextInit' >>= C.newForeignPtr cdTextDestroy+    b <- BS.useAsCStringLen bs $ \(bs', l) -> withCdText (Cdio Nothing $ Just x) $ \x' ->+        cdTextDataInit' x' bs' $ fromIntegral l+    return $ if b == Just 0+        then Just . Cdio Nothing $ Just x+        else Nothing++-- | Create a new empty CDTEXT object.+foreign import ccall "cdio/compat/cdtext.h cdtext_init"+  cdTextInit' :: IO (C.Ptr CdText)++foreign import ccall safe "cdio/compat/cdtext.h cdtext_data_init_safe"+  cdTextDataInit' :: C.Ptr CdText -> C.Ptr C.CChar -> C.CSize -> IO C.CInt+++-- | Free the memory indicated by a C-style pointer, avoiding a segfault if+-- passed a @NULL@ pointer.+cdioFree :: C.Ptr a -> IO ()+cdioFree = mkFree cdioFree'++foreign import ccall "cdio/memory.h &cdio_free"+  cdioFree' :: C.FunPtr (C.Ptr a -> IO ())++-- | Retrieve the actual function with a @free@-style signature.+foreign import ccall "dynamic"+  mkFree :: C.FunPtr (C.Ptr a -> IO ()) -> C.Ptr a -> IO ()+++-- | Convert a return code indicating an error or success/failure into a+-- type-safe representation.+errorOrBool :: (Integral a, Enum b) => a -> Either b Bool+errorOrBool = fmap M.toBool . errorOrInt+++-- | Convert the custom indeterminate boolean to more ideomatic Haskell.+bool3 :: C.CInt -> Maybe Bool+bool3 0 = Just False+bool3 1 = Just True+bool3 _ = Nothing+++-- | Convert a return code indicating an error or a numeric value into a+-- type-safe representation.+errorOrInt :: (Integral a, Enum b) => a -> Either b a+errorOrInt i+    | i < 0 = Left . toEnum $ fromIntegral i+    | otherwise = Right i++-- | Filter out an error value expressed as part of a C-style enum.+maybeError :: Eq a => [a] -> a -> Maybe a+maybeError es i+    | elem i es = Nothing+    | otherwise = Just i+++-- | Unmarshall a block of binary data from a C-style array with an explicit+-- length.  Returns 'Nothing' if the returned size is negative.+peekByteStringLen+    :: (Integral b, S.Storable b)+    => C.Ptr (C.Ptr a)+    -> C.Ptr b+    -> IO (Maybe BS.ByteString)+peekByteStringLen p l = do+    p' <- S.peek p+    l' <- S.peek l+    if l' < 0 || p' == C.nullPtr+         then return Nothing+         else Just <$> BS.packCStringLen (C.castPtr p', fromIntegral l')+++-- | Combine an ordered value and an array of bit flags into a single value.+joinEnumFlags+    :: (Enum a, Enum b, Bounded b, I.Ix b, Integral c, B.Bits c)+    => a+    -> A.BitArray b+    -> c+joinEnumFlags a bs = fromIntegral (fromEnum a) + bs'+  where bs' = foldr set 0x0 . zip [fst bnds .. snd bnds] $ drop fstBit [0..]+        bnds = (minBound, maxBound)+        set (e, i) b = case bs A.!? e of+            Just True -> B.setBit b i+            _ -> b+        fstBit = B.countTrailingZeros . fromEnum $ fst bnds++-- | Split a number into an ordered value (below the 'minBound') and an array+-- of bit flags.+modEnumFlags+    :: (Integral a, B.Bits a, Enum b, Bounded b, Enum c, Bounded c, I.Ix c)+    => a+    -> (Maybe b, A.BitArray c)+modEnumFlags i = (toEnumMaybe $ fromIntegral fs, bs)+  where fs = mod i . fromIntegral . fromEnum $ fst bnds+        bs = A.listArray bnds . map (B.testBit i) . drop fstBit $ take lstBit [0..]+        bnds = (minBound, maxBound)+        fstBit = B.countTrailingZeros . fromEnum $ fst bnds+        lstBit = B.countTrailingZeros . fromEnum $ snd bnds+++-- | Will not work if the 'Enum' instance has been redefined to not be+-- sequential.+-- +-- From <https://stackoverflow.com/a/2744712/7634517>+toEnumMaybe :: (Enum a, Bounded a) => Int -> Maybe a+toEnumMaybe i = if i < fromEnum n || i > fromEnum x+    then Nothing+    else Just e+  where e = toEnum i+        n = asTypeOf minBound e+        x = asTypeOf maxBound e+++-- | Temporarily copy a list of 'String's to pass them to a C function as a+-- @NULL@-terminated array, cleaning up the allocated memory afterward.+allocaStringArray :: [String] -> (C.Ptr C.CString -> IO a) -> IO a+allocaStringArray [] f = f C.nullPtr+allocaStringArray ss f = M.withMany C.withCString ss $ \ss' -> M.withArray0 C.nullPtr ss' f+++-- | Retrieve the value of a C-style string which needs to be manually freed.+peekFString :: C.CString -> IO String+peekFString c = do+    s <- C.peekCString c+    cdioFree c+    return s++-- | Retrieve the values of an array of C-style strings which all need to be+-- manually freed.+peekFStringArray :: C.Ptr C.CString -> IO [String]+peekFStringArray p = do+    ss <- M.maybePeek (M.peekArray0 C.nullPtr) p+    maybe (return []) (mapM peekFString) ss
+ src/Foreign/Libcdio/Read.hs view
@@ -0,0 +1,253 @@+{-# LANGUAGE ForeignFunctionInterface #-}++{-|+Description:    Functions providing a means to retrieve the data stored on a disc.++Copyright:      (c) 2018-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      stable+Portability:    non-portable (requires libcdio)++After obtaining landmarks through "Foreign.Libcdio.Disc" (and likely+"Foreign.Libcdio.Track"), this module provides the functions required to+actually retrive the primary data from the disc.  Some knowledge of its+physical layout is required, which may be determined through+'Foreign.Libcdio.Track.trackFormat'.+++= @read.h@++== Types+* @cdio_read_mode_t@                -> 'ReadMode'++    - @CDIO_READ_MODE_M1F1@         -> 'Mode1Form1'+    - @CDIO_READ_MODE_M1F2@         -> 'Mode1Form2'+    - @CDIO_READ_MODE_M2F1@         -> 'Mode2Form1'+    - @CDIO_READ_MODE_M2F2@         -> 'Mode2Form2'++== Symbols+* @cdio_lseek@                      -> 'seek'+* @cdio_read@                       -> 'readBytes'+* @cdio_read_audio_sector@          -> 'readAudioSector'+* @cdio_read_audio_sectors@         -> 'readAudioSectors'+* @cdio_read_data_sectors@          -> 'readDataSectors'+* @cdio_read_mode1_sector@          -> 'readDataModeSector'+* @cdio_read_mode1_sectors@         -> 'readDataModeSectors'+* @cdio_read_mode2_sector@          -> 'readXaModeSector'+* @cdio_read_mode2_sectors@         -> 'readXaModeSectors'+* @cdio_read_sector@                -> 'readSector'+* @cdio_read_sectors@               -> 'readSectors'+++= "Sound.Libcdio.Read.Data"+Each of the single-sector @read*@ aliases have been removed for consistency.++* 'ReadMode'                        (removed; unnecessary low-level detail)++* 'readAudioSectors'                -> 'Sound.Libcdio.Read.Data.readAudio'+* 'readBytes'                       -> 'Sound.Libcdio.Read.Data.readRaw' (note that the count is now the number of /sectors/ rather than bytes)+* 'readDataModeSectors'             -> 'Sound.Libcdio.Read.Data.readData'+* 'readDataSectors'                 (removed; unnecessary low-level detail)+* 'readXaModeSectors'               -> 'Sound.Libcdio.Read.Data.readXa'+-}+module Foreign.Libcdio.Read+    ( -- * Types+      ReadMode ( .. )+    , Whence ( .. )+      -- * Functions+      -- ** Raw+    , seek+    , readBytes+      -- ** Sector+    , readSector, readSectors+    , readAudioSector, readAudioSectors+    , readDataSectors+    , readDataModeSector, readDataModeSectors+    , readXaModeSector, readXaModeSectors+    ) where+++import qualified Control.Monad as N++import qualified Data.ByteString as BS+import qualified Data.Maybe as Y++import qualified Foreign.C.Types as C+import qualified Foreign.Ptr as C+import qualified Foreign.Storable as S++import qualified Foreign.Marshal.Alloc as M+import qualified Foreign.Marshal.Utils as M++import Foreign.Libcdio.Device+import Foreign.Libcdio.Marshal+import Foreign.Libcdio.Types.Enums+import Foreign.Libcdio.Types.Internal+++-- | Reposition the read pointer in the 'Cdio' session for a future call to+-- 'readBytes'.+seek :: Cdio -> Int -> Whence -> IO (Either DriverReturnCode Word)+seek c o w = do+    o' <- withCdio c $ \c' -> seek' c' (fromIntegral o) (fromIntegral $ fromEnum w)+    return . fmap fromIntegral $ maybe (Left Uninitialized) errorOrInt o'++foreign import ccall safe "cdio/compat/read.h cdio_lseek"+  seek' :: C.Ptr Cdio -> C.CLong -> C.CInt -> IO C.CLong+++collapseReturnCode :: Maybe DriverReturnCode -> a -> Either DriverReturnCode a+collapseReturnCode (Just Success) a = Right a+collapseReturnCode (Just e) _ = Left e+collapseReturnCode Nothing _ = Left Uninitialized+++withCdioByteString+    :: Cdio+    -> (C.Ptr Cdio -> C.Ptr (C.Ptr ()) -> C.Ptr C.CUInt -> IO a)+        -- ^ A foreign function which will read a given number of bytes into a+        -- referenced buffer, potentially returning a numeric error code.  Note+        -- that this marshalling /will/ try to free the inner pointer of the+        -- second argument, so the function should @malloc@ a temporary value+        -- accordingly.+    -> IO (Maybe a, Maybe BS.ByteString)+withCdioByteString c g = M.alloca $ \bs' -> M.alloca $ \s' -> do+    a <- withCdio c $ \c' -> g c' bs' s'+    bs <- peekByteStringLen bs' s'+    p <- S.peek bs'+    N.unless (p == C.nullPtr) $ M.free p+    return (a, bs)++-- | Marshalling function for handling read instructions operating on a given+-- number of whole-sector blocks.+readCdioSectors+    :: Cdio+    -> (C.Ptr Cdio -> C.Ptr (C.Ptr ()) -> C.Ptr C.CUInt -> IO C.CInt)+    -> IO (Either DriverReturnCode BS.ByteString)+readCdioSectors c f = do+    (r, bs) <- withCdioByteString c f+    return $ collapseReturnCode (toEnum . fromIntegral <$> r) (Y.fromMaybe BS.empty bs)+++-- | Read a given number of bytes from the disc.  With data of a known+-- structure, use 'readSectors' or similar instead, which /don't/ include the+-- headers and footers described in "Foreign.Libcdio.Sector".+readBytes :: Cdio -> Word -> IO (Maybe BS.ByteString)+readBytes c l = fmap snd <$> withCdioByteString c $ \c' bs' s' ->+    readBytes' c' bs' s' $ fromIntegral l++foreign import ccall safe "cdio/compat/read.h read_bytes"+  readBytes' :: C.Ptr Cdio -> C.Ptr (C.Ptr ()) -> C.Ptr C.CUInt -> C.CULong -> IO ()+++-- | Read the data contained in a specific sector from the disc.+readSector :: Cdio -> Lsn -> ReadMode -> IO (Either DriverReturnCode BS.ByteString)+readSector c o m = readCdioSectors c $ \c' bs' s' ->+    readSector' c' bs' s' o (fromIntegral $ fromEnum m)++foreign import ccall safe "cdio/compat/read.h read_sector"+  readSector' :: C.Ptr Cdio -> C.Ptr (C.Ptr ()) -> C.Ptr C.CUInt -> Lsn -> C.CInt -> IO C.CInt++-- | Read the data contained in the given number of sectors from the disc,+-- beginning with the specified sector.+readSectors :: Cdio -> Lsn -> ReadMode -> Word -> IO (Either DriverReturnCode BS.ByteString)+readSectors c o m l = readCdioSectors c $ \c' bs' s' ->+    readSectors' c' bs' s' o (fromIntegral $ fromEnum m) (fromIntegral l)++foreign import ccall safe "cdio/compat/read.h read_sectors"+  readSectors' :: C.Ptr Cdio -> C.Ptr (C.Ptr ()) -> C.Ptr C.CUInt -> Lsn -> C.CInt -> C.CUInt -> IO C.CInt+++-- | Similar to calling 'readSector' with 'AudioMode', depending on the driver+-- implementation.+readAudioSector :: Cdio -> Lsn -> IO (Either DriverReturnCode BS.ByteString)+readAudioSector c o = readCdioSectors c $ \c' bs' s' ->+    readAudioSector' c' bs' s' o++foreign import ccall safe "cdio/compat/read.h read_audio_sector"+  readAudioSector' :: C.Ptr Cdio -> C.Ptr (C.Ptr ()) -> C.Ptr C.CUInt -> Lsn -> IO C.CInt++-- | Similar to calling 'readSectors' with 'AudioMode', depending on the driver+-- implementation.+readAudioSectors :: Cdio -> Lsn -> Word -> IO (Either DriverReturnCode BS.ByteString)+readAudioSectors c o l = readCdioSectors c $ \c' bs' s' ->+    readAudioSectors' c' bs' s' o $ fromIntegral l++foreign import ccall safe "cdio/compat/read.h read_audio_sectors"+  readAudioSectors' :: C.Ptr Cdio -> C.Ptr (C.Ptr ()) -> C.Ptr C.CUInt -> Lsn -> C.CUInt -> IO C.CInt+++-- | Read the raw data from a given number of sectors on the disc, beginning+-- with the specified sector.+readDataSectors+    :: Cdio+    -> Lsn+    -> Word+        -- ^ Sector size (e.g. 'Foreign.Libcdio.Sector.dataSize' or+        -- 'Foreign.Libcdio.Sector.dataSizeRawXa').+    -> Word+        -- ^ Number of sectors to read.+    -> IO (Either DriverReturnCode BS.ByteString)+readDataSectors c o z l = readCdioSectors c $ \c' bs' s' ->+    readDataSectors' c' bs' s' o (fromIntegral z) (fromIntegral l)++foreign import ccall safe "cdio/compat/read.h read_data_sectors"+  readDataSectors' :: C.Ptr Cdio -> C.Ptr (C.Ptr ()) -> C.Ptr C.CUInt -> Lsn -> C.CUShort -> C.CUInt -> IO C.CInt+++-- | Similar to calling 'readSector', depending on the driver implementation.+readDataModeSector+    :: Cdio+    -> Lsn+    -> Bool+        -- ^ If 'True' Form 2, otherwise Form 1 (see "Foreign.Libcdio.Sector").+    -> IO (Either DriverReturnCode BS.ByteString)+readDataModeSector c o m = readCdioSectors c $ \c' bs' s' ->+    readDataModeSector' c' bs' s' o $ M.fromBool m++foreign import ccall safe "cdio/compat/read.h read_mode1_sector"+  readDataModeSector' :: C.Ptr Cdio -> C.Ptr (C.Ptr ()) -> C.Ptr C.CUInt -> Lsn -> C.CUChar -> IO C.CInt++-- | Similar to calling 'readSectors', depending on the driver implementation.+readDataModeSectors+    :: Cdio+    -> Lsn+    -> Bool+        -- ^ If 'True' Form 2, otherwise Form 1 (see "Foreign.Libcdio.Sector").+    -> Word+    -> IO (Either DriverReturnCode BS.ByteString)+readDataModeSectors c o m l = readCdioSectors c $ \c' bs' s' ->+    readDataModeSectors' c' bs' s' o (M.fromBool m) (fromIntegral l)++foreign import ccall safe "cdio/compat/read.h read_mode1_sectors"+  readDataModeSectors' :: C.Ptr Cdio -> C.Ptr (C.Ptr ()) -> C.Ptr C.CUInt -> Lsn -> C.CUChar -> C.CUInt -> IO C.CInt+++-- | Similar to calling 'readSector', depending on the driver implementation.+readXaModeSector+    :: Cdio+    -> Lsn+    -> Bool+        -- ^ If 'True' Form 2, otherwise Form 1 (see "Foreign.Libcdio.Sector").+    -> IO (Either DriverReturnCode BS.ByteString)+readXaModeSector c o m = readCdioSectors c $ \c' bs' s' ->+    readXaModeSector' c' bs' s' o $ M.fromBool m++foreign import ccall safe "cdio/compat/read.h read_mode2_sector"+  readXaModeSector' :: C.Ptr Cdio -> C.Ptr (C.Ptr ()) -> C.Ptr C.CUInt -> Lsn -> C.CUChar -> IO C.CInt++-- | Similar to calling 'readSectors', depending on the driver implementation.+readXaModeSectors+    :: Cdio+    -> Lsn+    -> Bool+        -- ^ If 'True' Form 2, otherwise Form 1 (see "Foreign.Libcdio.Sector").+    -> Word+    -> IO (Either DriverReturnCode BS.ByteString)+readXaModeSectors c o m l = readCdioSectors c $ \c' bs' s' ->+    readXaModeSectors' c' bs' s' o (M.fromBool m) (fromIntegral l)++foreign import ccall safe "cdio/compat/read.h read_mode2_sectors"+  readXaModeSectors' :: C.Ptr Cdio -> C.Ptr (C.Ptr ()) -> C.Ptr C.CUInt -> Lsn -> C.CUChar -> C.CUInt -> IO C.CInt
+ src/Foreign/Libcdio/Sector.hs view
@@ -0,0 +1,674 @@+{-# LANGUAGE ForeignFunctionInterface #-}++{-|+Description:    Values related to on-disc data layout: track boundaries, sector sizes, address formats, etc.++Copyright:      (c) 2018-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      stable+Portability:    non-portable (requires libcdio)++The bulk of this module deals with the sizes of various parts of disc sectors,+and so a brief description of each is likely helpful; for more information, see+the libcdio user guide, or any of the other various documentation that people+have written.  Depending on the accuracy required, multiple methods of encoding+data onto discs were developed enabling different degrees of error detection+and recovery.  For ease of implementation, these check regions are spaced+evenly throughout the data, effectively dividing it into blocks of 'sectorSize'+bytes.  The inner structure of each block is thus:++= Sector layout++== Audio++As audio CDs are intended to be listened to by human ears, often in noisy+environments, byte-perfect fidelity was deemed unnecessary; data fills the+entire sector without leaving room for checksums or synchronization points.+This structure is more technically described as "CD-DA" (Digital Audio).++@+|- 'sectorSize' -|+@++== Data (Mode 1)++The original structure described in the /Yellow Book/ standard.  Mode 1, Form 1+is notably the layout used for CD-ROMs.  It would be most correct to describe+these as "Mode 1" and "Mode 2" with no reference to form, but the libcdio+documentation has adopted the practice below as a parallel to the XA names.++=== Mode 1, Form 1++@+|------------------------------------ 'sectorSize' -------------------------------------|+ 'syncSize' + 'headerSize' + __'dataSize'__ + 'errorDetectionSize' + 'padSize' + 'errorCorrectionSize'+           |------------------------------- 'syncedSize' -------------------------------|+                                   |-------------------- 'tailSize' --------------------|+@++=== Mode 1, Form 2++@+|------------ 'sectorSize' -----------|+ 'syncSize' + 'headerSize' + __'dataSizeRaw'__+           |------ 'syncedSize' ------|+@+++== XA (Mode 2)++Developed as a later extension to the Mode 1, Form 2 (technically just "Mode+2") standard above to allow different data to be interleaved.++=== Mode 2, Form 1++@+|--------------------------------------- 'sectorSize' ----------------------------------------|+ 'syncSize' + 'headerSize' + 'subheaderSize' + __'dataSize'__ + 'errorDetectionSize' + 'errorCorrectionSize'+|---------- 'syncHeaderSizeXa' ---------|            |-------------- 'tailSizeXa' --------------|+           |------ 'headerSizeXa' ------|+           |---------------------------------- 'syncedSize' ----------------------------------|+                        |--------------------------- 'dataSizeRaw' ---------------------------|+@++=== Mode 2, Form 2++@+|--------------------------- 'sectorSize' --------------------------|+ 'syncSize' + 'headerSize' + 'subheaderSize' + __'dataSizeRawXa'__ + 'padSizeXa'+|---------- 'syncHeaderSizeXa' ---------|+           |------ 'headerSizeXa' ------|+           |--------------------- 'syncedSize' ---------------------|+                        |-------------- 'dataSizeRaw' --------------|+                        |----- 'taggedDataSizeRaw' -----|+@+++= @sector.h@++== Defines+* @CDIO_CD_CHUNK_SIZE@              -> 'chunkSize'+* @CDIO_CD_ECC_SIZE@                -> 'errorCorrectionSize'+* @CDIO_CD_EDC_SIZE@                -> 'errorDetectionSize'+* @CDIO_CD_FRAMESIZE@               -> 'dataSize'+* @CDIO_CD_FRAMESIZE_RAW@           -> 'sectorSize'+* @CDIO_CD_FRAMESIZE_RAW0@          -> 'dataSizeRaw'+* @CDIO_CD_FRAMESIZE_RAW1@          -> 'syncedSize'+* @CDIO_CD_FRAMESIZE_RAWER@         -> 'sectorSizeMax'+* @CDIO_CD_FRAMESIZE_SUB@           -> 'framesizeSub'+* @CDIO_CD_FRAMES_PER_MIN@          -> 'framesPerMin'+* @CDIO_CD_FRAMES_PER_SEC@          -> 'framesPerSec'+* @CDIO_CD_HEADER_SIZE@             -> 'headerSize'+* @CDIO_CD_M1F1_ZERO_SIZE@          -> 'padSize'+* @CDIO_CD_MAX_LSN@                 (removed; identical to @'maxBound' :: 'Lsn'@)+* @CDIO_CD_MAX_SESSIONS@            -> 'maxSessions'+* @CDIO_CD_MINS@                    -> 'cdMins'+* @CDIO_CD_MIN_LSN@                 (removed; identical to @'minBound' :: 'Lsn'@)+* @CDIO_CD_MIN_SESSION_NO@          -> 'minSessionNo'+* @CDIO_CD_NUM_OF_CHUNKS@           -> 'chunksPerSector'+* @CDIO_CD_SECS_PER_MIN@            -> 'secsPerMin'+* @CDIO_CD_SUBHEADER_SIZE@          -> 'subheaderSize'+* @CDIO_CD_SYNC_SIZE@               -> 'syncSize'+* @CDIO_CD_XA_HEADER@               -> 'headerSizeXa'+* @CDIO_CD_XA_SYNC_HEADER@          -> 'syncHeaderSizeXa'+* @CDIO_CD_XA_TAIL@                 -> 'tailSizeXa'+* @CDIO_POSTGAP_SECTORS@            -> 'postgapSectors'+* @CDIO_PREGAP_SECTORS@             -> 'pregapSectors'+* @M2F2_SECTOR_SIZE@                -> 'dataSizeRawXa'+* @M2RAW_SECTOR_SIZE@               (removed; identical to 'dataSizeRaw')+* @M2SUB_SECTOR_SIZE@               -> 'taggedDataSizeRaw'+* @msf_t_SIZEOF@                    (removed; structural constant not required for Haskell)++== Types+* @cdio_cd_minutes_sectors@         (removed; most values were simple calculations on @CDIO_CD_FRAMES_PER_MIN@, which can be done manually)++    - @CDIO_CD_MAX_SECTORS@         -> 'maxSectors'++* @cdio_subchannel@                 -> 'SubchannelData'++    - @CDIO_SUBCHANNEL_SUBQ_DATA@   -> 'QChannelData'++* @flag_t@                          -> 'Flags' and 'Flag'++    - @SCMS@                        -> 'SerialCopyManagement'++== Symbols+* @CDIO_SECTOR_SYNC_HEADER@         -> 'sectorSyncHeader'+* @cdio_lba_to_lsn@                 -> 'lbaToLsn'+* @cdio_lba_to_msf@                 -> 'lbaToMsf'+* @cdio_lba_to_msf_str@             -> 'lbaToMsfStr'+* @cdio_lsn_to_lba@                 -> 'lsnToLba'+* @cdio_lsn_to_msf@                 -> 'lsnToMsf'+* @cdio_msf_to_lba@                 -> 'msfToLba'+* @cdio_msf_to_lsn@                 -> 'msfToLsn'+* @cdio_msf_to_str@                 -> 'msfToStr'+++= "Sound.Libcdio.Read.Data"++* 'Flag'                            (currently removed; unused in the translated portion of the interface)+* 'Flags'                           (currently removed; unused in the translated portion of the interface)+* 'Lba'                             (removed; only one address format is needed, and 'Lsn' is more widespread)+* 'Msf'                             (removed; only one address format is needed, and timestamps can be confusing for non-audio data)+* 'SubchannelData'                  (currently removed; unused in the translated portion of the interface)++* 'cdMins'                          -> 'Sound.Libcdio.Read.Data.maxCdMinutes'+* 'chunkSize'                       (removed; unnecessary low-level detail)+* 'chunksPerSector'                 (removed; unnecessary low-level detail)+* 'framesizeSub'                    (removed; unnecessary low-level detail)+* 'lbaToLsn'                        (removed; only 'Lsn' is used in @Sound@)+* 'lbaToMsf'                        (removed; only 'Lsn' is used in @Sound@)+* 'lbaToMsfStr'                     -> 'Sound.Libcdio.Read.Data.audioTimestamp'+* 'lsnToLba'                        (removed; only 'Lsn' is used in @Sound@)+* 'lsnToMsf'                        (removed; only 'Lsn' is used in @Sound@)+* 'maxSectors'                      -> 'Sound.Libcdio.Read.Data.maxSectors'+* 'maxSessions'                     (removed; explicit session handling not yet implemented by libcdio)+* 'minSessionNo'                    (removed; explicit session handling not yet implemented by libcdio)+* 'msfToLba'                        (removed; only 'Lsn' is used in @Sound@)+* 'msfToLsn'                        (removed; only 'Lsn' is used in @Sound@)+* 'msfToStr'                        (removed; only 'Lsn' is used in @Sound@)+* 'postgapSectors'                  -> 'Sound.Libcdio.Read.Data.defaultPostgapSectors'+* 'pregapSectors'                   -> 'Sound.Libcdio.Read.Data.defaultPregapSectors'+* 'secsPerMin'                      (removed; real-world constant)+* 'sectorSyncHeader'                (removed; unnecessary low-level detail)+* 'framesPerMin'                    (removed; simple arithmatic of 'framesPerSec'++All size constants (e.g. 'sectorSize') likewise removed as unnecessary.+-}+module Foreign.Libcdio.Sector+    ( -- * Types+      SubchannelData ( .. )+    , Flags+    , Flag ( .. )+    , Lba+    , Lsn+    , Msf ( .. )+      -- * Conversions+    , lbaToLsn+    , lsnToLba+    , lbaToMsf+    , msfToLba+    , lsnToMsf+    , msfToLsn+    , lbaToMsfStr+    , msfToStr+      -- * Basic counts+    , chunkSize+    , minSessionNo, maxSessions+    , pregapSectors, postgapSectors+    , maxSectors+    , framesizeSub+      -- ** Units of time+    , chunksPerSector+    , framesPerSec+    , secsPerMin+    , framesPerMin+    , cdMins+      -- * Sector blocks+    , sectorSize+    , syncedSize+    , sectorSizeMax+      -- ** Headers+    , sectorSyncHeader+    , syncSize+    , headerSize+    , subheaderSize+    , headerSizeXa+    , syncHeaderSizeXa+      -- ** Data+    , dataSize+    , dataSizeRaw+    , dataSizeRawXa+    , taggedDataSizeRaw+      -- ** Error correction+    , errorDetectionSize+    , errorCorrectionSize+    , padSize+    , padSizeXa+    , tailSize+    , tailSizeXa+    ) where+++import qualified Data.Array.BitArray as A+import qualified Data.ByteString as BS++import qualified Foreign.C.String as C+import qualified Foreign.C.Types as C+import qualified Foreign.Ptr as C++import qualified Foreign.Marshal.Alloc as M+import qualified Foreign.Marshal.Utils as M+import qualified Foreign.Storable as S++import qualified System.IO.Unsafe as IO.Unsafe+++import Foreign.Libcdio.Marshal+import Foreign.Libcdio.Types.Enums+import Foreign.Libcdio.Types.Internal+import Foreign.Libcdio.Types.Offsets+import Foreign.Libcdio.Util+++-- | The collection of metadata describing a particular track.+type Flags = A.BitArray Flag+++-- | The number of sectors spanned by a track pre-gap by default.+pregapSectors :: Word+pregapSectors = fromIntegral pregapSectors'++foreign import ccall safe "cdio/compat/sector.h pregap_sectors"+  pregapSectors' :: C.CUInt++-- | The number of sectors spanned by a track post-gap by default.+postgapSectors :: Word+postgapSectors = fromIntegral postgapSectors'++foreign import ccall safe "cdio/compat/sector.h postgap_sectors"+  postgapSectors' :: C.CUInt+++-- | The typical maximum length of a disc, though it's not a strict limit.+cdMins :: Word+cdMins = fromIntegral cdMins'++foreign import ccall safe "cdio/compat/sector.h cd_mins"+  cdMins' :: C.CUInt++-- | The number of seconds in a minute.+secsPerMin :: Word+secsPerMin = fromIntegral secsPerMin'++foreign import ccall safe "cdio/compat/sector.h secs_per_min"+  secsPerMin' :: C.CUInt++-- | The number of disc sectors comprising a second of audio data.+framesPerSec :: Word+framesPerSec = fromIntegral framesPerSec'++foreign import ccall safe "cdio/compat/sector.h frames_per_sec"+  framesPerSec' :: C.CUInt++-- | The number of bytes in a disc sector's sync header.+syncSize :: Word+syncSize = fromIntegral syncSize'++foreign import ccall safe "cdio/compat/sector.h sync_size"+  syncSize' :: C.CUInt++-- | The size of the smallest meaningful segment of data, in bytes.+chunkSize :: Word+chunkSize = fromIntegral chunkSize'++foreign import ccall safe "cdio/compat/sector.h chunk_size"+  chunkSize' :: C.CUInt++-- | The number of data chunks comprising a disc sector.+chunksPerSector :: Word+chunksPerSector = fromIntegral chunksPerSector'++foreign import ccall safe "cdio/compat/sector.h chunks_per_frame"+  chunksPerSector' :: C.CUInt++-- | The size of a segment of data in the subchannel, in bytes.+framesizeSub :: Word+framesizeSub = fromIntegral framesizeSub'++foreign import ccall safe "cdio/compat/sector.h framesize_sub"+  framesizeSub' :: C.CUInt+++-- | The size of the address of a data sector, in bytes.+headerSize :: Word+headerSize = fromIntegral headerSize'++foreign import ccall safe "cdio/compat/sector.h header_size"+  headerSize' :: C.CUInt++-- | The size of the subheader of an XA sector, in bytes.+subheaderSize :: Word+subheaderSize = fromIntegral subheaderSize'++foreign import ccall safe "cdio/compat/sector.h subheader_size"+  subheaderSize' :: C.CUInt++-- | The size of the EDC error correction segment, in bytes.+errorDetectionSize :: Word+errorDetectionSize = fromIntegral errorDetectionSize'++foreign import ccall safe "cdio/compat/sector.h edc_size"+  errorDetectionSize' :: C.CUInt++-- | The amount of padding between the EDC and ECC segments in a Mode 1 sector,+-- in bytes.+padSize :: Word+padSize = fromIntegral padSize'++foreign import ccall safe "cdio/compat/sector.h mode1_pad_size"+  padSize' :: C.CUInt++-- | The size of the ECC error correction segment, in bytes.+errorCorrectionSize :: Word+errorCorrectionSize = fromIntegral errorCorrectionSize'++foreign import ccall safe "cdio/compat/sector.h ecc_size"+  errorCorrectionSize' :: C.CUInt+++-- | The amount of data which may be contained in a disc sector /with/ error+-- correction, in bytes.+dataSize :: Word+dataSize = fromIntegral dataSize'++foreign import ccall safe "cdio/compat/sector.h framesize"+  dataSize' :: C.CUInt++-- | The size of an entire disc sector, in bytes.+sectorSize :: Word+sectorSize = fromIntegral sectorSize'++foreign import ccall safe "cdio/compat/sector.h framesize_raw"+  sectorSize' :: C.CUInt++-- | The maximum number of bytes that may be returned from a single call.+sectorSizeMax :: Word+sectorSizeMax = fromIntegral sectorSizeMax'++foreign import ccall safe "cdio/compat/sector.h framesize_rawer"+  sectorSizeMax' :: C.CUInt++-- | The size of a disc sector in bytes, ignoring the sync header.+syncedSize :: Word+syncedSize = fromIntegral syncedSize'++foreign import ccall safe "cdio/compat/sector.h framesize_raw1"+  syncedSize' :: C.CUInt++-- | The amount of data which may be contained in a disc sector /without/ error+-- correction, in bytes.+dataSizeRaw :: Word+dataSizeRaw = fromIntegral dataSizeRaw'++foreign import ccall safe "cdio/compat/sector.h framesize_raw0"+  dataSizeRaw' :: C.CUInt+++-- | The total size of the meaningful XA sector headers, in bytes.+headerSizeXa :: Word+headerSizeXa = fromIntegral headerSizeXa'++foreign import ccall safe "cdio/compat/sector.h header_size_xa"+  headerSizeXa' :: C.CUInt++-- | The total size of all data sector error correction segments, in bytes.+tailSize :: Word+tailSize = errorDetectionSize + padSize + errorCorrectionSize++-- | The total size of all XA sector error correction segments, in bytes.+tailSizeXa :: Word+tailSizeXa = fromIntegral tailSizeXa'++foreign import ccall safe "cdio/compat/sector.h tail_size_xa"+  tailSizeXa' :: C.CUInt++-- | The total size of all headers in an XA sector, including the sync marker.+syncHeaderSizeXa :: Word+syncHeaderSizeXa = fromIntegral syncHeaderSizeXa'++foreign import ccall safe "cdio/compat/sector.h sync_size_xa"+  syncHeaderSizeXa' :: C.CUInt++-- | The amount of padding at the end of an XA sector without error correction,+-- in bytes.+padSizeXa :: Word+padSizeXa = dataSizeRaw - taggedDataSizeRaw+++-- | The byte sequence used to mark the start of a disc sector, to allow+-- correcting drift while reading.+sectorSyncHeader :: BS.ByteString+sectorSyncHeader = IO.Unsafe.unsafePerformIO $+    BS.packCStringLen (sectorSyncHeader', fromIntegral syncSize)++foreign import ccall safe "cdio/compat/sector.h sector_sync_header"+  sectorSyncHeader' :: C.Ptr C.CChar+++-- | The amount of data contained in an XA sector without error correction, in+-- bytes.+dataSizeRawXa :: Word+dataSizeRawXa = fromIntegral dataSizeRawXa'++foreign import ccall safe "cdio/compat/sector.h data_size_xa"+  dataSizeRawXa' :: C.CUInt++-- | The size of tagged data (counting the subheader) contained in an XA sector+-- without error correction, in bytes.+taggedDataSizeRaw :: Word+taggedDataSizeRaw = fromIntegral taggedDataSizeRaw'++foreign import ccall safe "cdio/compat/sector.h tagged_size_xa"+  taggedDataSizeRaw' :: C.CUInt+++-- | How many sessions are allowed on a disc.+maxSessions :: Word+maxSessions = fromIntegral maxSessions'++foreign import ccall safe "cdio/compat/sector.h max_session"+  maxSessions' :: C.CUInt++-- | The smallest session number on a disc.+minSessionNo :: Word+minSessionNo = fromIntegral minSessionNo'++foreign import ccall safe "cdio/compat/sector.h min_session"+  minSessionNo' :: C.CUInt+++-- | A shortcut for calculating @'framesPerSec' * 'secsPerMin'@+framesPerMin :: Word+framesPerMin = fromIntegral framesPerMin'++foreign import ccall safe "cdio/compat/sector.h frames_per_min"+  framesPerMin' :: C.CUInt+++-- | The maximum number of sectors allowed to be stored on a disc.+maxSectors :: Word+maxSectors = fromIntegral maxSectors'++foreign import ccall safe "cdio/compat/sector.h max_sectors"+  maxSectors' :: C.CUInt+++-- | Minute\/second\/frame structure for addresses.  Generally only makes sense+-- for audio discs.+data Msf = Msf+    { minute :: Word+    , second :: Word+        -- ^ 'secsPerMin'+    , frame :: Word+        -- ^ 'framesPerSec'+    }+  deriving ( Show, Read )+instance Eq Msf where+    l == r = compare l r == EQ+instance Ord Msf where+    compare l r = case minute l' `compare` minute r' of+        EQ -> case second l' `compare` second r' of+            EQ -> frame l' `compare` frame r'+            x -> x+        x -> x+      where l' = normalize l+            r' = normalize r+            normalize msf@(Msf m s f)+                | f >= framesPerSec = normalize $ Msf m (s + div f framesPerSec) (mod f framesPerSec)+                | s >= secsPerMin = Msf (m + div s secsPerMin) (mod s secsPerMin) f+                | otherwise = msf+instance Bounded Msf where+    minBound = Msf 0 0 0+    maxBound = Msf maxBound (secsPerMin - 1) (framesPerSec - 1)+instance S.Storable Msf where+    sizeOf _    = msfSizeOf+    alignment _ = msfAlign+    peek c = do+        m <- S.peekByteOff c msfM+        s <- S.peekByteOff c msfS+        f <- S.peekByteOff c msfF+        return $ Msf (fromBcd8 m) (fromBcd8 s) (fromBcd8 f)+    poke c hs = do+        S.pokeByteOff c msfM . toBcd8 $ minute hs+        S.pokeByteOff c msfS . toBcd8 $ second hs+        S.pokeByteOff c msfF . toBcd8 $ frame hs+instance Enum Msf where+    fromEnum msf = fromInteger+        $ toInteger (frame msf)+        + toInteger (second msf) * fromIntegral framesPerSec+        + toInteger (minute msf) * fromIntegral framesPerMin+    toEnum i = Msf+        { minute = div i' framesPerMin+        , second = flip mod secsPerMin $ div i' framesPerSec+        , frame = mod i' framesPerSec+        }+      where i' = fromIntegral i+    pred (Msf 0 0 0) = error "Enum.pred(Msf): tried to take `pred' of minBound"+    pred (Msf m s f)+        | f >= framesPerSec = pred $ Msf m (s + div f framesPerSec) (mod f framesPerSec)+        | s >= secsPerMin = pred $ Msf (m + div s secsPerMin) (mod s secsPerMin) f+        | f == 0 && s == 0 = Msf (m - 1) (secsPerMin - 1) (framesPerSec - 1)+        | f == 0 = Msf m (s - 1) (framesPerSec - 1)+        | otherwise = Msf m s (f - 1)+    succ msf@(Msf m s f)+        | msf >= maxBound = error "Enum.succ(Msf): tried to take `succ' of maxBound"+        | otherwise = let (fd, fm) = overflow f 1 framesPerSec+                          (sd, sm) = overflow s fd secsPerMin+                      in Msf (m + sd) sm fm+      where -- Relies on unsigned type, and @y + b < maxBound@+            overflow x y b+                | x > maxBound - y = (div (x - b + y) b + 1, mod (x - b + y) b)+                | otherwise = (div (x + y) b, mod (x + y) b)++{- Use @sizeOf Msf@+msfSizeof :: Word+msfSizeof = fromIntegral msfSizeof'++foreign import ccall safe "cdio/compat/sector.h sizeof_msf_const"+  msfSizeof' :: C.CSize+-}+++{- Never used after definition.+-- | Address in one of the two primary address formats.+data CdromAddr+    = MsfAddr Msf+    | LbaAddr Lba+  deriving ( Eq, Show, Read, Ord )+-- | Note that, while the 'peek' implementation attempts to detect which form+-- the address takes, it may get it wrong and read a 'Msf' address as an 'Lba'+-- or vice versa.  If the type is otherwise known, it may be better to read+-- the pointer as that type directly, and wrap into the union manually.+instance S.Storable CdromAddr where+    sizeOf _    = adrSizeOf+    alignment _ = adrAlign+    peek c = do+        msf <- S.peek $ C.castPtr c+        lba <- S.peek $ C.castPtr c+        -- Barring uncleared bits, an LBA has an extra byte.+        if mod 0x100 lba /= 0+           || second msf >= secsPerMin+           || frame msf >= framesPerSec+        then return $ LbaAddr lba+        else return $ MsfAddr msf+    poke c (MsfAddr hs) = S.poke (C.castPtr c) hs+    poke c (LbaAddr hs) = S.poke (C.castPtr c) hs+-}+++-- | Print a logical address as the corresponding timestamp, assuming audio+-- data.+lbaToMsfStr :: Lba -> String+lbaToMsfStr l = IO.Unsafe.unsafePerformIO $+    lbaToMsfStr' (fromIntegral l) >>= peekFString++foreign import ccall safe "cdio/compat/sector.h cdio_lba_to_msf_str"+  lbaToMsfStr' :: CLba -> IO C.CString++-- | Print a disc timestamp in the standard "MM:SS:FF" format.+msfToStr :: Msf -> String+msfToStr msf = IO.Unsafe.unsafePerformIO $+    M.with msf msfToStr' >>= C.peekCString++foreign import ccall safe "cdio/compat/sector.h cdio_msf_to_str"+  msfToStr' :: C.Ptr Msf -> IO C.CString++-- | Convert an LBA address into the corresponding LSN.+lbaToLsn :: Lba -> Lsn+lbaToLsn = fromIntegral . lbaToLsn' . fromIntegral++-- C erroneously returns @lba_t@.+foreign import ccall safe "cdio/compat/sector.h cdio_lba_to_lsn"+  lbaToLsn' :: CLba -> CLba++-- | Convert an LBA address into the corresponding timestamp, assuming audio+-- data.+lbaToMsf :: Lba -> Msf+lbaToMsf l = IO.Unsafe.unsafePerformIO . M.alloca $ \m' ->+    lbaToMsf' (fromIntegral l) m' >> S.peek m'++foreign import ccall safe "cdio/compat/sector.h cdio_lba_to_msf"+  lbaToMsf' :: CLba -> C.Ptr Msf -> IO ()++-- | Convert an LSN address into the corresponding LBA.+lsnToLba :: Lsn -> Lba+lsnToLba = fromIntegral . lsnToLba' . fromIntegral++foreign import ccall safe "cdio/compat/sector.h cdio_lsn_to_lba"+  lsnToLba' :: CLsn -> CLba++-- | Convert an LSN address into the corresponding timestamp, assuming audio+-- data.+lsnToMsf :: Lsn -> Msf+lsnToMsf l = IO.Unsafe.unsafePerformIO . M.alloca $ \m' ->+    lsnToMsf' (fromIntegral l) m' >> S.peek m'++foreign import ccall safe "cdio/compat/sector.h cdio_lsn_to_msf"+  lsnToMsf' :: CLsn -> C.Ptr Msf -> IO ()++-- | Convert a timestamp into the corresponding LBA address, assuming audio+-- data.+msfToLba :: Msf -> Lba+msfToLba = fromIntegral . IO.Unsafe.unsafePerformIO . flip M.with msfToLba'++foreign import ccall safe "cdio/compat/sector.h cdio_msf_to_lba"+  msfToLba' :: C.Ptr Msf -> IO CLsn++-- | Convert a timestamp into the corresponding LSN address, assuming audio+-- data.+msfToLsn :: Msf -> Lsn+msfToLsn = fromIntegral . IO.Unsafe.unsafePerformIO . flip M.with msfToLsn'++foreign import ccall safe "cdio/compat/sector.h cdio_msf_to_lsn"+  msfToLsn' :: C.Ptr Msf -> IO CLsn++{- Not exported+-- | Convert a split timestamp into the corresponding LBA address, assuming+-- audio data.+msf3ToLba :: Word -> Word -> Word -> Lba+msf3ToLba m s f = fromIntegral $ msf3ToLba' (fromIntegral m) (fromIntegral s) (fromIntegral f)++foreign import ccall safe "cdio/compat/sector.h cdio_msf3_to_lba"+  msf3ToLba' :: C.CUInt -> C.CUInt -> C.CUInt -> CLba++-- | Read a timestamp in the form MM:SS:FF into the corresponding LBA address,+-- assuming audio data.+mmssffToLba :: String -> Maybe Lba+mmssffToLba s = invalidLba . IO.Unsafe.unsafePerformIO $ C.withCString s mmssffToLba++foreign import ccall safe "cdio/compat/sector.h cdio_mmssff_to_lba"+  mmssffToLba' :: C.CString -> IO CLba+-}
+ src/Foreign/Libcdio/Track.hs view
@@ -0,0 +1,315 @@+{-# LANGUAGE ForeignFunctionInterface #-}++{-|+Description:    Information-gathering on the location and form of disc tracks.++Copyright:      (c) 2018-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      stable+Portability:    non-portable (requires libcdio)++What many people would think of as the most important division on a CD isn't+quite as an integral a part of the physical data layout: they are described in+a table of contents before the first track of any recording session, and may+have lower-resolution "echoes" in the subchannels alongside the data, but it+would be hard to otherwise recover the track boundaries from the data itself.+This module, then, provides the functions to retrieve that metadata from the+table of contents and from the subchannels.+++= @track.h@++== Defines+* @CDIO_CDROM_CDI_TRACK@            (removed; only has utility in library code)+* @CDIO_CDROM_DATA_TRACK@           (removed; only has utility in library code)+* @CDIO_INVALID_TRACK@              (removed; handled via 'Nothing')+* @CDIO_CDROM_LBA@                  (removed; only has utility in library code)+* @CDIO_CDROM_LEADOUT_TRACK@        -> 'DiscLeadout'+* @CDIO_CDROM_MSF@                  (removed; only has utility in library code)+* @CDIO_CDROM_XA_TRACK@             (removed; only has utility in library code)+* @CDIO_CD_MAX_TRACKS@              -> 'maxTrack'+* @CDIO_CD_MIN_TRACK_NO@            -> 'minTrack'++== Types+* @track_flag_t@                    -> 'Maybe' 'Bool' (CDIO_TRACK_FLAG_ERROR is never used in library code)+* @track_flags_t@                   (removed; never used in the public interface)+* @track_format_t@                  -> 'TrackFormat'++    -@TRACK_FORMAT_PSX@             -> 'FormatPlaystation'+    -@TRACK_FORMAT_ERROR@           (removed; handled via 'Nothing')++* @trackmode_t@                     (removed; never used in the public API)++== Symbols+* @cdio_get_first_track_num@        -> 'firstTrackNum'+* @cdio_get_last_track_num@         -> 'lastTrackNum'+* @cdio_get_track@                  -> 'trackAt'+* @cdio_get_track_channels@         -> 'numChannels'+* @cdio_get_track_copy_permit@      -> 'copyPermit'+* @cdio_get_track_format@           -> 'trackFormat'+* @cdio_get_track_green@            -> 'isGreen'+* @cdio_get_track_isrc@             -> 'trackIsrc'+* @cdio_get_track_last_lsn@         -> 'trackLastLsn'+* @cdio_get_track_lba@              -> 'trackLba'+* @cdio_get_track_lsn@              -> 'trackLsn'+* @cdio_get_track_msf@              -> 'trackMsf'+* @cdio_get_track_preemphasis@      -> 'hasPreemphasis'+* @cdio_get_track_pregap_lba@       -> 'pregapLba'+* @cdio_get_track_pregap_lsn@       -> 'pregapLsn'+* @cdio_get_track_sec_count@        -> 'sectorCount'+* @track_format2str@                -> 'trackFormatString'+++= "Sound.Libcdio.Track"++* 'firstTrackNum'                   -> 'Sound.Libcdio.Track.firstDiscTrack'+* 'isrcLength'                      (removed; unnecessary low-level detail)+* 'lastTrackNum'                    -> 'Sound.Libcdio.Track.lastDiscTrack'+* 'numChannels'                     -> 'Sound.Libcdio.Track.quadAudio'+* 'pregapLba'                       (removed; only 'Lsn' is used in @Sound@)+* 'pregapLsn'                       -> 'Sound.Libcdio.Track.pregap'+* 'sectorCount'                     -> 'Sound.Libcdio.Track.totalLength'+* 'trackFormat'                     -> 'Sound.Libcdio.Track.format'+* 'trackIsrc'                       -> @"Sound.Libcdio.Read.Data".'Sound.Libcdio.Read.Data.isrc'@+* 'trackLastLsn'                    -> 'Sound.Libcdio.Track.offsetEnd'+* 'trackLba'                        (removed; only 'Lsn' is used in @Sound@)+* 'trackLsn'                        -> 'Sound.Libcdio.Track.offset'+* 'trackMsf'                        (removed; only 'Lsn' is used in @Sound@)+-}+module Foreign.Libcdio.Track+    ( -- * Types+      Track ( .. )+    , TrackNum+    , minTrack+    , maxTrack+    , TrackFormat ( .. )+    , trackFormatString+      -- * Location+    , firstTrackNum+    , lastTrackNum+    , trackAt+    , trackLba, trackLsn+    , trackMsf+    , trackLastLsn+    , pregapLba, pregapLsn+    , sectorCount+      -- * Data+    , trackFormat, isGreen+    , hasPreemphasis+    , copyPermit+    , numChannels+    , trackIsrc+    , isrcLength+    ) where+++import qualified Foreign.C.String as C+import qualified Foreign.C.Types as C+import qualified Foreign.Ptr as C++import qualified Foreign.Marshal.Alloc as M+import qualified Foreign.Marshal.Utils as M+import qualified Foreign.Storable as S++import qualified System.IO.Unsafe as IO.Unsafe++import Foreign.Libcdio.Marshal+import Foreign.Libcdio.Sector+import Foreign.Libcdio.Types.Enums+import Foreign.Libcdio.Types.Internal++import Sound.Libcdio.Common+++withCdioTrack :: (C.Ptr Cdio -> CTrack -> IO a) -> (a -> Maybe b) -> Cdio -> Track -> IO (Maybe b)+withCdioTrack f g c = fmap (>>= g) . withCdio c . flip f . withTrack+++-- | Filter out @TRACK_FORMAT_ERROR@ values to fit the 'Enum'.+invalidFormat :: CTrackFormat -> Maybe TrackFormat+invalidFormat = fmap (toEnum . fromIntegral) . maybeError [trackFormatError]++foreign import ccall safe "cdio/compat/track.h track_format_error"+  trackFormatError :: CTrackFormat++-- | Describe the data layout of a 'Track' in a human-readable manner, as+-- opposed to the machine representation returned by the 'Show' instance.+trackFormatString :: TrackFormat -> String+trackFormatString = IO.Unsafe.unsafePerformIO .+    C.peekCString . trackFormatString' . fromIntegral . fromEnum++foreign import ccall safe "cdio/compat/track.h track_format_string"+  trackFormatString' :: CTrackFormat -> C.CString+++-- | Give up a small amount of nuance in order to use standard types.+fromTrackFlagStatus :: Integral a => a -> Maybe Bool+fromTrackFlagStatus c = case toEnum $ fromIntegral c of+    FlagTrue  -> Just True+    FlagFalse -> Just False+    _         -> Nothing+++-- | The number of the first track on the disc.  This will almost always be 1,+-- but that is not strictly guaranteed; the (perhaps theoretical) example is of+-- a multi-disc set, where later discs pick the numbering back up where the+-- previous one left off.+-- +-- Returns 'Nothing' if the 'Cdio' object has already been closed, or if the+-- disc table of contents can't be read.+firstTrackNum :: Cdio -> IO (Maybe Track)+firstTrackNum c = (>>= invalidTrack) <$> withCdio c firstTrackNum'++foreign import ccall safe "cdio/compat/track.h cdio_get_first_track_num"+  firstTrackNum' :: C.Ptr Cdio -> IO CTrack++-- | The number of the last track on the disc.+-- +-- Returns 'Nothing' if the 'Cdio' object has already been closed, or if the+-- disc table of contents can't be read.+lastTrackNum :: Cdio -> IO (Maybe Track)+lastTrackNum c = (>>= invalidTrack) <$> withCdio c lastTrackNum'++foreign import ccall safe "cdio/compat/track.h cdio_get_last_track_num"+  lastTrackNum' :: C.Ptr Cdio -> IO CTrack+++-- | The track which contains the given address.+-- +-- Returns 'Nothing' if the 'Cdio' object has already been closed, or if the+-- address is beyond the written data on the disc.  Note that 'DiscLeadout' is+-- treated as if it were a single sector long:+-- +-- >>> Just endTrack <- lastTrackNum cdio+-- >>> Just endAddr <- trackLastLsn cdio endTrack+-- >>> trackAt cdio $ endAddr + 1+-- Just DiscLeadout+-- >>> trackAt cdio $ endAddr + 2+-- Nothing+trackAt :: Cdio -> Lsn -> IO (Maybe Track)+trackAt c = fmap (>>= invalidTrack) . withCdio c . flip trackAt' . fromIntegral++foreign import ccall safe "cdio/compat/track.h cdio_get_track"+  trackAt' :: C.Ptr Cdio -> C.CInt -> IO CTrack+++-- | The number of channels in the given track; either 2 or 4 per the standard.+numChannels :: Cdio -> Track -> IO (Maybe Word)+numChannels = withCdioTrack numChannels' numChannelsError++-- | The user doesn't care about which type of error it is here.+numChannelsError :: (Integral a, Integral b) => a -> Maybe b+numChannelsError i+    | i < 0 = Nothing+    | otherwise = Just $ fromIntegral i++foreign import ccall safe "cdio/compat/track.h cdio_get_track_channels"+  numChannels' :: C.Ptr Cdio -> CTrack -> IO C.CInt+++-- | Whether the track may be legally copied.+copyPermit :: Cdio -> Track -> IO (Maybe Bool)+copyPermit = withCdioTrack copyPermit' fromTrackFlagStatus++foreign import ccall safe "cdio/compat/track.h cdio_get_track_copy_permit"+  copyPermit' :: C.Ptr Cdio -> CTrack -> IO C.CInt+++-- | Whether preemphasis has been applied to the track for noise reduction.+hasPreemphasis :: Cdio -> Track -> IO (Maybe Bool)+hasPreemphasis = withCdioTrack hasPreemphasis' fromTrackFlagStatus++foreign import ccall safe "cdio/compat/track.h cdio_get_track_preemphasis"+  hasPreemphasis' :: C.Ptr Cdio -> CTrack -> IO C.CInt+++-- | The raw data structure of a track.+trackFormat :: Cdio -> Track -> IO (Maybe TrackFormat)+trackFormat = withCdioTrack trackFormat' invalidFormat++foreign import ccall safe "cdio/compat/track.h cdio_get_track_format"+  trackFormat' :: C.Ptr Cdio -> CTrack -> IO C.CInt+++-- | Whether the track data was stored using the Green Book (CD-i) standard.+isGreen :: Cdio -> Track -> IO (Maybe Bool)+isGreen c t = do+    f <- firstTrackNum c+    l <- lastTrackNum c+    if Just t < f || Just t > l+    then return Nothing+    else withCdioTrack isGreen' (Just . M.toBool) c t++foreign import ccall safe "cdio/compat/track.h cdio_get_track_green"+  isGreen' :: C.Ptr Cdio -> CTrack -> IO C.CUChar+++-- | The address of the end of the given track.+trackLastLsn :: Cdio -> Track -> IO (Maybe Lsn)+trackLastLsn = withCdioTrack trackLastLsn' invalidLsn++foreign import ccall safe "cdio/compat/track.h cdio_get_track_last_lsn"+  trackLastLsn' :: C.Ptr Cdio -> CTrack -> IO C.CInt++-- | The address of the start of the given track.+trackLba :: Cdio -> Track -> IO (Maybe Lba)+trackLba = withCdioTrack trackLba' invalidLba++foreign import ccall safe "cdio/compat/track.h cdio_get_track_lba"+  trackLba' :: C.Ptr Cdio -> CTrack -> IO C.CInt++-- | The address of the start of the given track.+trackLsn :: Cdio -> Track -> IO (Maybe Lsn)+trackLsn = withCdioTrack trackLsn' invalidLsn++foreign import ccall safe "cdio/compat/track.h cdio_get_track_lsn"+  trackLsn' :: C.Ptr Cdio -> CTrack -> IO C.CInt++-- | The address of the start of any pregap before the given track.+pregapLba :: Cdio -> Track -> IO (Maybe Lba)+pregapLba = withCdioTrack pregapLba' invalidLba++foreign import ccall safe "cdio/compat/track.h cdio_get_track_pregap_lba"+  pregapLba' :: C.Ptr Cdio -> CTrack -> IO C.CInt++-- | The address of the start of any pregap before the given track.+pregapLsn :: Cdio -> Track -> IO (Maybe Lsn)+pregapLsn = withCdioTrack pregapLsn' invalidLsn++foreign import ccall safe "cdio/compat/track.h cdio_get_track_pregap_lsn"+  pregapLsn' :: C.Ptr Cdio -> CTrack -> IO C.CInt+++-- | The International Standard Recording Code the given track.  This may also+-- be retrieved by @'Foreign.Libcdio.CdText.getField'+-- 'Foreign.Libcdio.CdText.Isrc' $ 'Just' t@, though that references a+-- different source and thus may not have the same return value.+trackIsrc :: Cdio -> Track -> IO (Maybe String)+trackIsrc c t = withCdio c (flip trackIsrc' $ withTrack t) >>=+    maybe (return Nothing) (M.maybePeek peekFString)++foreign import ccall safe "cdio/compat/track.h cdio_get_track_isrc"+  trackIsrc' :: C.Ptr Cdio -> CTrack -> IO C.CString+++-- | The timestamp at which the given track begins.+trackMsf :: Cdio -> Track -> IO (Maybe Msf)+trackMsf c t = M.alloca $ \m' -> do+    b <- withCdio c $ \c' -> trackMsf' c' (withTrack t) m'+    case M.toBool <$> b of+        Just True -> M.maybePeek S.peek m'+        _ -> return Nothing++foreign import ccall safe "cdio/compat/track.h cdio_get_track_msf"+  trackMsf' :: C.Ptr Cdio -> CTrack -> C.Ptr Msf -> IO CBool+++-- | The number of sectors "assigned" to the specified track, including any in+-- the pregap between it and the following one.+sectorCount :: Cdio -> Track -> IO (Maybe Word)+sectorCount = withCdioTrack sectorCount' $ maybeError [0] . fromIntegral++foreign import ccall safe "cdio/compat/track.h cdio_get_track_sec_count"+  sectorCount' :: C.Ptr Cdio -> CTrack -> IO C.CUInt
+ src/Foreign/Libcdio/Types.hs view
@@ -0,0 +1,115 @@+{-# OPTIONS_HADDOCK not-home #-}++{-|+Description:    Common types used in the module-mirroring interface.++Copyright:      (c) 2020-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      stable+Portability:    non-portable (requires libcdio)++The original header defined a rather heterogeneous collection of typedefs,+enums, and preprocessor macros, none of which provide much utility when+separated from their associated functions.  Instead of following that design+decision (which only makes sense under the C @#include@ model), this module+instead exports every type used by the interface /without/ any constructors or+associated functions, for any type signatures which may expose an object only+in passing it along.+++= @types.h@++== Defines+* @CDIO_INVALID_LBA@                (removed; handled via 'Nothing')+* @CDIO_INVALID_LSN@                (removed; handled via 'Nothing')+* @CDIO_INVALID_SESSION@            (removed; handled via 'Nothing')+* @CDIO_ISRC_SIZE@                  -> @"Foreign.Libcdio.Track".'isrcLength'@+* @CDIO_MCN_SIZE@                   -> @"Foreign.Libcdio.Disc".'mcnLength'@+* @__cd_offsetof@                   (removed; structural calculation encapsulated behind the scenes)++== Types+* @CdioDataFree_t@                  (removed; pointer handling is encapsulated behind the scenes)+* @bitfield_t@                      (removed; accomplished with greater safety through "Data.Array.BitArray")+* @bool_3way_t@                     -> 'Maybe' 'Bool'++    - @nope@                        -> 'Just' 'False'+    - @yep@                         -> 'Just' 'True'+    - @dunno@                       -> 'Nothing'++* @cdio_cdrom_addr@                 (removed; never used in library code)+* @cdio_fs_anal_t@                  -> @"Foreign.Libcdio.CdTypes".'Filesystem'@, 'FilesystemClasses', and 'IsoAnalysis'+* @cdio_isrc_t@                     (removed; never used in library code)+* @cdio_mcn_t@                      (removed; never used in library code)+* @cdio_track_flag@                 (removed; identical in all but name to 'Flag')+* @cdio_utf8_t@                     (removed; 'Char' already serves this purpose)+* @lba_t@                           -> @"Foreign.Libcdio.Sector".'Lba'@+* @lsn_t@                           -> @"Foreign.Libcdio.Sector".'Lsn'@+* @msf_t@                           -> @"Foreign.Libcdio.Sector".'Msf'@++    - @m@                           -> 'minute'+    - @s@                           -> 'second'+    - @f@                           -> 'frame'++* @session_t@                       (removed: only used internally)+* @track_t@                         -> @"Foreign.Libcdio.Track".'Track'@+++= "Sound.Libcdio.Types"+The exact collection of exported types has been changed to reflect those used+by the higher-level interface, but the modules are otherwise very similar; many+types are shared between the two.+-}+module Foreign.Libcdio.Types+    ( -- * Disc+      Cdio+    , Whence+    , Lba+    , Lsn+    , Msf+    , Bcd+    , Track+    , TrackNum+    , TrackFormat+    , ReadMode+    , SessionArg+      -- * CdText+    , SubchannelData+    , Field+    , Genre+    , Language+    , Flag+    , Flags+      -- * Hardware+    , DriverId+    , DriverReturnCode+    , HardwareInfo+    , DriveCapabilityRead+    , DriveReadCaps+    , DriveCapabilityWrite+    , DriveWriteCaps+    , DriveCapabilityMisc+    , DriveMiscCaps+    , DriveCaps+    , DiscMode+      -- * Data+    , Filesystem+    , FilesystemClass+    , FilesystemClasses+    , IsoAnalysis+      -- * Logging+    , LogEntry+    , LogLevel+    ) where+++import Foreign.Libcdio.CdText+import Foreign.Libcdio.CdTypes+import Foreign.Libcdio.Device+import Foreign.Libcdio.Disc+import Foreign.Libcdio.Logging+import Foreign.Libcdio.Read+import Foreign.Libcdio.Sector+import Foreign.Libcdio.Track+import Foreign.Libcdio.Util
+ src/Foreign/Libcdio/Types/Enums.chs view
@@ -0,0 +1,453 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-# OPTIONS_HADDOCK not-home #-}++#include "cdio/compat/version.h"++{-|+Description:    c2hs-generated types for re-export by more relevant modules.++Copyright:      (c) 2018-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      stable+Portability:    non-portable (requires libcdio)++Many of the enums in the C library are large things with explicit numeric+representation, and maintaining them in pure Haskell would be a nightmare.  On+the other hand, keeping them in their natural modules means those can never be+analyzed for coverage.  Splitting the former out here allows the best of both+worlds — losing typeclass coverage reports on the enums is a small price.  Just+note that since this isn't exposed, it /can not/ be used directly by any other+c2hs-generated modules.+-}+module Foreign.Libcdio.Types.Enums+    ( -- * "Foreign.Libcdio.CdText"+      CField+    , Field ( .. )+    , CGenre+    , Genre ( .. )+    , CLanguage+    , Language ( .. )+      -- * "Foreign.Libcdio.CdTypes"+    , Filesystem_ ( .. )+    , FilesystemClass ( .. )+      -- * "Foreign.Libcdio.Device"+    , DriveCapabilityMisc ( .. )+    , DriveCapabilityRead ( .. )+    , DriveCapabilityWrite ( .. )+    , CDriverId+    , DriverId ( .. )+    , CDriverReturnCode+    , DriverReturnCode ( .. )+      -- * "Foreign.Libcdio.Disc"+    , CDiscMode+    , DiscMode ( .. )+      -- * "Foreign.Libcdio.Logging"+    , CLogLevel+    , LogLevel ( .. )+      -- * "Foreign.Libcdio.Read"+    , ReadMode ( .. )+    , Whence ( .. )+      -- * "Foreign.Libcdio.Sector"+    , SubchannelData ( .. )+    , Flag ( .. )+      -- * "Foreign.Libcdio.Track"+    , CTrackFormat+    , TrackFormat ( .. )+    , TrackFlagStatus ( .. )+    ) where+++import Data.Ix ( Ix )+++#include "cdio/compat/cdtext.h"+++-- | The underlying type of the C @cdtext_field_t@, i.e. 'Field'.+type CField = {#type cdtext_field_t#}++-- | Descriptions of the content contained in an associated CD Text field.+{#enum cdtext_field_t as Field+    { underscoreToCase+    , CDTEXT_FIELD_DISCID as DiscId+    , CDTEXT_FIELD_GENRE as GenreName+    } omit ( CDTEXT_FIELD_INVALID )+    with prefix = "cdtext_field"+    deriving ( Eq, Show, Read, Ord, Bounded )+#}+++-- | The underlying type of the C @cdtext_genre_t@, i.e. 'Genre'.+type CGenre = {#type cdtext_genre_t#}++-- | Genres recognized in the CD Text standard.+{#enum cdtext_genre_t as Genre+    { underscoreToCase+    , CDTEXT_GENRE_ADULT_CONTEMP as AdultContemporary+    , CDTEXT_GENRE_CHRIST_CONTEMP as ChristianContemporary+    , CDTEXT_GENRE_HIPHOP as HipHop+    , CDTEXT_GENRE_LATIN as LatinMusic+    , CDTEXT_GENRE_NEWAGE as NewAge+    , CDTEXT_GENRE_RYTHMANDBLUES as RhythmAndBlues+    , CDTEXT_GENRE_SOUNDEFFECTS as SoundEffects+    } omit ( CDTEXT_GENRE_UNUSED )+    with prefix = "cdtext_genre"+    deriving ( Eq, Show, Read, Ord, Bounded )+#}+++-- | The underlying type of the C @cdtext_lang_t@, i.e. 'Language'.+type CLanguage = {#type cdtext_lang_t#}++-- | Written languages recognized in the CD Text standard.+#if LIBCDIO_SINCE_VERSION_2_1+{#enum cdtext_lang_t as Language+    { underscoreToCase+    , CDTEXT_LANGUAGE_UNKNOWN as UnknownLanguage+    , CDTEXT_LANGUAGE_SERBO_CROAT as SerboCroatian+    , CDTEXT_LANGUAGE_SRANANTONGO as SrananTongo+    } omit+    ( CDTEXT_LANGUAGE_INVALID+    , CDTEXT_LANGUAGE_BLOCK_UNUSED+    )+    with prefix = "cdtext_language"+    deriving ( Eq, Show, Read, Ord, Bounded )+#}+#else+{#enum cdtext_lang_t as Language+    { underscoreToCase+    , CDTEXT_LANGUAGE_UNKNOWN as UnknownLanguage+    , CDTEXT_LANGUAGE_SERBO_CROAT as SerboCroatian+    , CDTEXT_LANGUAGE_SRANANTONGO as SrananTongo+    }+    with prefix = "cdtext_language"+    deriving ( Eq, Show, Read, Ord, Bounded )+#}+#endif++++#include "cdio/compat/cd_types.h"+++-- | Internal filesystem type, including ones that conflate+-- 'Foreign.Libcdio.CdTypes.Filesystem' with+-- 'Foreign.Libcdio.CdTypes.IsoAnalysis'; these are separated in+-- 'Foreign.Libcdio.CdTypes.cdType'.+{#enum cdio_fs_t as Filesystem_+    {underscoreToCase}+    with prefix = "cdio"+    deriving ( Eq, Show, Read, Ord, Bounded )+#}+++-- | Higher-level descriptions of discs/filesystems.+{#enum fs_cap_t as FilesystemClass+    { underscoreToCase+    , FS_ANAL_CDTV as CommodoreCdtv+    , FS_ANAL_VIDEOCD as VideoCd+    , FS_ANAL_ROCKRIDGE as RockRidge+    , FS_ANAL_SVCD as SuperVideoCd+    , FS_ANAL_CVD as ChoijiVideoCd+    , FS_ANAL_XISO as XboxIsoClass+    , FS_ANAL_ISO9660_ANY as Iso9660Class+    }+    with prefix = "fs_anal"+    deriving ( Eq, Show, Read, Ord, Bounded, Ix )+#}++++#include "cdio/compat/device.h"+++-- | Miscellaneous properties a device can have, typically describing hardware+-- features, which are collected in 'Foreign.Libcdio.Device.DriveMiscCaps'.+{#enum cdio_drive_cap_misc_t as DriveCapabilityMisc+    { underscoreToCase+    } omit+    ( CDIO_DRIVE_CAP_ERROR+    , CDIO_DRIVE_CAP_UNKNOWN+    )+    with prefix = "cdio_drive_cap"+    deriving ( Eq, Show, Read, Ord, Bounded, Ix )+#}++-- | Read-related properties a device can have, mostly describing what formats+-- it understands, which are collected in 'Foreign.Libcdio.Device.DriveReadCaps'.+-- +-- The difference between 'ReadAnalogAudio' and 'ReadDigitalAudio' is poorly+-- documented in libcdio; they have been named here according to their assumed+-- meanings (see <https://www.cdrfaq.org/faq02.html#S2-4-3>), but that pattern+-- may not be completely accurate.+{#enum cdio_drive_cap_read_t as DriveCapabilityRead+    { underscoreToCase+    , CDIO_DRIVE_CAP_READ_AUDIO as ReadAnalogAudio+    , CDIO_DRIVE_CAP_READ_CD_DA as ReadDigitalAudio+    , CDIO_DRIVE_CAP_READ_CD_G as ReadCdGraphics+    , CDIO_DRIVE_CAP_READ_CD_R as ReadCdRecordable+    , CDIO_DRIVE_CAP_READ_CD_RW as ReadCdReWritable+    , CDIO_DRIVE_CAP_READ_DVD_R as ReadDvdRecordable+    , CDIO_DRIVE_CAP_READ_DVD_PR as ReadDvdPlusRecordable+    , CDIO_DRIVE_CAP_READ_DVD_RW as ReadDvdReWritable+    , CDIO_DRIVE_CAP_READ_DVD_RPW as ReadDvdPlusReWritable+    , CDIO_DRIVE_CAP_READ_C2_ERRS as ReadC2ErrorCorrection+    }+    with prefix = "cdio_drive_cap"+    deriving ( Eq, Show, Read, Ord, Bounded, Ix )+#}++-- | Write-related properties a device can have, mostly describing what formats+-- it can burn, which are collected in 'Foreign.Libcdio.Device.DriveWriteCaps'.+{#enum cdio_drive_cap_write_t as DriveCapabilityWrite+    { underscoreToCase+    , CDIO_DRIVE_CAP_WRITE_CD_R as WriteCdRecordable+    , CDIO_DRIVE_CAP_WRITE_CD_RW as WriteCdReWritable+    , CDIO_DRIVE_CAP_WRITE_DVD_R as WriteDvdRecordable+    , CDIO_DRIVE_CAP_WRITE_DVD_PR as WriteDvdPlusRecordable+    , CDIO_DRIVE_CAP_WRITE_DVD_RW as WriteDvdReWritable+    , CDIO_DRIVE_CAP_WRITE_DVD_RPW as WriteDvdPlusReWritable+    } omit+    ( CDIO_DRIVE_CAP_WRITE_CD+    , CDIO_DRIVE_CAP_WRITE_DVD+    , CDIO_DRIVE_CAP_WRITE+    )+    with prefix = "cdio_drive_cap"+    deriving ( Eq, Show, Read, Ord, Bounded, Ix )+#}+++{- Barely even used internally.+-- | Different types of device that can be read, which are collected in+-- 'Foreign.Libcdio.Device.SrcCategories'.+{#enum cdio_src_category_mask_t as SrcCategoryMask+    {underscoreToCase}+    with prefix = "cdio"+    deriving ( Eq, Show, Read, Ord, Bounded, Ix )+#}+-}+++-- | The underlying type of the C @driver_id_t@, i.e. 'DriverId'.+type CDriverId = {#type driver_id_t#}++-- | Devices or file types supported by the library.+{#enum define DriverId+    { DRIVER_UNKNOWN as DriverUnknown+    , DRIVER_AIX as DriverAix+    , DRIVER_BSDI as DriverBsdi+    , DRIVER_FREEBSD as DriverFreeBsd+    , DRIVER_NETBSD as DriverNetBsd+    , DRIVER_LINUX as DriverLinux+    , DRIVER_SOLARIS as DriverSolaris+    , DRIVER_OS2 as DriverOs2+    , DRIVER_OSX as DriverOsX+    , DRIVER_WIN32 as DriverWin32+    , DRIVER_CDRDAO as DriverCdrDao+    , DRIVER_BINCUE as DriverBinCue+    , DRIVER_NRG as DriverNrg+    , DRIVER_DEVICE as DriverDevice+    }+    deriving ( Eq, Show, Read, Ord, Bounded )+#}+++-- | The underlying type of the C @driver_return_code_t@, i.e.+-- 'DriverReturnCode'.+type CDriverReturnCode = {#type driver_return_code_t#}++-- | Descriptions of various error states which may be returned by driver+-- functions.+{#enum driver_return_code_t as DriverReturnCode+    { underscoreToCase+    , DRIVER_OP_ERROR as DriverError+    , DRIVER_OP_UNINIT as Uninitialized+    } with prefix = "driver_op"+    deriving ( Eq, Show, Read, Ord, Bounded )+#}++++#include "cdio/compat/disc.h"+++-- | The underlying type of the C @discmode_t@, i.e. 'DiscMode'.+type CDiscMode = {#type discmode_t#}++-- | Different types of disc.  Modes are combined from several sources, along+-- with some libcdio-specific additions:+--+-- * MMC-5 6.33.3.13 (Send CUESHEET)+-- * MMC-5 Table 400 "DVD Book"+-- * GNU/Linux @\/usr\/include\/linux\/cdrom.h@+--+-- As C2HS and Haddock don't yet interact well enough to document Enum fields,+-- some of the less obvious mappings include:+--+-- * 'DataCdMode': CD-ROM form 1+-- * 'MixedCdMode': some combination of 'AudioCdMode', 'DataCdMode', and 'XaCdMode'+-- * 'DvdPlusRecordableMode': DVD+R+-- * 'DvdPlusReWritableMode': DVD+RW+{#enum discmode_t as DiscMode+    { underscoreToCase+    , CDIO_DISC_MODE_CD_DA as AudioCdMode+    , CDIO_DISC_MODE_CD_DATA as DataCdMode+    , CDIO_DISC_MODE_CD_XA as XaCdMode+    , CDIO_DISC_MODE_CD_MIXED as MixedCdMode+    , CDIO_DISC_MODE_DVD_ROM as DvdRomMode+    , CDIO_DISC_MODE_DVD_RAM as DvdRamMode+    , CDIO_DISC_MODE_DVD_R as DvdRecordableMode+    , CDIO_DISC_MODE_DVD_RW as DvdReWritableMode+    , CDIO_DISC_MODE_HD_DVD_ROM as HighDefinitionDvdRomMode+    , CDIO_DISC_MODE_HD_DVD_RAM as HighDefinitionDvdRamMode+    , CDIO_DISC_MODE_HD_DVD_R as HighDefinitionDvdRecordableMode+    , CDIO_DISC_MODE_DVD_PR as DvdPlusRecordableMode+    , CDIO_DISC_MODE_DVD_PRW as DvdPlusReWritableMode+    , CDIO_DISC_MODE_DVD_PR_DL as DoubleLayerDvdPlusRecordableMode+    , CDIO_DISC_MODE_DVD_PRW_DL as DoubleLayerDvdPlusReWritableMode+    , CDIO_DISC_MODE_DVD_OTHER as OtherDvdMode+    , CDIO_DISC_MODE_NO_INFO as NoModeInfo+    , CDIO_DISC_MODE_CD_I as CdIMode+    } omit ( CDIO_DISC_MODE_ERROR )+    with prefix = "cdio_disc_mode"+    deriving ( Eq, Show, Read, Ord, Bounded )+#}++++#include "cdio/compat/logging.h"+++-- | The underlying type of the C @cdio_log_level_t@, i.e. 'LogLevel'.+type CLogLevel = {#type cdio_log_level_t#}++-- | How much detail should be recorded in the logs.+{#enum cdio_log_level_t as LogLevel+    {underscoreToCase}+    with prefix = "cdio"+    deriving ( Eq, Show, Read, Ord, Bounded )+#}++++#include "cdio/compat/read.h"+++-- | How data is laid out on a disc.+{#enum cdio_read_mode_t as ReadMode+    { underscoreToCase+    , CDIO_READ_MODE_AUDIO as AudioMode+    , CDIO_READ_MODE_M1F1 as Mode1Form1+    , CDIO_READ_MODE_M1F2 as Mode1Form2+    , CDIO_READ_MODE_M2F1 as Mode2Form1+    , CDIO_READ_MODE_M2F2 as Mode2Form2+    }+    with prefix = "cdio_read_mode"+    deriving ( Eq, Show, Read, Ord, Bounded )+#}+++-- | Which location an offset passed to 'Foreign.Libcdio.Read.seek' should be+-- based on.+{#enum whence_t as Whence+    {underscoreToCase}+    with prefix = "whence"+    deriving ( Eq, Show, Read, Ord, Bounded )+#}++++#include "cdio/compat/sector.h"+++-- | Types of information stored on disc subchannels.+{#enum cdio_subchannel as SubchannelData+    { underscoreToCase+    , CDIO_SUBCHANNEL_SUBQ_DATA as QChannelData+    }+    with prefix = "cdio_subchannel"+    deriving ( Eq, Show, Read, Ord, Bounded )+#}+++-- | Metadata describing the layout or type of data on a track.+{#enum flag_t as Flag+    { underscoreToCase+    , DATA as DataTrack+    , SCMS as SerialCopyManagement+    } omit ( NONE )+    deriving ( Eq, Show, Read, Ord, Bounded, Ix )+#}+++{- Not actually an 'Enum', but rather shortcuts for basic multiplications.+-- | How many sectors are contained in various lengths of disc.+{#enum cdio_cd_minutes_sectors as CdMinutesSectors+    {underscoreToCase}+    with prefix = "cdio"+    deriving ( Eq, Show, Read, Ord, Bounded )+#}+-}++++#include "cdio/compat/track.h"+++-- | The underlying type of the C @track_format_t@, i.e. 'TrackFormat'.+type CTrackFormat = {#type track_format_t#}++-- | The structure in which data is stored on a segment of a disc.  The exact+-- representation of these values is discussed in "Foreign.Libcdio.Sector".+{#enum track_format_t as TrackFormat+    { underscoreToCase+    , TRACK_FORMAT_CDI as FormatCdI+    , TRACK_FORMAT_PSX as FormatPlaystation+    } omit ( TRACK_FORMAT_ERROR )+    with prefix = "track"+    deriving ( Eq, Show, Read, Ord, Bounded )+#}+++{- Barely even used internally.+-- | The block format in which the data is saved in a track on disc.+{#enum trackmode_t as TrackMode+    {underscoreToCase}+    deriving ( Eq, Show, Read, Ord, Bounded )+#}+-}+++-- | Whether a track has a particular flag specified.+{#enum track_flag_t as TrackFlagStatus+    {underscoreToCase}+    with prefix = "cdio_track"+    deriving ( Eq, Show, Read, Ord, Bounded )+#}++++#include "cdio/util.h"+++{- Similar semantics from 'Maybe Bool'.+-- | A version of 'Bool' which also provides a third, non-definitive state.+{#enum bool_3way_t as Bool3+    {nope as No, yep as Yes, dunno as Unknown}+    deriving ( Eq, Show, Read, Ix )+#}+-- Need to explicitly instance Ord and Bounded as the below is the logical+-- order, but @dunno@ is assigned @3@ in the C code.+instance Ord Bool3 where+    No <= _             = True+    _ <= Yes            = True+    Unknown <= Unknown  = True+    _ <= _              = False+instance Bounded Bool3 where+    minBound = No+    maxBound = Yes+-- Needs: Bits, FiniteBits, Generic, Rep, Data, Storable for parity with Bool+-}
+ src/Foreign/Libcdio/Types/Internal.hs view
@@ -0,0 +1,409 @@+{-# LANGUAGE ForeignFunctionInterface #-}++{-|+Description:    Common type definitions used pervasively in libcdio, along with+                low-level features intended for internal use.++Copyright:      (c) 2018-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      stable+Portability:    non-portable (requires libcdio)++While most of @types.h@ is user-facing, it's undesirable to export the+@newtype@ constructors, for type safety.  Hiding them breaks c2hs automatic+marshalling, which means that we have to write custom marshalling functions.+Exporting those clutters the user surface with unnecessary and+likely-never-used code, so the types in this module got split off for use+internally — at which point the constructors may as well be exported anyway.+-}+module Foreign.Libcdio.Types.Internal+    ( -- * Addresses+      Lba ( .. )+    , CLba+    , Lsn ( .. )+    , CLsn+      -- * Segments+    , Track ( .. )+    , CTrack+    , TrackNum+    , minTrack+    , maxTrack+      -- * Data+    , CBitfield+    , isrcLength+    , mcnLength+      -- * Marshalling+    , invalidLba+    , invalidLsn+    , invalidZeroLsn+    , invalidTrack+    , invalidZeroTrack+    , withLba+    , withLsn+    , withTrack+    ) where+++import qualified Data.Bits as B+import qualified Data.Ix as I+import qualified Data.List as L+import qualified Data.Maybe as Y++import qualified Foreign.C.Types as C+import qualified Foreign.Ptr as C+import qualified Foreign.Storable as S++import qualified Text.Printf as P++import Data.Bits ((.&.), (.|.))++import Foreign.Libcdio.Marshal+++{- 'Char' is already native.+type CUtf8 = C.CChar++-- | A character explicitly encoded as UTF-8.+newtype Utf8 = Utf8 CUtf8+  deriving ( Eq, Ord, Show, Read, Bounded )+-}+++-- | The representation of the various @DriveCaps*@ at the C boundary.+type CBitfield = C.CUInt++{- Accomplished with "Data.Array.BitArray".+-- | The type used for bit-fields in structs with eight or less flags.+newtype Bitfield = Bitfield CBitfield+  deriving ( Eq, Ord, Show, Read, Bounded )+-}+++-- | Marshal an address to a type which pins the required size of the C+-- representation, rather than the polymorphism of 'fromIntegral'.+withLba :: Lba -> CLba+withLba (Lba i) = i++type CLba = C.CInt++-- | The type-safe representation of a Logical Block Address, counting sectors+-- from the very beginning of the write session.  See also 'Lsn'.+newtype Lba = Lba CLba+  deriving ( Eq, Ord, Show, Read )+instance Bounded Lba where+    minBound = Lba . lsnToLba $ fromIntegral (minBound :: Lsn)+    maxBound = Lba . lsnToLba $ fromIntegral (maxBound :: Lsn)+instance Enum Lba where+    toEnum = Lba . toEnum+    fromEnum (Lba i) = fromEnum i+instance I.Ix Lba where+    range (Lba a, Lba b) = map Lba [a..b]+    inRange (a, b) i = a <= i && i <= b+    index r@(a, b) i = Y.fromMaybe (error $ "Ix(Lba).index: Index (" ++ show i ++ ") out of range (" ++ show r ++ ")")+                     $ L.elemIndex i [a..b]+instance Num Lba where+    Lba a + Lba b = Lba $ a + b+    Lba a - Lba b = Lba $ a - b+    Lba a * Lba b = Lba $ a * b+    abs (Lba i) = Lba $ abs i+    signum (Lba i) = Lba $ signum i+    fromInteger = Lba . fromInteger+instance Real Lba where+    toRational (Lba i) = toRational i+instance Integral Lba where+    quotRem (Lba i) (Lba d) = (Lba q, Lba r)+      where (q, r) = quotRem i d+    toInteger (Lba i) = toInteger i+instance B.Bits Lba where+    (Lba a) .&. (Lba b) = Lba $ a .&. b+    (Lba a) .|. (Lba b) = Lba $ a .|. b+    xor (Lba a) (Lba b) = Lba $ B.xor a b+    complement (Lba i) = Lba $ B.complement i+    shift (Lba i) = Lba . B.shift i+    rotate (Lba i) = Lba . B.rotate i+    bitSize (Lba i) = B.finiteBitSize i+    bitSizeMaybe (Lba i) = B.bitSizeMaybe i+    isSigned (Lba i) = B.isSigned i+    testBit (Lba i) = B.testBit i+    bit = Lba . B.bit+    popCount (Lba i) = B.popCount i+instance B.FiniteBits Lba where+    finiteBitSize (Lba i) = B.finiteBitSize i+instance P.PrintfArg Lba where+    formatArg = P.formatArg . (fromIntegral :: Lba -> Int)+instance S.Storable Lba where+    sizeOf (Lba i)    = S.sizeOf i+    alignment (Lba i) = S.alignment i+    peek p            = Lba <$> S.peek (C.castPtr p)+    poke p (Lba i)    = S.poke (C.castPtr p) i++foreign import ccall safe "cdio/compat/sector.h cdio_lsn_to_lba"+  lsnToLba :: CLsn -> CLba++foreign import ccall safe "cdio/compat/disc.h invalid_lba"+  invalidLba' :: CLba++-- | Filter out @CDIO_INVALID_LBA@ values for type-safe errors.+invalidLba :: CLba -> Maybe Lba+invalidLba = fmap fromIntegral . maybeError [invalidLba']+++-- | Marshal an address to a type which pins the required size of the C+-- representation, rather than the polymorphism of 'fromIntegral'.+withLsn :: Lsn -> CLsn+withLsn (Lsn i) = i++type CLsn = C.CInt++-- | The type-safe representation of a Logical Sector Number, counting sectors+-- from the start of track 1; this notably excludes the blank session lead-in.+-- See also 'Lba'.+newtype Lsn = Lsn CLsn+  deriving ( Eq, Ord, Show, Read )+instance Bounded Lsn where+    minBound = Lsn minLsn+    maxBound = Lsn maxLsn+instance Enum Lsn where+    toEnum = Lsn . toEnum+    fromEnum (Lsn i) = fromEnum i+instance I.Ix Lsn where+    range (Lsn a, Lsn b) = map Lsn [a..b]+    inRange (a, b) i = a <= i && i <= b+    index r@(a, b) i = Y.fromMaybe (error $ "Ix(Lsn).index: Index (" ++ show i ++ ") out of range (" ++ show r ++ ")")+                     $ L.elemIndex i [a..b]+instance Num Lsn where+    Lsn a + Lsn b = Lsn $ a + b+    Lsn a - Lsn b = Lsn $ a - b+    Lsn a * Lsn b = Lsn $ a * b+    abs (Lsn i) = Lsn $ abs i+    signum (Lsn i) = Lsn $ signum i+    fromInteger = Lsn . fromInteger+instance Real Lsn where+    toRational (Lsn i) = toRational i+instance Integral Lsn where+    quotRem (Lsn i) (Lsn d) = (Lsn q, Lsn r)+      where (q, r) = quotRem i d+    toInteger (Lsn i) = toInteger i+instance B.Bits Lsn where+    (Lsn a) .&. (Lsn b) = Lsn $ a .&. b+    (Lsn a) .|. (Lsn b) = Lsn $ a .|. b+    xor (Lsn a) (Lsn b) = Lsn $ B.xor a b+    complement (Lsn i) = Lsn $ B.complement i+    shift (Lsn i) = Lsn . B.shift i+    rotate (Lsn i) = Lsn . B.rotate i+    bitSize (Lsn i) = B.finiteBitSize i+    bitSizeMaybe (Lsn i) = B.bitSizeMaybe i+    isSigned (Lsn i) = B.isSigned i+    testBit (Lsn i) = B.testBit i+    bit = Lsn . B.bit+    popCount (Lsn i) = B.popCount i+instance B.FiniteBits Lsn where+    finiteBitSize (Lsn i) = B.finiteBitSize i+instance P.PrintfArg Lsn where+    formatArg = P.formatArg . (fromIntegral :: Lsn -> Int)+instance S.Storable Lsn where+    sizeOf (Lsn i)    = S.sizeOf i+    alignment (Lsn i) = S.alignment i+    peek p            = Lsn <$> S.peek (C.castPtr p)+    poke p (Lsn i)    = S.poke (C.castPtr p) i++foreign import ccall safe "cdio/compat/sector.h min_lsn"+  minLsn :: CLsn++foreign import ccall safe "cdio/compat/sector.h max_lsn"+  maxLsn :: CLsn++foreign import ccall safe "cdio/compat/disc.h invalid_lsn"+  invalidLsn' :: CLsn++-- | Filter out @CDIO_INVALID_LSN@ values for type-safe errors.+invalidLsn :: CLsn -> Maybe Lsn+invalidLsn = fmap fromIntegral . maybeError [invalidLsn']++-- | Filter out both @0@ and @CDIO_INVALID_LSN@ values for type-safe errors.+invalidZeroLsn :: CLsn -> Maybe Lsn+invalidZeroLsn = fmap fromIntegral . maybeError [0, invalidLsn']+++-- | Marshal a track number to a type which pins the required size of the C+-- representation, rather than the polymorphism of 'fromIntegral'.  Note that+-- @withTrack 'DiscLeadout' /= fromIntegral (fromEnum 'DiscLeadout')@+withTrack :: Track -> CTrack+withTrack DiscPregap = 0+withTrack (Track (TrackNum i)) = fromIntegral i + minTrack'+withTrack DiscLeadout = leadoutTrack'++type CTrack = C.CUChar++-- | Opaque newtype representing the numeric index of a 'Track', while+-- enforcing the invariants inherant to the specification.  Of very limited+-- utility outside that context.+newtype TrackNum = TrackNum Word+  deriving ( Eq, Ord )+instance Bounded TrackNum where+    minBound = TrackNum 0+    maxBound = TrackNum $ maxTrackW - minTrackW+instance Show TrackNum where+    show (TrackNum i) = show $ i + minTrackW+instance Read TrackNum where+    readsPrec d = \str -> do+        (i, str') <- readsPrec d str+        return (TrackNum $ i - minTrackW, str')++-- | An index into the segmentation within a write session on a disc.+data Track+    = DiscPregap+        -- ^ The (usually buffer) data located before the first track on a+        -- disc.+    | Track TrackNum+        -- ^ The common understanding of a CD track: a segment of the data on+        -- the disc containing (usually) a single song.+    | DiscLeadout+        -- ^ Any (usually buffer) data located after the end of the last track+        -- on a disc.+  deriving ( Eq, Ord, Show )+instance Bounded Track where+    minBound = DiscPregap+    maxBound = DiscLeadout+-- | Note that @'fromEnum' 'DiscLeadout'@ uses a value (== 100) chosen to be+-- contiguous to the rest of the datatype rather than that used internally+-- (== 0xAA).  'toEnum' accepts both values.+instance Enum Track where+    toEnum i+        | i < fromIntegral minTrack' = DiscPregap+        | i > fromIntegral maxTrack' = DiscLeadout+        | otherwise = Track . TrackNum $ fromIntegral i - minTrackW+    fromEnum DiscPregap = fromIntegral minTrack' - 1+    fromEnum (Track (TrackNum i)) = fromIntegral $ i + minTrackW+    fromEnum DiscLeadout = fromIntegral maxTrack' + 1+    pred DiscPregap = error "Enum.pred(Track): tried to take `pred' of DiscPregap"+    pred (Track n@(TrackNum i))+        | n == minBound = DiscPregap+        | n > maxBound = DiscLeadout+        | otherwise = Track . TrackNum $ i - 1+    pred DiscLeadout = Track maxBound+    succ DiscPregap = Track minBound+    succ (Track n@(TrackNum i))+        | n >= maxBound = DiscLeadout+        | otherwise = Track . TrackNum $ i + 1+    succ DiscLeadout = error "Enum.succ(Track): tried to take `succ' of DiscLeadout"+instance Read Track where+    readsPrec d = \s ->+        [ (DiscPregap, s')+        | ("DiscPregap", s') <- lex s+        ] +++        [ (DiscLeadout, s')+        | ("DiscLeadout", s') <- lex s+        ] +++        [ (packTrack i, s')+        | (i, s') <- readParen (d > 10) readsTrack s+        ]+      where packTrack i+                | i < minTrackW = DiscPregap+                | i > maxTrackW = DiscLeadout+                | otherwise = Track . TrackNum $ i - minTrackW+            readsTrack s =+                [ (i, s'')+                | ("Track", s') <- lex s+                , (i, s'') <- readsPrec 10 s'+                ]+instance I.Ix Track where+    range (a, b) = map toEnum [fromEnum a..fromEnum b]+    inRange (a, b) i = a <= i && i <= b+    index r@(a, b) i = Y.fromMaybe (error $ "Ix(Track).index: Index (" ++ show i ++ ") out of range (" ++ show r ++ ")")+                     $ L.elemIndex i [a..b]+instance Num Track where+    a + b = toEnum $ fromEnum a + fromEnum b+    a - b = toEnum $ fromEnum a - fromEnum b+    a * b = toEnum $ fromEnum a * fromEnum b+    abs t = t+    signum _ = DiscPregap+    fromInteger = toEnum . fromInteger+instance P.PrintfArg Track where+    formatArg t = P.formatInt $ withTrack t+-- | Note that 'S.poke' uses the official representation of 'DiscLeadout'+-- (@CDIO_CDROM_LEADOUT_TRACK == 0xAA@, as used by libcdio) rather than the+-- hscdio @'fromEnum' 'DiscLeadout'@ (== 100), as the latter was chosen for+-- proximity to the other constructors.+instance S.Storable Track where+    sizeOf _    = S.sizeOf leadoutTrack'+    alignment _ = S.alignment leadoutTrack'+    peek p      = toEnum . fromIntegral <$> S.peek (C.castPtr p :: C.Ptr CTrack)+    poke p      = S.poke (C.castPtr p) . withTrack++-- | The first data track on a disc (i.e. @'Track' 1@).+minTrack :: Track+minTrack = fromIntegral minTrack'++minTrackW :: Word+minTrackW = fromIntegral minTrack'++foreign import ccall safe "cdio/compat/track.h min_tracks"+  minTrack' :: CTrack++-- | The highest data track allowed by the specifications (i.e. @'Track' 99@).+maxTrack :: Track+maxTrack = fromIntegral maxTrack'++maxTrackW :: Word+maxTrackW = fromIntegral maxTrack'++foreign import ccall safe "cdio/compat/track.h max_tracks"+  maxTrack' :: CTrack++foreign import ccall safe "cdio/compat/track.h leadout_track"+  leadoutTrack' :: CTrack++foreign import ccall safe "cdio/compat/track.h invalid_track"+  invalidTrack' :: CTrack++-- | Filter out @CDIO_INVALID_TRACK@ values for type-safe errors.+invalidTrack :: CTrack -> Maybe Track+invalidTrack = fmap (toEnum . fromIntegral) . maybeError [invalidTrack']++-- | Filter out @CDIO_INVALID_TRACK@ and 'DiscPregap' values for type-safe+-- errors.+invalidZeroTrack :: CTrack -> Maybe Track+invalidZeroTrack = fmap (toEnum . fromIntegral) . maybeError [0, invalidTrack']+++-- | Number of ASCII bytes in a media catalog number.+mcnLength :: Word+mcnLength = fromIntegral mcnLength'++foreign import ccall safe "cdio/compat/types.h mcn_length"+  mcnLength' :: C.CUChar++{- Never used after definition.+-- | Some Media Catalog Number which identifies a disc; in practice usually a+-- UPC/EAN bar code.+newtype Mcn = Mcn String+  deriving ( Eq, Ord, Show, Read, Bounded )+instance S.Storable Mcn where+    sizeOf _       = S.sizeOf C.nullPtr+    alignment _    = S.alignment C.nullPtr+    peek p         = Mcn <$> C.peekCStringLen (C.castPtr p, mcnLength)+    poke p (Mcn s) = undefined+--}+++-- | Number of ASCII characters in an International Standard Recording Code.+isrcLength :: Word+isrcLength = fromIntegral isrcLength'++foreign import ccall safe "cdio/compat/types.h isrc_length"+  isrcLength' :: C.CUChar++{- Never used after definition.+-- | The International Standard Recording Code attached to a track of a disc,+-- as assigned by a central agency.+newtype Isrc = Isrc String+  deriving ( Eq, Ord, Show, Read, Bounded )+instance S.Storable Isrc where+    sizeOf _        = S.sizeOf C.nullPtr+    alignment _     = S.alignment C.nullPtr+    peek p          = Isrc <$> C.peekCStringLen (C.castPtr p, isrcLength)+    poke p (Isrc s) = undefined+-}
+ src/Foreign/Libcdio/Types/Offsets.chs view
@@ -0,0 +1,127 @@+{-|+Description:    c2hs-generated byte offsets for members of C structs.++Copyright:      (c) 2020 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      stable+Portability:    non-portable (requires libcdio)++Since this library already handles marshalling to and from C types itself, the+only remaining benefit to using c2hs for datatypes is not having to worry about+tracking the internal byte arrangement of C structs.  That can be done just as+easily externally here, with the added benefit of being able to analyze+coverage of the primary modules.  Just note that since this isn't exposed, it+/can not/ be used directly by any other c2hs-generated modules.+-}+module Foreign.Libcdio.Types.Offsets where+++import qualified Foreign.C.String as C+import qualified Foreign.Ptr as C++import qualified Foreign.Marshal.Array as M+import qualified Foreign.Storable as S+++pokeCString :: String -> Int -> C.CString -> IO ()+pokeCString s l p = C.withCStringLen (s ++ "\NUL") $ \(c, cl) ->+    if l < cl+    then M.copyArray p c (l - 1) >> S.poke (C.plusPtr p $ l - 1) '\NUL'+    else M.copyArray p c cl+++#include "cdio/compat/cd_types.h"+++iaSizeOf :: Int+iaSizeOf = {#sizeof cdio_iso_analysis_t#}++iaAlign :: Int+iaAlign = {#alignof cdio_iso_analysis_t#}++iaJolietLevel :: Int+iaJolietLevel = {#offsetof cdio_iso_analysis_t->joliet_level#}++iaLabel :: Int+iaLabel = {#offsetof cdio_iso_analysis_t->iso_label#}++iaIsoSize :: Int+iaIsoSize = {#offsetof cdio_iso_analysis_t->isofs_size#}++iaUDFMajor :: Int+iaUDFMajor = {#offsetof cdio_iso_analysis_t->UDFVerMajor#}++iaUDFMinor :: Int+iaUDFMinor = {#offsetof cdio_iso_analysis_t->UDFVerMinor#}++++#include "cdio/compat/device.h"+++hiSizeOf :: Int+hiSizeOf = {#sizeof cdio_hwinfo#}++hiAlign :: Int+hiAlign = {#alignof cdio_hwinfo#}++hiVendor :: Int+hiVendor = {#offsetof cdio_hwinfo->psz_vendor#}++hiModel :: Int+hiModel = {#offsetof cdio_hwinfo->psz_model#}++hiRevision :: Int+hiRevision = {#offsetof cdio_hwinfo->psz_revision#}++++#include "cdio/compat/logging.h"+++leSizeOf :: Int+leSizeOf = {#sizeof cdio_log_entry_t#}++leAlign :: Int+leAlign = {#alignof cdio_log_entry_t#}++leLevel :: Int+leLevel = {#offsetof cdio_log_entry_t->level#}++leMessage :: Int+leMessage = {#offsetof cdio_log_entry_t->message#}++lePrevious :: Int+lePrevious = {#offsetof cdio_log_entry_t->prev#}++++#include "cdio/compat/sector.h"+++-- c2hs can't handle the packed datatype, so get the values from C itself.+msfSizeOf :: Int+msfSizeOf = fromIntegral $ {#call pure sizeof_msf#}++msfAlign :: Int+msfAlign = {#alignof msf_t#}++msfM :: Int+msfM = {#offsetof msf_t->m#}++msfS :: Int+msfS = {#offsetof msf_t->s#}++msfF :: Int+msfF = {#offsetof msf_t->f#}+++{- Never used after definition.+adrSizeOf :: Int+adrSizeOf = {#sizeof cdio_cdrom_addr#}++adrAlign :: Int+adrAlign = {#alignof cdio_cdrom_addr#}+-}
+ src/Foreign/Libcdio/Util.hs view
@@ -0,0 +1,289 @@+{-# LANGUAGE ForeignFunctionInterface #-}++{-|+Description:    Miscellaneous utility functions, of limited utility.++Copyright:      (c) 2018-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      stable+Portability:    non-portable (requires libcdio)++Most functions defined by the C header either encapsulate math to perform on+an object or the system state, or edit `String's in some (barring allocations)+pure manner, including a few with general utility rather than being specific to+libcdio.  However, most are also restricted to internal use, and not provided+as symbols exported by the library itself; those internal functions are still+present in the Haskell source as well, for anyone interested.  As such, this+module and the functions it provides should rarely need to be used.+++= @util.h@++== Defines+* @CDIO_FREE_IF_NOT_NULL@           (removed; Haskell handles its own memory management)+* @CLAMP@                           (removed; preprocessor logic isn't required in Haskell)+* @IN@                              (removed; preprocessor logic isn't required in Haskell)+* @MAX@                             (removed; preprocessor logic isn't required in Haskell)+* @MAX@                             (removed; preprocessor logic isn't required in Haskell)++== Symbols+* @_cdio_strfreev@                  (removed; list is automatically freed)+* @_cdio_strsplit@                  -> 'Foreign.Libcdio.Util.strsplit'+* @cdio_from_bcd8@                  -> 'Foreign.Libcdio.Util.fromBcd8'+* @cdio_realpath@                   -> 'Foreign.Libcdio.Util.realpath'+* @cdio_to_bcd8@                    -> 'Foreign.Libcdio.Util.toBcd8'+-}+module Foreign.Libcdio.Util+    ( Bcd+    , toBcd8, fromBcd8+    , strsplit+    , realpath+    ) where+++{- Used only by not exported symbols+import qualified Foreign.ForeignPtr as C++import qualified Foreign.Marshal.Alloc as M+import qualified Foreign.Marshal.Array as M+import qualified Foreign.Marshal.Utils as M++import qualified System.IO.Unsafe as IO.Unsafe++import Foreign.Libcdio.Types.Internal+-}++import qualified Data.Word as W+++import qualified Data.Ix as I++import qualified Foreign.C.String as C+import qualified Foreign.C.Types as C+import qualified Foreign.Ptr as C++import qualified Foreign.Marshal.Utils as M+import qualified Foreign.Storable as S++import qualified Numeric as NM++import qualified Text.Printf as P+++import Foreign.Libcdio.Marshal+++{- Not exported+-- | Calculate how many blocks of a given size are required to contain the+-- given number of bytes.+len2blocks+    :: W.Word32+        -- ^ The number of bytes to fit.+    -> W.Word16+        -- ^ The size of each block.+    -> Lsn+len2blocks b s = fromIntegral $ len2blocks' (fromIntegral b) (fromIntegral s)++foreign import ccall safe "cdio/util.h _cdio_len2blocks"+  len2blocks' :: C.CUInt -> C.CUShort -> C.CInt++-- | Round up to the next block boundery after a given offset.+ceil2block+    :: Int+        -- ^ The base address to round.+    -> W.Word16+        -- ^ The size of each block.+    -> Int+ceil2block p s = fromIntegral $ ceil2block' (fromIntegral p) (fromIntegral s)++foreign import ccall safe "cdio/util.h _cdio_ceil2block"+  ceil2block' :: C.CInt -> C.CUShort -> C.CInt+++-- | Add a given length after a given address, potentially putting it at the+-- start of a new block if there is not enough space remaining in the one in+-- which the address is located.+ofsAdd+    :: Int+        -- ^ The base addres.+    -> Int+        -- ^ The number of bytes to add.+    -> W.Word16+        -- ^ The size of each block.+    -> Int+ofsAdd p a s = fromIntegral $ ofsAdd' (fromIntegral p) (fromIntegral a) (fromIntegral s)++foreign import ccall safe "cdio/util.h _cdio_ofs_add"+  ofsAdd' :: C.CInt -> C.CInt -> C.CUShort -> C.CInt+++-- | Print a 'True'/'False' value as "yes"/"no".+--+-- A similar, but not identical, result may be obtained with 'show'.+boolStr :: Bool -> String+boolStr = IO.Unsafe.unsafePerformIO . C.peekCString . boolStr' . M.fromBool++foreign import ccall safe "cdio/util.h _cdio_bool_str"+  boolStr' :: C.CInt -> C.CString+++-- | Copy the contents of one memory address to another, newly allocated one.+memdup :: C.Ptr a -> Word+    -> IO (Maybe (C.ForeignPtr a))+        -- ^ 'Nothing' if the source is 'nullPtr',+                                    -- or a pointer to the new memory.+memdup p s = do+    p' <- memdup' p (fromIntegral s)+    if p == C.nullPtr+    then return Nothing+    else Just <$> C.newForeignPtr cdioFreePtr p'++foreign import ccall safe "cdio/util.h _cdio_memdup"+  memdup' :: C.Ptr a -> C.CSize -> IO (C.Ptr a)+++-- | Create a copy of a string with all characters transformed to upper case.+--+-- This should be functionally identical to @map toUpper@.+strdupUpper :: String -> IO String+strdupUpper s = C.withCString s strdupUpper' >>= peekFString++foreign import ccall safe "cdio/util.h _cdio_strdup_upper"+  strdupUpper' :: C.CString -> IO C.CString++-- | Duplicate a path and make it platform compliant.  Typically needed for+-- MinGW\/MSYS where a "\/c\/..." path must be translated to "c:\/...".+strdupFixpath :: String -> IO (Maybe String)+strdupFixpath s = C.withCString s strdupFixpath' >>= peekNullFString++foreign import ccall safe "cdio/util.h _cdio_strdup_fixpath"+  strdupFixpath' :: C.CString -> IO C.CString+++-- | Count the number of C-style string pointers in a NULL-terminated array.+--+-- As we are already know the list is fully populated, this offers no benefit+-- over 'length'; Haskell's type system will not insert anything acting like a+-- string which is actually @NULL@.+strlenv :: [String] -> IO Word+strlenv ss = M.withMany C.withCString ss $ \ss' ->+    fromIntegral <$> M.withArray0 C.nullPtr ss' strlenv'++foreign import ccall safe "cdio/util.h _cdio_strlenv"+  strlenv' :: C.Ptr C.CString -> IO C.CSize+-}+++-- | Return the substrings between a given delimiter, dropping any empty ones.+--+-- The Haskell repositories provide this via+-- [split](https://hackage.haskell.org/package/split).+--+-- > strsplit str d == Data.List.Split.wordsBy (== d) str+strsplit :: String -> Char -> IO [String]+strsplit s c = C.withCString s (flip strsplit' . fromIntegral $ fromEnum c) >>= peekFStringArray++foreign import ccall safe "cdio/util.h _cdio_strsplit"+  strsplit' :: C.CString -> C.CChar -> IO (C.Ptr C.CString)+++-- | A bitwise encoding where the lower four bits encode a number modulo 10,+-- and the upper encode the same divided by 10.+newtype Bcd = Bcd W.Word8+instance Eq Bcd where+    a == b = fromBcd8 a == fromBcd8 b+instance Ord Bcd where+    compare a b = compare (fromBcd8 a) (fromBcd8 b)+instance Show Bcd where+    showsPrec p i@(Bcd w)+        | mod w 0x10 >= 0xA = showParen (p > application) $+            showString ("Bcd 0x" ++ pad) . NM.showHex w+        | otherwise = showsPrec p $ fromBcd8 i+      where application = 10+            pad | i >= 0x10 = ""+                | otherwise = "0"+instance Read Bcd where+    readsPrec p s =+           map toBcd8Fst (readsPrec p s)+        ++ readParen (p > application)+            (\r -> [ (Bcd i, v ++ ' ' : u)+                   | ("Bcd", t) <- lex r+                   , ('0':'x':l, u) <- lex t+                   , (i, v) <- NM.readHex l+                   ]) s+      where toBcd8Fst (w, b) = (toBcd8 w, b)+            application = 10+-- | >>> map fromBcd8 [minBound, maxBound]+-- [0, 159]+instance Bounded Bcd where+    minBound = Bcd 0+    maxBound = Bcd 0xF9+instance Enum Bcd where+    toEnum i = toBcd8 $ toEnum i+    fromEnum b = fromEnum $ fromBcd8 b+    succ i+        | i >= maxBound = error "Enum.succ(Bcd): tried to take `succ' of maxBound"+        | otherwise = toBcd8 . succ $ fromBcd8 i+    pred i+        | i <= minBound = error "Enum.pred(Bcd): tried to take `pred' of minBound"+        | otherwise = toBcd8 . pred $ fromBcd8 i+instance I.Ix Bcd where+    range (a, b) = map toBcd8 $ I.range (fromBcd8 a, fromBcd8 b)+    inRange (a, b) i = I.inRange (fromBcd8 a, fromBcd8 b) $ fromBcd8 i+    index (a, b) i = I.index (fromBcd8 a, fromBcd8 b) $ fromBcd8 i+instance Num Bcd where+    a + b = toBcd8 $ fromBcd8 a + fromBcd8 b+    a - b = toBcd8 $ fromBcd8 a - fromBcd8 b+    a * b = toBcd8 $ fromBcd8 a * fromBcd8 b+    abs i = i+    signum b = toBcd8 . signum $ fromBcd8 b+    fromInteger i = toBcd8 $ fromInteger i+instance Real Bcd where+    toRational b = toRational $ fromBcd8 b+instance Integral Bcd where+    quotRem dividend divisor = (toBcd8 q, toBcd8 r)+      where (q, r) = quotRem (fromBcd8 dividend) (fromBcd8 divisor)+    toInteger b = toInteger $ fromBcd8 b+instance P.PrintfArg Bcd where+    formatArg = P.formatArg . fromBcd8+instance S.Storable Bcd where+    sizeOf (Bcd i)    = S.sizeOf i+    alignment (Bcd i) = S.alignment i+    peek p            = Bcd <$> S.peek (C.castPtr p)+    poke p (Bcd i)    = S.poke (C.castPtr p) i++-- | Encode a number according to the libcdio BCD encoding.  If the value is+-- greater than @'maxBound' :: 'Bcd'@, it wraps back around to @0@.+toBcd8 :: Word -> Bcd+toBcd8 = Bcd . fromIntegral . toBcd8' . fromIntegral++foreign import ccall safe "cdio/util.h cdio_to_bcd8"+  toBcd8' :: C.CUInt -> C.CUInt++-- | Decode a number in the libcdio BCD encoding.+fromBcd8 :: Bcd -> Word+fromBcd8 (Bcd i) = fromIntegral . fromBcd8' $ fromIntegral i++foreign import ccall safe "cdio/util.h cdio_from_bcd8"+  fromBcd8' :: C.CUInt -> C.CUInt+++-- | Same as POSIX.1-2001 realpath, if the system provides it.  If not,+-- libcdio's "poor-man's simulation" of its behavior.+--+-- The Haskell repositories provide a similar alternative in+-- @System.Directory.canonicalizePath@ from+-- [directory](https://hackage.haskell.org/package/directory).+realpath :: String -> IO (Maybe String)+realpath s = C.withCString s (`realpath'` C.nullPtr) >>= M.maybePeek peekFString++foreign import ccall safe "cdio/util.h cdio_realpath"+  realpath' :: C.CString -> C.CString -> IO C.CString+++{- Pointer logic is not exposed.+-- | Some function which matches the free() prototype.+type DataFree = C.FunPtr (C.Ptr () -> IO ())+-}
+ src/Foreign/Libcdio/Version.hs view
@@ -0,0 +1,90 @@+{-# LANGUAGE ForeignFunctionInterface #-}++{-|+Description:    Objects used to determine which version of the C library is used.++Copyright:      (c) 2018-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      stable+Portability:    non-portable (requires libcdio)++The values in this module are best treated as informational; it may be helpful+to use 'cdioVersionString' in printing copyright, for example, and+'libcdioVersionNum' does serve a purpose in the tests, but all are of little+value outside of such very particular situations.  Instead, an effort has been+made to have all version differences in the base library degrade gracefully,+and those fallback values are able to be handled transparently.  For example,+rather than explicitly testing whether libcdio is new enough to have exposed+@cdtext_data_init@, simply call 'Foreign.Libcdio.CdText.cdTextDataInit' and+have a plan for if it returns 'Nothing' rather than a @'Just'+'Foreign.Libcdio.CdText.CdText'@.+++= @version.h@++== Defines+* @CDIO_VERSION@                    (removed; identical to 'cdioVersionString')+* @LIBCDIO_VERSION_NUM@             (removed; identical to 'libcdioVersionNum')++== Symbols+* @cdio_version_string@             -> 'cdioVersionString'+* @libcdio_version_num@             -> 'libcdioVersionNum'+++= "Sound.Libcdio"+Re-exported unchanged as there is little reason for it to be a separate module,+and no changes need to be made to the types.+-}+module Foreign.Libcdio.Version+    ( V.Version+    , V.makeVersion+    , cdioVersionString+    , libcdioVersionNum+    , apiVersion+    ) where+++import qualified Data.Version as V++import qualified Foreign.C.String as C+import qualified Foreign.C.Types as C++import qualified System.IO.Unsafe as IO.Unsafe+++-- | The value of the preprocessor macro @CDIO_VERSION@, listing both the+-- SemVar-style version of libcdio and the full architecture of the system+-- which compiled it (e.g. @2.0.0 x86_64-pc-linux-gnu@).+cdioVersionString :: String+cdioVersionString = IO.Unsafe.unsafePerformIO $ C.peekCString cdioVersionString'++foreign import ccall safe "cdio/compat/version.h get_cdio_version_string"+  cdioVersionString' :: C.CString+++-- | The value of the preprocessor macro @LIBCDIO_VERSION_NUM@, containing a+-- numeric representation of the version suitable for arithmetic testing.+libcdioVersionNum :: V.Version+libcdioVersionNum+    | v <= 94 = V.makeVersion [0, v]+    | v == 1 = V.makeVersion [1]+    | otherwise = V.makeVersion [j, n, p]+  where v = fromIntegral cdioVersionNum'+        (j, v') = divMod v 10000+        (n, p) = divMod v' 100++foreign import ccall safe "cdio/compat/version.h get_cdio_version_num"+  cdioVersionNum' :: C.CUInt+++-- | The value of the preprocessor macro @CDIO_API_VERSION@, containing a+-- single, monotonically increasing constant representing changes to the public+-- interface.  However, as it's somewhat unclear what changes warrant bumping+-- this number, it is typically better to use 'libcdioVersionNum' instead.+apiVersion :: Word+apiVersion = fromIntegral apiVersion'++foreign import ccall safe "cdio/compat/version.h get_cdio_version_api"+  apiVersion' :: C.CUInt
+ src/Sound/Libcdio.hs view
@@ -0,0 +1,48 @@+{-# OPTIONS_HADDOCK not-home #-}++{-|+Description:    High-level bindings providing a idiomatic Haskell interface to libcdio.++Copyright:      (c) 2019-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      stable+Portability:    non-portable (requires libcdio)++One of the goals of these bindings is to make it not only possible to interface+with the libcdio library, but to do so as comfortably and safely as possible.+In that, the "Foreign.Libcdio" interface is a bit lacking, due to its mutable+state and requirement of threading 'IO' through computations.  The modules in+this namespace provide an alternative which builds on that base, with a more+native style.  As a general rule, a project should /only/ import modules from+the @Sound@ or the @Foreign@ namespaces, not both, as while the types can often+be interchanged, several function names have been reused and so may collide.+-}+module Sound.Libcdio+    ( -- * Types+      -- ** Session+      Cdio+    , CdioError ( .. )+    , CdioErrorType ( .. )+    , SessionArg ( .. )+    , AccessMode ( .. )+      -- ** Version+    , Foreign.Version+    , Foreign.makeVersion+      -- * Evaluation+    , open+    , openMode+    , runCdio+    , getArg+    , getAccessMode+      -- * Library data+    , Foreign.cdioVersionString+    , Foreign.libcdioVersionNum+    , Foreign.apiVersion+    ) where+++import qualified Foreign.Libcdio.Version as Foreign++import Sound.Libcdio.Types.Cdio
+ src/Sound/Libcdio/Common.hs view
@@ -0,0 +1,20 @@+{-# LANGUAGE CPP #-}++module Sound.Libcdio.Common+    ( (<>)+    , CBool+    ) where+++#if MIN_VERSION_base(4,11,0)+#else+import Data.Monoid ( (<>) )+#endif+++#if MIN_VERSION_base(4,10,0)+import Foreign.C.Types ( CBool )+#else+import qualified Foreign.C.Types as C+type CBool = C.CUChar+#endif
+ src/Sound/Libcdio/Device.hs view
@@ -0,0 +1,143 @@+{-|+Description:    Information and procedures related to a system's (usually) physical disc drives.++Copyright:      (c) 2019-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      stable+Portability:    non-portable (requires libcdio)++Any software dealing with CDs has to deal with the fact that they are,+ultimately, a physical medium and thus reading from them requires interfacing+with system hardware.  This module provides the means to do just that.  Note+that, unlike the C and "Foreign.Libcdio" interfaces, however, this /doesn't/+provide any means to open a read session; that functionality is instead+exported directly from "Sound.Libcdio".+-}+module Sound.Libcdio.Device+    ( -- * Types+      Foreign.HardwareInfo ( .. )+    , Foreign.emptyHardwareInfo+    , Foreign.DriverId ( .. )+    , Foreign.DriverReturnCode ( .. )+      -- ** Capabilities+    , Foreign.DriveCaps+    , Foreign.DriveCapabilityRead ( .. )+    , Foreign.DriveReadCaps+    , Foreign.DriveCapabilityWrite ( .. )+    , Foreign.DriveWriteCaps+    , Foreign.capsWriteCd+    , Foreign.capsWriteDvd+    , Foreign.capsWrite+    , Foreign.DriveCapabilityMisc ( .. )+    , Foreign.DriveMiscCaps+      -- * Drivers+    , driver+    , Foreign.drivers+    , Foreign.osDriver+    , isImageDriver+    , isDevice+      -- * Session+    , setBlocksize+    , setSpeed+    , isMediaChanged+      -- * Devices+    , Foreign.devices+    , Foreign.defaultDevice+    , Foreign.defaultDeviceDriver+    , capabilities+    , deviceCapabilities+      -- ** Images+    , isCue+    , Foreign.isToc+    , Foreign.isNrg+      -- ** Hardware+    , hardware+    , haveAtapi+    , ejectDevice+    , closeDeviceTray+    , closeDeviceTray'+    ) where+++import qualified Data.Maybe as Y++import qualified Foreign.Libcdio.Device as Foreign++import Sound.Libcdio.Types.Cdio+++-- | Get the driver through which the disc is being read.+driver :: Cdio Foreign.DriverId+driver = liftCdio $ fmap (Y.fromMaybe Foreign.DriverUnknown) . Foreign.driverId++-- | Whether a particular driver deals with image files saved to disc, or a CD+-- drive itself.+isImageDriver :: Foreign.DriverId -> Bool+isImageDriver = not . flip elem Foreign.deviceDrivers+++-- | Get a description of the device in use.+hardware :: Cdio Foreign.HardwareInfo+hardware = liftCdio $ fmap (Y.fromMaybe Foreign.emptyHardwareInfo) . Foreign.hwinfo++-- | Which features are provided by the current device.  See+-- 'deviceCapabilities' when a session has not yet been opened.+capabilities :: Cdio Foreign.DriveCaps+capabilities = liftCdio Foreign.driveCap++-- | Whether ATAPI commands are understood by the current device.+-- +-- Returns 'Nothing' if the capability can't be determined.+haveAtapi :: Cdio (Maybe Bool)+haveAtapi = liftCdio Foreign.haveAtapi+++-- | Which features are provided by a particular device.  See 'capabilities'+-- for accessing these within a 'Cdio' session.+deviceCapabilities :: FilePath -> IO Foreign.DriveCaps+deviceCapabilities = Foreign.driveCapDevice+++-- | Open a particular device's tray or otherwise free any disc it holds for+-- removal, replacement, or insertion.+ejectDevice :: Maybe FilePath -> IO Foreign.DriverReturnCode+ejectDevice = Foreign.ejectDrive++-- | If a device supports discs on an extending, motorized tray (i.e. a+-- standard CD drive), close it.+closeDeviceTray :: Maybe FilePath -> IO Foreign.DriverReturnCode+closeDeviceTray = fmap fst . flip Foreign.closeTray Foreign.DriverUnknown++-- | As 'closeDeviceTray'', but specify the driver to use in case of ambiguity.+closeDeviceTray' :: Maybe FilePath -> Foreign.DriverId -> IO Foreign.DriverReturnCode+closeDeviceTray' p = fmap fst . Foreign.closeTray p+++-- | Specify how much data should be read from a disc at once.  Note that this+-- only affects the transport; any reading functions operate on independant+-- byte counts or other sizes derived from such.+setBlocksize :: Int -> Cdio Foreign.DriverReturnCode+setBlocksize s = liftCdio $ flip Foreign.setBlocksize s++-- | Specify the speed at which the disc is read.  Lower values result in+-- slower IO, but better accuracy.+setSpeed :: Int -> Cdio Foreign.DriverReturnCode+setSpeed s = liftCdio $ flip Foreign.setSpeed s+++-- | Check if any data in the read session has been changed since the last call+-- of this function.  This is most helpful when multiple 'Cdio' computations+-- are run on a partial call of 'Sound.Libcdio.Types.Cdio.open' or similar.+isMediaChanged :: Cdio (Either Foreign.DriverReturnCode Bool)+isMediaChanged = liftCdio Foreign.isMediaChanged+++-- | Whether a file is valid according to the (loose) CUE standard.+isCue :: FilePath -> IO Bool+isCue = fmap Y.isJust . Foreign.binFromCue++-- | Whether the path represents a physical disc drive in the system.+isDevice :: FilePath -> IO Bool+isDevice = flip Foreign.isDevice Foreign.DriverDevice
+ src/Sound/Libcdio/Logging.hs view
@@ -0,0 +1,92 @@+{-|+Description:    Control over and access to library log output.++Copyright:      (c) 2020-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      stable+Portability:    non-portable (requires libcdio)++The underlying library is rather loud in its error and warning messages,+potentially emitting a lot of impure terminal clutter even on some+otherwise-pure functions.  Very helpfully, it also provides a mechanism for+integrating the logs with whatever framework is in place for the larger+project; that mechanism can be leveraged to cache the logs in memory until+specifically asked for, at which point they can be packaged into Haskell types.+Some of the immediacy—and therefore user ability to match note to source—is+unfortunately lost, but the apparent purity is worth it.+-}+module Sound.Libcdio.Logging+    ( -- * Types+      LibcdioLogger ( .. )+    , Foreign.LogEntry ( .. )+    , Foreign.LogLevel ( .. )+      -- * Utility+    , isolateLogs+    , Foreign.setupLogger+    ) where+++import qualified Foreign.Libcdio.Logging as Foreign+++-- | An environment which integrates the libcdio logging interface; will almost+-- always be a 'Monad', but as an 'Applicative' might technically be able to+-- implement these, that constraint isn't enforced.+class LibcdioLogger m where+    logCutoff :: m Foreign.LogLevel+        -- ^ Check the current minimum severity which will be recorded in the+        -- logs.+    setLogCutoff :: Foreign.LogLevel -> m ()+        -- ^ Set the minimum severity required for a message to be recorded in+        -- the logs.+    readLog :: m [Foreign.LogEntry]+        -- ^ Retrieve all messages currently in the log for further processing.+        -- Note that this retains the contents of the log for future calls; to+        -- remove them, a separate call to 'clearLog' must be made.+        --+        -- >>> putLog $ LogEntry LogWarn "Testing log reading" >>= readLog+        -- [LogEntry LogWarn "Testing log reading"]+        --+        -- >>> clearLog >>= readLog+        -- []+    clearLog :: m ()+        -- ^ Empty all messages currently in the log.  There is no way to+        -- selectively remove only some messages; if that is desired, call+        -- 'readLog' first:+        --+        -- >>> setupLogger+        -- >>> msgs <- readLog+        -- >>> clearLog+        -- >>> mapM_ putLog $ filter p msgs+    putLog :: Foreign.LogEntry -> m ()+        -- ^ Append a message to the logs.++-- | The required initialization function 'Foreign.setupLogger' isn't called+-- automatically; /make sure/ to do so manually before using any of these.+instance LibcdioLogger IO where+    logCutoff = Foreign.logCutoff+    setLogCutoff = Foreign.setLogCutoff+    readLog = Foreign.readLog+    clearLog = Foreign.clearLog+    putLog = Foreign.putLog+++-- | Keep the monad pure by preventing it from reading stale logs, but since+-- the outer IO might still care about them, restore the entire stack after.+--+-- Note that the logs are /not/ thread-safe; messages from other threads may be+-- interwoven with those from the passed computation even after this function+-- is called.+isolateLogs :: (Monad m, LibcdioLogger m) => m a -> m a+isolateLogs a' = do+    es <- readLog+    clearLog++    a <- a'+    es' <- readLog+    clearLog++    mapM_ putLog $ es ++ es'+    return a
+ src/Sound/Libcdio/Read/CdText.hs view
@@ -0,0 +1,415 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE MultiParamTypeClasses #-}++{-|+Description:    Functions providing metadata about the contents of a disc.++Copyright:      (c) 2019-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      stable+Portability:    non-portable (requires libcdio)++Metadata is stored in a binary format both library-internally and on the disc.+Most audio archivists will recognize it as "those information fields in a CUE+file" (though there are [other+formats](https://www.gnu.org/software/libcdio/cd-text-format.html#Sony-Text-File-Format-_0028Input-Sheet-Version-0_002e7T_0029)+as well), and casual listeners will recognize it as the scrolling text that+you're always happy to see, on the rare times your music player shows it.+Little-used and even-less-known, however, is that a single disc can+theoretically contain metadata in up to eight different languages; because of+the complexity that introduces, it makes more sense to use a second monadic+interface than to try to provide a single monolithic datatype within 'Cdio'.+-}+module Sound.Libcdio.Read.CdText+    ( -- * Types+      CdText+    , CdTextError ( .. )+    , CdTextErrorType ( .. )+    , Info ( .. )+    , emptyInfo+    , Foreign.Genre ( .. )+    , Foreign.Language ( .. )+      -- * Evaluation+    , cdText+    , parseCdText+    , withLanguage+    , withIndex+    , withAll+    , runCdText+      -- * Data+    , language+    , languages+    , firstTrack+    , lastTrack+    , info+    , discId+    , genre+    , cdTextRaw+    ) where+++import qualified Control.Applicative as A+#if MIN_VERSION_mtl(2,2,1)+import qualified Control.Monad.Except as N.E+#else+import qualified Control.Monad.Error as N.E+#endif+import qualified Control.Monad.Fail as N.F++import qualified Data.ByteString as BS+import qualified Data.Maybe as Y+import qualified Data.Text as T++import qualified Foreign.Libcdio.CdText as Foreign+import qualified Foreign.Libcdio.Disc as Foreign+import qualified Foreign.Libcdio.Logging as Foreign++import qualified Text.Show as R++import Sound.Libcdio.Logging+import Sound.Libcdio.Track+import Sound.Libcdio.Types.Cdio++import Control.Applicative ( (<|>) )+import Data.Functor ( ($>) )+++-- | A computation within the environment of metadata (in a particular+-- language) stored on a CD.  The options for affecting that environment+-- from within are limited by design, as this library is intended for /reading/+-- discs rather than /authoring/ them.+newtype CdText a = CdText (Maybe InitialLanguage -> Foreign.Cdio -> IO (Either CdTextError a))+instance Functor CdText where+    fmap f (CdText a) = CdText $ \l c -> fmap f <$> a l c+instance Applicative CdText where+    pure a = CdText $ \_ _ -> return $ Right a+    CdText f <*> CdText a = CdText $ \l c -> do+        f' <- f l c+        a' <- a l c+        return $ f' <*> a'+-- | 'A.empty' fails with 'CdTextEmpty'.+instance A.Alternative CdText where+    empty = CdText $ \_ _ -> return . Left . CdTextError CdTextEmpty $ T.pack "empty"+    CdText f <|> CdText g = CdText $ \l c -> f l c <|> g l c+instance Monad CdText where+    CdText a >>= f = CdText $ \l c -> do+        a' <- a l c+        let bind' a'' = let CdText b = f a'' in b l c+        either (return . Left) bind' a'+-- | Wraps the text in a 'FreeformCdTextError', for recovery with 'N.E.catchError'.+instance N.F.MonadFail CdText where+    fail e = CdText $ \_ _ ->+        return . Left $ CdTextError (FreeformCdTextError $ T.pack e) (T.pack "fail")+instance N.E.MonadError CdTextError CdText where+    throwError err = CdText $ \_ _ -> return $ Left err+    catchError (CdText f) e = CdText $ \l c -> f l c >>= \a' -> case a' of+        Left err ->+            let CdText g = e err+            in  g l c+        Right a -> return $ Right a+instance LibcdioLogger CdText where+    logCutoff = CdText $ \_ _ -> Right <$> Foreign.logCutoff+    setLogCutoff l = CdText $ \_ _ -> Right <$> Foreign.setLogCutoff l+    readLog = CdText $ \_ _ -> Right <$> Foreign.readLog+    clearLog = CdText $ \_ _ -> Right <$> Foreign.clearLog+    putLog e = CdText $ \_ _ -> Right <$> Foreign.putLog e++-- | Lift a metadata computation from the C-style "Foreign.Libcdio" interface+-- into the monadic "Sound.Libcdio".+liftCdText :: (Foreign.Cdio -> IO a) -> CdText a+liftCdText f = CdText $ \_ c -> Right <$> f c+++-- | Associates a well-typed error with human-readable context information.+data CdTextError = CdTextError CdTextErrorType T.Text+  deriving ( Eq, Show, Read )++-- | Potential situations which may cause a computation to fail.+data CdTextErrorType+    = InvalidBlock Word+        -- ^ The requested language index is outside of the bounds accessible+        -- by the library (@[0..7]@ in libcdio 2.1 and after, or the smaller+        -- range of languages returned by 'languages' before that version).+    | LanguageNotFound Foreign.Language+        -- ^ The CdText data does not contain the requested language, or+        -- 'Foreign.UnknownLanguage' was requested (prior to libcdio 2.1 there+        -- was no way to select the latter blocks; even after that version,+        -- 'withIndex' must be used instead).+    | BadBinaryRead+        -- ^ The binary data can not be parsed into a CdText object.+    | NoCdText+        -- ^ The CD contains no CdText data.+    | CdTextEmpty+        -- ^ 'A.empty' was called and no better alternative was encountered.+    | FreeformCdTextError T.Text+        -- ^ Escape hatch from structured typing to allow user-specified+        -- (and user-triggered) errors.+  deriving ( Eq, Show, Read )+++-- | The language which was active at the beginning of the 'CdText'+-- computation.+data InitialLanguage+    = Lang Foreign.Language+        -- ^ The language was chosen specifically.+    | Index Word+        -- ^ The language was chosen by index.+    | Default+        -- ^ No language was explicitly set.++-- | Restore the active language to whatever it was before a 'CdText'+-- computation was run.+resetLanguage :: Maybe InitialLanguage -> Foreign.Cdio -> IO ()+resetLanguage Nothing _ = mempty+resetLanguage (Just (Lang l)) c = Foreign.selectLanguage c l >> mempty+resetLanguage (Just (Index i)) c = Foreign.selectLanguageIndex c i >> mempty+resetLanguage (Just Default) c = Foreign.selectLanguageIndex c 0 >> mempty+++-- | Textual metadata describing a single track on a disc, or the disc itself.+data Info = Info+    { title      :: Maybe T.Text+    , performer  :: Maybe T.Text+    , songwriter :: Maybe T.Text+    , composer   :: Maybe T.Text+    , arranger   :: Maybe T.Text+    , message    :: Maybe T.Text+        -- ^ An otherwise-uncategorized comment.+    , code       :: Maybe T.Text+        -- ^ Either a UPC/EAN (for the disc) or an ISRC (for a track).+    }+  deriving ( Eq )+-- | Modeled after the standard record syntax, but omitting any 'Nothing'+-- fields for space reasons.+instance Show Info where+    showsPrec d ts = R.showParen (d > 10)+        $ R.showString "Info { "+        . maybeShows title "title"+        . maybeShows performer "performer"+        . maybeShows songwriter "songwriter"+        . maybeShows composer "composer"+        . maybeShows arranger "arranger"+        . maybeShows message "message"+        . maybeShows code "code"+        . R.showString "}"+      where maybeShows f n+                | Just t <- f ts =+                      R.showString (n ++ " = ")+                    . shows t+                    . R.showString ", "+                | otherwise = id+instance Read Info where+    readsPrec p =+           readParen (p > 10) $ \r ->+            [ (Info t f w c a m o, r10)+            | ("Info", r1) <- lex r+            , ("{", r2) <- lex r1+            , (t, r3) <- maybeLex "title" r2+            , (f, r4) <- maybeLex "performer" r3+            , (w, r5) <- maybeLex "songwriter" r4+            , (c, r6) <- maybeLex "composer" r5+            , (a, r7) <- maybeLex "arranger" r6+            , (m, r8) <- maybeLex "message" r7+            , (o, r9) <- maybeLex "code" r8+            , ("}", r10) <- lex r9+            ]+      where maybeLex t s' = do+                (t', s1) <- lex s'+                if t == t'+                then do+                    ("=", s2) <- lex s1+                    (x, s3) <- reads s2+                    (",", s4) <- lex s3+                    return (Just x, s4)+                else return (Nothing, s')++-- | An 'Info' object with values suitable as defaults.+emptyInfo :: Info+emptyInfo = Info+    { title      = Nothing+    , performer  = Nothing+    , songwriter = Nothing+    , composer   = Nothing+    , arranger   = Nothing+    , message    = Nothing+    , code       = Nothing+    }+++-- | Use a C-style 'Foreign.Cdio' object as the base to run a Haskell-style+-- 'CdText' computation.+-- +-- Note that some invariants of the monadic interface may not work as expected+-- when used with the mutable objects, usually due to changing the active+-- language block:+-- +-- @+-- l  <- 'Foreign.language' cdio+-- _  <- 'runCdText' cdio $ 'withIndex' i g+-- l' <- 'Foreign.language' cdio+-- (l == l') == undefined+-- @+runCdText :: Foreign.Cdio -> CdText a -> IO (Either CdTextError a)+runCdText c (CdText f) = isolateLogs $ f Nothing c+++-- | Run the given computation within the CdText data associated with the+-- 'Cdio' session.  At this top level, a @'withIndex' 0@ specifically will+-- almost always have the same effect as running the computation directly.+-- Fails with 'NoCdText' if the disc doesn't provide any metadata.+cdText :: CdText a -> Cdio (Either CdTextError a)+cdText (CdText f) = liftCdio $ \c' -> if Foreign.hasCdText c'+    then isolateLogs $ f (Just Default) c'+    else return . Left . CdTextError NoCdText $ T.pack "cdText"++-- | Given a binary stream, attempt to parse it as a CdText block and run the+-- given computation.  Returns @'Left' 'BadBinaryRead'@ if that parse fails.+-- At this top level, a @'withIndex' 0@ specifically will almost always have+-- the same effect as running the computation directly.+--+-- Note that binary CdText dumps will frequently include four bytes at the+-- beginning indicating the size of the file; this implementation expects that+-- those bytes /are not/ included.  If your dump does indeed begin with them,+-- @'BS.drop' 4@ before passing the 'BS.ByteString' to this function.+--+-- /Before libcdio 0.94:  Always returns @'Left' 'BadBinaryRead'@/+parseCdText :: BS.ByteString -> CdText a -> IO (Either CdTextError a)+parseCdText bs (CdText f) = isolateLogs $ do+    c <- Foreign.cdTextDataInit bs+    case c of+        Just c' -> f (Just Default) c'+        Nothing -> return . Left . CdTextError BadBinaryRead $ T.pack "parseCdText"+++-- | Try to use a specific language as the context for the given computation;+-- as this will frequently fail with 'LanguageNotFound' if given anything other+-- than 'Foreign.English', it is recommended that you provide a fallback with+-- 'A.<|>' or at least allow recovery with 'A.optional'.  Note that+-- 'Foreign.UnknownLanguage' will always fail.+withLanguage :: Foreign.Language -> CdText a -> CdText a+withLanguage l (CdText f) = CdText $ \l' c -> isolateLogs $ do+    b <- Foreign.selectLanguage c l+    a <- if b+        then f (Just $ Lang l) c+        else return . Left . CdTextError (LanguageNotFound l) $ T.pack "withLanguage"+    resetLanguage l' c+    return a++-- | Run the given computation over the data in a specific block.  Fails with+-- 'InvalidBlock' if the index can't be accessed.+withIndex :: Word -> CdText a -> CdText a+withIndex i x = CdText $ \l c -> do+    a <- withIndex' "withIndex" c x i+    resetLanguage l c+    return a++-- | Underlying logic for index-based block selection.  Fails with+-- 'InvalidBlock' if the index can't be accessed.+withIndex'+    :: String+        -- ^ The function calling this, for error printing.+    -> Foreign.Cdio+        -- ^ The underlying disc session.+    -> CdText a+        -- ^ The computation to run.+    -> Word+        -- ^ The index to select.+    -> IO (Either CdTextError a)+withIndex' s c (CdText f) i = do+    b <- Foreign.selectLanguageIndex c i+    if b+    then f (Just $ Index i) c+    else return . Left . CdTextError (InvalidBlock i) $ T.pack s++-- | Run the given computation over /all/ of the accessible languages in the+-- CdText data.  When successful, the resulting list can be associated exactly+-- with the list of 'languages':+--+-- >>> ls <- 'languages'+-- >>> Right ls' <- 'cdText' $ 'withAll' 'language'+-- >>> ls == ls'+-- True+withAll :: CdText a -> CdText [Maybe a]+withAll x = CdText $ \l c -> do+    ls <- Foreign.listAllLanguages c+    let is = zipWith ($>) ls [0..]+    as <- mapM (withBlock c) is+    resetLanguage l c+    return $ sequence as+  where withBlock c (Just i) = fmap Just <$> withIndex' "withAll" c x i+        withBlock _ Nothing = return $ Right Nothing+++-- | Get the raw binary data making up the CdText data, if any exists on the+-- disc.+cdTextRaw :: Cdio (Maybe BS.ByteString)+cdTextRaw = liftCdio Foreign.cdTextRaw+++-- | Get the language in which any info is currently being retrieved.+language :: CdText Foreign.Language+language = liftCdText $ fmap (Y.fromMaybe Foreign.UnknownLanguage) . Foreign.language++-- | List every language with associated data in the CdText data associated+-- with the session.  Drops any 'Foreign.UnknownLanguage' values from the end+-- of the list.  For a version which operates within the 'CdText' monad, the+-- construction @'withAll' 'language'@ will have an identical effect.+--+-- /Before libcdio 2.1.0:  Silently drops any 'Nothing' or/+-- /@'Just' 'Foreign.UnknownLanguage'@ values, even in the middle of the list,/+-- /and only lists any single language a maximum of one time./+languages :: Cdio [Maybe Foreign.Language]+languages = liftCdio Foreign.listAllLanguages+++-- | The earliest track with any associated metadata in the current language.+-- Note that this may differ from 'Sound.Libcdio.Track.minTrack' which gives+-- the first track on the disk, CDTEXT or not.+firstTrack :: CdText Track+firstTrack = liftCdText $ fmap (Y.fromMaybe 1) . Foreign.firstTrack++-- | The final track with any associated metadata in the current language.+-- Note that this may differ from 'Sound.Libcdio.Track.maxTrack' which gives+-- the last track on the disc, CDTEXT or not.+lastTrack :: CdText Track+lastTrack = liftCdText $ fmap (Y.fromMaybe 1) . Foreign.lastTrack+++-- | Publisher-specific catalogue number, or some other context-specific+-- identifier.  Note that this may be different than @'code' $ 'info'+-- 'Nothing'@ which is (assumed to be) the unambiguous bar code unique to this+-- disc release.+discId :: CdText (Maybe T.Text)+discId = liftCdText $ \c -> fmap T.pack <$> Foreign.cdTextGet c Foreign.DiscId Nothing++-- | The genre describing the music on this disc, and any associated+-- human-readable name or subgenre.+genre :: CdText (Maybe Foreign.Genre, Maybe T.Text)+genre = liftCdText $ \c -> do+    g <- Foreign.genre c+    s <- Foreign.cdTextGet c Foreign.GenreName Nothing+    return (g, T.pack <$> s)+++-- | Retrieve the collection of data associated with a specific track, or if+-- 'Nothing', the disc itself.+info :: Maybe Track -> CdText Info+info t = liftCdText $ \c -> do+    l <- Foreign.cdTextGet c Foreign.Title t+    p <- Foreign.cdTextGet c Foreign.Performer t+    s <- Foreign.cdTextGet c Foreign.Songwriter t+    w <- Foreign.cdTextGet c Foreign.Composer t+    a <- Foreign.cdTextGet c Foreign.Arranger t+    m <- Foreign.cdTextGet c Foreign.Message t+    o <- Foreign.cdTextGet c (if Y.isNothing t then Foreign.UpcEan else Foreign.Isrc) t+    return $ Info+        { title = T.pack <$> l+        , performer = T.pack <$> p+        , songwriter = T.pack <$> s+        , composer = T.pack <$> w+        , arranger = T.pack <$> a+        , message = T.pack <$> m+        , code = T.pack <$> o+        }
+ src/Sound/Libcdio/Read/Data.hs view
@@ -0,0 +1,173 @@+{-|+Description:    Methods of retreaving the actual stored data.++Copyright:      (c) 2019-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      stable+Portability:    non-portable (requires libcdio)++This module is likely what most usage of the library revolves around:+retrieving the data stored on a CD.  For more discussion of the layout, see+"Foreign.Libcdio.Sector".+-}+module Sound.Libcdio.Read.Data+    ( -- * Types+      Foreign.Lsn+    , Foreign.Whence ( .. )+    , Foreign.DiscMode ( .. )+    , Foreign.isCdRom+    , Foreign.isDvd+      -- * Info+    , discMode+    , discJolietLevel+    , lastAddress+    , lastSessionAddress+    , audioTimestamp+    , catalogue+    , isrc+      -- * Read+      -- $read-design+    , seek+    , readRaw+    , readAudio+    , readData+    , readXa+      -- * Basic counts+    , Foreign.framesPerSec+    , maxCdSectors+    , maxCdMinutes+    , defaultPregapSectors+    , defaultPostgapSectors+    ) where+++import qualified Data.ByteString as BS+import qualified Data.Text as T++import qualified Foreign.Libcdio.Device as Foreign+import qualified Foreign.Libcdio.Disc as Foreign+import qualified Foreign.Libcdio.Read as Foreign+import qualified Foreign.Libcdio.Sector as Foreign+import qualified Foreign.Libcdio.Track as Foreign++import Sound.Libcdio.Device+import Sound.Libcdio.Types.Cdio+++-- | Determine which type of disc is being accessed.+discMode :: Cdio (Maybe Foreign.DiscMode)+discMode = liftCdio Foreign.discMode++-- | The original ISO 9660 (data) filesystem specification was rather+-- restrictive in what files could be named; the Joliet extensions allow such+-- exciting features as lowercase letters, not to mention full Unicode support.+discJolietLevel :: Cdio (Maybe Word)+discJolietLevel = liftCdio Foreign.discJolietLevel+++-- | Get the size of a disc in blocks, or equivalently the address of the end+-- of the readable data.+lastAddress :: Cdio (Maybe Foreign.Lsn)+lastAddress = liftCdio Foreign.lastLsn++-- | Get the starting address of the last write session of a disc.+lastSessionAddress :: Cdio (Either DriverReturnCode Foreign.Lsn)+lastSessionAddress = liftCdio Foreign.lastSession+++-- | The number of sectors spanned by a track pre-gap by default.+defaultPregapSectors :: Word+defaultPregapSectors = Foreign.pregapSectors++-- | The number of sectors spanned by a track post-gap by default.+defaultPostgapSectors :: Word+defaultPostgapSectors = Foreign.postgapSectors+++-- | Print a disc timestamp in the standard "MM:SS:FF" format, assuming the+-- address refers to audio data.+audioTimestamp :: Foreign.Lsn -> T.Text+audioTimestamp = T.pack . Foreign.msfToStr . Foreign.lsnToMsf++-- | The maximum number of sectors allowed to be stored on a disc.+maxCdSectors :: Word+maxCdSectors = Foreign.maxSectors++-- | The typical maximum length of a disc, though it's not a strict limit.+maxCdMinutes :: Word+maxCdMinutes = Foreign.cdMins+++-- | Get the media catalog number from a disc.  This may also be retrieved+-- by @'Sound.Libcdio.Read.CdText.code' $ 'Sound.Libcdio.Read.CdText.info'+-- 'Nothing'@, though that references a different source and thus may not have+-- the same return value.+catalogue :: Cdio (Maybe T.Text)+catalogue = liftCdio $ \c -> fmap T.pack <$> Foreign.cdMcn c++-- | The International Standard Recording Code the given track.  This may also+-- be retrieved by @'Sound.Libcdio.Read.CdText.code' .+-- 'Sound.Libcdio.Read.CdText.info' $ 'Just' t@, though that references a+-- different source and thus may not have the same return value.+isrc :: Foreign.Track -> Cdio (Maybe T.Text)+isrc t = liftCdio $ \c -> fmap T.pack <$> Foreign.trackIsrc c t+++-- $read-design+-- For now, the library isn't able to automatically determine which @read*@+-- function should be used; refer to 'Sound.Libcdio.Track.format', and switch+-- on its return value.  For more info on the various data layouts, see the+-- intro to "Foreign.Libcdio.Sector".+--+-- Compared to the C and @Foreign@ interfaces, /all/ read functions have been+-- tweaked for better internal consistency.  Where a @cdio_read@ or+-- 'Foreign.readBytes' call would ask for the number of bytes to read, here it+-- asks for the number of /sectors/.  On the other hand, the formerly+-- sector-oriented commands operate from the current 'seek' position rather+-- than, effectively, hiding a 'seek' behind the scenes.+++-- | Reposition the read pointer in the 'Cdio' session for a future call to+-- one of the @read*@ functions.+seek :: Int -> Foreign.Whence -> Cdio Foreign.Lsn+seek o w = liftCdioError $ \c -> do +    o' <- Foreign.seek c (o * fromIntegral Foreign.sectorSize) w+    pos <- case flip mod Foreign.sectorSize <$> o' of+        Right drift | drift /= 0 -> Foreign.seek c (fromIntegral $ negate drift) Foreign.SeekCurrent+        _ -> return o'+    return . packCdioError' "seek" $ fromIntegral . flip div Foreign.sectorSize <$> pos+++-- | Read a given number of sectors from the disc.  With data of a known+-- structure, use 'readAudio', 'readData', or 'readXa', which /don't/ include+-- the headers and footers described in "Foreign.Libcdio.Sector".+readRaw :: Word -> Cdio BS.ByteString+readRaw l = liftCdioError $ \c -> do+    bs <- Foreign.readBytes c (l * Foreign.sectorSize)+    return . packCdioError' "readAudio" $ maybe (Left Foreign.DriverError) Right bs++-- | Read a given number of sectors stored as CD-DA from the disc.+readAudio :: Word -> Cdio BS.ByteString+readAudio l = seek 0 Foreign.SeekCurrent >>= liftCdioError' (\c o ->+    packCdioError' "readAudio" <$> Foreign.readAudioSectors c o l)++-- | Read a given number of sectors stored as Mode 1 data from the disc.+readData+    :: Bool+        -- ^ If 'True' Form 2, otherwise Form 1 (see "Foreign.Libcdio.Sector").+    -> Word+    -> Cdio BS.ByteString+readData m l = seek 0 Foreign.SeekCurrent >>= liftCdioError' (\c o ->+    packCdioError' "readData" <$> Foreign.readDataModeSectors c o m l)++-- | Read a given number of sectors stored according to the Mode 2 extension+-- from the disc.+readXa+    :: Bool+        -- ^ If 'True' Form 2, otherwise Form 1 (see "Foreign.Libcdio.Sector").+    -> Word+    -> Cdio BS.ByteString+readXa f l = seek 0 Foreign.SeekCurrent >>= liftCdioError' (\c o ->+    packCdioError' "readXA" <$> Foreign.readXaModeSectors c o f l)
+ src/Sound/Libcdio/Read/Filesystem.hs view
@@ -0,0 +1,40 @@+{-|+Description:    Objects used to describe the CD and filesystem format.++Copyright:      (c) 2020-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      stable+Portability:    non-portable (requires libcdio)++Like any drive, discs may store their data according to many different+filesystem structures.  These are abstracted to a degree in libcdio, but as+each track may store its data differently, and at the very least+'Foreign.Audio' is handled differently than any of the file-oriented layouts,+it is still helpful to know the underlying structure.  This module, then, is a+counterpart to "Sound.Libcdio.Read.Data", providing information about the+/structure/ for the latter's retrieval of /data/.+-}+module Sound.Libcdio.Read.Filesystem+    ( -- * Types+      Foreign.Filesystem ( .. )+    , Foreign.FilesystemClass ( .. )+    , Foreign.FilesystemClasses+    , Foreign.fsAny+    , Foreign.fsAnyVcd+    , Foreign.IsoAnalysis ( .. )+      -- * Query+    , trackType+    ) where+++import qualified Foreign.Libcdio.CdTypes as Foreign++import Sound.Libcdio.Track+import Sound.Libcdio.Types.Cdio+++-- | Determine what type of file system is stored in the given track of a disc.+trackType :: Track -> Cdio (Maybe Foreign.Filesystem, Foreign.FilesystemClasses, Maybe Foreign.IsoAnalysis)+trackType = liftCdio . flip Foreign.trackType
+ src/Sound/Libcdio/Track.hs view
@@ -0,0 +1,128 @@+{-|+Description:    Information about the division of a single disc into tracks.++Copyright:      (c) 2019-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      stable+Portability:    non-portable (requires libcdio)++What many people would think of as the most important division on a CD isn't+quite as an integral a part of the physical data layout: they are described in+a table of contents before the first track of any recording session, and may+have lower-resolution "echoes" in the subchannels alongside the data, but it+would be hard to otherwise recover the track boundaries from the data itself.+This module, then, provides the functions to retrieve that metadata from the+table of contents and from the subchannels.+-}+module Sound.Libcdio.Track+    ( -- * Types+      Foreign.Track ( .. )+    , Foreign.minTrack+    , Foreign.maxTrack+    , Foreign.TrackNum+    , Foreign.TrackFormat ( .. )+      -- * Location+    , firstDiscTrack+    , lastDiscTrack+    , tracks+      -- ** Address+    , trackAt+    , pregap+    , offset+    , offsetEnd+    , totalLength+      -- * Data+    , format+    , isGreen+    , hasPreemphasis+    , copyPermit+    , quadAudio+    ) where+++import qualified Foreign.Libcdio.Disc as Foreign+import qualified Foreign.Libcdio.Track as Foreign++import Sound.Libcdio.Read.Data+import Sound.Libcdio.Types.Cdio+++-- | The number of the first track on the disc.  This will almost always be 1,+-- but that is not strictly guaranteed; the (perhaps theoretical) example is of+-- a multi-disc set, where later discs pick the numbering back up where the+-- previous one left off.+-- +-- Returns 'Nothing' if the disc table of contents can't be read.+firstDiscTrack :: Cdio (Maybe Foreign.Track)+firstDiscTrack = liftCdio Foreign.firstTrackNum++-- | The number of the last track on the disc.+-- +-- Returns 'Nothing' if the disc table of contents can't be read.+lastDiscTrack :: Cdio (Maybe Foreign.Track)+lastDiscTrack = liftCdio Foreign.lastTrackNum+++-- | Get the number of tracks on a CD.+-- +-- Returns 'Nothing' if the disc table of contents can't be read.+tracks :: Cdio (Maybe Foreign.Track)+tracks = liftCdio Foreign.numTracks++-- | The track which contains the given address.+-- +-- Returns 'Nothing' if the address is beyond the written data on the disc.+-- Note that 'Foreign.DiscLeadout' is treated as if it were a single sector+-- long:+-- +-- >>> Just endTrack <- lastDiscTrack+-- >>> Just endAddr <- offsetEnd endTrack+-- >>> trackAt $ endAddr + 1+-- Just DiscLeadout+-- >>> trackAt $ endAddr + 2+-- Nothing+trackAt :: Lsn -> Cdio (Maybe Foreign.Track)+trackAt = liftCdio . flip Foreign.trackAt+++-- | The address of the start of any pregap before the given track.+pregap :: Foreign.Track -> Cdio (Maybe Lsn)+pregap = liftCdio . flip Foreign.pregapLsn++-- | The address of the start of the given track.+offset :: Foreign.Track -> Cdio (Maybe Lsn)+offset = liftCdio . flip Foreign.trackLsn++-- | The address of the end of the given track.+offsetEnd :: Foreign.Track -> Cdio (Maybe Lsn)+offsetEnd = liftCdio . flip Foreign.trackLastLsn++-- | The number of sectors "assigned" to the specified track, including any in+-- the pregap between it and the following one.+totalLength :: Foreign.Track -> Cdio (Maybe Word)+totalLength = liftCdio . flip Foreign.sectorCount+++-- | The raw data structure of a track.+format :: Foreign.Track -> Cdio (Maybe Foreign.TrackFormat)+format = liftCdio . flip Foreign.trackFormat++-- | Whether the track data was stored using the Green Book (CD-i) standard.+isGreen :: Foreign.Track -> Cdio (Maybe Bool)+isGreen = liftCdio . flip Foreign.isGreen+++-- | Whether preemphasis has been applied to the track for noise reduction.+hasPreemphasis :: Foreign.Track -> Cdio (Maybe Bool)+hasPreemphasis = liftCdio . flip Foreign.hasPreemphasis++-- | Whether the track may be legally copied.+copyPermit :: Foreign.Track -> Cdio (Maybe Bool)+copyPermit = liftCdio . flip Foreign.copyPermit++-- | Whether the track was encoded with a richer 4-channel structure, or+-- whether it just includes the standard stereo (2-channel) layout.+quadAudio :: Foreign.Track -> Cdio (Maybe Bool)+quadAudio t = liftCdio $ \c -> fmap (> 2) <$> Foreign.numChannels c t
+ src/Sound/Libcdio/Types.hs view
@@ -0,0 +1,61 @@+{-# OPTIONS_HADDOCK not-home #-}++{-|+Description:    Common types used in the high-level interface.++Copyright:      (c) 2019-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      stable+Portability:    non-portable (requires libcdio)+-}+module Sound.Libcdio.Types+    ( -- * Disc+      Cdio+    , CdioError+    , CdioErrorType+    , Whence+    , Lsn+    , Track+    , TrackNum+    , TrackFormat+    , SessionArg+      -- * CdText+    , CdText+    , CdTextError+    , CdTextErrorType+    , Info+    , Genre+    , Language+      -- * Hardware+    , DriverId+    , DriverReturnCode+    , HardwareInfo+    , DriveCapabilityRead+    , DriveReadCaps+    , DriveCapabilityWrite+    , DriveWriteCaps+    , DriveCapabilityMisc+    , DriveMiscCaps+    , DriveCaps+    , DiscMode+      -- * Data+    , Filesystem+    , FilesystemClass+    , FilesystemClasses+    , IsoAnalysis+      -- * Logging+    , LibcdioLogger+    , LogEntry+    , LogLevel+    ) where+++import Sound.Libcdio.Device+import Sound.Libcdio.Logging+import Sound.Libcdio.Read.CdText+import Sound.Libcdio.Read.Data+import Sound.Libcdio.Read.Filesystem+import Sound.Libcdio.Track+import Sound.Libcdio.Types.Cdio
+ src/Sound/Libcdio/Types/Cdio.hs view
@@ -0,0 +1,243 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE MultiParamTypeClasses #-}++{-|+Description:    Internal module to allow constructor access without pollution.++Copyright:      (c) 2019-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      stable+Portability:    non-portable (requires libcdio)+-}+module Sound.Libcdio.Types.Cdio+    ( Cdio+    , CdioError ( .. )+    , CdioErrorType ( .. )+    , Foreign.SessionArg ( .. )+    , Foreign.AccessMode ( .. )+    , liftCdio+    , liftCdio'+    , liftCdioError+    , liftCdioError'+    , packCdioError+    , packCdioError'+    , open+    , openMode+    , getArg+    , getAccessMode+    , runCdio+    ) where+++import qualified Control.Applicative as A+#if MIN_VERSION_mtl(2,2,1)+import qualified Control.Monad.Except as N.E+#else+import qualified Control.Monad.Error as N.E+#endif+import qualified Control.Monad.Fail as N.F++import qualified Data.Text as T++import qualified Foreign.Libcdio.Device as Foreign+import qualified Foreign.Libcdio.Logging as Foreign++import Sound.Libcdio.Logging++import Control.Applicative ( (<|>) )+import Data.Array.BitArray ( (!) )+++-- | A computation within the environment of the data (music or file) stored on+-- a CD.  The options for affecting that environment from within are limited by+-- design, as this library is intended for /reading/ discs rather than+-- /authoring/ them.+newtype Cdio a = Cdio (Foreign.Cdio -> IO (Either CdioError a))+instance Functor Cdio where+    fmap f (Cdio a) = Cdio $ \c -> fmap f <$> a c+instance Applicative Cdio where+    pure a = Cdio . const . return $ Right a+    Cdio f <*> Cdio a = Cdio $ \c -> do+        f' <- f c+        a' <- a c+        return $ f' <*> a'+-- | 'A.empty' fails with 'CdioEmpty'.+instance A.Alternative Cdio where+    empty = Cdio $ \_ -> return . Left . CdioError CdioEmpty $ T.pack "empty"+    Cdio f <|> Cdio g = Cdio $ \c -> f c <|> g c+instance Monad Cdio where+    Cdio a >>= f = Cdio $ \c -> do+        a' <- a c+        case a' of+            Left e -> return $ Left e+            Right x -> let Cdio b = f x in b c+-- | Wraps the text in a 'FreeformCdioError', for recovery with 'N.E.catchError'.+instance N.F.MonadFail Cdio where+    fail e = Cdio . const . return . flip errorText "fail" . FreeformCdioError $ T.pack e+instance N.E.MonadError CdioError Cdio where+    throwError err = Cdio . const . return $ Left err+    catchError (Cdio f) e = Cdio $ \c -> f c >>= \a' -> case a' of+        Left err ->+            let Cdio g = e err+            in  g c+        Right a -> return $ Right a+instance LibcdioLogger Cdio where+    logCutoff = Cdio $ \_ -> Right <$> Foreign.logCutoff+    setLogCutoff l = Cdio $ \_ -> Right <$> Foreign.setLogCutoff l+    readLog = Cdio $ \_ -> Right <$> Foreign.readLog+    clearLog = Cdio $ \_ -> Right <$> Foreign.clearLog+    putLog e = Cdio $ \_ -> Right <$> Foreign.putLog e++-- | Lift a computation from the C-style "Foreign.Libcdio" interface into the+-- monadic "Sound.Libcdio".+liftCdio :: (Foreign.Cdio -> IO a) -> Cdio a+liftCdio f = Cdio $ fmap Right . f++-- | As 'liftCdio', but for functions which take a second argument alongside+-- the read session.+liftCdio' :: (Foreign.Cdio -> a -> IO b) -> a -> Cdio b+liftCdio' f a = Cdio $ fmap Right . flip f a++-- | As 'liftCdio', but for functions which may return an error code indicating+-- failure.+liftCdioError :: (Foreign.Cdio -> IO (Either CdioError a)) -> Cdio a+{-# INLINE liftCdioError #-}+liftCdioError = Cdio++-- | As 'liftCdio'', but for functions which may return an error code indicating+-- failure.+liftCdioError' :: (Foreign.Cdio -> a -> IO (Either CdioError b)) -> a -> Cdio b+liftCdioError' f a = Cdio $ flip f a+++-- | Associates a well-typed error with human-readable context information.+data CdioError = CdioError CdioErrorType T.Text+  deriving ( Eq, Show, Read )++-- | Potential situations which may cause a computation to fail.+data CdioErrorType+    = DriverError+        -- ^ A requested operation failed for some unknown reason, or the+        -- operating system doesn't support the 'Sound.Libcdio.Device.DriverId'+        -- in use.+    | BadParameter+        -- ^ Some value passed to a requested operation was rejected as+        -- nonsensical or otherwise breaking the value-level invariants.+    | NotPermitted+        -- ^ The ability to perform a requested operation has been restricted+        -- (e.g., the user doesn't have permission to access the disc drive).+    | SessionClosed+        -- ^ The underlying library closed the 'Cdio' session prematurely.+    | Unsupported+        -- ^ A requested operation isn't available with driver used by the+        -- 'Cdio' session.  Refer to 'Sound.Libcdio.Device.capabilities' and+        -- 'Sound.Libcdio.Device.deviceCapabilities' to reduce these.+    | CdioEmpty+        -- ^ 'A.empty' was called and no better alternative was encountered.+    | FreeformCdioError T.Text+        -- ^ Escape hatch from structured typing to allow user-specified+        -- (and user-triggered) errors.+  deriving ( Eq, Show, Read )++errorText :: CdioErrorType -> String -> Either CdioError a+errorText e = Left . CdioError e . T.pack++packCdioError :: String -> Foreign.DriverReturnCode -> a -> Either CdioError a+packCdioError _ Foreign.Success = Right+packCdioError s Foreign.DriverError = const $ errorText DriverError s+packCdioError s Foreign.Unsupported = const $ errorText Unsupported s+packCdioError s Foreign.Uninitialized = const $ errorText BadParameter s+packCdioError s Foreign.NotPermitted = const $ errorText NotPermitted s+packCdioError s Foreign.BadParameter = const $ errorText BadParameter s+packCdioError s Foreign.BadPointer = const $ errorText BadParameter s+packCdioError s Foreign.NoDriver = const $ errorText DriverError s+packCdioError _ Foreign.MmcSenseData = Right++packCdioError' :: String -> Either Foreign.DriverReturnCode a -> Either CdioError a+packCdioError' _ (Right a) = Right a+packCdioError' s (Left Foreign.Success) = errorText DriverError s+packCdioError' s (Left e) = packCdioError s e undefined+++-- | Use a C-style @"Foreign.Libcdio".'Foreign.Cdio'@ object as the base to run+-- a Haskell-style @"Sound.Libcdio".'Cdio'@ computation.+-- +-- Note that some invariants of the monadic interface may not work as expected+-- when used with the mutable objects.+runCdio :: Foreign.Cdio -> Cdio a -> IO (Either CdioError a)+runCdio c (Cdio f) = isolateLogs $ f c+++-- | Open a session to read data from the disc drive/image at the given+-- location.  If passed 'Nothing' instead, uses the path considered "default";+-- on operating systems with a concept of numbered devices (e.g., Window's @D:@+-- drive, FreeBSD's @\/dev\/cd0@) will usually return the first such device+-- found to be suitable.+open+    :: Maybe FilePath+    -> Bool+        -- ^ Whether the disc should be ejected after the computation.+    -> Cdio a+    -> IO (Either CdioError a)+open = open' "open" Nothing+++-- | Open a session to read data from the disc drive/image at the given+-- location, using a specific instruction set.  If passed 'Nothing' instead,+-- uses the path considered "default"; on operating systems with a concept of+-- numbered devices (e.g., Window's @D:@ drive, FreeBSD's @\/dev\/cd0@) will+-- usually return the first such device found to be suitable.+openMode+    :: Foreign.AccessMode+    -> Maybe FilePath+    -> Bool+        -- ^ Whether the disc should be ejected after the computation.+    -> Cdio a+    -> IO (Either CdioError a)+openMode = open' "openMode" . Just+++open'+    :: String+        -- ^ The name of the calling function, for error reporting.+    -> Maybe Foreign.AccessMode+    -> Maybe FilePath+    -> Bool+        -- ^ Whether the disc should be ejected after the computation.+    -> Cdio a+    -> IO (Either CdioError a)+open' s m p e (Cdio f) = isolateLogs $ do+    -- Rely on the driver autodetect behaviour.+    c <-  case m of+        Just m' -> Foreign.cdioOpenAm p Foreign.DriverUnknown m'+        Nothing -> Foreign.cdioOpen p Foreign.DriverUnknown+    case c of+        Just c' -> do+            a <- f c'+            -- This isn't actually necessary since the failure code is ignored,+            -- but it's a small cost to be sure nothing weird happens (e.g.+            -- printing a warning message).+            (_, _, cap) <- Foreign.driveCap c'+            let e' = if e && cap ! Foreign.MiscEject+                then Foreign.ejectMedia c'+                else return Foreign.Success+            e' >> return a+        -- There may be a chance memory allocation fails, but far and away the+        -- most common is a path which is not actually a device.+        Nothing -> do+            return $ errorText BadParameter s+++-- | Retrieve the session value associated with the given key.  The particular+-- case of @"access-mode"@ is instead handled by 'getAccessMode'.+getArg :: Foreign.SessionArg -> Cdio (Maybe T.Text)+getArg k = liftCdio $ \c -> do+    v <- Foreign.getArg c k+    return $ T.pack <$> v++-- | Check what instruction set is in use for reading the disc.  Other session+-- values are handled by 'getArg'.+getAccessMode :: Cdio (Maybe Foreign.AccessMode)+getAccessMode = liftCdio Foreign.getAccessMode
+ src/c/cdio/compat/cdtext.c view
@@ -0,0 +1,100 @@+#include "cdio/compat/cdtext.h"++#include "stdlib.h"+#include "string.h"++#include "cdio/compat/device.h"+#include "cdio/memory.h"+#include "cdio/compat/track.h"+#include "cdio/compat/version.h"+++// FFI-compatible wrappers++cdtext_genre_t genre_unused() {+    return CDTEXT_GENRE_UNUSED;+}++cdtext_lang_t language_unknown() {+    return CDTEXT_LANGUAGE_UNKNOWN;+}++cdtext_lang_t language_invalid() {+#if LIBCDIO_SINCE_VERSION_2_1+    return CDTEXT_LANGUAGE_INVALID;+#else+    return CDTEXT_LANGUAGE_UNKNOWN;+#endif+}++cdtext_lang_t language_unused() {+#if LIBCDIO_SINCE_VERSION_2_1+    return CDTEXT_LANGUAGE_BLOCK_UNUSED;+#else+    return CDTEXT_LANGUAGE_UNKNOWN;+#endif+}+++// Symbol compatibility definitions++cdtext_lang_t cdtext_str2lang_safe(const char* str) {+#if LIBCDIO_SINCE_VERSION_2_1+    return cdtext_str2lang(str);+#else+    return CDTEXT_LANGUAGE_UNKNOWN;+#endif+}+++int cdtext_data_init_safe(cdtext_t* cdtext, uint8_t* data, size_t len) {+#if LIBCDIO_SINCE_VERSION_0_94+    return cdtext_data_init(cdtext, data, len);+#else+    return -1;+#endif+}+++cdtext_lang_t* cdtext_list_languages_v2_safe(cdtext_t* cdtext) {+#if LIBCDIO_SINCE_VERSION_2_1+    return cdtext_list_languages_v2(cdtext);+#else+    return cdtext_list_languages(cdtext);+#endif+}++bool cdtext_set_language_index_safe(cdtext_t* cdtext, int i) {+#if LIBCDIO_SINCE_VERSION_2_1+    return cdtext_set_language_index(cdtext, i);+#else+    // If we don't have a builtin index function, fall back on the list of+    // languages we *do* have, and derive an index from that.++    cdtext_lang_t* langs = cdtext_list_languages(cdtext);+    cdtext_lang_t nub_langs[CDTEXT_NUM_BLOCKS_MAX];++    // The Haskell interface drops both blocks without a known language and+    // blocks with a language which was already used (since+    // `cdtext_select_language` is unable to select either), but the C list is+    // messier and needs to be cleaned for the index to be predictable.+    int found = 0;+    for (int j = 0; j < CDTEXT_NUM_BLOCKS_MAX; ++j) {+        if (langs[j] == CDTEXT_LANGUAGE_UNKNOWN)+            continue;+        for (int k = 0; k <= found; ++k) {+            if (k == found) {+                nub_langs[found] = langs[j];+                ++found;+                break;+            } else if (langs[k] == langs[j])+                break;+        }+    }++    if (i < 0 || i >= found)+        return cdtext_select_language(cdtext, CDTEXT_LANGUAGE_UNKNOWN);+    else+        return cdtext_select_language(cdtext, nub_langs[i]);+#endif+}
+ src/c/cdio/compat/device.c view
@@ -0,0 +1,110 @@+#include "cdio/compat/device.h"++#include "cdio/compat/version.h"++#include "stdlib.h"+++// FFI-compatible wrappers++const unsigned int vendor_len() {+    return CDIO_MMC_HW_VENDOR_LEN;+}++const unsigned int model_len() {+    return CDIO_MMC_HW_MODEL_LEN;+}++const unsigned int revision_len() {+    return CDIO_MMC_HW_REVISION_LEN;+}+++bitfield_t drive_cap_error() {+    return CDIO_DRIVE_CAP_ERROR;+}++bitfield_t drive_cap_unknown() {+    return CDIO_DRIVE_CAP_UNKNOWN;+}+++const driver_id_t* get_drivers() {+    return cdio_drivers;+}++const driver_id_t* get_device_drivers() {+    return cdio_device_drivers;+}++const driver_id_t get_os_driver() {+    return cdio_os_driver;+}+++// Symbol compatibility definitions++CdIo_t* cdio_open_bsdi_safe(const char* src) {+#if LIBCDIO_SINCE_VERSION_1_0+    return NULL;+#else+    return cdio_open_bsdi(src);+#endif+}++CdIo_t* cdio_open_am_bsdi_safe(const char* src, const char* mode) {+#if LIBCDIO_SINCE_VERSION_1_0+    return NULL;+#else+    return cdio_open_am_bsdi(src, mode);+#endif+}++char* cdio_get_default_device_bsdi_safe() {+#if LIBCDIO_SINCE_VERSION_1_0+    return NULL;+#else+    return cdio_get_default_device_bsdi();+#endif+}++char** cdio_get_devices_bsdi_safe() {+#if LIBCDIO_SINCE_VERSION_1_0+    return NULL;+#else+    return cdio_get_devices_bsdi();+#endif+}+++CdIo_t* cdio_open_os2_safe(const char* src) {+#if LIBCDIO_SINCE_VERSION_1_0+    return NULL;+#else+    return cdio_open_os2(src);+#endif+}++CdIo_t* cdio_open_am_os2_safe(const char* src, const char* mode) {+#if LIBCDIO_SINCE_VERSION_1_0+    return NULL;+#else+    return cdio_open_am_os2(src, mode);+#endif+}++char* cdio_get_default_device_os2_safe() {+#if LIBCDIO_SINCE_VERSION_1_0+    return NULL;+#else+    return cdio_get_default_device_os2();+#endif+}++char** cdio_get_devices_os2_safe() {+#if LIBCDIO_SINCE_VERSION_1_0+    return NULL;+#else+    return cdio_get_devices_os2();+#endif+}
+ src/c/cdio/compat/disc.c view
@@ -0,0 +1,32 @@+#include "cdio/compat/disc.h"++#include "cdio/compat/mmc.h"+++// FFI-compatible wrappers++const char* discmode_string(discmode_t dm) {+    if (dm > CDIO_DISC_MODE_CD_I || dm < CDIO_DISC_MODE_CD_DA)+        return discmode2str[CDIO_DISC_MODE_ERROR];+    else+        return discmode2str[dm];+}+++discmode_t discmode_error() {+    return CDIO_DISC_MODE_ERROR;+}+++// Marshalling aids++void get_cdtext_raw_len(CdIo_t* cdio, uint8_t** data, unsigned int* length) {+    *data = cdio_get_cdtext_raw(cdio);+    // Source diving to lib/driver/generic.h:read_cdtext_generic()+    if (data && *data)+        // The CDTEXT length includes the two always-null bytes before the+        // data, but *not* the two length bytes themselves.+        *length = CDIO_MMC_GET_LEN16(*data) - 2;+    else+        *length = 0;+}
+ src/c/cdio/compat/logging.c view
@@ -0,0 +1,91 @@+#include "cdio/compat/logging.h"++#include <stdlib.h>+#include <string.h>+++// Avoid unnecessary repeated calls; don't seem to mess anything up, but may as+// well keep clean.+bool replaced_cdio_logger = false;+++cdio_log_level_t get_cdio_log_level() {+    return cdio_loglevel_default;+}++void set_cdio_log_level(cdio_log_level_t l) {+    // The `_default` refers to the default handler, but it has explicitly been+    // opened up to alternate implementations as well.+    cdio_loglevel_default = l;+}+++void haskell_log_handler(cdio_log_level_t lvl, const char* msg) {+    if (lvl >= cdio_loglevel_default) {+        cdio_log_entry_t* entry = (cdio_log_entry_t*) malloc(sizeof(cdio_log_entry_t));+        if (!entry)+            return;++        // The Haskell garbage collector could easily clean anything logged+        // from the bindings before it's read.+        char* message = malloc(strlen(msg) + 1);+        if (!message) {+            free(entry);+            return;+        }+        else+            strcpy(message, msg);++        entry->level = lvl;+        entry->prev = haskell_log;+        entry->message = message;++        haskell_log = entry;+    }+}++void setup_cdio_logger() {+    if (!replaced_cdio_logger) {+        cdio_log_set_handler(*haskell_log_handler);+        haskell_log = NULL;+        replaced_cdio_logger = true;+    }+}+++cdio_log_entry_t** read_cdio_log() {+    if (!haskell_log)+        return NULL;++    // We need the total number of entries for determining allocation size.+    int count = 0;+    cdio_log_entry_t* entry = haskell_log;+    while (entry) {+        ++count;+        entry = entry->prev;+    }++    cdio_log_entry_t** out = (cdio_log_entry_t**) calloc(count + 1, sizeof(cdio_log_entry_t*));+    if (!out)+        return NULL;++    // ...and since we have the total anyway, may as well reverse the FILO into+    // chronological order now.+    entry = haskell_log;+    for (int i = count - 1; i >= 0; --i) {+        out[i] = entry;+        entry = entry->prev;+    }++    return out;+}++void free_cdio_log() {+    while (haskell_log) {+        cdio_log_entry_t* entry = haskell_log;+        haskell_log = entry->prev;+        if (entry->message)+            free((void *)entry->message);+        free(entry);+    }+}
+ src/c/cdio/compat/read.c view
@@ -0,0 +1,89 @@+#include "cdio/compat/read.h"++#include "stdlib.h"++#include "cdio/compat/sector.h"+++// Allocate the proper sizes in C, as Haskell marshalling for anything but+// simple `Storable` types is a bit awkward.++void read_bytes(const CdIo_t* cdio, void** buf, ssize_t* out, size_t bytes) {+    *buf = malloc(bytes);+    *out = cdio_read(cdio, *buf, bytes);+}+++uint16_t sector_size(cdio_read_mode_t mode) {+    switch (mode) {+        case CDIO_READ_MODE_AUDIO:+            return CDIO_CD_FRAMESIZE_RAW;+        case CDIO_READ_MODE_M1F1:+            return CDIO_CD_FRAMESIZE;+        case CDIO_READ_MODE_M1F2:+            return CDIO_CD_FRAMESIZE_RAW0;+        case CDIO_READ_MODE_M2F1:+            return CDIO_CD_FRAMESIZE;+        case CDIO_READ_MODE_M2F2:+            return M2F2_SECTOR_SIZE;+        default:+            return 0;+    }+}++void setup_read(void** buff, uint32_t* bytes, uint16_t blocksize, uint32_t blocks) {+    *bytes = blocksize * blocks;+    *buff = malloc(*bytes);+}+++// Marshalling aids++driver_return_code_t read_sector(const CdIo_t* cdio, void** buff, uint32_t* bytes, lsn_t lsn, cdio_read_mode_t mode) {+    setup_read(buff, bytes, sector_size(mode), 1);+    return cdio_read_sector(cdio, *buff, lsn, mode);+}++driver_return_code_t read_sectors(const CdIo_t* cdio, void** buff, uint32_t* bytes, lsn_t lsn, cdio_read_mode_t mode, uint32_t blocks) {+    setup_read(buff, bytes, sector_size(mode), blocks);+    return cdio_read_sectors(cdio, *buff, lsn, mode, blocks);+}+++driver_return_code_t read_data_sectors(const CdIo_t* cdio, void** buff, uint32_t* bytes, lsn_t lsn, uint16_t blocksize, uint32_t blocks) {+    setup_read(buff, bytes, blocksize, blocks);+    return cdio_read_data_sectors(cdio, *buff, lsn, blocksize, blocks);+}+++driver_return_code_t read_audio_sector(const CdIo_t* cdio, void** buff, uint32_t* bytes, lsn_t lsn) {+    setup_read(buff, bytes, sector_size(CDIO_READ_MODE_AUDIO), 1);+    return cdio_read_audio_sector(cdio, *buff, lsn);+}++driver_return_code_t read_audio_sectors(const CdIo_t* cdio, void** buff, uint32_t* bytes, lsn_t lsn, uint32_t blocks) {+    setup_read(buff, bytes, sector_size(CDIO_READ_MODE_AUDIO), blocks);+    return cdio_read_audio_sectors(cdio, *buff, lsn, blocks);+}+++driver_return_code_t read_mode1_sector(const CdIo_t* cdio, void** buff, uint32_t* bytes, lsn_t lsn, bool form2) {+    setup_read(buff, bytes, sector_size((form2 ? CDIO_READ_MODE_M1F2 : CDIO_READ_MODE_M1F1)), 1);+    return cdio_read_mode1_sector(cdio, *buff, lsn, form2);+}++driver_return_code_t read_mode1_sectors(const CdIo_t* cdio, void** buff, uint32_t* bytes, lsn_t lsn, bool form2, uint32_t blocks) {+    setup_read(buff, bytes, sector_size((form2 ? CDIO_READ_MODE_M1F2 : CDIO_READ_MODE_M1F1)), blocks);+    return cdio_read_mode1_sectors(cdio, *buff, lsn, form2, blocks);+}+++driver_return_code_t read_mode2_sector(const CdIo_t* cdio, void** buff, uint32_t* bytes, lsn_t lsn, bool form2) {+    setup_read(buff, bytes, sector_size((form2 ? CDIO_READ_MODE_M2F2 : CDIO_READ_MODE_M2F1)), 1);+    return cdio_read_mode2_sector(cdio, *buff, lsn, form2);+}++driver_return_code_t read_mode2_sectors(const CdIo_t* cdio, void** buff, uint32_t* bytes, lsn_t lsn, bool form2, uint32_t blocks) {+    setup_read(buff, bytes, sector_size((form2 ? CDIO_READ_MODE_M2F2 : CDIO_READ_MODE_M2F1)), blocks);+    return cdio_read_mode2_sectors(cdio, *buff, lsn, form2, blocks);+}
+ src/c/cdio/compat/sector.c view
@@ -0,0 +1,152 @@+#include "cdio/compat/sector.h"++#include "string.h"+++// FFI-compatible wrappings++lsn_t min_lsn() {+    return CDIO_CD_MIN_LSN;+}++lsn_t max_lsn() {+    return CDIO_CD_MAX_LSN;+}+++lba_t invalid_lba() {+    return CDIO_INVALID_LBA;+}++lsn_t invalid_lsn() {+    return CDIO_INVALID_LSN;+}+++size_t sizeof_msf() {+    return sizeof(msf_t);+}+++unsigned int pregap_sectors() {+    return CDIO_PREGAP_SECTORS;+}++unsigned int postgap_sectors() {+    return CDIO_POSTGAP_SECTORS;+}+++unsigned int cd_mins() {+    return CDIO_CD_MINS;+}++unsigned int secs_per_min() {+    return CDIO_CD_SECS_PER_MIN;+}++unsigned int frames_per_min() {+    return CDIO_CD_FRAMES_PER_MIN;+}++unsigned int frames_per_sec() {+    return CDIO_CD_FRAMES_PER_SEC;+}++unsigned int chunks_per_frame() {+    return CDIO_CD_NUM_OF_CHUNKS;+}+++unsigned int min_session() {+    return CDIO_CD_MIN_SESSION_NO;+}++unsigned int max_session() {+    return CDIO_CD_MAX_SESSIONS;+}+++unsigned int sync_size() {+    return CDIO_CD_SYNC_SIZE;+}++unsigned int chunk_size() {+    return CDIO_CD_CHUNK_SIZE;+}++unsigned int framesize_sub() {+    return CDIO_CD_FRAMESIZE_SUB;+}++unsigned int header_size() {+    return CDIO_CD_HEADER_SIZE;+}++unsigned int subheader_size() {+    return CDIO_CD_SUBHEADER_SIZE;+}++unsigned int edc_size() {+    return CDIO_CD_EDC_SIZE;+}++unsigned int mode1_pad_size() {+    return CDIO_CD_M1F1_ZERO_SIZE;+}++unsigned int ecc_size() {+    return CDIO_CD_ECC_SIZE;+}+++unsigned int framesize() {+    return CDIO_CD_FRAMESIZE;+}++unsigned int framesize_raw() {+    return CDIO_CD_FRAMESIZE_RAW;+}++unsigned int framesize_rawer() {+    return CDIO_CD_FRAMESIZE_RAWER;+}++unsigned int framesize_raw0() {+    return CDIO_CD_FRAMESIZE_RAW0;+}++unsigned int framesize_raw1() {+    return CDIO_CD_FRAMESIZE_RAW1;+}+++unsigned int header_size_xa() {+    return CDIO_CD_XA_HEADER;+}++unsigned int tail_size_xa() {+    return CDIO_CD_XA_TAIL;+}++unsigned int sync_size_xa() {+    return CDIO_CD_XA_SYNC_HEADER;+}++unsigned int data_size_xa() {+    return M2F2_SECTOR_SIZE;+}++unsigned int tagged_size_xa() {+    return M2SUB_SECTOR_SIZE;+}+++const uint8_t* sector_sync_header() {+    return CDIO_SECTOR_SYNC_HEADER;+}+++cdio_cd_minutes_sectors max_sectors() {+    return CDIO_CD_MAX_SECTORS;+}
+ src/c/cdio/compat/track.c view
@@ -0,0 +1,31 @@+#include "cdio/compat/track.h"+++// FFI-compatible wrappings++const char* track_format_string(track_format_t tf) {+    if (tf > TRACK_FORMAT_ERROR || tf < TRACK_FORMAT_AUDIO)+        return track_format2str[TRACK_FORMAT_ERROR];+    else+        return track_format2str[tf];+}++track_t invalid_track() {+    return CDIO_INVALID_TRACK;+}++track_t leadout_track() {+    return CDIO_CDROM_LEADOUT_TRACK;+}++track_format_t track_format_error() {+    return TRACK_FORMAT_ERROR;+}++track_t min_tracks() {+    return CDIO_CD_MIN_TRACK_NO;+}++track_t max_tracks() {+    return CDIO_CD_MAX_TRACKS;+}
+ src/c/cdio/compat/types.c view
@@ -0,0 +1,10 @@+#include "cdio/compat/types.h"+++unsigned char mcn_length() {+    return CDIO_MCN_SIZE;+}++unsigned char isrc_length() {+    return CDIO_ISRC_SIZE;+}
+ src/c/cdio/compat/version.c view
@@ -0,0 +1,16 @@+#include "cdio/compat/version.h"+++// FFI-compatible wrappings++const char* get_cdio_version_string() {+    return cdio_version_string;+}++const unsigned int get_cdio_version_num() {+    return libcdio_version_num;+}++const unsigned int get_cdio_version_api() {+    return CDIO_API_VERSION;+}
+ test/Data/Text/Encoding/MsJIS/Test/Classes.hs view
@@ -0,0 +1,65 @@+{-|+Description:    ++Copyright:      (c) 2020-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Data.Text.Encoding.MsJIS.Test.Classes+    ( laws+    , genJISChar+    , genDecodeError+    , genEncodeError+    ) where+++import qualified Hedgehog as H+import qualified Hedgehog.Gen as H.G+import qualified Hedgehog.Classes as H.C++import qualified Data.Text as T++import Data.Text.Encoding.MsJIS++import Test.Libcdio.Property.Common+++laws :: [LawsGroup]+laws =+    [ ("JISChar", map (\f -> f genJISChar)+        [ H.C.eqLaws+        , ordLaws'+        , H.C.showLaws+        , H.C.showReadLaws+        , H.C.boundedEnumLaws+        ]+    ), ("JISDecodeError", map (\f -> f genDecodeError)+        [ H.C.eqLaws+        , H.C.showLaws+        , H.C.showReadLaws+        ]+    ), ("JISEncodeError", map (\f -> f genEncodeError)+        [ H.C.eqLaws+        , H.C.showLaws+        , H.C.showReadLaws+        ]+    )]+++genJISChar :: H.Gen JISChar+genJISChar = H.G.enumBounded++genDecodeError :: H.Gen JISDecodeError+genDecodeError = do+    s <- genSample+    c <- H.G.maybe genJISChar+    return $ JISDecodeError (T.unpack s) c++genEncodeError :: H.Gen JISEncodeError+genEncodeError = do+    s <- genSample+    c <- H.G.maybe H.G.unicode+    return $ JISEncodeError (T.unpack s) c
+ test/Data/Text/Encoding/MsJIS/Test/Unit.hs view
@@ -0,0 +1,107 @@+{-|+Description:    ++Copyright:      (c) 2020 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Data.Text.Encoding.MsJIS.Test.Unit (tests) where+++import qualified Test.HUnit as U+import Test.HUnit ( (@=?), (@?=), (~:) )++import qualified Data.ByteString as BS+import qualified Data.Maybe as Y+import qualified Data.Text as T++import qualified System.IO.Unsafe as IO.U++import Data.Text.Encoding.MsJIS++import Test.Libcdio.Unit.Common+++testFile :: FilePath+testFile = dataFile "CP932.txt"++charRef :: [(JISChar, T.Text)]+charRef = IO.U.unsafePerformIO $ do+    ls <- lines <$> readFile testFile+    return . flip Y.mapMaybe ls $ \l -> case words l of+        [] -> Nothing+        [_] -> Nothing+        (('#':_):_) -> Nothing+        (_:('#':_):_) -> Nothing+        (j:u:_) -> Just (toJIS $ read j, T.singleton . toEnum $ read u)+  where toJIS i+            | i > 0xFF = uncurry Double . mapBoth fromIntegral $ divMod i (0x100 :: Word)+            | otherwise = Single $ fromIntegral i+++tests :: U.Test+tests = "Data.Text.Encoding.MsJIS" ~: U.TestList+    [ decode+    , encode+    , duplicatesDuplicated+    ]+++decode :: U.Test+decode = "JIS characters are read correctly" ~: U.TestList+    [ show j ++ " -> " ++ T.unpack u ~: U.TestCase (decodeMsJIS' (unpack j) @?= Right u)+    | (j, u) <- charRef+    ]++encode :: U.Test+encode = "JIS characters are encoded correctly" ~: U.TestList+    [ T.unpack u ++ " -> " ++ show j ~: U.TestCase (Right (unpack j) @=? encodeMsJIS' u)+    | (j, u) <- charRef+    , notElem j duplicateChars+    ]++duplicatesDuplicated :: U.Test+duplicatesDuplicated = "Duplicate JIS characters roundtrip to something else" ~: U.TestList+    [ U.TestCase $ do+        c <- either decodeFailure return $ decodeMsJIS' bs+        bs' <- either encodeFailure return $ encodeMsJIS' c+        U.assert $ bs /= bs'+    | bs <- map unpack duplicateChars+    ]+  where decodeFailure = U.assertFailure . mappend "JIS decode failed with " . show+        encodeFailure = U.assertFailure . mappend "JIS encode failed with " . show++unpack :: JISChar -> BS.ByteString+unpack (Single w) = BS.singleton w+unpack (Double l t) = BS.pack [l, t]++duplicateChars :: [JISChar]+duplicateChars =+    [ Double 0x81 0xBE+    , Double 0x81 0xBF+    , Double 0x81 0xCA+    , Double 0x81 0xDA+    , Double 0x81 0xDB+    , Double 0x81 0xDF+    , Double 0x81 0xE0+    , Double 0x81 0xE3+    , Double 0x81 0xE6+    , Double 0x81 0xE7+    ] +++    [ Double 0x87 t+    | t <- [0x54..0x5D]+    ] +++    [ Double 0x87 0x82+    , Double 0x87 0x84+    , Double 0x87 0x8A+    , Double 0x87 0x9A+    ] +++    [ Double 0xED t+    | t <- [0x40..0x7E] ++ [0x80..0xFC]+    ] +++    [ Double 0xEE t+    | t <- [0x40..0x7E] ++ [0x80..0xEC] ++ [0xEF..0xFC]+    ]
+ test/Foreign/Libcdio/CdText/Test/Classes.hs view
@@ -0,0 +1,60 @@+{-|+Description:    ++Copyright:      (c) 2019 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Foreign.Libcdio.CdText.Test.Classes+    ( laws+    , genGenre+    , genLanguage+    ) where+++import qualified Hedgehog as H+import qualified Hedgehog.Gen as H.G+import qualified Hedgehog.Classes as H.C++import Test.Libcdio.Property.Common++import Foreign.Libcdio.CdText+++laws :: [LawsGroup]+laws =+    [ ("Field", map (\f -> f genField)+        [ H.C.eqLaws+        , ordLaws'+        , H.C.showLaws+        , H.C.showReadLaws+        , H.C.boundedEnumLaws+        ]+    ), ("Genre", map (\f -> f genGenre)+        [ H.C.eqLaws+        , ordLaws'+        , H.C.showLaws+        , H.C.showReadLaws+        , H.C.boundedEnumLaws+        ]+    ), ("Language", map (\f -> f genLanguage)+        [ H.C.eqLaws+        , ordLaws'+        , H.C.showLaws+        , H.C.showReadLaws+        , H.C.boundedEnumLaws+        ]+    )]+++genField :: H.Gen Field+genField = H.G.enumBounded++genGenre :: H.Gen Genre+genGenre = H.G.enumBounded++genLanguage :: H.Gen Language+genLanguage = enumSparse
+ test/Foreign/Libcdio/CdTypes/Test/Classes.hs view
@@ -0,0 +1,84 @@+{-|+Description:    ++Copyright:      (c) 2019 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Foreign.Libcdio.CdTypes.Test.Classes+    ( laws+    , genFilesystem+    , genFilesystemClass+    , genIsoAnalysis+    ) where+++import qualified Hedgehog as H+import qualified Hedgehog.Gen as H.G+import qualified Hedgehog.Range as H.R+import qualified Hedgehog.Classes as H.C++import qualified Data.Text as T++import qualified Foreign.C.Types as C++import Foreign.Libcdio.CdTypes++import Test.Libcdio.Property.Common+++laws :: [LawsGroup]+laws =+    [ ("Filesystem", map (\f -> f genFilesystem)+        [ H.C.eqLaws+        , ordLaws'+        , H.C.showLaws+        , H.C.showReadLaws+        , H.C.boundedEnumLaws+        ]+    ), ("FilesystemClass", map (\f -> f genFilesystemClass)+        [ H.C.eqLaws+        , ordLaws'+        , H.C.showLaws+        , H.C.showReadLaws+        , H.C.boundedEnumLaws+        ]+    ), ("IsoAnalysis", map (\f -> f genIsoAnalysis)+        [ H.C.eqLaws+        , H.C.showLaws+        , H.C.showReadLaws+        , storableLaws'+        ]+    )]+++genFilesystem :: H.Gen Filesystem+genFilesystem = H.G.enumBounded++genFilesystemClass :: H.Gen FilesystemClass+genFilesystemClass = enumSparse++genIsoAnalysis :: H.Gen IsoAnalysis+genIsoAnalysis = do+    j <- H.G.maybe . H.G.word $ H.R.constant 1 3+    l <- genSample+    s <- H.G.integral (H.R.linearBounded :: H.R.Range C.CUInt)+    v <- H.G.maybe $ H.G.element+        [ (1, 0)+        , (1, 1)+        , (1, 2)+        , (1, 50)+        , (2, 0)+        , (2, 1)+        , (2, 50)+        , (2, 60)+        ]+    return $ IsoAnalysis+        { jolietLevel = j+        , label = T.unpack l+        , fsSize = fromIntegral s+        , udfVersion = v+        }
+ test/Foreign/Libcdio/Device/Test/Classes.hs view
@@ -0,0 +1,127 @@+{-|+Description:    ++Copyright:      (c) 2019-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Foreign.Libcdio.Device.Test.Classes+    ( laws+    , genDriveCapabilityRead+    , genDriveCapabilityWrite+    , genDriveCapabilityMisc+    , genHardwareInfo+    , genDriverId+    , genDriverReturnCode+    , genSessionArg+    , genAccessMode+    ) where+++import qualified Hedgehog as H+import qualified Hedgehog.Gen as H.G+import qualified Hedgehog.Range as H.R+import qualified Hedgehog.Classes as H.C++import Foreign.Libcdio.Device++import Test.Libcdio.Property.Common+++laws :: [LawsGroup]+laws =+    [ ("DriveCapabilityRead", map (\f -> f genDriveCapabilityRead)+        [ H.C.eqLaws+        , ordLaws'+        , H.C.showLaws+        , H.C.showReadLaws+        , H.C.boundedEnumLaws+        ]+    ), ("DriveCapabilityWrite", map (\f -> f genDriveCapabilityWrite)+        [ H.C.eqLaws+        , ordLaws'+        , H.C.showLaws+        , H.C.showReadLaws+        , H.C.boundedEnumLaws+        ]+    ), ("DriveCapabilityMisc", map (\f -> f genDriveCapabilityMisc)+        [ H.C.eqLaws+        , ordLaws'+        , H.C.showLaws+        , H.C.showReadLaws+        , H.C.boundedEnumLaws+        ]+    ), ("HardwareInfo", map (\f -> f genHardwareInfo)+        [ H.C.eqLaws+        , H.C.showLaws+        , H.C.showReadLaws+        , storableLaws'+        ]+    ), ("DriverId", map (\f -> f genDriverId)+        [ H.C.eqLaws+        , ordLaws'+        , H.C.showLaws+        , H.C.showReadLaws+        , H.C.boundedEnumLaws+        ]+    ), ("DriverReturnCode", map (\f -> f genDriverReturnCode)+        [ H.C.eqLaws+        , ordLaws'+        , H.C.showLaws+        , H.C.showReadLaws+        , H.C.boundedEnumLaws+        ]+    ), ("SessionArg", map (\f -> f genSessionArg)+        [ H.C.eqLaws+        , ordLaws'+        , H.C.showLaws+        , H.C.showReadLaws+        , H.C.boundedEnumLaws+        , storableLaws'+        ]+    ), ("AccessMode", map (\f -> f genAccessMode)+        [ H.C.eqLaws+        , ordLaws'+        , H.C.showLaws+        , H.C.showReadLaws+        , H.C.boundedEnumLaws+        , storableLaws'+        ]+    )]+++genDriveCapabilityRead :: H.Gen DriveCapabilityRead+genDriveCapabilityRead = enumSparse++genDriveCapabilityWrite :: H.Gen DriveCapabilityWrite+genDriveCapabilityWrite = enumSparse++genDriveCapabilityMisc :: H.Gen DriveCapabilityMisc+genDriveCapabilityMisc = enumSparse++genHardwareInfo :: H.Gen HardwareInfo+genHardwareInfo = do+    --TODO: Test other string lengths+    v <- H.G.string (H.R.singleton $ fromIntegral vendorLength) H.G.ascii+    m <- H.G.string (H.R.singleton $ fromIntegral modelLength) H.G.ascii+    r <- H.G.string (H.R.singleton $ fromIntegral revisionLength) H.G.ascii+    return $ HardwareInfo+        { vendor = v+        , model = m+        , revision = r+        }++genDriverId :: H.Gen DriverId+genDriverId = enumSparse++genDriverReturnCode :: H.Gen DriverReturnCode+genDriverReturnCode = enumSparse++genSessionArg :: H.Gen SessionArg+genSessionArg = H.G.enumBounded++genAccessMode :: H.Gen AccessMode+genAccessMode = H.G.enumBounded
+ test/Foreign/Libcdio/Disc/Test/Classes.hs view
@@ -0,0 +1,39 @@+{-|+Description:    ++Copyright:      (c) 2019 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Foreign.Libcdio.Disc.Test.Classes+    ( laws+    , genDiscMode+    ) where+++import qualified Hedgehog as H+import qualified Hedgehog.Gen as H.G+import qualified Hedgehog.Classes as H.C++import Foreign.Libcdio.Disc++import Test.Libcdio.Property.Common+++laws :: [LawsGroup]+laws =+    [ ("DiscMode", map (\f -> f genDiscMode)+        [ H.C.eqLaws+        , ordLaws'+        , H.C.showLaws+        , H.C.showReadLaws+        , H.C.boundedEnumLaws+        ]+    )]+++genDiscMode :: H.Gen DiscMode+genDiscMode = H.G.enumBounded
+ test/Foreign/Libcdio/Logging/Test/Classes.hs view
@@ -0,0 +1,57 @@+{-|+Description:    ++Copyright:      (c) 2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Foreign.Libcdio.Logging.Test.Classes+    ( laws+    , genLogEntry+    , genLogLevel+    ) where+++import qualified Hedgehog as H+import qualified Hedgehog.Gen as H.G+import qualified Hedgehog.Classes as H.C++import qualified Data.Text as T++import Foreign.Libcdio.Logging++import Test.Libcdio.Property.Common+++laws :: [LawsGroup]+laws =+    [ ("LogLevel", map (\f -> f genLogLevel)+        [ H.C.eqLaws+        , ordLaws'+        , H.C.showLaws+        , H.C.showReadLaws+        , H.C.boundedEnumLaws+        ]+    ), ("LogEntry", map (\f -> f genLogEntry)+        [ H.C.eqLaws+        , H.C.showLaws+        , H.C.showReadLaws+        , storableLaws'+        ]+    )]+++genLogLevel :: H.Gen LogLevel+genLogLevel = H.G.enumBounded++genLogEntry :: H.Gen LogEntry+genLogEntry = do+    l <- genLogLevel+    m <- genSample+    return $ LogEntry+        { logLevel = l+        , logMessage = T.unpack m+        }
+ test/Foreign/Libcdio/Logging/Test/Property.hs view
@@ -0,0 +1,82 @@+{-# LANGUAGE OverloadedStrings #-}++{-|+Description:    ++Copyright:      (c) 2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Foreign.Libcdio.Logging.Test.Property+    ( properties+    ) where+++import qualified Hedgehog as H+import qualified Hedgehog.Gen as H.G+import qualified Hedgehog.Range as H.R++import Foreign.Libcdio.Logging+import Foreign.Libcdio.Logging.Test.Classes++import Test.Libcdio.Property.Common++import Hedgehog ( (===) )+++properties :: H.Group+properties = H.Group "Foreign.Libcdio.Logging"+    [ setGetCutoff+    , filtered+ -- , retrieval+    , persistance+    , clear+    ]+++setGetCutoff :: Test+setGetCutoff = packTest "Cutoff level is successfully recovered" $ do+    H.evalIO setupLogger+    l <- H.forAll genLogLevel+    H.evalIO $ setLogCutoff l+    l' <- H.evalIO logCutoff+    l === l'+++logTest :: ([LogEntry] -> LogLevel -> H.PropertyT IO ()) -> H.PropertyT IO ()+logTest prop = do+    H.evalIO setupLogger+    H.evalIO clearLog+    minLevel <- H.forAll genLogLevel+    msgs <- H.forAll $ H.G.list (H.R.linear 0 16) genLogEntry+    H.evalIO $ setLogCutoff minLevel+    H.evalIO $ mapM_ putLog msgs+    prop msgs minLevel+    H.evalIO clearLog+++filtered :: Test+filtered = packTest "Log entries below the cutoff are hidden" . logTest $ \_ minLevel -> do+    msgs <- H.evalIO readLog+    H.annotateShow msgs+    H.assert . flip all msgs $ \msg -> logLevel msg >= minLevel++retrieval :: Test+retrieval = packTest "Log entries are read unchanged" . logTest $ \msgs minLevel -> do+    msgs' <- H.evalIO readLog+    filter (\msg -> logLevel msg >= minLevel) msgs === msgs'++persistance :: Test+persistance = packTest "'readLog' doesn't modify the logs" . logTest $ \_ _ -> do+    msgs <- H.evalIO readLog+    msgs' <- H.evalIO readLog+    msgs === msgs'++clear :: Test+clear = packTest "Clearing removes the entire log" . logTest $ \_ _ -> do+    H.evalIO clearLog+    msgs' <- H.evalIO readLog+    msgs' === []
+ test/Foreign/Libcdio/Read/Test/Classes.hs view
@@ -0,0 +1,50 @@+{-|+Description:    ++Copyright:      (c) 2019 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Foreign.Libcdio.Read.Test.Classes+    ( laws+    , genReadMode+    , genWhence+    ) where+++import qualified Hedgehog as H+import qualified Hedgehog.Gen as H.G+import qualified Hedgehog.Classes as H.C++import Foreign.Libcdio.Read++import Test.Libcdio.Property.Common+++laws :: [LawsGroup]+laws =+    [ ("ReadMode", map (\f -> f genReadMode)+        [ H.C.eqLaws+        , ordLaws'+        , H.C.showLaws+        , H.C.showReadLaws+        , H.C.boundedEnumLaws+        ]+    ), ("Whence", map (\f -> f genWhence)+        [ H.C.eqLaws+        , ordLaws'+        , H.C.showLaws+        , H.C.showReadLaws+        , H.C.boundedEnumLaws+        ]+    )]+++genReadMode :: H.Gen ReadMode+genReadMode = H.G.enumBounded++genWhence :: H.Gen Whence+genWhence = H.G.enumBounded
+ test/Foreign/Libcdio/Sector/Test/Classes.hs view
@@ -0,0 +1,91 @@+{-|+Description:    ++Copyright:      (c) 2019 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Foreign.Libcdio.Sector.Test.Classes+    ( laws+    , genSubchannelData+    , genFlag+    , genLba+    , genLsn+    , genMsf+    ) where+++import qualified Hedgehog as H+import qualified Hedgehog.Gen as H.G+import qualified Hedgehog.Classes as H.C+import qualified Hedgehog.Range as H.R++import Foreign.Libcdio.Sector++import Test.Libcdio.Property.Common+++laws :: [LawsGroup]+laws =+    [ ("SubchannelData", map (\f -> f genSubchannelData)+        [ H.C.eqLaws+        , ordLaws'+        , H.C.showLaws+        , H.C.showReadLaws+        , H.C.boundedEnumLaws+        ]+    ), ("Flag", map (\f -> f genFlag)+        [ H.C.eqLaws+        , ordLaws'+        , H.C.showLaws+        , H.C.showReadLaws+        , H.C.boundedEnumLaws+        ]+    ), ("Lba", map (\f -> f genLba)+        [ H.C.eqLaws+        , ordLaws'+        , H.C.showLaws+        , H.C.showReadLaws+        , H.C.boundedEnumLaws+        , H.C.bitsLaws+        , storableLaws'+        ]+    ), ("Integral Lba", [H.C.integralLaws $ nonZero genLba]+    ), ("Lsn", map (\f -> f genLsn)+        [ H.C.eqLaws+        , ordLaws'+        , H.C.showLaws+        , H.C.showReadLaws+        , H.C.boundedEnumLaws+        , H.C.bitsLaws+        , storableLaws'+        ]+    ), ("Integral Lsn", [H.C.integralLaws $ nonZero genLsn]+    ), ("Msf", map (\f -> f genMsf)+        [ H.C.eqLaws+        , ordLaws'+        , H.C.showLaws+        , H.C.showReadLaws+        , H.C.boundedEnumLaws+        , storableLaws'+        ]+    )]+++genSubchannelData :: H.Gen SubchannelData+genSubchannelData = H.G.enumBounded++genFlag :: H.Gen Flag+genFlag = enumSparse++genLba :: H.Gen Lba+genLba = H.G.integral (H.R.linearBounded :: H.R.Range Lba)++genLsn :: H.Gen Lsn+genLsn = H.G.integral (H.R.linearBounded :: H.R.Range Lsn)++genMsf :: H.Gen Msf+genMsf = H.G.enumBounded
+ test/Foreign/Libcdio/Track/Test/Classes.hs view
@@ -0,0 +1,63 @@+{-|+Description:    ++Copyright:      (c) 2019-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Foreign.Libcdio.Track.Test.Classes+    ( laws+    , genTrack+    , genTrackNum+    , genTrackFormat+    ) where+++import qualified Hedgehog as H+import qualified Hedgehog.Gen as H.G+import qualified Hedgehog.Classes as H.C++import Foreign.Libcdio.Track++import Test.Libcdio.Property.Common+++laws :: [LawsGroup]+laws =+    [ ("Track", map (\f -> f genTrack)+        [ H.C.eqLaws+        , ordLaws'+        , H.C.showLaws+        , H.C.showReadLaws+        , H.C.boundedEnumLaws+        , storableLaws'+        ]+    ), ("TrackNum", map (\f -> f genTrackNum)+        [ H.C.eqLaws+        , ordLaws'+        , H.C.showLaws+        , H.C.showReadLaws+        ]+    ), ("TrackFormat", map (\f -> f genTrackFormat)+        [ H.C.eqLaws+        , ordLaws'+        , H.C.showLaws+        , H.C.showReadLaws+        , H.C.boundedEnumLaws+        ]+    )]+++genTrack :: H.Gen Track+genTrack = H.G.enumBounded++genTrackNum :: H.Gen TrackNum+genTrackNum = do+    Track t <- H.G.enum minTrack maxTrack+    return t++genTrackFormat :: H.Gen TrackFormat+genTrackFormat = H.G.enumBounded
+ test/Foreign/Libcdio/Util/Test/Classes.hs view
@@ -0,0 +1,41 @@+{-|+Description:    ++Copyright:      (c) 2019-2020 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Foreign.Libcdio.Util.Test.Classes+    ( laws+    , genBcd+    ) where+++import qualified Hedgehog as H+import qualified Hedgehog.Gen as H.G+import qualified Hedgehog.Classes as H.C++import Foreign.Libcdio.Types++import Test.Libcdio.Property.Common+++laws :: [LawsGroup]+laws =+    [ ("Bcd", map (\f -> f genBcd)+        [ H.C.eqLaws+        , ordLaws'+        , H.C.showLaws+        , H.C.showReadLaws+        , H.C.boundedEnumLaws+        , storableLaws'+        ]+    ), ("Integral Bcd", [H.C.integralLaws $ nonZero genBcd]+    )]+++genBcd :: H.Gen Bcd+genBcd = H.G.enumBounded
+ test/Sound/Libcdio/CdText/Test/Classes.hs view
@@ -0,0 +1,78 @@+{-|+Description:    ++Copyright:      (c) 2020 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Sound.Libcdio.CdText.Test.Classes+    ( laws+    , genCdTextError+    , genCdTextErrorType+    , genInfo+    ) where+++import qualified Hedgehog as H+import qualified Hedgehog.Gen as H.G+import qualified Hedgehog.Range as H.R+import qualified Hedgehog.Classes as H.C++import Sound.Libcdio.Read.CdText++import Foreign.Libcdio.CdText.Test.Classes hiding ( laws )+import Test.Libcdio.Property.Common+++laws :: [LawsGroup]+laws =+    [ ("Info", map (\f -> f genInfo)+        [ H.C.eqLaws+        , H.C.showLaws+        , H.C.showReadLaws+        ]+    ), ("CdTextErrrorType", map (\f -> f genCdTextErrorType)+        [ H.C.eqLaws+        , H.C.showLaws+        , H.C.showReadLaws+        ]+    ), ("CdTextErrror", map (\f -> f genCdTextError)+        [ H.C.eqLaws+        , H.C.showLaws+        , H.C.showReadLaws+        ]+    )]+++genCdTextErrorType :: H.Gen CdTextErrorType+genCdTextErrorType = H.G.choice+    [ InvalidBlock <$> H.G.word H.R.linearBounded+    , LanguageNotFound <$> genLanguage+    , H.G.constant BadBinaryRead+    , FreeformCdTextError <$> genSample+    ]++genCdTextError :: H.Gen CdTextError+genCdTextError = CdTextError <$> genCdTextErrorType <*> genSample++genInfo :: H.Gen Info+genInfo = do+    t <- H.G.maybe genSample+    p <- H.G.maybe genSample+    s <- H.G.maybe genSample+    c <- H.G.maybe genSample+    a <- H.G.maybe genSample+    m <- H.G.maybe genSample+    o <- H.G.maybe genSample+    return $ Info+        { title = t+        , performer = p+        , songwriter = s+        , composer = c+        , arranger = a+        , message = m+        , code = o+        }
+ test/Sound/Libcdio/Cdio/Test/Classes.hs view
@@ -0,0 +1,55 @@+{-|+Description:    ++Copyright:      (c) 2020-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Sound.Libcdio.Cdio.Test.Classes+    ( laws+    , genCdioError+    , genCdioErrorType+    ) where+++import qualified Hedgehog as H+import qualified Hedgehog.Gen as H.G+import qualified Hedgehog.Classes as H.C++import Sound.Libcdio++import Test.Libcdio.Property.Common+++laws :: [LawsGroup]+laws =+    [ ("CdioErrrorType", map (\f -> f genCdioErrorType)+        [ H.C.eqLaws+        , H.C.showLaws+        , H.C.showReadLaws+        ]+    ), ("CdioErrror", map (\f -> f genCdioError)+        [ H.C.eqLaws+        , H.C.showLaws+        , H.C.showReadLaws+        ]+    )]+++genCdioErrorType :: H.Gen CdioErrorType+genCdioErrorType = H.G.frequency+    [ (6, H.G.element+        [ DriverError+        , BadParameter+        , NotPermitted+        , SessionClosed+        , Unsupported+        ])+    , (1, FreeformCdioError <$> genSample)+    ]++genCdioError :: H.Gen CdioError+genCdioError = CdioError <$> genCdioErrorType <*> genSample
+ test/Test/Libcdio/Property.hs view
@@ -0,0 +1,79 @@+{-|+Description:    ++Copyright:      (c) 2019-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    non-portable (requires "GHC.IO.Encoding")+-}+module Main where+++import qualified Data.Bool as B++import qualified GHC.IO.Encoding as GIO++import qualified Hedgehog as H+import qualified Hedgehog.Classes as H.C++import qualified System.Exit as E+import qualified System.IO as IO++import qualified Data.Text.Encoding.MsJIS.Test.Classes as MsJIS++import qualified Foreign.Libcdio.CdText.Test.Classes as CdText+import qualified Foreign.Libcdio.CdTypes.Test.Classes as CdTypes+import qualified Foreign.Libcdio.Device.Test.Classes as Device+import qualified Foreign.Libcdio.Disc.Test.Classes as Disc+import qualified Foreign.Libcdio.Logging.Test.Classes as Logging+import qualified Foreign.Libcdio.Read.Test.Classes as Read+import qualified Foreign.Libcdio.Sector.Test.Classes as Sector+import qualified Foreign.Libcdio.Track.Test.Classes as Track+import qualified Foreign.Libcdio.Util.Test.Classes as Util++import qualified Sound.Libcdio.Cdio.Test.Classes as S.Cdio+import qualified Sound.Libcdio.CdText.Test.Classes as S.CdText++import qualified Foreign.Libcdio.Logging.Test.Property as Logging++import Test.Libcdio.Property.Common+++laws :: [LawsGroup]+laws = concat+    [ MsJIS.laws+    , CdText.laws+    , CdTypes.laws+    , Device.laws+    , Disc.laws+    , Logging.laws+    , Read.laws+    , Sector.laws+    , Track.laws+    , Util.laws+    , S.Cdio.laws+    , S.CdText.laws+    ]+++parallelProperties :: [H.Group]+parallelProperties =+    [+    ]++sequentialProperties :: [H.Group]+sequentialProperties =+    [ Logging.properties+    ]+++main :: IO ()+main = do+    GIO.setLocaleEncoding IO.utf8+    lawsResult <- H.C.lawsCheckMany laws+    parallelResults <- mapM H.checkParallel parallelProperties+    sequentialResults <- mapM H.checkSequential sequentialProperties+    B.bool E.exitFailure E.exitSuccess . and $+        lawsResult : parallelResults ++ sequentialResults
+ test/Test/Libcdio/Property/Common.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE CPP #-}+{-# OPTIONS_GHC -Wno-redundant-constraints #-}++{-|+Description:    ++Copyright:      (c) 2019-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Test.Libcdio.Property.Common where+++import qualified Data.String as S+import qualified Data.Text as T++import qualified Hedgehog as H+import qualified Hedgehog.Gen as H.G+import qualified Hedgehog.Classes as H.C+import qualified Hedgehog.Range as H.R++import qualified Foreign.Storable as S+++type Test = (H.PropertyName, H.Property)+type LawsGroup = (String, [H.C.Laws])+++enumSparse :: (Enum a, Bounded a) => H.Gen a+enumSparse = H.G.element [minBound..maxBound]++nonZero :: (Eq a, Num a) => H.Gen a -> H.Gen a+nonZero = H.G.filter (/= 0)+++packTest :: String -> H.PropertyT IO () -> Test+packTest name prop = (S.fromString name, H.property prop)+++genSample :: H.Gen T.Text+genSample = H.G.text (H.R.linear 1 12) $ H.G.frequency [c7, c8]+  where c7 = (0x5F, H.G.enum ' ' '~')+        c8 = (0x60, H.G.enum '\xA0' '\xFF')+++ordLaws' :: (Ord a, Show a) => H.Gen a -> H.C.Laws+#if MIN_VERSION_hedgehog_classes(0,2,1)+ordLaws' = H.C.ordLaws+#else+ordLaws' = const $ H.C.Laws "Ord" []+#endif++storableLaws' :: (Eq a, Show a, S.Storable a) => H.Gen a -> H.C.Laws+#if MIN_VERSION_hedgehog_classes(0,2,6)+storableLaws' = H.C.storableLaws+#else+storableLaws' = const $ H.C.Laws "Storable" []+#endif
+ test/Test/Libcdio/Unit.hs view
@@ -0,0 +1,41 @@+{-|+Description:    ++Copyright:      (c) 2019 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Main where+++import qualified Control.Monad as M+import qualified System.Exit as E+import qualified Test.HUnit as U++import qualified Data.Text.Encoding.MsJIS.Test.Unit as MsJIS++import qualified Test.Libcdio.Unit.Foreign.CarolusRex as Rex+import qualified Test.Libcdio.Unit.Foreign.DeeperDance as Dance+import qualified Test.Libcdio.Unit.Foreign.RevolutionDays as Revolution++import qualified Test.Libcdio.Unit.Sound.CarolusRex as S.Rex+import qualified Test.Libcdio.Unit.Sound.DeeperDance as S.Dance+import qualified Test.Libcdio.Unit.Sound.RevolutionDays as S.Revolution+++main :: IO ()+main = do+    results <- U.runTestTT $ U.TestList+        [ MsJIS.tests+        , Dance.tests+        , Revolution.tests+        , Rex.tests+        , S.Dance.tests+        , S.Rex.tests+        , S.Revolution.tests+        ]+    +    M.unless (U.errors results == 0 && U.failures results == 0) E.exitFailure
+ test/Test/Libcdio/Unit/Common.hs view
@@ -0,0 +1,22 @@+{-|+Description:    ++Copyright:      (c) 2019-2020 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Test.Libcdio.Unit.Common where+++dataDir :: FilePath+dataDir = "test/datafiles/unit/"++dataFile :: FilePath -> FilePath+dataFile = (++) dataDir+++mapBoth :: (a -> b) -> (a, a) -> (b, b)+mapBoth f (l, r) = (f l, f r)
+ test/Test/Libcdio/Unit/Foreign/CarolusRex.hs view
@@ -0,0 +1,102 @@+{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}++{-|+Description:    Tests of multi-block CDTEXT in the Foreign interface.++Copyright:      (c) 2019-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable++The CDTEXT file used in this module was generated using the tool written by+Pigeon at <https://pigeonsnest.co.uk/stuff/cdtext.html> (warning for a /lot/ of+swearing).  The encoding was later manually set to ASCII.+-}+module Test.Libcdio.Unit.Foreign.CarolusRex (tests) where+++import qualified Test.HUnit as U+import Test.HUnit ( (@?), (@?=), (~:) )++import qualified Data.ByteString as BS+import qualified Data.Maybe as Y++import Foreign.Libcdio.CdText++import Test.Libcdio.Unit.Common+++testFile :: FilePath+testFile = dataFile "carolus-rex.cdtext"+++tests :: U.Test+tests = "Foreign.Libcdio.Test.CarolusRex" ~: U.TestList+    [ parse+    ]++parse :: U.Test+parse = "Binary CDTEXT is read properly" ~: U.TestCase $ do+    bs <- BS.readFile testFile+    x' <- cdTextDataInit bs+    +    Y.isJust x' @? "Failed to read binary CdText"+    let Just x = x'+    +    checkLanguage x English+    checkLanguage x Swedish++checkLanguage :: Cdio -> Language -> U.Assertion+checkLanguage x l = do+    b <- selectLanguage x l+    b @? "Unable to change language to " ++ show l+    +    l' <- language x+    l' @?= Just l+    +    t1 <- firstTrack x+    t1 @?= Just 1+    +    tl <- lastTrack x+    tl @?= Just (fromIntegral $ length titlesEnglish)+    +    t <- cdTextGet x Title Nothing+    t @?= Just "Carolus Rex"+    +    p <- cdTextGet x Performer Nothing+    p @?= Just "Sabaton"+    +    ts <- mapM (cdTextGet x Title . Just . fromIntegral) [1 .. length titlesEnglish]+    ts @?= if l == English then titlesEnglish else titlesSwedish++titlesEnglish :: [Maybe String]+titlesEnglish = map Just+        [ "Dominium maris Baltici"+        , "The Lion from the North"+        , "Gott mit uns"+        , "A Lifetime of War"+        , "1648"+        , "The Carolean's Prayer"+        , "Carolus Rex"+        , "Killing Ground"+        , "Poltava"+        , "Long Live the King"+        , "Ruina Imperii"+        ]++titlesSwedish :: [Maybe String]+titlesSwedish = map Just+    [ "Dominium maris Baltici"+    , "Lejonet fraan Norden"+    , "Gott mit uns"+    , "En Livstid i krig"+    , "1648"+    , "Karolinens bo:n"+    , "Carolus Rex"+    , "Ett slag fa:rgat ro:tt"+    , "Poltava"+    , "Konungens likfa:rd"+    , "Ruina Imperii"+    ]
+ test/Test/Libcdio/Unit/Foreign/DeeperDance.hs view
@@ -0,0 +1,85 @@+{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}++{-|+Description:    ++Copyright:      (c) 2019-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable++The CDTEXT file used in this module comes via James Olin Oden at+<https://bugzilla.redhat.com/show_bug.cgi?id=1321677#c3>.+-}+module Test.Libcdio.Unit.Foreign.DeeperDance (tests) where+++import qualified Test.HUnit as U+import Test.HUnit ( (@?), (@?=), (~:) )++import qualified Control.Monad as M++import qualified Data.ByteString as BS+import qualified Data.Maybe as Y++import Foreign.Libcdio.CdText++import Test.Libcdio.Unit.Common+++testFile :: FilePath+testFile = dataFile "deeper-dance.cdtext"+++tests :: U.Test+tests = "Foreign.Libcdio.Test.DeeperDance" ~: U.TestList+    [ parse+    ]++parse :: U.Test+parse = "Binary CDTEXT is read properly" ~: U.TestCase $ do+    bs <- BS.readFile testFile+    x' <- cdTextDataInit bs++    Y.isJust x' @? "Failed to read binary CdText"+    let Just x = x'++    l <- language x+    l @?= Just English++    t1 <- firstTrack x+    t1 @?= Just 1++    tl <- lastTrack x+    tl @?= Just (fromIntegral $ length titles)++    t <- cdTextGet x Title Nothing+    t @?= Just "Deeper Dance"++    p <- cdTextGet x Performer Nothing+    p @?= performer++    ts <- M.forM [1 .. length titles] $ \i -> do+         t' <- cdTextGet x Title . Just $ fromIntegral i+         p' <- cdTextGet x Performer . Just $ fromIntegral i+         return (t', p')+    ts @?= zip titles (repeat performer)++performer :: Maybe String+performer = Just "James Olin Oden"++titles :: [Maybe String]+titles = map Just+    [ "Deeper Dance"+    , "The Hunt"+    , "Harold's Dream"+    , "Jazz Fusion No. 9"+    , "Love's Tattoo"+    , "The Day I Told Her Micheal Domhnaill Died"+    , "The Fool Amongst the Keeners"+    , "Love Is Not Tame"+    , "Dear John and the Big Red Pickup Truck"+    , "Dance Right Out of My Grave"+    ]
+ test/Test/Libcdio/Unit/Foreign/RevolutionDays.hs view
@@ -0,0 +1,77 @@+{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}++{-|+Description:    ++Copyright:      (c) 2019-2020 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable++The CDTEXT file used in this module comes via Pigeon at+<https://pigeonsnest.co.uk/stuff/cdtext.html> (warning for a /lot/ of+swearing).  The encoding was later manually set to ASCII.+-}+module Test.Libcdio.Unit.Foreign.RevolutionDays (tests) where+++import qualified Test.HUnit as U+import Test.HUnit ( (@?), (@?=), (~:) )++import qualified Data.ByteString as BS+import qualified Data.Maybe as Y++import Foreign.Libcdio.CdText++import Test.Libcdio.Unit.Common+++testFile :: FilePath+testFile = dataFile "revolution-days.cdtext"+++tests :: U.Test+tests = "Foreign.Libcdio.Test.RevolutionDays" ~: U.TestList+    [ parse+    ]++parse :: U.Test+parse = "Binary CDTEXT is read properly" ~: U.TestCase $ do+    bs <- BS.readFile testFile+    x' <- cdTextDataInit bs++    Y.isJust x' @? "Failed to read binary CdText"+    let Just x = x'++    t1 <- firstTrack x+    t1 @?= Just 1++    tl <- lastTrack x+    tl @?= Just (fromIntegral $ length titles)++    t <- cdTextGet x Title Nothing+    t @?= Just "REVOLUTION DAYS"++    p <- cdTextGet x Performer Nothing+    p @?= Just "BARCLAY JAMES HARVEST FEATURING LES HOLROYD"++    ts <- mapM (cdTextGet x Title . Just . fromIntegral) [1 .. length titles]+    ts @?= titles++titles :: [Maybe String]+titles = map Just+    [ "IT'S MY LIFE"+    , "MISSING YOU"+    , "THAT WAS THEN... THIS IS NOW"+    , "PRELUDE"+    , "JANUARY MORNING"+    , "LOVE ON THE LINE"+    , "QUIERO EL SOL"+    , "TOTALLY COOL"+    , "LIFE IS FOR LIVING"+    , "SLEEPY SUNDAY"+    , "REVOLUTION DAY"+    , "MARLENE (from the BERLIN SUITE)"+    ]
+ test/Test/Libcdio/Unit/Sound/CarolusRex.hs view
@@ -0,0 +1,92 @@+{-|+Description:    Tests of multi-block CDTEXT in the Sound interface.++Copyright:      (c) 2020-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable++The CDTEXT file used in this module was generated using the tool written by+Pigeon at <https://pigeonsnest.co.uk/stuff/cdtext.html> (warning for a /lot/ of+swearing).  The encoding was later manually set to ASCII.+-}+module Test.Libcdio.Unit.Sound.CarolusRex (tests) where+++import qualified Test.HUnit as U+import Test.HUnit ( (@?=), (~:) )++import qualified Data.ByteString as BS+import qualified Data.Maybe as Y+import qualified Data.Text as T++import Sound.Libcdio.Read.CdText++import Test.Libcdio.Unit.Sound.Common+++testFile :: FilePath+testFile = dataFile "carolus-rex.cdtext"+++tests :: U.Test+tests = "Sound.Libcdio.Test.CarolusRex" ~: U.TestList+    [ binary+    ]++binary :: U.Test+binary = "Binary CDTEXT is read properly" ~: U.TestCase $ do+    bs <- BS.readFile testFile+    x <- parseCdText bs . withAll $ do+        l <- language+        a <- checkLanguage $ zip langs [infoEnglish, infoSwedish]+        return (l, a)+    either (const $ U.assertFailure "Could not parse binary data") runAssertions x++runAssertions :: [Maybe (Language, U.Assertion)] -> IO ()+runAssertions xs = do+    let (ls, as) = unzip $ Y.catMaybes xs+    ls @?= langs+    sequence_ as+++langs :: [Language]+langs = [English, Swedish]++infoEnglish :: [Info]+infoEnglish = emptyInfo+    { title = Just $ T.pack "Carolus Rex"+    , performer = Just $ T.pack "Sabaton"+    } : map (\t -> emptyInfo { title = Just $ T.pack t })+        [ "Dominium maris Baltici"+        , "The Lion from the North"+        , "Gott mit uns"+        , "A Lifetime of War"+        , "1648"+        , "The Carolean's Prayer"+        , "Carolus Rex"+        , "Killing Ground"+        , "Poltava"+        , "Long Live the King"+        , "Ruina Imperii"+        ]++infoSwedish :: [Info]+infoSwedish = emptyInfo+    { title = Just $ T.pack "Carolus Rex"+    , performer = Just $ T.pack "Sabaton"+    } : map (\t -> emptyInfo { title = Just $ T.pack t })+        [ "Dominium maris Baltici"+        , "Lejonet fraan Norden"+        , "Gott mit uns"+        , "En Livstid i krig"+        , "1648"+        , "Karolinens bo:n"+        , "Carolus Rex"+        , "Ett slag fa:rgat ro:tt"+        , "Poltava"+        , "Konungens likfa:rd"+        , "Ruina Imperii"+        ]
+ test/Test/Libcdio/Unit/Sound/Common.hs view
@@ -0,0 +1,38 @@+{-|+Description:    ++Copyright:      (c) 2020-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Test.Libcdio.Unit.Sound.Common+    ( module Test.Libcdio.Unit.Common+    , checkLanguage+    ) where+++import qualified Test.HUnit as U+import Test.HUnit ( (@?=) )++import Sound.Libcdio.Read.CdText++import Test.Libcdio.Unit.Common+++checkLanguage :: [(Language, [Info])] -> CdText U.Assertion+checkLanguage ls = do+    l <- language+    let is' = lookup l ls+    t1 <- firstTrack+    tl <- lastTrack+    i <- info Nothing+    is <- mapM (info . Just) [t1..tl]+    return $ case is' of+        Just is'' -> do+            t1 @?= 1+            tl @?= fromIntegral (length is)+            i : is @?= is''+        Nothing -> U.assertFailure "Unexpected language in CdText"
+ test/Test/Libcdio/Unit/Sound/DeeperDance.hs view
@@ -0,0 +1,66 @@+{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}++{-|+Description:    ++Copyright:      (c) 2020-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable++The CDTEXT file used in this module comes via James Olin Oden at+<https://bugzilla.redhat.com/show_bug.cgi?id=1321677#c3>.+-}+module Test.Libcdio.Unit.Sound.DeeperDance (tests) where+++import qualified Test.HUnit as U+import Test.HUnit ( (~:) )++import qualified Data.ByteString as BS+import qualified Data.Either.Compat as E+import qualified Data.Text as T++import Sound.Libcdio.Read.CdText++import Test.Libcdio.Unit.Sound.Common+++testFile :: FilePath+testFile = dataFile "deeper-dance.cdtext"+++tests :: U.Test+tests = "Sound.Libcdio.Test.DeeperDance" ~: U.TestList+    [ binary+    ]++binary :: U.Test+binary = "Binary CDTEXT is read properly" ~: U.TestCase $ do+    bs <- BS.readFile testFile+    x <- parseCdText bs $ checkLanguage [(English, infos)]+    E.fromRight (U.assertFailure "Could not parse binary data") x+++performer' :: Maybe T.Text+performer' = Just $ T.pack "James Olin Oden"++infos :: [Info]+infos = map (\t -> emptyInfo+    { title = Just $ T.pack t+    , performer = performer'+    })+    [ "Deeper Dance"+    , "Deeper Dance"+    , "The Hunt"+    , "Harold's Dream"+    , "Jazz Fusion No. 9"+    , "Love's Tattoo"+    , "The Day I Told Her Micheal Domhnaill Died"+    , "The Fool Amongst the Keeners"+    , "Love Is Not Tame"+    , "Dear John and the Big Red Pickup Truck"+    , "Dance Right Out of My Grave"+    ]
+ test/Test/Libcdio/Unit/Sound/RevolutionDays.hs view
@@ -0,0 +1,63 @@+{-|+Description:    ++Copyright:      (c) 2020-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable++The CDTEXT file used in this module comes via Pigeon at+<https://pigeonsnest.co.uk/stuff/cdtext.html> (warning for a /lot/ of+swearing).  The encoding was later manually set to ASCII.+-}+module Test.Libcdio.Unit.Sound.RevolutionDays (tests) where+++import qualified Test.HUnit as U+import Test.HUnit ( (~:) )++import qualified Data.ByteString as BS+import qualified Data.Either.Compat as E+import qualified Data.Text as T++import Sound.Libcdio.Read.CdText++import Test.Libcdio.Unit.Sound.Common+++testFile :: FilePath+testFile = dataFile "revolution-days.cdtext"+++tests :: U.Test+tests = "Sound.Libcdio.Test.RevolutionDays" ~: U.TestList+    [ binary+    ]++binary :: U.Test+binary = "Binary CDTEXT is read properly" ~: U.TestCase $ do+    bs <- BS.readFile testFile+    x <- parseCdText bs . withLanguage English $ checkLanguage [(English, infos)]+    E.fromRight (U.assertFailure "Could not read binary data") x+++infos :: [Info]+infos = emptyInfo+    { title = Just $ T.pack "REVOLUTION DAYS"+    , performer = Just $ T.pack "BARCLAY JAMES HARVEST FEATURING LES HOLROYD"+    } : map (\t -> emptyInfo { title = Just $ T.pack t })+        [ "IT'S MY LIFE"+        , "MISSING YOU"+        , "THAT WAS THEN... THIS IS NOW"+        , "PRELUDE"+        , "JANUARY MORNING"+        , "LOVE ON THE LINE"+        , "QUIERO EL SOL"+        , "TOTALLY COOL"+        , "LIFE IS FOR LIVING"+        , "SLEEPY SUNDAY"+        , "REVOLUTION DAY"+        , "MARLENE (from the BERLIN SUITE)"+        ]
+ test/Test/Libcdio/Upstream.hs view
@@ -0,0 +1,54 @@+{-|+Description:    ++Copyright:      (c) 2019-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Main where+++import qualified Control.Monad as M+import qualified System.Exit as E+import qualified Test.HUnit as U++import qualified Test.Libcdio.Upstream.Foreign.BinCue as BinCue+import qualified Test.Libcdio.Upstream.Foreign.CdrDao as CdrDao+import qualified Test.Libcdio.Upstream.Foreign.FreeBsd as FreeBsd+import qualified Test.Libcdio.Upstream.Foreign.Linux as Linux+import qualified Test.Libcdio.Upstream.Foreign.Nrg as Nrg+import qualified Test.Libcdio.Upstream.Foreign.OsX as OsX+import qualified Test.Libcdio.Upstream.Foreign.Pregap as Pregap+import qualified Test.Libcdio.Upstream.Foreign.Solaris as Solaris+import qualified Test.Libcdio.Upstream.Foreign.SizeOf as SizeOf+import qualified Test.Libcdio.Upstream.Foreign.Track as Track+import qualified Test.Libcdio.Upstream.Foreign.Win32 as Win32++import qualified Test.Libcdio.Upstream.Sound.Image as Sound.Image+import qualified Test.Libcdio.Upstream.Sound.System as Sound.System+import qualified Test.Libcdio.Upstream.Sound.Track as Sound.Track+++main :: IO ()+main = do+    results <- U.runTestTT $ U.TestList+        [ BinCue.tests+        , CdrDao.tests+        , FreeBsd.tests+        , Linux.tests+        , Nrg.tests+        , OsX.tests+        , Pregap.tests+        , Solaris.tests+        , SizeOf.tests+        , Track.tests+        , Win32.tests+        , Sound.Image.tests+        , Sound.System.tests+        , Sound.Track.tests+        ]+    +    M.unless (U.errors results == 0 && U.failures results == 0) E.exitFailure
+ test/Test/Libcdio/Upstream/Foreign/BinCue.hs view
@@ -0,0 +1,86 @@+{-|+Description:    ++Copyright:      (c) 2019-2020 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Test.Libcdio.Upstream.Foreign.BinCue+    ( tests+    , goodCues+    , badCues+    ) where+++import qualified Test.HUnit as U+import Test.HUnit ( (@?), (@?=), (~:) )++import qualified Data.Maybe as Y++-- import qualified System.Directory as D++import Foreign.Libcdio.Device++import Test.Libcdio.Upstream.Foreign.Common+++tests :: U.Test+tests = "Foreign.Libcdio.Test.BinCue" ~: U.TestList+    [ parse+    , open+    ]+++parse :: U.Test+parse = "Distinguish valid and invalid CUE files" ~: U.TestList+    (map good goodCues ++ map bad badCues)+  where good = cueTest Y.isJust "is not recognized as a CUE file"+        bad = cueTest Y.isNothing "should not be recognized as a CUE file"+        cueTest t s f = U.TestCase $ t <$> binFromCue (dataFile f) @? "'" ++ f ++ "' " ++ s++goodCues :: [FilePath]+goodCues =+    [ "cdda.cue"+    , "isofs-m1.cue"+    ]++badCues :: [FilePath]+badCues =+    [ "bad-cat1.cue"+    , "bad-cat2.cue"+    , "bad-cat3.cue"+    , "bad-mode1.cue"+    , "bad-msf-1.cue"+    , "bad-msf-2.cue"+    , "bad-msf-3.cue"+    ]+++open :: U.Test+open = "CUE files open the associated device correctly" ~: U.TestCase $ do+    c <- cdioOpen (Just $ dataFile "cdda.cue") DriverUnknown+    cdio <- case c of+        Nothing -> U.assertFailure "Can't open the CUE file"+        Just c' -> return c'+    +    b <- setBlocksize cdio 2048+    b @?= Unsupported+    +    checkMmc cdio $ Just False+    checkAccessMode cdio [Image]+    +    {- Seems to be either an unimplemented or a reverted equivalence+    d <- D.withCurrentDirectory dataDir . defaultDevice $ Just cdio+    device <- case d of+        Nothing -> U.assertFailure "No default device returned for the CUE file"+        Just d' -> return d'+    checkSource cdio [device]+    -}+    +    s <- setSpeed cdio 5+    s @?= Unsupported+    +    return ()
+ test/Test/Libcdio/Upstream/Foreign/CdrDao.hs view
@@ -0,0 +1,85 @@+{-|+Description:    ++Copyright:      (c) 2019-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Test.Libcdio.Upstream.Foreign.CdrDao+    ( tests+    , goodToc+    , badToc+    ) where+++import qualified Test.HUnit as U+import Test.HUnit ( (@?), (~:) )++import qualified System.Directory as D++import Foreign.Libcdio.Device++import Test.Libcdio.Upstream.Foreign.Common+++tests :: U.Test+tests = "Foreign.Libcdio.Test.CdrDao" ~: U.TestList+    [ parse+    , open+    ]+++parse :: U.Test+parse = "Distinguish valid and invalid TOC files" ~: U.TestList+    (map good goodToc ++ map bad badToc)+  where good = tocTest id "is not recognized as a TOC file"+        bad = tocTest not "should not be recognized as a TOC file"+        tocTest t s f = U.TestCase . D.withCurrentDirectory dataDir $ fmap t (isToc f) @? "'" ++ f ++ "' " ++ s++goodToc :: [FilePath]+goodToc =+    [ "cdtext.toc"+    , "t1.toc"+    , "t2.toc"+    , "t3.toc"+    , "t4.toc"+    , "t5.toc"+    , "t6.toc"+    , "t7.toc"+    , "t8.toc"+    , "t9.toc"+    , "t10.toc"+    , "data1.toc"+    , "data2.toc"+    , "data5.toc"+    , "data6.toc"+    , "data7.toc"+    , "vcd2.toc"+    ]++badToc :: [FilePath]+badToc =+    [ "bad-cat1.toc"+    , "bad-cat2.toc"+    , "bad-cat3.toc"+    , "bad-file.toc"+    , "bad-mode1.toc"+    , "bad-msf-1.toc"+    , "bad-msf-2.toc"+    , "bad-msf-3.toc"+    ]+++open :: U.Test+open = "TOC files open the associated device correctly" ~: U.TestCase $ do+    c <- cdioOpen (Just $ dataFile "cdtext.toc") DriverUnknown+    cdio <- case c of+        Nothing -> U.assertFailure "Can't open the TOC file"+        Just c' -> return c'+    +    checkMmc cdio $ Just False+    checkAccessMode cdio [Image]+    checkSource cdio [dataFile "cdtext.toc"]
+ test/Test/Libcdio/Upstream/Foreign/Common.hs view
@@ -0,0 +1,84 @@+{-|+Description:    ++Copyright:      (c) 2019-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable++The semantics of several functions in this module were copied from+@test/driver/helper.*@ in the libcdio source, but their implementation was+rewritten for the Haskell wrapper.+-}+module Test.Libcdio.Upstream.Foreign.Common where+++import qualified Test.HUnit as U+import Test.HUnit ( (@?), (@=?), (~:) )++import qualified Control.Monad as M++import qualified Data.Char as C+import qualified Data.Maybe as Y++import Foreign.Libcdio.Device+++dataDir :: String+dataDir = "test/datafiles/upstream/"++dataFile :: String -> String+dataFile = (++) dataDir+++checkArg :: SessionArg -> Cdio -> [String] -> U.Assertion+checkArg k c ss = do+    v <- getArg c k+    value <- case v of+        Nothing -> U.assertFailure $ show k ++ "' isn't assigned"+        Just v' -> return v'+    null ss || elem value ss @? show k ++ "' has invalid value '" ++ value ++ "'"++checkAccessMode :: Cdio -> [AccessMode] -> U.Assertion+checkAccessMode c ms = do+    v <- getAccessMode c+    value <- case v of+        Nothing -> U.assertFailure "'access-mode' isn't assigned"+        Just v' -> return v'+    null ms || elem value ms @? "'access-mode' has invalid value '" ++ show value ++ "'"++checkSource :: Cdio -> [String] -> U.Assertion+checkSource = checkArg Source+++-- | Whether the session advertises MMC support.  A 'Nothing' value indicates+-- that the actual state doesn't matter, just that it's advertised at all.+-- +-- The C function takes a numeric value translating to the following:+-- +--   * @1@ -> 'Just' 'False'+--   * @2@ -> 'Just' 'True'+--   * @3@ -> 'Nothing'+checkMmc :: Cdio -> Maybe Bool -> U.Assertion+checkMmc c b = do+    v <- getArg c MmcSupported+    Y.isJust v @? "Session does not describe MMC status."+    case b of+        Just _ -> map C.toLower . show <$> b @=? v+        Nothing -> return ()+++find :: DriverId -> Maybe AccessMode -> ((Cdio, String) -> U.Assertion) -> U.Test+find d m f = "The driver is able to find its devices" ~: U.TestCase $ do+    ss <- devices d+    not (null ss) @? "Can't find a device"+    let open s = case m of+            Nothing -> cdioOpen s d+            Just m' -> cdioOpenAm s d m'+    cs <- mapM (open . Just) ss+    cs' <- M.forM (zip ss cs) $ \(s, c) -> case c of+        Nothing -> U.assertFailure $ "Can't open device '" ++ s ++ "'"+        Just c' -> return c'+    mapM_ f $ zip cs' ss
+ test/Test/Libcdio/Upstream/Foreign/FreeBsd.hs view
@@ -0,0 +1,38 @@+{-|+Description:    ++Copyright:      (c) 2019 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Test.Libcdio.Upstream.Foreign.FreeBsd (tests) where+++import qualified Test.HUnit as U+import Test.HUnit ( (~:) )++import Foreign.Libcdio.Device++import Test.Libcdio.Upstream.Foreign.Common+++tests :: U.Test+tests = "Foreign.Libcdio.Test.FreeBsd" ~: U.TestList tests'+  where tests' | haveDriver DriverFreeBsd =+                    [ open+                    , find DriverFreeBsd Nothing $ \(c, s) -> checkSource c [s]+                    ]+               | otherwise = []++open :: U.Test+open = "The driver opens devices correctly" ~: U.TestCase $ do+    c <- cdioOpen Nothing DriverFreeBsd+    cdio <- case c of+        Nothing -> U.assertFailure "Can't open the default device"+        Just c' -> return c'+    +    checkAccessMode cdio [Ioctl_, Cam]+    checkMmc cdio $ Just False
+ test/Test/Libcdio/Upstream/Foreign/Linux.hs view
@@ -0,0 +1,47 @@+{-|+Description:    ++Copyright:      (c) 2019-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Test.Libcdio.Upstream.Foreign.Linux (tests) where+++import qualified Test.HUnit as U+import Test.HUnit ( (~:) )++import Foreign.Libcdio.Device++import Test.Libcdio.Upstream.Foreign.Common+++tests :: U.Test+tests = "Foreign.Libcdio.Test.Linux" ~: U.TestList tests'+  where tests' | haveDriver DriverLinux =+                  [ find DriverLinux (Just MmcReadWrite) check+                  ]+               | otherwise = []++check :: (Cdio, String) -> U.Assertion+check (cdio, source) = do+    {- Exact behaviour dependant on whether there's a disc in the drive+    tc <- lastTrackNum cdio+    if Y.fromMaybe maxTrack tc >= maxTrack - 1+    then mempty+    else do+        l <- trackLsn cdio maxTrack+        Y.isNothing l @? "Overlarge track not detected"+    -}+    +    checkSource cdio [source]+    checkMmc cdio Nothing+    +    checkArg ScsiTuple cdio []+    +    {- Access mode doesn't seem implemented+    checkAccessMode cdio [MmcReadWrite]+    -}
+ test/Test/Libcdio/Upstream/Foreign/Nrg.hs view
@@ -0,0 +1,50 @@+{-|+Description:    ++Copyright:      (c) 2019-2020 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Test.Libcdio.Upstream.Foreign.Nrg+    ( tests+    , goodNrg+    ) where+++import qualified Test.HUnit as U+import Test.HUnit ( (@=?), (~:) )++import Foreign.Libcdio.CdText+import Foreign.Libcdio.Device++import Test.Libcdio.Upstream.Foreign.Common+++tests :: U.Test+tests = "Foreign.Libcdio.Test.Nrg" ~: U.TestList $ map open goodNrg+++goodNrg :: [FilePath]+goodNrg+    | haveDriver DriverNrg = ["p1.nrg"]+    | otherwise = []+++open :: FilePath -> U.Test+open f = "Nero images open the associated device correctly" ~: U.TestCase $ do+    c <- cdioOpen (Just $ dataFile f) DriverUnknown+    cdio <- case c of+        Nothing -> U.assertFailure "Can't open the Nero file"+        Just c' -> return c'+    +    p <- cdTextGet cdio Performer Nothing+    Just "Richard Stallman" @=? p+    t <- cdTextGet cdio Title Nothing+    Just "Join us now we have the software" @=? t+    +    checkMmc cdio $ Just False+    checkAccessMode cdio [Image]+    checkSource cdio [dataFile f]
+ test/Test/Libcdio/Upstream/Foreign/OsX.hs view
@@ -0,0 +1,39 @@+{-|+Description:    ++Copyright:      (c) 2019 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Test.Libcdio.Upstream.Foreign.OsX (tests) where+++import qualified Test.HUnit as U+import Test.HUnit ( (@?), (~:) )++import qualified Data.Maybe as Y++import Foreign.Libcdio.Device+import Foreign.Libcdio.Disc++import Test.Libcdio.Upstream.Foreign.Common+++tests :: U.Test+tests = "Foreign.Libcdio.Test.OsX" ~: U.TestList tests'+  where tests' | haveDriver DriverOsX =+                  [ find DriverOsX Nothing check+                  ]+               | otherwise = []++check :: (Cdio, String) -> U.Assertion+check (cdio, source) = do+    checkSource cdio [source]+    -- can't supply arbitrary access modes+    --checkAccessMode cdio ["OS X"]+    +    m <- discMode cdio+    Y.isJust m @? "Error getting disc mode for device '" ++ source ++ "'"
+ test/Test/Libcdio/Upstream/Foreign/Pregap.hs view
@@ -0,0 +1,54 @@+{-|+Description:    ++Copyright:      (c) 2019-2020 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Test.Libcdio.Upstream.Foreign.Pregap+    ( tests+    , gaps+    ) where+++import qualified Test.HUnit as U+import Test.HUnit ( (@=?), (~:) )++import qualified Control.Monad as M++import qualified System.Directory as D++import Foreign.Libcdio.Device+import Foreign.Libcdio.Track+import Foreign.Libcdio.Types++import Test.Libcdio.Upstream.Foreign.Common+++tests :: U.Test+tests = "Foreign.Libcdio.Test.Pregap" ~: map ((\f (a,b,c)->f a b c) checkGap) gaps++gaps :: [(DriverId, FilePath, [(Track, Maybe Lsn)])]+gaps =+    [ (DriverCdrDao, "t2.toc", [(1, Just 4425), (2, Nothing)])+    , (DriverBinCue, "p1.cue", [(1, Just 0), (2, Just 150), (3, Nothing)])+    ] +++    [ (DriverNrg, "p1.nrg", [(2, Just 225), (3, Nothing)])+    | haveDriver DriverNrg+    ]++checkGap :: DriverId -> FilePath -> [(Track, Maybe Lsn)] -> U.Assertion+checkGap d s gs+    | haveDriver d = do+        c <- D.withCurrentDirectory dataDir $ cdioOpen (Just s) d+        cdio <- case c of+            Nothing -> U.assertFailure $ "Can't open the disc image '" ++ s ++ "'"+            Just c' -> return c'+        +        M.forM_ gs $ \(t, g) -> do+            p <- pregapLsn cdio t+            g @=? p+    | otherwise = return ()
+ test/Test/Libcdio/Upstream/Foreign/SizeOf.hs view
@@ -0,0 +1,26 @@+{-|+Description:    ++Copyright:      (c) 2019 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Test.Libcdio.Upstream.Foreign.SizeOf (tests) where+++import qualified Test.HUnit as U+import Test.HUnit ( (~=?), (~:) )++import qualified Foreign.Storable as S++import Foreign.Libcdio.Sector+++tests :: U.Test+tests = "Foreign.Libcdio.Test.SizeOf" ~: U.TestList+    [ 3 ~=? S.sizeOf (Msf 0 0 0)+    --TODO: More from iso9660_private.h+    ]
+ test/Test/Libcdio/Upstream/Foreign/Solaris.hs view
@@ -0,0 +1,32 @@+{-|+Description:    ++Copyright:      (c) 2019 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Test.Libcdio.Upstream.Foreign.Solaris (tests) where+++import qualified Test.HUnit as U+import Test.HUnit ( (~:) )++import Foreign.Libcdio.Device++import Test.Libcdio.Upstream.Foreign.Common+++tests :: U.Test+tests = "Foreign.Libcdio.Test.Solaris" ~: U.TestList tests'+  where tests' | haveDriver DriverSolaris =+                  [ find DriverSolaris (Just Scsi) check+                  ]+               | otherwise = []++check :: (Cdio, String) -> U.Assertion+check (cdio, source) = do+    checkSource cdio [source]+    checkAccessMode cdio [Scsi]
+ test/Test/Libcdio/Upstream/Foreign/Track.hs view
@@ -0,0 +1,44 @@+{-|+Description:    ++Copyright:      (c) 2019 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Test.Libcdio.Upstream.Foreign.Track (tests) where+++import qualified Test.HUnit as U+import Test.HUnit ( (@?), (@=?), (~:) )++import qualified Data.Maybe as Y++import Foreign.Libcdio.Device+import Foreign.Libcdio.Track++import Test.Libcdio.Upstream.Foreign.Common+++tests :: U.Test+tests = "Foreign.Libcdio.Test.Track" ~: U.TestList+    [ open+    ]++open :: U.Test+open = "Track accessing works correctly" ~: U.TestCase $ do+    c <- cdioOpen (Just . dataFile $ "cdda.cue") DriverUnknown+    cdio <- case c of+        Nothing -> U.assertFailure "Can't open the image file"+        Just c' -> return c'+    +    t <- trackAt cdio 1000+    Y.isNothing t @? "Overlarge addresses aren't caught"+    +    ts <- mapM (trackAt cdio) $ 301 : [0..9]+    mapM_ (Just 1 @=?) ts+    +    l <- trackAt cdio 302+    Just DiscLeadout @=? l
+ test/Test/Libcdio/Upstream/Foreign/Win32.hs view
@@ -0,0 +1,36 @@+{-|+Description:    ++Copyright:      (c) 2019-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Test.Libcdio.Upstream.Foreign.Win32 (tests) where+++import qualified Test.HUnit as U+import Test.HUnit ( (~:) )++import Foreign.Libcdio.Device++import Test.Libcdio.Upstream.Foreign.Common+++tests :: U.Test+tests = "Foreign.Libcdio.Test.Win32" ~: U.TestList tests'+  where tests' | haveDriver DriverWin32 =+                  [ find DriverWin32 Nothing $ \(c, s) -> checkSource c [s]+                  , find DriverWin32 (Just Aspi) $ flip checkAccessMode [Aspi] . fst+                  , find DriverWin32 (Just Ioctl_) checkIoctl+                  ]+               | otherwise = []++checkIoctl :: (Cdio, String) -> U.Assertion+checkIoctl (cdio, _) = do+    checkArg ScsiTuple cdio []+    +    checkAccessMode cdio [Ioctl_]+    checkMmc cdio $ Just True
+ test/Test/Libcdio/Upstream/Sound/Common.hs view
@@ -0,0 +1,88 @@+{-# LANGUAGE CPP #-}++{-|+Description:    ++Copyright:      (c) 2020-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Test.Libcdio.Upstream.Sound.Common+    ( Foreign.dataDir+    , checkArg+    , checkAccessMode+    , checkSource+    , checkMmc+    , testCdio+    , testCdioMode+    ) where+++import qualified Test.HUnit as U+import Test.HUnit ( (~:), (@=?) )++import qualified Data.Maybe as Y+import qualified Data.Text as T++import qualified System.Directory as D++import Sound.Libcdio++import qualified Test.Libcdio.Upstream.Foreign.Common as Foreign+++-- | Whether the session argument is one of the allowed values.  An empty list+-- indicates that the actual value doesn't matter, just that it exists.+checkArg :: SessionArg -> [T.Text] -> Cdio U.Assertion+checkArg k ss = do+    v <- getArg k+    return $ case v of+        Nothing -> U.assertFailure $ show k ++ "' isn't assigned"+        Just v' -> if null ss || elem v' ss+            then return ()+            else U.assertFailure $ show k ++ "' has invalid value '" ++ T.unpack v' ++ "'"++checkAccessMode :: [AccessMode] -> Cdio U.Assertion+checkAccessMode ms = do+    v <- getAccessMode+    return $ case v of+        Nothing -> U.assertFailure "'access-mode' isn't assigned"+        Just v' -> if null ms || elem v' ms+            then return ()+            else U.assertFailure $ "'access-mode' has invalid value '" ++ show v' ++ "'"++checkSource :: [FilePath] -> Cdio U.Assertion+checkSource = checkArg Source . map T.pack+++-- | Whether the session advertises MMC support.  A 'Nothing' value indicates+-- that the actual state doesn't matter, just that it's advertised at all.+-- +-- The C function takes a numeric value translating to the following:+-- +--   * @1@ -> 'Just' 'False'+--   * @2@ -> 'Just' 'True'+--   * @3@ -> 'Nothing'+checkMmc :: Maybe Bool -> Cdio U.Assertion+checkMmc b = do+    v <- getArg MmcSupported+    return $ if Y.isJust v+        then case b of+            Just _ -> (T.toLower . T.pack . show <$> b) @=? v+            Nothing -> return ()+        else U.assertFailure "Session does not describe MMC status."+++testCdio :: [FilePath] -> (FilePath -> Cdio [U.Assertion]) -> U.Test+testCdio = testCdioMode Nothing++testCdioMode :: Maybe AccessMode -> [FilePath] -> (FilePath -> Cdio [U.Assertion]) -> U.Test+testCdioMode m fs c = U.TestList . flip map fs $ \f -> f ~: U.TestCase $ do+    o <- D.withCurrentDirectory Foreign.dataDir . open' (Just f) False $ c f+    either (const $ U.assertFailure "Can't open the image or device") sequence_ o+  where open' = case m of+            Just m' -> openMode m'+            Nothing -> open
+ test/Test/Libcdio/Upstream/Sound/Image.hs view
@@ -0,0 +1,134 @@+{-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS_GHC -Wno-unused-local-binds #-}++{-|+Description:    ++Copyright:      (c) 2020-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Test.Libcdio.Upstream.Sound.Image (tests) where+++import qualified Test.HUnit as U+import Test.HUnit ( (@=?), (~:) )++import qualified Data.Either.Compat as E+import qualified Data.Maybe as Y+import qualified Data.Text as T++import qualified System.Directory as D++import Sound.Libcdio+import Sound.Libcdio.Device+import Sound.Libcdio.Read.CdText++import Test.Libcdio.Upstream.Sound.Common++import qualified Test.Libcdio.Upstream.Foreign.BinCue as Foreign+import qualified Test.Libcdio.Upstream.Foreign.CdrDao as Foreign+import qualified Test.Libcdio.Upstream.Foreign.Nrg as Foreign+++tests :: U.Test+tests = "Sound.Libcdio.Test.Image" ~: U.TestList+    [ parseTests+    , run+    ]+++parseTests :: U.Test+parseTests = "Distinguish valid and invalid image files" ~: U.TestList+    [ parseCue+    , parseToc+    ]++parseCue :: U.Test+parseCue = "CUE" ~: U.TestList+    (map good Foreign.goodCues ++ map bad Foreign.badCues)+  where good = parseTest "CUE" True+        bad = parseTest "CUE" False++parseToc :: U.Test+parseToc = "TOC" ~: U.TestList+    (map good Foreign.goodToc ++ map bad Foreign.badToc)+  where good = parseTest "TOC" True+        bad = parseTest "TOC" False++parseTest :: String -> Bool -> FilePath -> U.Test+parseTest i y f = msg ~: U.TestCase . D.withCurrentDirectory dataDir $ do+    o <- open (Just f) False $ return ()+    y @=? E.isRight o+  where msg | y = f' ++ "is not recognized as a " ++ i'+            | otherwise = f' ++ "should not be recognized as a " ++ i'+        f' = "'" ++ f ++ "' "+        i' = i ++ " file"+++goodAll :: [FilePath]+goodAll = Foreign.goodCues ++ Foreign.goodToc ++ Foreign.goodNrg++goodCdText :: [FilePath]+goodCdText = ["cdda.cue", "cdtext.toc"] ++ Foreign.goodNrg+++run :: U.Test+run = U.TestList+    [ runAll+    , testCdText+    ]++runAll :: U.Test+runAll = "Expected session behaviour" ~: testCdio goodAll $ \f -> do+    _ <- setBlocksize 2048+    +    m <- checkMmc $ Just False+    a <- checkAccessMode [Image]+    +    let f' = T.unpack . T.replace ".cue" ".bin" $ T.pack f+    s <- checkSource [f']+    +    _ <- setSpeed 5+    +    return [m, a, s]++testCdText :: U.Test+testCdText = "Properly-formed CDTEXT" ~: testCdio goodCdText . const $ do+    is <- cdText . withAll $ do+        i <- info Nothing+        i1 <- info $ Just 1+        l' <- discId+        g' <- genre+        return (i, i1, l', g')+    let is' = E.fromRight [] is+    +    let checkCdText (i, i1, _, _) = map (\f -> f i) discTests ++ map (\f -> f i1) trackTests+        --checkCdText (i, i1, l', g') = map (\f -> f i) discTests ++ [l l', g g'] ++ map (\f -> f i1) trackTests+        p i = Just "Richard Stallman" @=? performer i+        t i = Just "Join us now we have the software" @=? title i+        s i = Nothing @=? songwriter i+        c i = Nothing @=? composer i+        a i = Nothing @=? arranger i+        m i = Nothing @=? message i+        o i = Nothing @=? code i+        l l' = Just "0000010271955" @=? l'+        g g' = (Nothing, Nothing) @=? g'+        --discTests = [p, t, s, c, a, m, o]+        discTests = [p, t]+        p1 i1 = Just "Richard S" @=?  performer i1+        t1 i1 = Just "Soft" @=? title i1+        s1 i1 = Nothing @=? songwriter i1+        c1 i1 = Nothing @=? composer i1+        a1 i1 = Nothing @=? arranger i1+        m1 i1 = Nothing @=? message i1+        o1 i1 = Just "US-XX1-98-01234" @=? code i1+        --trackTests = [p1, t1, s1, c1, a1, m1, o1]+        trackTests = []+    return $ case length is' of+        0 -> [U.assertFailure "Can't access the CD Text"]+        1 -> checkCdText . head $ Y.catMaybes is'+        _ -> [U.assertFailure "Trailing CD Text languages"]
+ test/Test/Libcdio/Upstream/Sound/System.hs view
@@ -0,0 +1,104 @@+{-# LANGUAGE OverloadedStrings #-}++{-|+Description:    ++Copyright:      (c) 2020-2021 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Test.Libcdio.Upstream.Sound.System (tests) where+++import qualified Test.HUnit as U+import Test.HUnit ( (@?), (~:) )++import qualified Data.Maybe as Y++import Sound.Libcdio+import Sound.Libcdio.Device+import Sound.Libcdio.Read.Data++import Test.Libcdio.Upstream.Sound.Common+++tests :: U.Test+tests = "Sound.Libcdio.Test.System" ~: U.TestList+    [ haveSystemDriver d ts+    | (d, ts) <-+        [ (DriverFreeBsd, testsBsd)+        , (DriverLinux, testsLinux)+        , (DriverOsX, testsOsx)+        , (DriverSolaris, testsSolaris)+        , (DriverWin32, testsWin32)+        ]+    ]++testsBsd :: U.Test+testsBsd = find DriverFreeBsd Nothing $ \p -> do+    s <- checkSource [p]+    a <- checkAccessMode [Ioctl_, Cam]+    m <- checkMmc $ Just False+    return [s, a, m]++testsLinux :: U.Test+testsLinux = find DriverLinux (Just MmcReadWrite) $ \p -> do+    s <- checkSource [p]+    m <- checkMmc Nothing+    t <- checkArg ScsiTuple []+    return [s, m, t]++testsOsx :: U.Test+testsOsx = find DriverOsX Nothing $ \p -> do+    s <- checkSource [p]+    -- can't supply arbitrary access modes+    --a <- checkAccessMode ["OS X"]+    +    d <- discMode+    let d' = Y.isJust d @? "Error getting disc mode"+    +    return [s, d']++testsSolaris :: U.Test+testsSolaris = find DriverSolaris (Just Scsi) $ \p -> do+    s <- checkSource [p]+    a <- checkAccessMode [Scsi]+    return [s, a]++testsWin32 :: U.Test+testsWin32 = U.TestList $ map (uncurry $ find DriverWin32)+    [ ( Nothing, \p -> do+        s <- checkSource [p]+        return [s]+      )+    , ( Just Aspi, \p -> do+        s <- checkSource [p]+        a <- checkAccessMode [Aspi]+        return [s, a]+      )+    , ( Just Ioctl_, \p -> do+        s <- checkSource [p]+        t <- checkArg ScsiTuple []+        a <- checkAccessMode [Ioctl_]+        m <- checkMmc $ Just True+        return [s, t, a, m]+      )+    ]+++haveSystemDriver :: DriverId -> U.Test -> U.Test+haveSystemDriver d ts+    | elem d drivers = drop 6 (show d) ~: ts+    | otherwise = U.TestList []++find :: DriverId -> Maybe AccessMode -> (FilePath -> Cdio [U.Assertion]) -> U.Test+find d m c = U.TestCase $ do+    ps <- devices d+    -- Don't actually want to fail on no device, for systems without CD drives+    sequence_ . unwrap $ testCdioMode m ps c+  where unwrap (U.TestCase a) = [a]+        unwrap (U.TestList ts) = concatMap unwrap ts+        unwrap (U.TestLabel _ t) = unwrap t
+ test/Test/Libcdio/Upstream/Sound/Track.hs view
@@ -0,0 +1,51 @@+{-|+Description:    ++Copyright:      (c) 2020 Sam May+License:        GPL-3.0-or-later+Maintainer:     ag@eitilt.life++Stability:      experimental+Portability:    portable+-}+module Test.Libcdio.Upstream.Sound.Track (tests) where+++import qualified Test.HUnit as U+import Test.HUnit ( (@?), (@=?), (~:) )++import qualified Control.Monad as M++import qualified Data.Maybe as Y++import Sound.Libcdio.Track++import Test.Libcdio.Upstream.Sound.Common++import qualified Test.Libcdio.Upstream.Foreign.Pregap as Foreign+++tests :: U.Test+tests = "Sound.Libcdio.Test.Track" ~: U.TestList+    [ gaps+    , address+    ]++gaps :: U.Test+gaps = "Pregap lengths" ~: U.TestList $ map (\(_,b,c) -> checkGap b c) Foreign.gaps+  where checkGap f gs = testCdio [f] . const . M.forM gs $ \(t, g) -> do+            p <- pregap t+            return $ g @=? p++address :: U.Test+address = "Sector addressing" ~: testCdio ["cdda.cue"] . const $ do+    t <- trackAt 1000+    let t' = Y.isNothing t @? "Overlarge addresses aren't caught"+    +    ts <- mapM trackAt $ 301 : [0..9]+    let ts' = mapM_ (Just 1 @=?) ts+    +    l <- trackAt 302+    let l' = Just DiscLeadout @=? l+    +    return [t', ts', l']
+ test/datafiles/unit/CP932.txt view
@@ -0,0 +1,7998 @@+#+#    Name:     cp932 to Unicode table+#    Unicode version: 2.0+#    Table version: 2.01+#    Table format:  Format A+#    Date:          04/15/98+#+#    Contact:       Shawn.Steele@microsoft.com+#+#    General notes: none+#+#    Format: Three tab-separated columns+#        Column #1 is the cp932 code (in hex)+#        Column #2 is the Unicode (in hex as 0xXXXX)+#        Column #3 is the Unicode name (follows a comment sign, '#')+#+#    The entries are in cp932 order+#+0x00	0x0000	#NULL+0x01	0x0001	#START OF HEADING+0x02	0x0002	#START OF TEXT+0x03	0x0003	#END OF TEXT+0x04	0x0004	#END OF TRANSMISSION+0x05	0x0005	#ENQUIRY+0x06	0x0006	#ACKNOWLEDGE+0x07	0x0007	#BELL+0x08	0x0008	#BACKSPACE+0x09	0x0009	#HORIZONTAL TABULATION+0x0A	0x000A	#LINE FEED+0x0B	0x000B	#VERTICAL TABULATION+0x0C	0x000C	#FORM FEED+0x0D	0x000D	#CARRIAGE RETURN+0x0E	0x000E	#SHIFT OUT+0x0F	0x000F	#SHIFT IN+0x10	0x0010	#DATA LINK ESCAPE+0x11	0x0011	#DEVICE CONTROL ONE+0x12	0x0012	#DEVICE CONTROL TWO+0x13	0x0013	#DEVICE CONTROL THREE+0x14	0x0014	#DEVICE CONTROL FOUR+0x15	0x0015	#NEGATIVE ACKNOWLEDGE+0x16	0x0016	#SYNCHRONOUS IDLE+0x17	0x0017	#END OF TRANSMISSION BLOCK+0x18	0x0018	#CANCEL+0x19	0x0019	#END OF MEDIUM+0x1A	0x001A	#SUBSTITUTE+0x1B	0x001B	#ESCAPE+0x1C	0x001C	#FILE SEPARATOR+0x1D	0x001D	#GROUP SEPARATOR+0x1E	0x001E	#RECORD SEPARATOR+0x1F	0x001F	#UNIT SEPARATOR+0x20	0x0020	#SPACE+0x21	0x0021	#EXCLAMATION MARK+0x22	0x0022	#QUOTATION MARK+0x23	0x0023	#NUMBER SIGN+0x24	0x0024	#DOLLAR SIGN+0x25	0x0025	#PERCENT SIGN+0x26	0x0026	#AMPERSAND+0x27	0x0027	#APOSTROPHE+0x28	0x0028	#LEFT PARENTHESIS+0x29	0x0029	#RIGHT PARENTHESIS+0x2A	0x002A	#ASTERISK+0x2B	0x002B	#PLUS SIGN+0x2C	0x002C	#COMMA+0x2D	0x002D	#HYPHEN-MINUS+0x2E	0x002E	#FULL STOP+0x2F	0x002F	#SOLIDUS+0x30	0x0030	#DIGIT ZERO+0x31	0x0031	#DIGIT ONE+0x32	0x0032	#DIGIT TWO+0x33	0x0033	#DIGIT THREE+0x34	0x0034	#DIGIT FOUR+0x35	0x0035	#DIGIT FIVE+0x36	0x0036	#DIGIT SIX+0x37	0x0037	#DIGIT SEVEN+0x38	0x0038	#DIGIT EIGHT+0x39	0x0039	#DIGIT NINE+0x3A	0x003A	#COLON+0x3B	0x003B	#SEMICOLON+0x3C	0x003C	#LESS-THAN SIGN+0x3D	0x003D	#EQUALS SIGN+0x3E	0x003E	#GREATER-THAN SIGN+0x3F	0x003F	#QUESTION MARK+0x40	0x0040	#COMMERCIAL AT+0x41	0x0041	#LATIN CAPITAL LETTER A+0x42	0x0042	#LATIN CAPITAL LETTER B+0x43	0x0043	#LATIN CAPITAL LETTER C+0x44	0x0044	#LATIN CAPITAL LETTER D+0x45	0x0045	#LATIN CAPITAL LETTER E+0x46	0x0046	#LATIN CAPITAL LETTER F+0x47	0x0047	#LATIN CAPITAL LETTER G+0x48	0x0048	#LATIN CAPITAL LETTER H+0x49	0x0049	#LATIN CAPITAL LETTER I+0x4A	0x004A	#LATIN CAPITAL LETTER J+0x4B	0x004B	#LATIN CAPITAL LETTER K+0x4C	0x004C	#LATIN CAPITAL LETTER L+0x4D	0x004D	#LATIN CAPITAL LETTER M+0x4E	0x004E	#LATIN CAPITAL LETTER N+0x4F	0x004F	#LATIN CAPITAL LETTER O+0x50	0x0050	#LATIN CAPITAL LETTER P+0x51	0x0051	#LATIN CAPITAL LETTER Q+0x52	0x0052	#LATIN CAPITAL LETTER R+0x53	0x0053	#LATIN CAPITAL LETTER S+0x54	0x0054	#LATIN CAPITAL LETTER T+0x55	0x0055	#LATIN CAPITAL LETTER U+0x56	0x0056	#LATIN CAPITAL LETTER V+0x57	0x0057	#LATIN CAPITAL LETTER W+0x58	0x0058	#LATIN CAPITAL LETTER X+0x59	0x0059	#LATIN CAPITAL LETTER Y+0x5A	0x005A	#LATIN CAPITAL LETTER Z+0x5B	0x005B	#LEFT SQUARE BRACKET+0x5C	0x005C	#REVERSE SOLIDUS+0x5D	0x005D	#RIGHT SQUARE BRACKET+0x5E	0x005E	#CIRCUMFLEX ACCENT+0x5F	0x005F	#LOW LINE+0x60	0x0060	#GRAVE ACCENT+0x61	0x0061	#LATIN SMALL LETTER A+0x62	0x0062	#LATIN SMALL LETTER B+0x63	0x0063	#LATIN SMALL LETTER C+0x64	0x0064	#LATIN SMALL LETTER D+0x65	0x0065	#LATIN SMALL LETTER E+0x66	0x0066	#LATIN SMALL LETTER F+0x67	0x0067	#LATIN SMALL LETTER G+0x68	0x0068	#LATIN SMALL LETTER H+0x69	0x0069	#LATIN SMALL LETTER I+0x6A	0x006A	#LATIN SMALL LETTER J+0x6B	0x006B	#LATIN SMALL LETTER K+0x6C	0x006C	#LATIN SMALL LETTER L+0x6D	0x006D	#LATIN SMALL LETTER M+0x6E	0x006E	#LATIN SMALL LETTER N+0x6F	0x006F	#LATIN SMALL LETTER O+0x70	0x0070	#LATIN SMALL LETTER P+0x71	0x0071	#LATIN SMALL LETTER Q+0x72	0x0072	#LATIN SMALL LETTER R+0x73	0x0073	#LATIN SMALL LETTER S+0x74	0x0074	#LATIN SMALL LETTER T+0x75	0x0075	#LATIN SMALL LETTER U+0x76	0x0076	#LATIN SMALL LETTER V+0x77	0x0077	#LATIN SMALL LETTER W+0x78	0x0078	#LATIN SMALL LETTER X+0x79	0x0079	#LATIN SMALL LETTER Y+0x7A	0x007A	#LATIN SMALL LETTER Z+0x7B	0x007B	#LEFT CURLY BRACKET+0x7C	0x007C	#VERTICAL LINE+0x7D	0x007D	#RIGHT CURLY BRACKET+0x7E	0x007E	#TILDE+0x7F	0x007F	#DELETE+0x80	      	#UNDEFINED+0x81	      	#DBCS LEAD BYTE+0x82	      	#DBCS LEAD BYTE+0x83	      	#DBCS LEAD BYTE+0x84	      	#DBCS LEAD BYTE+0x85	      	#DBCS LEAD BYTE+0x86	      	#DBCS LEAD BYTE+0x87	      	#DBCS LEAD BYTE+0x88	      	#DBCS LEAD BYTE+0x89	      	#DBCS LEAD BYTE+0x8A	      	#DBCS LEAD BYTE+0x8B	      	#DBCS LEAD BYTE+0x8C	      	#DBCS LEAD BYTE+0x8D	      	#DBCS LEAD BYTE+0x8E	      	#DBCS LEAD BYTE+0x8F	      	#DBCS LEAD BYTE+0x90	      	#DBCS LEAD BYTE+0x91	      	#DBCS LEAD BYTE+0x92	      	#DBCS LEAD BYTE+0x93	      	#DBCS LEAD BYTE+0x94	      	#DBCS LEAD BYTE+0x95	      	#DBCS LEAD BYTE+0x96	      	#DBCS LEAD BYTE+0x97	      	#DBCS LEAD BYTE+0x98	      	#DBCS LEAD BYTE+0x99	      	#DBCS LEAD BYTE+0x9A	      	#DBCS LEAD BYTE+0x9B	      	#DBCS LEAD BYTE+0x9C	      	#DBCS LEAD BYTE+0x9D	      	#DBCS LEAD BYTE+0x9E	      	#DBCS LEAD BYTE+0x9F	      	#DBCS LEAD BYTE+0xA0	      	#UNDEFINED+0xA1	0xFF61	#HALFWIDTH IDEOGRAPHIC FULL STOP+0xA2	0xFF62	#HALFWIDTH LEFT CORNER BRACKET+0xA3	0xFF63	#HALFWIDTH RIGHT CORNER BRACKET+0xA4	0xFF64	#HALFWIDTH IDEOGRAPHIC COMMA+0xA5	0xFF65	#HALFWIDTH KATAKANA MIDDLE DOT+0xA6	0xFF66	#HALFWIDTH KATAKANA LETTER WO+0xA7	0xFF67	#HALFWIDTH KATAKANA LETTER SMALL A+0xA8	0xFF68	#HALFWIDTH KATAKANA LETTER SMALL I+0xA9	0xFF69	#HALFWIDTH KATAKANA LETTER SMALL U+0xAA	0xFF6A	#HALFWIDTH KATAKANA LETTER SMALL E+0xAB	0xFF6B	#HALFWIDTH KATAKANA LETTER SMALL O+0xAC	0xFF6C	#HALFWIDTH KATAKANA LETTER SMALL YA+0xAD	0xFF6D	#HALFWIDTH KATAKANA LETTER SMALL YU+0xAE	0xFF6E	#HALFWIDTH KATAKANA LETTER SMALL YO+0xAF	0xFF6F	#HALFWIDTH KATAKANA LETTER SMALL TU+0xB0	0xFF70	#HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK+0xB1	0xFF71	#HALFWIDTH KATAKANA LETTER A+0xB2	0xFF72	#HALFWIDTH KATAKANA LETTER I+0xB3	0xFF73	#HALFWIDTH KATAKANA LETTER U+0xB4	0xFF74	#HALFWIDTH KATAKANA LETTER E+0xB5	0xFF75	#HALFWIDTH KATAKANA LETTER O+0xB6	0xFF76	#HALFWIDTH KATAKANA LETTER KA+0xB7	0xFF77	#HALFWIDTH KATAKANA LETTER KI+0xB8	0xFF78	#HALFWIDTH KATAKANA LETTER KU+0xB9	0xFF79	#HALFWIDTH KATAKANA LETTER KE+0xBA	0xFF7A	#HALFWIDTH KATAKANA LETTER KO+0xBB	0xFF7B	#HALFWIDTH KATAKANA LETTER SA+0xBC	0xFF7C	#HALFWIDTH KATAKANA LETTER SI+0xBD	0xFF7D	#HALFWIDTH KATAKANA LETTER SU+0xBE	0xFF7E	#HALFWIDTH KATAKANA LETTER SE+0xBF	0xFF7F	#HALFWIDTH KATAKANA LETTER SO+0xC0	0xFF80	#HALFWIDTH KATAKANA LETTER TA+0xC1	0xFF81	#HALFWIDTH KATAKANA LETTER TI+0xC2	0xFF82	#HALFWIDTH KATAKANA LETTER TU+0xC3	0xFF83	#HALFWIDTH KATAKANA LETTER TE+0xC4	0xFF84	#HALFWIDTH KATAKANA LETTER TO+0xC5	0xFF85	#HALFWIDTH KATAKANA LETTER NA+0xC6	0xFF86	#HALFWIDTH KATAKANA LETTER NI+0xC7	0xFF87	#HALFWIDTH KATAKANA LETTER NU+0xC8	0xFF88	#HALFWIDTH KATAKANA LETTER NE+0xC9	0xFF89	#HALFWIDTH KATAKANA LETTER NO+0xCA	0xFF8A	#HALFWIDTH KATAKANA LETTER HA+0xCB	0xFF8B	#HALFWIDTH KATAKANA LETTER HI+0xCC	0xFF8C	#HALFWIDTH KATAKANA LETTER HU+0xCD	0xFF8D	#HALFWIDTH KATAKANA LETTER HE+0xCE	0xFF8E	#HALFWIDTH KATAKANA LETTER HO+0xCF	0xFF8F	#HALFWIDTH KATAKANA LETTER MA+0xD0	0xFF90	#HALFWIDTH KATAKANA LETTER MI+0xD1	0xFF91	#HALFWIDTH KATAKANA LETTER MU+0xD2	0xFF92	#HALFWIDTH KATAKANA LETTER ME+0xD3	0xFF93	#HALFWIDTH KATAKANA LETTER MO+0xD4	0xFF94	#HALFWIDTH KATAKANA LETTER YA+0xD5	0xFF95	#HALFWIDTH KATAKANA LETTER YU+0xD6	0xFF96	#HALFWIDTH KATAKANA LETTER YO+0xD7	0xFF97	#HALFWIDTH KATAKANA LETTER RA+0xD8	0xFF98	#HALFWIDTH KATAKANA LETTER RI+0xD9	0xFF99	#HALFWIDTH KATAKANA LETTER RU+0xDA	0xFF9A	#HALFWIDTH KATAKANA LETTER RE+0xDB	0xFF9B	#HALFWIDTH KATAKANA LETTER RO+0xDC	0xFF9C	#HALFWIDTH KATAKANA LETTER WA+0xDD	0xFF9D	#HALFWIDTH KATAKANA LETTER N+0xDE	0xFF9E	#HALFWIDTH KATAKANA VOICED SOUND MARK+0xDF	0xFF9F	#HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK+0xE0	      	#DBCS LEAD BYTE+0xE1	      	#DBCS LEAD BYTE+0xE2	      	#DBCS LEAD BYTE+0xE3	      	#DBCS LEAD BYTE+0xE4	      	#DBCS LEAD BYTE+0xE5	      	#DBCS LEAD BYTE+0xE6	      	#DBCS LEAD BYTE+0xE7	      	#DBCS LEAD BYTE+0xE8	      	#DBCS LEAD BYTE+0xE9	      	#DBCS LEAD BYTE+0xEA	      	#DBCS LEAD BYTE+0xEB	      	#DBCS LEAD BYTE+0xEC	      	#DBCS LEAD BYTE+0xED	      	#DBCS LEAD BYTE+0xEE	      	#DBCS LEAD BYTE+0xEF	      	#DBCS LEAD BYTE+0xF0	      	#DBCS LEAD BYTE+0xF1	      	#DBCS LEAD BYTE+0xF2	      	#DBCS LEAD BYTE+0xF3	      	#DBCS LEAD BYTE+0xF4	      	#DBCS LEAD BYTE+0xF5	      	#DBCS LEAD BYTE+0xF6	      	#DBCS LEAD BYTE+0xF7	      	#DBCS LEAD BYTE+0xF8	      	#DBCS LEAD BYTE+0xF9	      	#DBCS LEAD BYTE+0xFA	      	#DBCS LEAD BYTE+0xFB	      	#DBCS LEAD BYTE+0xFC	      	#DBCS LEAD BYTE+0xFD	      	#UNDEFINED+0xFE	      	#UNDEFINED+0xFF	      	#UNDEFINED+0x8140	0x3000	#IDEOGRAPHIC SPACE+0x8141	0x3001	#IDEOGRAPHIC COMMA+0x8142	0x3002	#IDEOGRAPHIC FULL STOP+0x8143	0xFF0C	#FULLWIDTH COMMA+0x8144	0xFF0E	#FULLWIDTH FULL STOP+0x8145	0x30FB	#KATAKANA MIDDLE DOT+0x8146	0xFF1A	#FULLWIDTH COLON+0x8147	0xFF1B	#FULLWIDTH SEMICOLON+0x8148	0xFF1F	#FULLWIDTH QUESTION MARK+0x8149	0xFF01	#FULLWIDTH EXCLAMATION MARK+0x814A	0x309B	#KATAKANA-HIRAGANA VOICED SOUND MARK+0x814B	0x309C	#KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK+0x814C	0x00B4	#ACUTE ACCENT+0x814D	0xFF40	#FULLWIDTH GRAVE ACCENT+0x814E	0x00A8	#DIAERESIS+0x814F	0xFF3E	#FULLWIDTH CIRCUMFLEX ACCENT+0x8150	0xFFE3	#FULLWIDTH MACRON+0x8151	0xFF3F	#FULLWIDTH LOW LINE+0x8152	0x30FD	#KATAKANA ITERATION MARK+0x8153	0x30FE	#KATAKANA VOICED ITERATION MARK+0x8154	0x309D	#HIRAGANA ITERATION MARK+0x8155	0x309E	#HIRAGANA VOICED ITERATION MARK+0x8156	0x3003	#DITTO MARK+0x8157	0x4EDD	#CJK UNIFIED IDEOGRAPH+0x8158	0x3005	#IDEOGRAPHIC ITERATION MARK+0x8159	0x3006	#IDEOGRAPHIC CLOSING MARK+0x815A	0x3007	#IDEOGRAPHIC NUMBER ZERO+0x815B	0x30FC	#KATAKANA-HIRAGANA PROLONGED SOUND MARK+0x815C	0x2015	#HORIZONTAL BAR+0x815D	0x2010	#HYPHEN+0x815E	0xFF0F	#FULLWIDTH SOLIDUS+0x815F	0xFF3C	#FULLWIDTH REVERSE SOLIDUS+0x8160	0xFF5E	#FULLWIDTH TILDE+0x8161	0x2225	#PARALLEL TO+0x8162	0xFF5C	#FULLWIDTH VERTICAL LINE+0x8163	0x2026	#HORIZONTAL ELLIPSIS+0x8164	0x2025	#TWO DOT LEADER+0x8165	0x2018	#LEFT SINGLE QUOTATION MARK+0x8166	0x2019	#RIGHT SINGLE QUOTATION MARK+0x8167	0x201C	#LEFT DOUBLE QUOTATION MARK+0x8168	0x201D	#RIGHT DOUBLE QUOTATION MARK+0x8169	0xFF08	#FULLWIDTH LEFT PARENTHESIS+0x816A	0xFF09	#FULLWIDTH RIGHT PARENTHESIS+0x816B	0x3014	#LEFT TORTOISE SHELL BRACKET+0x816C	0x3015	#RIGHT TORTOISE SHELL BRACKET+0x816D	0xFF3B	#FULLWIDTH LEFT SQUARE BRACKET+0x816E	0xFF3D	#FULLWIDTH RIGHT SQUARE BRACKET+0x816F	0xFF5B	#FULLWIDTH LEFT CURLY BRACKET+0x8170	0xFF5D	#FULLWIDTH RIGHT CURLY BRACKET+0x8171	0x3008	#LEFT ANGLE BRACKET+0x8172	0x3009	#RIGHT ANGLE BRACKET+0x8173	0x300A	#LEFT DOUBLE ANGLE BRACKET+0x8174	0x300B	#RIGHT DOUBLE ANGLE BRACKET+0x8175	0x300C	#LEFT CORNER BRACKET+0x8176	0x300D	#RIGHT CORNER BRACKET+0x8177	0x300E	#LEFT WHITE CORNER BRACKET+0x8178	0x300F	#RIGHT WHITE CORNER BRACKET+0x8179	0x3010	#LEFT BLACK LENTICULAR BRACKET+0x817A	0x3011	#RIGHT BLACK LENTICULAR BRACKET+0x817B	0xFF0B	#FULLWIDTH PLUS SIGN+0x817C	0xFF0D	#FULLWIDTH HYPHEN-MINUS+0x817D	0x00B1	#PLUS-MINUS SIGN+0x817E	0x00D7	#MULTIPLICATION SIGN+0x8180	0x00F7	#DIVISION SIGN+0x8181	0xFF1D	#FULLWIDTH EQUALS SIGN+0x8182	0x2260	#NOT EQUAL TO+0x8183	0xFF1C	#FULLWIDTH LESS-THAN SIGN+0x8184	0xFF1E	#FULLWIDTH GREATER-THAN SIGN+0x8185	0x2266	#LESS-THAN OVER EQUAL TO+0x8186	0x2267	#GREATER-THAN OVER EQUAL TO+0x8187	0x221E	#INFINITY+0x8188	0x2234	#THEREFORE+0x8189	0x2642	#MALE SIGN+0x818A	0x2640	#FEMALE SIGN+0x818B	0x00B0	#DEGREE SIGN+0x818C	0x2032	#PRIME+0x818D	0x2033	#DOUBLE PRIME+0x818E	0x2103	#DEGREE CELSIUS+0x818F	0xFFE5	#FULLWIDTH YEN SIGN+0x8190	0xFF04	#FULLWIDTH DOLLAR SIGN+0x8191	0xFFE0	#FULLWIDTH CENT SIGN+0x8192	0xFFE1	#FULLWIDTH POUND SIGN+0x8193	0xFF05	#FULLWIDTH PERCENT SIGN+0x8194	0xFF03	#FULLWIDTH NUMBER SIGN+0x8195	0xFF06	#FULLWIDTH AMPERSAND+0x8196	0xFF0A	#FULLWIDTH ASTERISK+0x8197	0xFF20	#FULLWIDTH COMMERCIAL AT+0x8198	0x00A7	#SECTION SIGN+0x8199	0x2606	#WHITE STAR+0x819A	0x2605	#BLACK STAR+0x819B	0x25CB	#WHITE CIRCLE+0x819C	0x25CF	#BLACK CIRCLE+0x819D	0x25CE	#BULLSEYE+0x819E	0x25C7	#WHITE DIAMOND+0x819F	0x25C6	#BLACK DIAMOND+0x81A0	0x25A1	#WHITE SQUARE+0x81A1	0x25A0	#BLACK SQUARE+0x81A2	0x25B3	#WHITE UP-POINTING TRIANGLE+0x81A3	0x25B2	#BLACK UP-POINTING TRIANGLE+0x81A4	0x25BD	#WHITE DOWN-POINTING TRIANGLE+0x81A5	0x25BC	#BLACK DOWN-POINTING TRIANGLE+0x81A6	0x203B	#REFERENCE MARK+0x81A7	0x3012	#POSTAL MARK+0x81A8	0x2192	#RIGHTWARDS ARROW+0x81A9	0x2190	#LEFTWARDS ARROW+0x81AA	0x2191	#UPWARDS ARROW+0x81AB	0x2193	#DOWNWARDS ARROW+0x81AC	0x3013	#GETA MARK+0x81B8	0x2208	#ELEMENT OF+0x81B9	0x220B	#CONTAINS AS MEMBER+0x81BA	0x2286	#SUBSET OF OR EQUAL TO+0x81BB	0x2287	#SUPERSET OF OR EQUAL TO+0x81BC	0x2282	#SUBSET OF+0x81BD	0x2283	#SUPERSET OF+0x81BE	0x222A	#UNION+0x81BF	0x2229	#INTERSECTION+0x81C8	0x2227	#LOGICAL AND+0x81C9	0x2228	#LOGICAL OR+0x81CA	0xFFE2	#FULLWIDTH NOT SIGN+0x81CB	0x21D2	#RIGHTWARDS DOUBLE ARROW+0x81CC	0x21D4	#LEFT RIGHT DOUBLE ARROW+0x81CD	0x2200	#FOR ALL+0x81CE	0x2203	#THERE EXISTS+0x81DA	0x2220	#ANGLE+0x81DB	0x22A5	#UP TACK+0x81DC	0x2312	#ARC+0x81DD	0x2202	#PARTIAL DIFFERENTIAL+0x81DE	0x2207	#NABLA+0x81DF	0x2261	#IDENTICAL TO+0x81E0	0x2252	#APPROXIMATELY EQUAL TO OR THE IMAGE OF+0x81E1	0x226A	#MUCH LESS-THAN+0x81E2	0x226B	#MUCH GREATER-THAN+0x81E3	0x221A	#SQUARE ROOT+0x81E4	0x223D	#REVERSED TILDE+0x81E5	0x221D	#PROPORTIONAL TO+0x81E6	0x2235	#BECAUSE+0x81E7	0x222B	#INTEGRAL+0x81E8	0x222C	#DOUBLE INTEGRAL+0x81F0	0x212B	#ANGSTROM SIGN+0x81F1	0x2030	#PER MILLE SIGN+0x81F2	0x266F	#MUSIC SHARP SIGN+0x81F3	0x266D	#MUSIC FLAT SIGN+0x81F4	0x266A	#EIGHTH NOTE+0x81F5	0x2020	#DAGGER+0x81F6	0x2021	#DOUBLE DAGGER+0x81F7	0x00B6	#PILCROW SIGN+0x81FC	0x25EF	#LARGE CIRCLE+0x824F	0xFF10	#FULLWIDTH DIGIT ZERO+0x8250	0xFF11	#FULLWIDTH DIGIT ONE+0x8251	0xFF12	#FULLWIDTH DIGIT TWO+0x8252	0xFF13	#FULLWIDTH DIGIT THREE+0x8253	0xFF14	#FULLWIDTH DIGIT FOUR+0x8254	0xFF15	#FULLWIDTH DIGIT FIVE+0x8255	0xFF16	#FULLWIDTH DIGIT SIX+0x8256	0xFF17	#FULLWIDTH DIGIT SEVEN+0x8257	0xFF18	#FULLWIDTH DIGIT EIGHT+0x8258	0xFF19	#FULLWIDTH DIGIT NINE+0x8260	0xFF21	#FULLWIDTH LATIN CAPITAL LETTER A+0x8261	0xFF22	#FULLWIDTH LATIN CAPITAL LETTER B+0x8262	0xFF23	#FULLWIDTH LATIN CAPITAL LETTER C+0x8263	0xFF24	#FULLWIDTH LATIN CAPITAL LETTER D+0x8264	0xFF25	#FULLWIDTH LATIN CAPITAL LETTER E+0x8265	0xFF26	#FULLWIDTH LATIN CAPITAL LETTER F+0x8266	0xFF27	#FULLWIDTH LATIN CAPITAL LETTER G+0x8267	0xFF28	#FULLWIDTH LATIN CAPITAL LETTER H+0x8268	0xFF29	#FULLWIDTH LATIN CAPITAL LETTER I+0x8269	0xFF2A	#FULLWIDTH LATIN CAPITAL LETTER J+0x826A	0xFF2B	#FULLWIDTH LATIN CAPITAL LETTER K+0x826B	0xFF2C	#FULLWIDTH LATIN CAPITAL LETTER L+0x826C	0xFF2D	#FULLWIDTH LATIN CAPITAL LETTER M+0x826D	0xFF2E	#FULLWIDTH LATIN CAPITAL LETTER N+0x826E	0xFF2F	#FULLWIDTH LATIN CAPITAL LETTER O+0x826F	0xFF30	#FULLWIDTH LATIN CAPITAL LETTER P+0x8270	0xFF31	#FULLWIDTH LATIN CAPITAL LETTER Q+0x8271	0xFF32	#FULLWIDTH LATIN CAPITAL LETTER R+0x8272	0xFF33	#FULLWIDTH LATIN CAPITAL LETTER S+0x8273	0xFF34	#FULLWIDTH LATIN CAPITAL LETTER T+0x8274	0xFF35	#FULLWIDTH LATIN CAPITAL LETTER U+0x8275	0xFF36	#FULLWIDTH LATIN CAPITAL LETTER V+0x8276	0xFF37	#FULLWIDTH LATIN CAPITAL LETTER W+0x8277	0xFF38	#FULLWIDTH LATIN CAPITAL LETTER X+0x8278	0xFF39	#FULLWIDTH LATIN CAPITAL LETTER Y+0x8279	0xFF3A	#FULLWIDTH LATIN CAPITAL LETTER Z+0x8281	0xFF41	#FULLWIDTH LATIN SMALL LETTER A+0x8282	0xFF42	#FULLWIDTH LATIN SMALL LETTER B+0x8283	0xFF43	#FULLWIDTH LATIN SMALL LETTER C+0x8284	0xFF44	#FULLWIDTH LATIN SMALL LETTER D+0x8285	0xFF45	#FULLWIDTH LATIN SMALL LETTER E+0x8286	0xFF46	#FULLWIDTH LATIN SMALL LETTER F+0x8287	0xFF47	#FULLWIDTH LATIN SMALL LETTER G+0x8288	0xFF48	#FULLWIDTH LATIN SMALL LETTER H+0x8289	0xFF49	#FULLWIDTH LATIN SMALL LETTER I+0x828A	0xFF4A	#FULLWIDTH LATIN SMALL LETTER J+0x828B	0xFF4B	#FULLWIDTH LATIN SMALL LETTER K+0x828C	0xFF4C	#FULLWIDTH LATIN SMALL LETTER L+0x828D	0xFF4D	#FULLWIDTH LATIN SMALL LETTER M+0x828E	0xFF4E	#FULLWIDTH LATIN SMALL LETTER N+0x828F	0xFF4F	#FULLWIDTH LATIN SMALL LETTER O+0x8290	0xFF50	#FULLWIDTH LATIN SMALL LETTER P+0x8291	0xFF51	#FULLWIDTH LATIN SMALL LETTER Q+0x8292	0xFF52	#FULLWIDTH LATIN SMALL LETTER R+0x8293	0xFF53	#FULLWIDTH LATIN SMALL LETTER S+0x8294	0xFF54	#FULLWIDTH LATIN SMALL LETTER T+0x8295	0xFF55	#FULLWIDTH LATIN SMALL LETTER U+0x8296	0xFF56	#FULLWIDTH LATIN SMALL LETTER V+0x8297	0xFF57	#FULLWIDTH LATIN SMALL LETTER W+0x8298	0xFF58	#FULLWIDTH LATIN SMALL LETTER X+0x8299	0xFF59	#FULLWIDTH LATIN SMALL LETTER Y+0x829A	0xFF5A	#FULLWIDTH LATIN SMALL LETTER Z+0x829F	0x3041	#HIRAGANA LETTER SMALL A+0x82A0	0x3042	#HIRAGANA LETTER A+0x82A1	0x3043	#HIRAGANA LETTER SMALL I+0x82A2	0x3044	#HIRAGANA LETTER I+0x82A3	0x3045	#HIRAGANA LETTER SMALL U+0x82A4	0x3046	#HIRAGANA LETTER U+0x82A5	0x3047	#HIRAGANA LETTER SMALL E+0x82A6	0x3048	#HIRAGANA LETTER E+0x82A7	0x3049	#HIRAGANA LETTER SMALL O+0x82A8	0x304A	#HIRAGANA LETTER O+0x82A9	0x304B	#HIRAGANA LETTER KA+0x82AA	0x304C	#HIRAGANA LETTER GA+0x82AB	0x304D	#HIRAGANA LETTER KI+0x82AC	0x304E	#HIRAGANA LETTER GI+0x82AD	0x304F	#HIRAGANA LETTER KU+0x82AE	0x3050	#HIRAGANA LETTER GU+0x82AF	0x3051	#HIRAGANA LETTER KE+0x82B0	0x3052	#HIRAGANA LETTER GE+0x82B1	0x3053	#HIRAGANA LETTER KO+0x82B2	0x3054	#HIRAGANA LETTER GO+0x82B3	0x3055	#HIRAGANA LETTER SA+0x82B4	0x3056	#HIRAGANA LETTER ZA+0x82B5	0x3057	#HIRAGANA LETTER SI+0x82B6	0x3058	#HIRAGANA LETTER ZI+0x82B7	0x3059	#HIRAGANA LETTER SU+0x82B8	0x305A	#HIRAGANA LETTER ZU+0x82B9	0x305B	#HIRAGANA LETTER SE+0x82BA	0x305C	#HIRAGANA LETTER ZE+0x82BB	0x305D	#HIRAGANA LETTER SO+0x82BC	0x305E	#HIRAGANA LETTER ZO+0x82BD	0x305F	#HIRAGANA LETTER TA+0x82BE	0x3060	#HIRAGANA LETTER DA+0x82BF	0x3061	#HIRAGANA LETTER TI+0x82C0	0x3062	#HIRAGANA LETTER DI+0x82C1	0x3063	#HIRAGANA LETTER SMALL TU+0x82C2	0x3064	#HIRAGANA LETTER TU+0x82C3	0x3065	#HIRAGANA LETTER DU+0x82C4	0x3066	#HIRAGANA LETTER TE+0x82C5	0x3067	#HIRAGANA LETTER DE+0x82C6	0x3068	#HIRAGANA LETTER TO+0x82C7	0x3069	#HIRAGANA LETTER DO+0x82C8	0x306A	#HIRAGANA LETTER NA+0x82C9	0x306B	#HIRAGANA LETTER NI+0x82CA	0x306C	#HIRAGANA LETTER NU+0x82CB	0x306D	#HIRAGANA LETTER NE+0x82CC	0x306E	#HIRAGANA LETTER NO+0x82CD	0x306F	#HIRAGANA LETTER HA+0x82CE	0x3070	#HIRAGANA LETTER BA+0x82CF	0x3071	#HIRAGANA LETTER PA+0x82D0	0x3072	#HIRAGANA LETTER HI+0x82D1	0x3073	#HIRAGANA LETTER BI+0x82D2	0x3074	#HIRAGANA LETTER PI+0x82D3	0x3075	#HIRAGANA LETTER HU+0x82D4	0x3076	#HIRAGANA LETTER BU+0x82D5	0x3077	#HIRAGANA LETTER PU+0x82D6	0x3078	#HIRAGANA LETTER HE+0x82D7	0x3079	#HIRAGANA LETTER BE+0x82D8	0x307A	#HIRAGANA LETTER PE+0x82D9	0x307B	#HIRAGANA LETTER HO+0x82DA	0x307C	#HIRAGANA LETTER BO+0x82DB	0x307D	#HIRAGANA LETTER PO+0x82DC	0x307E	#HIRAGANA LETTER MA+0x82DD	0x307F	#HIRAGANA LETTER MI+0x82DE	0x3080	#HIRAGANA LETTER MU+0x82DF	0x3081	#HIRAGANA LETTER ME+0x82E0	0x3082	#HIRAGANA LETTER MO+0x82E1	0x3083	#HIRAGANA LETTER SMALL YA+0x82E2	0x3084	#HIRAGANA LETTER YA+0x82E3	0x3085	#HIRAGANA LETTER SMALL YU+0x82E4	0x3086	#HIRAGANA LETTER YU+0x82E5	0x3087	#HIRAGANA LETTER SMALL YO+0x82E6	0x3088	#HIRAGANA LETTER YO+0x82E7	0x3089	#HIRAGANA LETTER RA+0x82E8	0x308A	#HIRAGANA LETTER RI+0x82E9	0x308B	#HIRAGANA LETTER RU+0x82EA	0x308C	#HIRAGANA LETTER RE+0x82EB	0x308D	#HIRAGANA LETTER RO+0x82EC	0x308E	#HIRAGANA LETTER SMALL WA+0x82ED	0x308F	#HIRAGANA LETTER WA+0x82EE	0x3090	#HIRAGANA LETTER WI+0x82EF	0x3091	#HIRAGANA LETTER WE+0x82F0	0x3092	#HIRAGANA LETTER WO+0x82F1	0x3093	#HIRAGANA LETTER N+0x8340	0x30A1	#KATAKANA LETTER SMALL A+0x8341	0x30A2	#KATAKANA LETTER A+0x8342	0x30A3	#KATAKANA LETTER SMALL I+0x8343	0x30A4	#KATAKANA LETTER I+0x8344	0x30A5	#KATAKANA LETTER SMALL U+0x8345	0x30A6	#KATAKANA LETTER U+0x8346	0x30A7	#KATAKANA LETTER SMALL E+0x8347	0x30A8	#KATAKANA LETTER E+0x8348	0x30A9	#KATAKANA LETTER SMALL O+0x8349	0x30AA	#KATAKANA LETTER O+0x834A	0x30AB	#KATAKANA LETTER KA+0x834B	0x30AC	#KATAKANA LETTER GA+0x834C	0x30AD	#KATAKANA LETTER KI+0x834D	0x30AE	#KATAKANA LETTER GI+0x834E	0x30AF	#KATAKANA LETTER KU+0x834F	0x30B0	#KATAKANA LETTER GU+0x8350	0x30B1	#KATAKANA LETTER KE+0x8351	0x30B2	#KATAKANA LETTER GE+0x8352	0x30B3	#KATAKANA LETTER KO+0x8353	0x30B4	#KATAKANA LETTER GO+0x8354	0x30B5	#KATAKANA LETTER SA+0x8355	0x30B6	#KATAKANA LETTER ZA+0x8356	0x30B7	#KATAKANA LETTER SI+0x8357	0x30B8	#KATAKANA LETTER ZI+0x8358	0x30B9	#KATAKANA LETTER SU+0x8359	0x30BA	#KATAKANA LETTER ZU+0x835A	0x30BB	#KATAKANA LETTER SE+0x835B	0x30BC	#KATAKANA LETTER ZE+0x835C	0x30BD	#KATAKANA LETTER SO+0x835D	0x30BE	#KATAKANA LETTER ZO+0x835E	0x30BF	#KATAKANA LETTER TA+0x835F	0x30C0	#KATAKANA LETTER DA+0x8360	0x30C1	#KATAKANA LETTER TI+0x8361	0x30C2	#KATAKANA LETTER DI+0x8362	0x30C3	#KATAKANA LETTER SMALL TU+0x8363	0x30C4	#KATAKANA LETTER TU+0x8364	0x30C5	#KATAKANA LETTER DU+0x8365	0x30C6	#KATAKANA LETTER TE+0x8366	0x30C7	#KATAKANA LETTER DE+0x8367	0x30C8	#KATAKANA LETTER TO+0x8368	0x30C9	#KATAKANA LETTER DO+0x8369	0x30CA	#KATAKANA LETTER NA+0x836A	0x30CB	#KATAKANA LETTER NI+0x836B	0x30CC	#KATAKANA LETTER NU+0x836C	0x30CD	#KATAKANA LETTER NE+0x836D	0x30CE	#KATAKANA LETTER NO+0x836E	0x30CF	#KATAKANA LETTER HA+0x836F	0x30D0	#KATAKANA LETTER BA+0x8370	0x30D1	#KATAKANA LETTER PA+0x8371	0x30D2	#KATAKANA LETTER HI+0x8372	0x30D3	#KATAKANA LETTER BI+0x8373	0x30D4	#KATAKANA LETTER PI+0x8374	0x30D5	#KATAKANA LETTER HU+0x8375	0x30D6	#KATAKANA LETTER BU+0x8376	0x30D7	#KATAKANA LETTER PU+0x8377	0x30D8	#KATAKANA LETTER HE+0x8378	0x30D9	#KATAKANA LETTER BE+0x8379	0x30DA	#KATAKANA LETTER PE+0x837A	0x30DB	#KATAKANA LETTER HO+0x837B	0x30DC	#KATAKANA LETTER BO+0x837C	0x30DD	#KATAKANA LETTER PO+0x837D	0x30DE	#KATAKANA LETTER MA+0x837E	0x30DF	#KATAKANA LETTER MI+0x8380	0x30E0	#KATAKANA LETTER MU+0x8381	0x30E1	#KATAKANA LETTER ME+0x8382	0x30E2	#KATAKANA LETTER MO+0x8383	0x30E3	#KATAKANA LETTER SMALL YA+0x8384	0x30E4	#KATAKANA LETTER YA+0x8385	0x30E5	#KATAKANA LETTER SMALL YU+0x8386	0x30E6	#KATAKANA LETTER YU+0x8387	0x30E7	#KATAKANA LETTER SMALL YO+0x8388	0x30E8	#KATAKANA LETTER YO+0x8389	0x30E9	#KATAKANA LETTER RA+0x838A	0x30EA	#KATAKANA LETTER RI+0x838B	0x30EB	#KATAKANA LETTER RU+0x838C	0x30EC	#KATAKANA LETTER RE+0x838D	0x30ED	#KATAKANA LETTER RO+0x838E	0x30EE	#KATAKANA LETTER SMALL WA+0x838F	0x30EF	#KATAKANA LETTER WA+0x8390	0x30F0	#KATAKANA LETTER WI+0x8391	0x30F1	#KATAKANA LETTER WE+0x8392	0x30F2	#KATAKANA LETTER WO+0x8393	0x30F3	#KATAKANA LETTER N+0x8394	0x30F4	#KATAKANA LETTER VU+0x8395	0x30F5	#KATAKANA LETTER SMALL KA+0x8396	0x30F6	#KATAKANA LETTER SMALL KE+0x839F	0x0391	#GREEK CAPITAL LETTER ALPHA+0x83A0	0x0392	#GREEK CAPITAL LETTER BETA+0x83A1	0x0393	#GREEK CAPITAL LETTER GAMMA+0x83A2	0x0394	#GREEK CAPITAL LETTER DELTA+0x83A3	0x0395	#GREEK CAPITAL LETTER EPSILON+0x83A4	0x0396	#GREEK CAPITAL LETTER ZETA+0x83A5	0x0397	#GREEK CAPITAL LETTER ETA+0x83A6	0x0398	#GREEK CAPITAL LETTER THETA+0x83A7	0x0399	#GREEK CAPITAL LETTER IOTA+0x83A8	0x039A	#GREEK CAPITAL LETTER KAPPA+0x83A9	0x039B	#GREEK CAPITAL LETTER LAMDA+0x83AA	0x039C	#GREEK CAPITAL LETTER MU+0x83AB	0x039D	#GREEK CAPITAL LETTER NU+0x83AC	0x039E	#GREEK CAPITAL LETTER XI+0x83AD	0x039F	#GREEK CAPITAL LETTER OMICRON+0x83AE	0x03A0	#GREEK CAPITAL LETTER PI+0x83AF	0x03A1	#GREEK CAPITAL LETTER RHO+0x83B0	0x03A3	#GREEK CAPITAL LETTER SIGMA+0x83B1	0x03A4	#GREEK CAPITAL LETTER TAU+0x83B2	0x03A5	#GREEK CAPITAL LETTER UPSILON+0x83B3	0x03A6	#GREEK CAPITAL LETTER PHI+0x83B4	0x03A7	#GREEK CAPITAL LETTER CHI+0x83B5	0x03A8	#GREEK CAPITAL LETTER PSI+0x83B6	0x03A9	#GREEK CAPITAL LETTER OMEGA+0x83BF	0x03B1	#GREEK SMALL LETTER ALPHA+0x83C0	0x03B2	#GREEK SMALL LETTER BETA+0x83C1	0x03B3	#GREEK SMALL LETTER GAMMA+0x83C2	0x03B4	#GREEK SMALL LETTER DELTA+0x83C3	0x03B5	#GREEK SMALL LETTER EPSILON+0x83C4	0x03B6	#GREEK SMALL LETTER ZETA+0x83C5	0x03B7	#GREEK SMALL LETTER ETA+0x83C6	0x03B8	#GREEK SMALL LETTER THETA+0x83C7	0x03B9	#GREEK SMALL LETTER IOTA+0x83C8	0x03BA	#GREEK SMALL LETTER KAPPA+0x83C9	0x03BB	#GREEK SMALL LETTER LAMDA+0x83CA	0x03BC	#GREEK SMALL LETTER MU+0x83CB	0x03BD	#GREEK SMALL LETTER NU+0x83CC	0x03BE	#GREEK SMALL LETTER XI+0x83CD	0x03BF	#GREEK SMALL LETTER OMICRON+0x83CE	0x03C0	#GREEK SMALL LETTER PI+0x83CF	0x03C1	#GREEK SMALL LETTER RHO+0x83D0	0x03C3	#GREEK SMALL LETTER SIGMA+0x83D1	0x03C4	#GREEK SMALL LETTER TAU+0x83D2	0x03C5	#GREEK SMALL LETTER UPSILON+0x83D3	0x03C6	#GREEK SMALL LETTER PHI+0x83D4	0x03C7	#GREEK SMALL LETTER CHI+0x83D5	0x03C8	#GREEK SMALL LETTER PSI+0x83D6	0x03C9	#GREEK SMALL LETTER OMEGA+0x8440	0x0410	#CYRILLIC CAPITAL LETTER A+0x8441	0x0411	#CYRILLIC CAPITAL LETTER BE+0x8442	0x0412	#CYRILLIC CAPITAL LETTER VE+0x8443	0x0413	#CYRILLIC CAPITAL LETTER GHE+0x8444	0x0414	#CYRILLIC CAPITAL LETTER DE+0x8445	0x0415	#CYRILLIC CAPITAL LETTER IE+0x8446	0x0401	#CYRILLIC CAPITAL LETTER IO+0x8447	0x0416	#CYRILLIC CAPITAL LETTER ZHE+0x8448	0x0417	#CYRILLIC CAPITAL LETTER ZE+0x8449	0x0418	#CYRILLIC CAPITAL LETTER I+0x844A	0x0419	#CYRILLIC CAPITAL LETTER SHORT I+0x844B	0x041A	#CYRILLIC CAPITAL LETTER KA+0x844C	0x041B	#CYRILLIC CAPITAL LETTER EL+0x844D	0x041C	#CYRILLIC CAPITAL LETTER EM+0x844E	0x041D	#CYRILLIC CAPITAL LETTER EN+0x844F	0x041E	#CYRILLIC CAPITAL LETTER O+0x8450	0x041F	#CYRILLIC CAPITAL LETTER PE+0x8451	0x0420	#CYRILLIC CAPITAL LETTER ER+0x8452	0x0421	#CYRILLIC CAPITAL LETTER ES+0x8453	0x0422	#CYRILLIC CAPITAL LETTER TE+0x8454	0x0423	#CYRILLIC CAPITAL LETTER U+0x8455	0x0424	#CYRILLIC CAPITAL LETTER EF+0x8456	0x0425	#CYRILLIC CAPITAL LETTER HA+0x8457	0x0426	#CYRILLIC CAPITAL LETTER TSE+0x8458	0x0427	#CYRILLIC CAPITAL LETTER CHE+0x8459	0x0428	#CYRILLIC CAPITAL LETTER SHA+0x845A	0x0429	#CYRILLIC CAPITAL LETTER SHCHA+0x845B	0x042A	#CYRILLIC CAPITAL LETTER HARD SIGN+0x845C	0x042B	#CYRILLIC CAPITAL LETTER YERU+0x845D	0x042C	#CYRILLIC CAPITAL LETTER SOFT SIGN+0x845E	0x042D	#CYRILLIC CAPITAL LETTER E+0x845F	0x042E	#CYRILLIC CAPITAL LETTER YU+0x8460	0x042F	#CYRILLIC CAPITAL LETTER YA+0x8470	0x0430	#CYRILLIC SMALL LETTER A+0x8471	0x0431	#CYRILLIC SMALL LETTER BE+0x8472	0x0432	#CYRILLIC SMALL LETTER VE+0x8473	0x0433	#CYRILLIC SMALL LETTER GHE+0x8474	0x0434	#CYRILLIC SMALL LETTER DE+0x8475	0x0435	#CYRILLIC SMALL LETTER IE+0x8476	0x0451	#CYRILLIC SMALL LETTER IO+0x8477	0x0436	#CYRILLIC SMALL LETTER ZHE+0x8478	0x0437	#CYRILLIC SMALL LETTER ZE+0x8479	0x0438	#CYRILLIC SMALL LETTER I+0x847A	0x0439	#CYRILLIC SMALL LETTER SHORT I+0x847B	0x043A	#CYRILLIC SMALL LETTER KA+0x847C	0x043B	#CYRILLIC SMALL LETTER EL+0x847D	0x043C	#CYRILLIC SMALL LETTER EM+0x847E	0x043D	#CYRILLIC SMALL LETTER EN+0x8480	0x043E	#CYRILLIC SMALL LETTER O+0x8481	0x043F	#CYRILLIC SMALL LETTER PE+0x8482	0x0440	#CYRILLIC SMALL LETTER ER+0x8483	0x0441	#CYRILLIC SMALL LETTER ES+0x8484	0x0442	#CYRILLIC SMALL LETTER TE+0x8485	0x0443	#CYRILLIC SMALL LETTER U+0x8486	0x0444	#CYRILLIC SMALL LETTER EF+0x8487	0x0445	#CYRILLIC SMALL LETTER HA+0x8488	0x0446	#CYRILLIC SMALL LETTER TSE+0x8489	0x0447	#CYRILLIC SMALL LETTER CHE+0x848A	0x0448	#CYRILLIC SMALL LETTER SHA+0x848B	0x0449	#CYRILLIC SMALL LETTER SHCHA+0x848C	0x044A	#CYRILLIC SMALL LETTER HARD SIGN+0x848D	0x044B	#CYRILLIC SMALL LETTER YERU+0x848E	0x044C	#CYRILLIC SMALL LETTER SOFT SIGN+0x848F	0x044D	#CYRILLIC SMALL LETTER E+0x8490	0x044E	#CYRILLIC SMALL LETTER YU+0x8491	0x044F	#CYRILLIC SMALL LETTER YA+0x849F	0x2500	#BOX DRAWINGS LIGHT HORIZONTAL+0x84A0	0x2502	#BOX DRAWINGS LIGHT VERTICAL+0x84A1	0x250C	#BOX DRAWINGS LIGHT DOWN AND RIGHT+0x84A2	0x2510	#BOX DRAWINGS LIGHT DOWN AND LEFT+0x84A3	0x2518	#BOX DRAWINGS LIGHT UP AND LEFT+0x84A4	0x2514	#BOX DRAWINGS LIGHT UP AND RIGHT+0x84A5	0x251C	#BOX DRAWINGS LIGHT VERTICAL AND RIGHT+0x84A6	0x252C	#BOX DRAWINGS LIGHT DOWN AND HORIZONTAL+0x84A7	0x2524	#BOX DRAWINGS LIGHT VERTICAL AND LEFT+0x84A8	0x2534	#BOX DRAWINGS LIGHT UP AND HORIZONTAL+0x84A9	0x253C	#BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL+0x84AA	0x2501	#BOX DRAWINGS HEAVY HORIZONTAL+0x84AB	0x2503	#BOX DRAWINGS HEAVY VERTICAL+0x84AC	0x250F	#BOX DRAWINGS HEAVY DOWN AND RIGHT+0x84AD	0x2513	#BOX DRAWINGS HEAVY DOWN AND LEFT+0x84AE	0x251B	#BOX DRAWINGS HEAVY UP AND LEFT+0x84AF	0x2517	#BOX DRAWINGS HEAVY UP AND RIGHT+0x84B0	0x2523	#BOX DRAWINGS HEAVY VERTICAL AND RIGHT+0x84B1	0x2533	#BOX DRAWINGS HEAVY DOWN AND HORIZONTAL+0x84B2	0x252B	#BOX DRAWINGS HEAVY VERTICAL AND LEFT+0x84B3	0x253B	#BOX DRAWINGS HEAVY UP AND HORIZONTAL+0x84B4	0x254B	#BOX DRAWINGS HEAVY VERTICAL AND HORIZONTAL+0x84B5	0x2520	#BOX DRAWINGS VERTICAL HEAVY AND RIGHT LIGHT+0x84B6	0x252F	#BOX DRAWINGS DOWN LIGHT AND HORIZONTAL HEAVY+0x84B7	0x2528	#BOX DRAWINGS VERTICAL HEAVY AND LEFT LIGHT+0x84B8	0x2537	#BOX DRAWINGS UP LIGHT AND HORIZONTAL HEAVY+0x84B9	0x253F	#BOX DRAWINGS VERTICAL LIGHT AND HORIZONTAL HEAVY+0x84BA	0x251D	#BOX DRAWINGS VERTICAL LIGHT AND RIGHT HEAVY+0x84BB	0x2530	#BOX DRAWINGS DOWN HEAVY AND HORIZONTAL LIGHT+0x84BC	0x2525	#BOX DRAWINGS VERTICAL LIGHT AND LEFT HEAVY+0x84BD	0x2538	#BOX DRAWINGS UP HEAVY AND HORIZONTAL LIGHT+0x84BE	0x2542	#BOX DRAWINGS VERTICAL HEAVY AND HORIZONTAL LIGHT+0x8740	0x2460	#CIRCLED DIGIT ONE+0x8741	0x2461	#CIRCLED DIGIT TWO+0x8742	0x2462	#CIRCLED DIGIT THREE+0x8743	0x2463	#CIRCLED DIGIT FOUR+0x8744	0x2464	#CIRCLED DIGIT FIVE+0x8745	0x2465	#CIRCLED DIGIT SIX+0x8746	0x2466	#CIRCLED DIGIT SEVEN+0x8747	0x2467	#CIRCLED DIGIT EIGHT+0x8748	0x2468	#CIRCLED DIGIT NINE+0x8749	0x2469	#CIRCLED NUMBER TEN+0x874A	0x246A	#CIRCLED NUMBER ELEVEN+0x874B	0x246B	#CIRCLED NUMBER TWELVE+0x874C	0x246C	#CIRCLED NUMBER THIRTEEN+0x874D	0x246D	#CIRCLED NUMBER FOURTEEN+0x874E	0x246E	#CIRCLED NUMBER FIFTEEN+0x874F	0x246F	#CIRCLED NUMBER SIXTEEN+0x8750	0x2470	#CIRCLED NUMBER SEVENTEEN+0x8751	0x2471	#CIRCLED NUMBER EIGHTEEN+0x8752	0x2472	#CIRCLED NUMBER NINETEEN+0x8753	0x2473	#CIRCLED NUMBER TWENTY+0x8754	0x2160	#ROMAN NUMERAL ONE+0x8755	0x2161	#ROMAN NUMERAL TWO+0x8756	0x2162	#ROMAN NUMERAL THREE+0x8757	0x2163	#ROMAN NUMERAL FOUR+0x8758	0x2164	#ROMAN NUMERAL FIVE+0x8759	0x2165	#ROMAN NUMERAL SIX+0x875A	0x2166	#ROMAN NUMERAL SEVEN+0x875B	0x2167	#ROMAN NUMERAL EIGHT+0x875C	0x2168	#ROMAN NUMERAL NINE+0x875D	0x2169	#ROMAN NUMERAL TEN+0x875F	0x3349	#SQUARE MIRI+0x8760	0x3314	#SQUARE KIRO+0x8761	0x3322	#SQUARE SENTI+0x8762	0x334D	#SQUARE MEETORU+0x8763	0x3318	#SQUARE GURAMU+0x8764	0x3327	#SQUARE TON+0x8765	0x3303	#SQUARE AARU+0x8766	0x3336	#SQUARE HEKUTAARU+0x8767	0x3351	#SQUARE RITTORU+0x8768	0x3357	#SQUARE WATTO+0x8769	0x330D	#SQUARE KARORII+0x876A	0x3326	#SQUARE DORU+0x876B	0x3323	#SQUARE SENTO+0x876C	0x332B	#SQUARE PAASENTO+0x876D	0x334A	#SQUARE MIRIBAARU+0x876E	0x333B	#SQUARE PEEZI+0x876F	0x339C	#SQUARE MM+0x8770	0x339D	#SQUARE CM+0x8771	0x339E	#SQUARE KM+0x8772	0x338E	#SQUARE MG+0x8773	0x338F	#SQUARE KG+0x8774	0x33C4	#SQUARE CC+0x8775	0x33A1	#SQUARE M SQUARED+0x877E	0x337B	#SQUARE ERA NAME HEISEI+0x8780	0x301D	#REVERSED DOUBLE PRIME QUOTATION MARK+0x8781	0x301F	#LOW DOUBLE PRIME QUOTATION MARK+0x8782	0x2116	#NUMERO SIGN+0x8783	0x33CD	#SQUARE KK+0x8784	0x2121	#TELEPHONE SIGN+0x8785	0x32A4	#CIRCLED IDEOGRAPH HIGH+0x8786	0x32A5	#CIRCLED IDEOGRAPH CENTRE+0x8787	0x32A6	#CIRCLED IDEOGRAPH LOW+0x8788	0x32A7	#CIRCLED IDEOGRAPH LEFT+0x8789	0x32A8	#CIRCLED IDEOGRAPH RIGHT+0x878A	0x3231	#PARENTHESIZED IDEOGRAPH STOCK+0x878B	0x3232	#PARENTHESIZED IDEOGRAPH HAVE+0x878C	0x3239	#PARENTHESIZED IDEOGRAPH REPRESENT+0x878D	0x337E	#SQUARE ERA NAME MEIZI+0x878E	0x337D	#SQUARE ERA NAME TAISYOU+0x878F	0x337C	#SQUARE ERA NAME SYOUWA+0x8790	0x2252	#APPROXIMATELY EQUAL TO OR THE IMAGE OF+0x8791	0x2261	#IDENTICAL TO+0x8792	0x222B	#INTEGRAL+0x8793	0x222E	#CONTOUR INTEGRAL+0x8794	0x2211	#N-ARY SUMMATION+0x8795	0x221A	#SQUARE ROOT+0x8796	0x22A5	#UP TACK+0x8797	0x2220	#ANGLE+0x8798	0x221F	#RIGHT ANGLE+0x8799	0x22BF	#RIGHT TRIANGLE+0x879A	0x2235	#BECAUSE+0x879B	0x2229	#INTERSECTION+0x879C	0x222A	#UNION+0x889F	0x4E9C	#CJK UNIFIED IDEOGRAPH+0x88A0	0x5516	#CJK UNIFIED IDEOGRAPH+0x88A1	0x5A03	#CJK UNIFIED IDEOGRAPH+0x88A2	0x963F	#CJK UNIFIED IDEOGRAPH+0x88A3	0x54C0	#CJK UNIFIED IDEOGRAPH+0x88A4	0x611B	#CJK UNIFIED IDEOGRAPH+0x88A5	0x6328	#CJK UNIFIED IDEOGRAPH+0x88A6	0x59F6	#CJK UNIFIED IDEOGRAPH+0x88A7	0x9022	#CJK UNIFIED IDEOGRAPH+0x88A8	0x8475	#CJK UNIFIED IDEOGRAPH+0x88A9	0x831C	#CJK UNIFIED IDEOGRAPH+0x88AA	0x7A50	#CJK UNIFIED IDEOGRAPH+0x88AB	0x60AA	#CJK UNIFIED IDEOGRAPH+0x88AC	0x63E1	#CJK UNIFIED IDEOGRAPH+0x88AD	0x6E25	#CJK UNIFIED IDEOGRAPH+0x88AE	0x65ED	#CJK UNIFIED IDEOGRAPH+0x88AF	0x8466	#CJK UNIFIED IDEOGRAPH+0x88B0	0x82A6	#CJK UNIFIED IDEOGRAPH+0x88B1	0x9BF5	#CJK UNIFIED IDEOGRAPH+0x88B2	0x6893	#CJK UNIFIED IDEOGRAPH+0x88B3	0x5727	#CJK UNIFIED IDEOGRAPH+0x88B4	0x65A1	#CJK UNIFIED IDEOGRAPH+0x88B5	0x6271	#CJK UNIFIED IDEOGRAPH+0x88B6	0x5B9B	#CJK UNIFIED IDEOGRAPH+0x88B7	0x59D0	#CJK UNIFIED IDEOGRAPH+0x88B8	0x867B	#CJK UNIFIED IDEOGRAPH+0x88B9	0x98F4	#CJK UNIFIED IDEOGRAPH+0x88BA	0x7D62	#CJK UNIFIED IDEOGRAPH+0x88BB	0x7DBE	#CJK UNIFIED IDEOGRAPH+0x88BC	0x9B8E	#CJK UNIFIED IDEOGRAPH+0x88BD	0x6216	#CJK UNIFIED IDEOGRAPH+0x88BE	0x7C9F	#CJK UNIFIED IDEOGRAPH+0x88BF	0x88B7	#CJK UNIFIED IDEOGRAPH+0x88C0	0x5B89	#CJK UNIFIED IDEOGRAPH+0x88C1	0x5EB5	#CJK UNIFIED IDEOGRAPH+0x88C2	0x6309	#CJK UNIFIED IDEOGRAPH+0x88C3	0x6697	#CJK UNIFIED IDEOGRAPH+0x88C4	0x6848	#CJK UNIFIED IDEOGRAPH+0x88C5	0x95C7	#CJK UNIFIED IDEOGRAPH+0x88C6	0x978D	#CJK UNIFIED IDEOGRAPH+0x88C7	0x674F	#CJK UNIFIED IDEOGRAPH+0x88C8	0x4EE5	#CJK UNIFIED IDEOGRAPH+0x88C9	0x4F0A	#CJK UNIFIED IDEOGRAPH+0x88CA	0x4F4D	#CJK UNIFIED IDEOGRAPH+0x88CB	0x4F9D	#CJK UNIFIED IDEOGRAPH+0x88CC	0x5049	#CJK UNIFIED IDEOGRAPH+0x88CD	0x56F2	#CJK UNIFIED IDEOGRAPH+0x88CE	0x5937	#CJK UNIFIED IDEOGRAPH+0x88CF	0x59D4	#CJK UNIFIED IDEOGRAPH+0x88D0	0x5A01	#CJK UNIFIED IDEOGRAPH+0x88D1	0x5C09	#CJK UNIFIED IDEOGRAPH+0x88D2	0x60DF	#CJK UNIFIED IDEOGRAPH+0x88D3	0x610F	#CJK UNIFIED IDEOGRAPH+0x88D4	0x6170	#CJK UNIFIED IDEOGRAPH+0x88D5	0x6613	#CJK UNIFIED IDEOGRAPH+0x88D6	0x6905	#CJK UNIFIED IDEOGRAPH+0x88D7	0x70BA	#CJK UNIFIED IDEOGRAPH+0x88D8	0x754F	#CJK UNIFIED IDEOGRAPH+0x88D9	0x7570	#CJK UNIFIED IDEOGRAPH+0x88DA	0x79FB	#CJK UNIFIED IDEOGRAPH+0x88DB	0x7DAD	#CJK UNIFIED IDEOGRAPH+0x88DC	0x7DEF	#CJK UNIFIED IDEOGRAPH+0x88DD	0x80C3	#CJK UNIFIED IDEOGRAPH+0x88DE	0x840E	#CJK UNIFIED IDEOGRAPH+0x88DF	0x8863	#CJK UNIFIED IDEOGRAPH+0x88E0	0x8B02	#CJK UNIFIED IDEOGRAPH+0x88E1	0x9055	#CJK UNIFIED IDEOGRAPH+0x88E2	0x907A	#CJK UNIFIED IDEOGRAPH+0x88E3	0x533B	#CJK UNIFIED IDEOGRAPH+0x88E4	0x4E95	#CJK UNIFIED IDEOGRAPH+0x88E5	0x4EA5	#CJK UNIFIED IDEOGRAPH+0x88E6	0x57DF	#CJK UNIFIED IDEOGRAPH+0x88E7	0x80B2	#CJK UNIFIED IDEOGRAPH+0x88E8	0x90C1	#CJK UNIFIED IDEOGRAPH+0x88E9	0x78EF	#CJK UNIFIED IDEOGRAPH+0x88EA	0x4E00	#CJK UNIFIED IDEOGRAPH+0x88EB	0x58F1	#CJK UNIFIED IDEOGRAPH+0x88EC	0x6EA2	#CJK UNIFIED IDEOGRAPH+0x88ED	0x9038	#CJK UNIFIED IDEOGRAPH+0x88EE	0x7A32	#CJK UNIFIED IDEOGRAPH+0x88EF	0x8328	#CJK UNIFIED IDEOGRAPH+0x88F0	0x828B	#CJK UNIFIED IDEOGRAPH+0x88F1	0x9C2F	#CJK UNIFIED IDEOGRAPH+0x88F2	0x5141	#CJK UNIFIED IDEOGRAPH+0x88F3	0x5370	#CJK UNIFIED IDEOGRAPH+0x88F4	0x54BD	#CJK UNIFIED IDEOGRAPH+0x88F5	0x54E1	#CJK UNIFIED IDEOGRAPH+0x88F6	0x56E0	#CJK UNIFIED IDEOGRAPH+0x88F7	0x59FB	#CJK UNIFIED IDEOGRAPH+0x88F8	0x5F15	#CJK UNIFIED IDEOGRAPH+0x88F9	0x98F2	#CJK UNIFIED IDEOGRAPH+0x88FA	0x6DEB	#CJK UNIFIED IDEOGRAPH+0x88FB	0x80E4	#CJK UNIFIED IDEOGRAPH+0x88FC	0x852D	#CJK UNIFIED IDEOGRAPH+0x8940	0x9662	#CJK UNIFIED IDEOGRAPH+0x8941	0x9670	#CJK UNIFIED IDEOGRAPH+0x8942	0x96A0	#CJK UNIFIED IDEOGRAPH+0x8943	0x97FB	#CJK UNIFIED IDEOGRAPH+0x8944	0x540B	#CJK UNIFIED IDEOGRAPH+0x8945	0x53F3	#CJK UNIFIED IDEOGRAPH+0x8946	0x5B87	#CJK UNIFIED IDEOGRAPH+0x8947	0x70CF	#CJK UNIFIED IDEOGRAPH+0x8948	0x7FBD	#CJK UNIFIED IDEOGRAPH+0x8949	0x8FC2	#CJK UNIFIED IDEOGRAPH+0x894A	0x96E8	#CJK UNIFIED IDEOGRAPH+0x894B	0x536F	#CJK UNIFIED IDEOGRAPH+0x894C	0x9D5C	#CJK UNIFIED IDEOGRAPH+0x894D	0x7ABA	#CJK UNIFIED IDEOGRAPH+0x894E	0x4E11	#CJK UNIFIED IDEOGRAPH+0x894F	0x7893	#CJK UNIFIED IDEOGRAPH+0x8950	0x81FC	#CJK UNIFIED IDEOGRAPH+0x8951	0x6E26	#CJK UNIFIED IDEOGRAPH+0x8952	0x5618	#CJK UNIFIED IDEOGRAPH+0x8953	0x5504	#CJK UNIFIED IDEOGRAPH+0x8954	0x6B1D	#CJK UNIFIED IDEOGRAPH+0x8955	0x851A	#CJK UNIFIED IDEOGRAPH+0x8956	0x9C3B	#CJK UNIFIED IDEOGRAPH+0x8957	0x59E5	#CJK UNIFIED IDEOGRAPH+0x8958	0x53A9	#CJK UNIFIED IDEOGRAPH+0x8959	0x6D66	#CJK UNIFIED IDEOGRAPH+0x895A	0x74DC	#CJK UNIFIED IDEOGRAPH+0x895B	0x958F	#CJK UNIFIED IDEOGRAPH+0x895C	0x5642	#CJK UNIFIED IDEOGRAPH+0x895D	0x4E91	#CJK UNIFIED IDEOGRAPH+0x895E	0x904B	#CJK UNIFIED IDEOGRAPH+0x895F	0x96F2	#CJK UNIFIED IDEOGRAPH+0x8960	0x834F	#CJK UNIFIED IDEOGRAPH+0x8961	0x990C	#CJK UNIFIED IDEOGRAPH+0x8962	0x53E1	#CJK UNIFIED IDEOGRAPH+0x8963	0x55B6	#CJK UNIFIED IDEOGRAPH+0x8964	0x5B30	#CJK UNIFIED IDEOGRAPH+0x8965	0x5F71	#CJK UNIFIED IDEOGRAPH+0x8966	0x6620	#CJK UNIFIED IDEOGRAPH+0x8967	0x66F3	#CJK UNIFIED IDEOGRAPH+0x8968	0x6804	#CJK UNIFIED IDEOGRAPH+0x8969	0x6C38	#CJK UNIFIED IDEOGRAPH+0x896A	0x6CF3	#CJK UNIFIED IDEOGRAPH+0x896B	0x6D29	#CJK UNIFIED IDEOGRAPH+0x896C	0x745B	#CJK UNIFIED IDEOGRAPH+0x896D	0x76C8	#CJK UNIFIED IDEOGRAPH+0x896E	0x7A4E	#CJK UNIFIED IDEOGRAPH+0x896F	0x9834	#CJK UNIFIED IDEOGRAPH+0x8970	0x82F1	#CJK UNIFIED IDEOGRAPH+0x8971	0x885B	#CJK UNIFIED IDEOGRAPH+0x8972	0x8A60	#CJK UNIFIED IDEOGRAPH+0x8973	0x92ED	#CJK UNIFIED IDEOGRAPH+0x8974	0x6DB2	#CJK UNIFIED IDEOGRAPH+0x8975	0x75AB	#CJK UNIFIED IDEOGRAPH+0x8976	0x76CA	#CJK UNIFIED IDEOGRAPH+0x8977	0x99C5	#CJK UNIFIED IDEOGRAPH+0x8978	0x60A6	#CJK UNIFIED IDEOGRAPH+0x8979	0x8B01	#CJK UNIFIED IDEOGRAPH+0x897A	0x8D8A	#CJK UNIFIED IDEOGRAPH+0x897B	0x95B2	#CJK UNIFIED IDEOGRAPH+0x897C	0x698E	#CJK UNIFIED IDEOGRAPH+0x897D	0x53AD	#CJK UNIFIED IDEOGRAPH+0x897E	0x5186	#CJK UNIFIED IDEOGRAPH+0x8980	0x5712	#CJK UNIFIED IDEOGRAPH+0x8981	0x5830	#CJK UNIFIED IDEOGRAPH+0x8982	0x5944	#CJK UNIFIED IDEOGRAPH+0x8983	0x5BB4	#CJK UNIFIED IDEOGRAPH+0x8984	0x5EF6	#CJK UNIFIED IDEOGRAPH+0x8985	0x6028	#CJK UNIFIED IDEOGRAPH+0x8986	0x63A9	#CJK UNIFIED IDEOGRAPH+0x8987	0x63F4	#CJK UNIFIED IDEOGRAPH+0x8988	0x6CBF	#CJK UNIFIED IDEOGRAPH+0x8989	0x6F14	#CJK UNIFIED IDEOGRAPH+0x898A	0x708E	#CJK UNIFIED IDEOGRAPH+0x898B	0x7114	#CJK UNIFIED IDEOGRAPH+0x898C	0x7159	#CJK UNIFIED IDEOGRAPH+0x898D	0x71D5	#CJK UNIFIED IDEOGRAPH+0x898E	0x733F	#CJK UNIFIED IDEOGRAPH+0x898F	0x7E01	#CJK UNIFIED IDEOGRAPH+0x8990	0x8276	#CJK UNIFIED IDEOGRAPH+0x8991	0x82D1	#CJK UNIFIED IDEOGRAPH+0x8992	0x8597	#CJK UNIFIED IDEOGRAPH+0x8993	0x9060	#CJK UNIFIED IDEOGRAPH+0x8994	0x925B	#CJK UNIFIED IDEOGRAPH+0x8995	0x9D1B	#CJK UNIFIED IDEOGRAPH+0x8996	0x5869	#CJK UNIFIED IDEOGRAPH+0x8997	0x65BC	#CJK UNIFIED IDEOGRAPH+0x8998	0x6C5A	#CJK UNIFIED IDEOGRAPH+0x8999	0x7525	#CJK UNIFIED IDEOGRAPH+0x899A	0x51F9	#CJK UNIFIED IDEOGRAPH+0x899B	0x592E	#CJK UNIFIED IDEOGRAPH+0x899C	0x5965	#CJK UNIFIED IDEOGRAPH+0x899D	0x5F80	#CJK UNIFIED IDEOGRAPH+0x899E	0x5FDC	#CJK UNIFIED IDEOGRAPH+0x899F	0x62BC	#CJK UNIFIED IDEOGRAPH+0x89A0	0x65FA	#CJK UNIFIED IDEOGRAPH+0x89A1	0x6A2A	#CJK UNIFIED IDEOGRAPH+0x89A2	0x6B27	#CJK UNIFIED IDEOGRAPH+0x89A3	0x6BB4	#CJK UNIFIED IDEOGRAPH+0x89A4	0x738B	#CJK UNIFIED IDEOGRAPH+0x89A5	0x7FC1	#CJK UNIFIED IDEOGRAPH+0x89A6	0x8956	#CJK UNIFIED IDEOGRAPH+0x89A7	0x9D2C	#CJK UNIFIED IDEOGRAPH+0x89A8	0x9D0E	#CJK UNIFIED IDEOGRAPH+0x89A9	0x9EC4	#CJK UNIFIED IDEOGRAPH+0x89AA	0x5CA1	#CJK UNIFIED IDEOGRAPH+0x89AB	0x6C96	#CJK UNIFIED IDEOGRAPH+0x89AC	0x837B	#CJK UNIFIED IDEOGRAPH+0x89AD	0x5104	#CJK UNIFIED IDEOGRAPH+0x89AE	0x5C4B	#CJK UNIFIED IDEOGRAPH+0x89AF	0x61B6	#CJK UNIFIED IDEOGRAPH+0x89B0	0x81C6	#CJK UNIFIED IDEOGRAPH+0x89B1	0x6876	#CJK UNIFIED IDEOGRAPH+0x89B2	0x7261	#CJK UNIFIED IDEOGRAPH+0x89B3	0x4E59	#CJK UNIFIED IDEOGRAPH+0x89B4	0x4FFA	#CJK UNIFIED IDEOGRAPH+0x89B5	0x5378	#CJK UNIFIED IDEOGRAPH+0x89B6	0x6069	#CJK UNIFIED IDEOGRAPH+0x89B7	0x6E29	#CJK UNIFIED IDEOGRAPH+0x89B8	0x7A4F	#CJK UNIFIED IDEOGRAPH+0x89B9	0x97F3	#CJK UNIFIED IDEOGRAPH+0x89BA	0x4E0B	#CJK UNIFIED IDEOGRAPH+0x89BB	0x5316	#CJK UNIFIED IDEOGRAPH+0x89BC	0x4EEE	#CJK UNIFIED IDEOGRAPH+0x89BD	0x4F55	#CJK UNIFIED IDEOGRAPH+0x89BE	0x4F3D	#CJK UNIFIED IDEOGRAPH+0x89BF	0x4FA1	#CJK UNIFIED IDEOGRAPH+0x89C0	0x4F73	#CJK UNIFIED IDEOGRAPH+0x89C1	0x52A0	#CJK UNIFIED IDEOGRAPH+0x89C2	0x53EF	#CJK UNIFIED IDEOGRAPH+0x89C3	0x5609	#CJK UNIFIED IDEOGRAPH+0x89C4	0x590F	#CJK UNIFIED IDEOGRAPH+0x89C5	0x5AC1	#CJK UNIFIED IDEOGRAPH+0x89C6	0x5BB6	#CJK UNIFIED IDEOGRAPH+0x89C7	0x5BE1	#CJK UNIFIED IDEOGRAPH+0x89C8	0x79D1	#CJK UNIFIED IDEOGRAPH+0x89C9	0x6687	#CJK UNIFIED IDEOGRAPH+0x89CA	0x679C	#CJK UNIFIED IDEOGRAPH+0x89CB	0x67B6	#CJK UNIFIED IDEOGRAPH+0x89CC	0x6B4C	#CJK UNIFIED IDEOGRAPH+0x89CD	0x6CB3	#CJK UNIFIED IDEOGRAPH+0x89CE	0x706B	#CJK UNIFIED IDEOGRAPH+0x89CF	0x73C2	#CJK UNIFIED IDEOGRAPH+0x89D0	0x798D	#CJK UNIFIED IDEOGRAPH+0x89D1	0x79BE	#CJK UNIFIED IDEOGRAPH+0x89D2	0x7A3C	#CJK UNIFIED IDEOGRAPH+0x89D3	0x7B87	#CJK UNIFIED IDEOGRAPH+0x89D4	0x82B1	#CJK UNIFIED IDEOGRAPH+0x89D5	0x82DB	#CJK UNIFIED IDEOGRAPH+0x89D6	0x8304	#CJK UNIFIED IDEOGRAPH+0x89D7	0x8377	#CJK UNIFIED IDEOGRAPH+0x89D8	0x83EF	#CJK UNIFIED IDEOGRAPH+0x89D9	0x83D3	#CJK UNIFIED IDEOGRAPH+0x89DA	0x8766	#CJK UNIFIED IDEOGRAPH+0x89DB	0x8AB2	#CJK UNIFIED IDEOGRAPH+0x89DC	0x5629	#CJK UNIFIED IDEOGRAPH+0x89DD	0x8CA8	#CJK UNIFIED IDEOGRAPH+0x89DE	0x8FE6	#CJK UNIFIED IDEOGRAPH+0x89DF	0x904E	#CJK UNIFIED IDEOGRAPH+0x89E0	0x971E	#CJK UNIFIED IDEOGRAPH+0x89E1	0x868A	#CJK UNIFIED IDEOGRAPH+0x89E2	0x4FC4	#CJK UNIFIED IDEOGRAPH+0x89E3	0x5CE8	#CJK UNIFIED IDEOGRAPH+0x89E4	0x6211	#CJK UNIFIED IDEOGRAPH+0x89E5	0x7259	#CJK UNIFIED IDEOGRAPH+0x89E6	0x753B	#CJK UNIFIED IDEOGRAPH+0x89E7	0x81E5	#CJK UNIFIED IDEOGRAPH+0x89E8	0x82BD	#CJK UNIFIED IDEOGRAPH+0x89E9	0x86FE	#CJK UNIFIED IDEOGRAPH+0x89EA	0x8CC0	#CJK UNIFIED IDEOGRAPH+0x89EB	0x96C5	#CJK UNIFIED IDEOGRAPH+0x89EC	0x9913	#CJK UNIFIED IDEOGRAPH+0x89ED	0x99D5	#CJK UNIFIED IDEOGRAPH+0x89EE	0x4ECB	#CJK UNIFIED IDEOGRAPH+0x89EF	0x4F1A	#CJK UNIFIED IDEOGRAPH+0x89F0	0x89E3	#CJK UNIFIED IDEOGRAPH+0x89F1	0x56DE	#CJK UNIFIED IDEOGRAPH+0x89F2	0x584A	#CJK UNIFIED IDEOGRAPH+0x89F3	0x58CA	#CJK UNIFIED IDEOGRAPH+0x89F4	0x5EFB	#CJK UNIFIED IDEOGRAPH+0x89F5	0x5FEB	#CJK UNIFIED IDEOGRAPH+0x89F6	0x602A	#CJK UNIFIED IDEOGRAPH+0x89F7	0x6094	#CJK UNIFIED IDEOGRAPH+0x89F8	0x6062	#CJK UNIFIED IDEOGRAPH+0x89F9	0x61D0	#CJK UNIFIED IDEOGRAPH+0x89FA	0x6212	#CJK UNIFIED IDEOGRAPH+0x89FB	0x62D0	#CJK UNIFIED IDEOGRAPH+0x89FC	0x6539	#CJK UNIFIED IDEOGRAPH+0x8A40	0x9B41	#CJK UNIFIED IDEOGRAPH+0x8A41	0x6666	#CJK UNIFIED IDEOGRAPH+0x8A42	0x68B0	#CJK UNIFIED IDEOGRAPH+0x8A43	0x6D77	#CJK UNIFIED IDEOGRAPH+0x8A44	0x7070	#CJK UNIFIED IDEOGRAPH+0x8A45	0x754C	#CJK UNIFIED IDEOGRAPH+0x8A46	0x7686	#CJK UNIFIED IDEOGRAPH+0x8A47	0x7D75	#CJK UNIFIED IDEOGRAPH+0x8A48	0x82A5	#CJK UNIFIED IDEOGRAPH+0x8A49	0x87F9	#CJK UNIFIED IDEOGRAPH+0x8A4A	0x958B	#CJK UNIFIED IDEOGRAPH+0x8A4B	0x968E	#CJK UNIFIED IDEOGRAPH+0x8A4C	0x8C9D	#CJK UNIFIED IDEOGRAPH+0x8A4D	0x51F1	#CJK UNIFIED IDEOGRAPH+0x8A4E	0x52BE	#CJK UNIFIED IDEOGRAPH+0x8A4F	0x5916	#CJK UNIFIED IDEOGRAPH+0x8A50	0x54B3	#CJK UNIFIED IDEOGRAPH+0x8A51	0x5BB3	#CJK UNIFIED IDEOGRAPH+0x8A52	0x5D16	#CJK UNIFIED IDEOGRAPH+0x8A53	0x6168	#CJK UNIFIED IDEOGRAPH+0x8A54	0x6982	#CJK UNIFIED IDEOGRAPH+0x8A55	0x6DAF	#CJK UNIFIED IDEOGRAPH+0x8A56	0x788D	#CJK UNIFIED IDEOGRAPH+0x8A57	0x84CB	#CJK UNIFIED IDEOGRAPH+0x8A58	0x8857	#CJK UNIFIED IDEOGRAPH+0x8A59	0x8A72	#CJK UNIFIED IDEOGRAPH+0x8A5A	0x93A7	#CJK UNIFIED IDEOGRAPH+0x8A5B	0x9AB8	#CJK UNIFIED IDEOGRAPH+0x8A5C	0x6D6C	#CJK UNIFIED IDEOGRAPH+0x8A5D	0x99A8	#CJK UNIFIED IDEOGRAPH+0x8A5E	0x86D9	#CJK UNIFIED IDEOGRAPH+0x8A5F	0x57A3	#CJK UNIFIED IDEOGRAPH+0x8A60	0x67FF	#CJK UNIFIED IDEOGRAPH+0x8A61	0x86CE	#CJK UNIFIED IDEOGRAPH+0x8A62	0x920E	#CJK UNIFIED IDEOGRAPH+0x8A63	0x5283	#CJK UNIFIED IDEOGRAPH+0x8A64	0x5687	#CJK UNIFIED IDEOGRAPH+0x8A65	0x5404	#CJK UNIFIED IDEOGRAPH+0x8A66	0x5ED3	#CJK UNIFIED IDEOGRAPH+0x8A67	0x62E1	#CJK UNIFIED IDEOGRAPH+0x8A68	0x64B9	#CJK UNIFIED IDEOGRAPH+0x8A69	0x683C	#CJK UNIFIED IDEOGRAPH+0x8A6A	0x6838	#CJK UNIFIED IDEOGRAPH+0x8A6B	0x6BBB	#CJK UNIFIED IDEOGRAPH+0x8A6C	0x7372	#CJK UNIFIED IDEOGRAPH+0x8A6D	0x78BA	#CJK UNIFIED IDEOGRAPH+0x8A6E	0x7A6B	#CJK UNIFIED IDEOGRAPH+0x8A6F	0x899A	#CJK UNIFIED IDEOGRAPH+0x8A70	0x89D2	#CJK UNIFIED IDEOGRAPH+0x8A71	0x8D6B	#CJK UNIFIED IDEOGRAPH+0x8A72	0x8F03	#CJK UNIFIED IDEOGRAPH+0x8A73	0x90ED	#CJK UNIFIED IDEOGRAPH+0x8A74	0x95A3	#CJK UNIFIED IDEOGRAPH+0x8A75	0x9694	#CJK UNIFIED IDEOGRAPH+0x8A76	0x9769	#CJK UNIFIED IDEOGRAPH+0x8A77	0x5B66	#CJK UNIFIED IDEOGRAPH+0x8A78	0x5CB3	#CJK UNIFIED IDEOGRAPH+0x8A79	0x697D	#CJK UNIFIED IDEOGRAPH+0x8A7A	0x984D	#CJK UNIFIED IDEOGRAPH+0x8A7B	0x984E	#CJK UNIFIED IDEOGRAPH+0x8A7C	0x639B	#CJK UNIFIED IDEOGRAPH+0x8A7D	0x7B20	#CJK UNIFIED IDEOGRAPH+0x8A7E	0x6A2B	#CJK UNIFIED IDEOGRAPH+0x8A80	0x6A7F	#CJK UNIFIED IDEOGRAPH+0x8A81	0x68B6	#CJK UNIFIED IDEOGRAPH+0x8A82	0x9C0D	#CJK UNIFIED IDEOGRAPH+0x8A83	0x6F5F	#CJK UNIFIED IDEOGRAPH+0x8A84	0x5272	#CJK UNIFIED IDEOGRAPH+0x8A85	0x559D	#CJK UNIFIED IDEOGRAPH+0x8A86	0x6070	#CJK UNIFIED IDEOGRAPH+0x8A87	0x62EC	#CJK UNIFIED IDEOGRAPH+0x8A88	0x6D3B	#CJK UNIFIED IDEOGRAPH+0x8A89	0x6E07	#CJK UNIFIED IDEOGRAPH+0x8A8A	0x6ED1	#CJK UNIFIED IDEOGRAPH+0x8A8B	0x845B	#CJK UNIFIED IDEOGRAPH+0x8A8C	0x8910	#CJK UNIFIED IDEOGRAPH+0x8A8D	0x8F44	#CJK UNIFIED IDEOGRAPH+0x8A8E	0x4E14	#CJK UNIFIED IDEOGRAPH+0x8A8F	0x9C39	#CJK UNIFIED IDEOGRAPH+0x8A90	0x53F6	#CJK UNIFIED IDEOGRAPH+0x8A91	0x691B	#CJK UNIFIED IDEOGRAPH+0x8A92	0x6A3A	#CJK UNIFIED IDEOGRAPH+0x8A93	0x9784	#CJK UNIFIED IDEOGRAPH+0x8A94	0x682A	#CJK UNIFIED IDEOGRAPH+0x8A95	0x515C	#CJK UNIFIED IDEOGRAPH+0x8A96	0x7AC3	#CJK UNIFIED IDEOGRAPH+0x8A97	0x84B2	#CJK UNIFIED IDEOGRAPH+0x8A98	0x91DC	#CJK UNIFIED IDEOGRAPH+0x8A99	0x938C	#CJK UNIFIED IDEOGRAPH+0x8A9A	0x565B	#CJK UNIFIED IDEOGRAPH+0x8A9B	0x9D28	#CJK UNIFIED IDEOGRAPH+0x8A9C	0x6822	#CJK UNIFIED IDEOGRAPH+0x8A9D	0x8305	#CJK UNIFIED IDEOGRAPH+0x8A9E	0x8431	#CJK UNIFIED IDEOGRAPH+0x8A9F	0x7CA5	#CJK UNIFIED IDEOGRAPH+0x8AA0	0x5208	#CJK UNIFIED IDEOGRAPH+0x8AA1	0x82C5	#CJK UNIFIED IDEOGRAPH+0x8AA2	0x74E6	#CJK UNIFIED IDEOGRAPH+0x8AA3	0x4E7E	#CJK UNIFIED IDEOGRAPH+0x8AA4	0x4F83	#CJK UNIFIED IDEOGRAPH+0x8AA5	0x51A0	#CJK UNIFIED IDEOGRAPH+0x8AA6	0x5BD2	#CJK UNIFIED IDEOGRAPH+0x8AA7	0x520A	#CJK UNIFIED IDEOGRAPH+0x8AA8	0x52D8	#CJK UNIFIED IDEOGRAPH+0x8AA9	0x52E7	#CJK UNIFIED IDEOGRAPH+0x8AAA	0x5DFB	#CJK UNIFIED IDEOGRAPH+0x8AAB	0x559A	#CJK UNIFIED IDEOGRAPH+0x8AAC	0x582A	#CJK UNIFIED IDEOGRAPH+0x8AAD	0x59E6	#CJK UNIFIED IDEOGRAPH+0x8AAE	0x5B8C	#CJK UNIFIED IDEOGRAPH+0x8AAF	0x5B98	#CJK UNIFIED IDEOGRAPH+0x8AB0	0x5BDB	#CJK UNIFIED IDEOGRAPH+0x8AB1	0x5E72	#CJK UNIFIED IDEOGRAPH+0x8AB2	0x5E79	#CJK UNIFIED IDEOGRAPH+0x8AB3	0x60A3	#CJK UNIFIED IDEOGRAPH+0x8AB4	0x611F	#CJK UNIFIED IDEOGRAPH+0x8AB5	0x6163	#CJK UNIFIED IDEOGRAPH+0x8AB6	0x61BE	#CJK UNIFIED IDEOGRAPH+0x8AB7	0x63DB	#CJK UNIFIED IDEOGRAPH+0x8AB8	0x6562	#CJK UNIFIED IDEOGRAPH+0x8AB9	0x67D1	#CJK UNIFIED IDEOGRAPH+0x8ABA	0x6853	#CJK UNIFIED IDEOGRAPH+0x8ABB	0x68FA	#CJK UNIFIED IDEOGRAPH+0x8ABC	0x6B3E	#CJK UNIFIED IDEOGRAPH+0x8ABD	0x6B53	#CJK UNIFIED IDEOGRAPH+0x8ABE	0x6C57	#CJK UNIFIED IDEOGRAPH+0x8ABF	0x6F22	#CJK UNIFIED IDEOGRAPH+0x8AC0	0x6F97	#CJK UNIFIED IDEOGRAPH+0x8AC1	0x6F45	#CJK UNIFIED IDEOGRAPH+0x8AC2	0x74B0	#CJK UNIFIED IDEOGRAPH+0x8AC3	0x7518	#CJK UNIFIED IDEOGRAPH+0x8AC4	0x76E3	#CJK UNIFIED IDEOGRAPH+0x8AC5	0x770B	#CJK UNIFIED IDEOGRAPH+0x8AC6	0x7AFF	#CJK UNIFIED IDEOGRAPH+0x8AC7	0x7BA1	#CJK UNIFIED IDEOGRAPH+0x8AC8	0x7C21	#CJK UNIFIED IDEOGRAPH+0x8AC9	0x7DE9	#CJK UNIFIED IDEOGRAPH+0x8ACA	0x7F36	#CJK UNIFIED IDEOGRAPH+0x8ACB	0x7FF0	#CJK UNIFIED IDEOGRAPH+0x8ACC	0x809D	#CJK UNIFIED IDEOGRAPH+0x8ACD	0x8266	#CJK UNIFIED IDEOGRAPH+0x8ACE	0x839E	#CJK UNIFIED IDEOGRAPH+0x8ACF	0x89B3	#CJK UNIFIED IDEOGRAPH+0x8AD0	0x8ACC	#CJK UNIFIED IDEOGRAPH+0x8AD1	0x8CAB	#CJK UNIFIED IDEOGRAPH+0x8AD2	0x9084	#CJK UNIFIED IDEOGRAPH+0x8AD3	0x9451	#CJK UNIFIED IDEOGRAPH+0x8AD4	0x9593	#CJK UNIFIED IDEOGRAPH+0x8AD5	0x9591	#CJK UNIFIED IDEOGRAPH+0x8AD6	0x95A2	#CJK UNIFIED IDEOGRAPH+0x8AD7	0x9665	#CJK UNIFIED IDEOGRAPH+0x8AD8	0x97D3	#CJK UNIFIED IDEOGRAPH+0x8AD9	0x9928	#CJK UNIFIED IDEOGRAPH+0x8ADA	0x8218	#CJK UNIFIED IDEOGRAPH+0x8ADB	0x4E38	#CJK UNIFIED IDEOGRAPH+0x8ADC	0x542B	#CJK UNIFIED IDEOGRAPH+0x8ADD	0x5CB8	#CJK UNIFIED IDEOGRAPH+0x8ADE	0x5DCC	#CJK UNIFIED IDEOGRAPH+0x8ADF	0x73A9	#CJK UNIFIED IDEOGRAPH+0x8AE0	0x764C	#CJK UNIFIED IDEOGRAPH+0x8AE1	0x773C	#CJK UNIFIED IDEOGRAPH+0x8AE2	0x5CA9	#CJK UNIFIED IDEOGRAPH+0x8AE3	0x7FEB	#CJK UNIFIED IDEOGRAPH+0x8AE4	0x8D0B	#CJK UNIFIED IDEOGRAPH+0x8AE5	0x96C1	#CJK UNIFIED IDEOGRAPH+0x8AE6	0x9811	#CJK UNIFIED IDEOGRAPH+0x8AE7	0x9854	#CJK UNIFIED IDEOGRAPH+0x8AE8	0x9858	#CJK UNIFIED IDEOGRAPH+0x8AE9	0x4F01	#CJK UNIFIED IDEOGRAPH+0x8AEA	0x4F0E	#CJK UNIFIED IDEOGRAPH+0x8AEB	0x5371	#CJK UNIFIED IDEOGRAPH+0x8AEC	0x559C	#CJK UNIFIED IDEOGRAPH+0x8AED	0x5668	#CJK UNIFIED IDEOGRAPH+0x8AEE	0x57FA	#CJK UNIFIED IDEOGRAPH+0x8AEF	0x5947	#CJK UNIFIED IDEOGRAPH+0x8AF0	0x5B09	#CJK UNIFIED IDEOGRAPH+0x8AF1	0x5BC4	#CJK UNIFIED IDEOGRAPH+0x8AF2	0x5C90	#CJK UNIFIED IDEOGRAPH+0x8AF3	0x5E0C	#CJK UNIFIED IDEOGRAPH+0x8AF4	0x5E7E	#CJK UNIFIED IDEOGRAPH+0x8AF5	0x5FCC	#CJK UNIFIED IDEOGRAPH+0x8AF6	0x63EE	#CJK UNIFIED IDEOGRAPH+0x8AF7	0x673A	#CJK UNIFIED IDEOGRAPH+0x8AF8	0x65D7	#CJK UNIFIED IDEOGRAPH+0x8AF9	0x65E2	#CJK UNIFIED IDEOGRAPH+0x8AFA	0x671F	#CJK UNIFIED IDEOGRAPH+0x8AFB	0x68CB	#CJK UNIFIED IDEOGRAPH+0x8AFC	0x68C4	#CJK UNIFIED IDEOGRAPH+0x8B40	0x6A5F	#CJK UNIFIED IDEOGRAPH+0x8B41	0x5E30	#CJK UNIFIED IDEOGRAPH+0x8B42	0x6BC5	#CJK UNIFIED IDEOGRAPH+0x8B43	0x6C17	#CJK UNIFIED IDEOGRAPH+0x8B44	0x6C7D	#CJK UNIFIED IDEOGRAPH+0x8B45	0x757F	#CJK UNIFIED IDEOGRAPH+0x8B46	0x7948	#CJK UNIFIED IDEOGRAPH+0x8B47	0x5B63	#CJK UNIFIED IDEOGRAPH+0x8B48	0x7A00	#CJK UNIFIED IDEOGRAPH+0x8B49	0x7D00	#CJK UNIFIED IDEOGRAPH+0x8B4A	0x5FBD	#CJK UNIFIED IDEOGRAPH+0x8B4B	0x898F	#CJK UNIFIED IDEOGRAPH+0x8B4C	0x8A18	#CJK UNIFIED IDEOGRAPH+0x8B4D	0x8CB4	#CJK UNIFIED IDEOGRAPH+0x8B4E	0x8D77	#CJK UNIFIED IDEOGRAPH+0x8B4F	0x8ECC	#CJK UNIFIED IDEOGRAPH+0x8B50	0x8F1D	#CJK UNIFIED IDEOGRAPH+0x8B51	0x98E2	#CJK UNIFIED IDEOGRAPH+0x8B52	0x9A0E	#CJK UNIFIED IDEOGRAPH+0x8B53	0x9B3C	#CJK UNIFIED IDEOGRAPH+0x8B54	0x4E80	#CJK UNIFIED IDEOGRAPH+0x8B55	0x507D	#CJK UNIFIED IDEOGRAPH+0x8B56	0x5100	#CJK UNIFIED IDEOGRAPH+0x8B57	0x5993	#CJK UNIFIED IDEOGRAPH+0x8B58	0x5B9C	#CJK UNIFIED IDEOGRAPH+0x8B59	0x622F	#CJK UNIFIED IDEOGRAPH+0x8B5A	0x6280	#CJK UNIFIED IDEOGRAPH+0x8B5B	0x64EC	#CJK UNIFIED IDEOGRAPH+0x8B5C	0x6B3A	#CJK UNIFIED IDEOGRAPH+0x8B5D	0x72A0	#CJK UNIFIED IDEOGRAPH+0x8B5E	0x7591	#CJK UNIFIED IDEOGRAPH+0x8B5F	0x7947	#CJK UNIFIED IDEOGRAPH+0x8B60	0x7FA9	#CJK UNIFIED IDEOGRAPH+0x8B61	0x87FB	#CJK UNIFIED IDEOGRAPH+0x8B62	0x8ABC	#CJK UNIFIED IDEOGRAPH+0x8B63	0x8B70	#CJK UNIFIED IDEOGRAPH+0x8B64	0x63AC	#CJK UNIFIED IDEOGRAPH+0x8B65	0x83CA	#CJK UNIFIED IDEOGRAPH+0x8B66	0x97A0	#CJK UNIFIED IDEOGRAPH+0x8B67	0x5409	#CJK UNIFIED IDEOGRAPH+0x8B68	0x5403	#CJK UNIFIED IDEOGRAPH+0x8B69	0x55AB	#CJK UNIFIED IDEOGRAPH+0x8B6A	0x6854	#CJK UNIFIED IDEOGRAPH+0x8B6B	0x6A58	#CJK UNIFIED IDEOGRAPH+0x8B6C	0x8A70	#CJK UNIFIED IDEOGRAPH+0x8B6D	0x7827	#CJK UNIFIED IDEOGRAPH+0x8B6E	0x6775	#CJK UNIFIED IDEOGRAPH+0x8B6F	0x9ECD	#CJK UNIFIED IDEOGRAPH+0x8B70	0x5374	#CJK UNIFIED IDEOGRAPH+0x8B71	0x5BA2	#CJK UNIFIED IDEOGRAPH+0x8B72	0x811A	#CJK UNIFIED IDEOGRAPH+0x8B73	0x8650	#CJK UNIFIED IDEOGRAPH+0x8B74	0x9006	#CJK UNIFIED IDEOGRAPH+0x8B75	0x4E18	#CJK UNIFIED IDEOGRAPH+0x8B76	0x4E45	#CJK UNIFIED IDEOGRAPH+0x8B77	0x4EC7	#CJK UNIFIED IDEOGRAPH+0x8B78	0x4F11	#CJK UNIFIED IDEOGRAPH+0x8B79	0x53CA	#CJK UNIFIED IDEOGRAPH+0x8B7A	0x5438	#CJK UNIFIED IDEOGRAPH+0x8B7B	0x5BAE	#CJK UNIFIED IDEOGRAPH+0x8B7C	0x5F13	#CJK UNIFIED IDEOGRAPH+0x8B7D	0x6025	#CJK UNIFIED IDEOGRAPH+0x8B7E	0x6551	#CJK UNIFIED IDEOGRAPH+0x8B80	0x673D	#CJK UNIFIED IDEOGRAPH+0x8B81	0x6C42	#CJK UNIFIED IDEOGRAPH+0x8B82	0x6C72	#CJK UNIFIED IDEOGRAPH+0x8B83	0x6CE3	#CJK UNIFIED IDEOGRAPH+0x8B84	0x7078	#CJK UNIFIED IDEOGRAPH+0x8B85	0x7403	#CJK UNIFIED IDEOGRAPH+0x8B86	0x7A76	#CJK UNIFIED IDEOGRAPH+0x8B87	0x7AAE	#CJK UNIFIED IDEOGRAPH+0x8B88	0x7B08	#CJK UNIFIED IDEOGRAPH+0x8B89	0x7D1A	#CJK UNIFIED IDEOGRAPH+0x8B8A	0x7CFE	#CJK UNIFIED IDEOGRAPH+0x8B8B	0x7D66	#CJK UNIFIED IDEOGRAPH+0x8B8C	0x65E7	#CJK UNIFIED IDEOGRAPH+0x8B8D	0x725B	#CJK UNIFIED IDEOGRAPH+0x8B8E	0x53BB	#CJK UNIFIED IDEOGRAPH+0x8B8F	0x5C45	#CJK UNIFIED IDEOGRAPH+0x8B90	0x5DE8	#CJK UNIFIED IDEOGRAPH+0x8B91	0x62D2	#CJK UNIFIED IDEOGRAPH+0x8B92	0x62E0	#CJK UNIFIED IDEOGRAPH+0x8B93	0x6319	#CJK UNIFIED IDEOGRAPH+0x8B94	0x6E20	#CJK UNIFIED IDEOGRAPH+0x8B95	0x865A	#CJK UNIFIED IDEOGRAPH+0x8B96	0x8A31	#CJK UNIFIED IDEOGRAPH+0x8B97	0x8DDD	#CJK UNIFIED IDEOGRAPH+0x8B98	0x92F8	#CJK UNIFIED IDEOGRAPH+0x8B99	0x6F01	#CJK UNIFIED IDEOGRAPH+0x8B9A	0x79A6	#CJK UNIFIED IDEOGRAPH+0x8B9B	0x9B5A	#CJK UNIFIED IDEOGRAPH+0x8B9C	0x4EA8	#CJK UNIFIED IDEOGRAPH+0x8B9D	0x4EAB	#CJK UNIFIED IDEOGRAPH+0x8B9E	0x4EAC	#CJK UNIFIED IDEOGRAPH+0x8B9F	0x4F9B	#CJK UNIFIED IDEOGRAPH+0x8BA0	0x4FA0	#CJK UNIFIED IDEOGRAPH+0x8BA1	0x50D1	#CJK UNIFIED IDEOGRAPH+0x8BA2	0x5147	#CJK UNIFIED IDEOGRAPH+0x8BA3	0x7AF6	#CJK UNIFIED IDEOGRAPH+0x8BA4	0x5171	#CJK UNIFIED IDEOGRAPH+0x8BA5	0x51F6	#CJK UNIFIED IDEOGRAPH+0x8BA6	0x5354	#CJK UNIFIED IDEOGRAPH+0x8BA7	0x5321	#CJK UNIFIED IDEOGRAPH+0x8BA8	0x537F	#CJK UNIFIED IDEOGRAPH+0x8BA9	0x53EB	#CJK UNIFIED IDEOGRAPH+0x8BAA	0x55AC	#CJK UNIFIED IDEOGRAPH+0x8BAB	0x5883	#CJK UNIFIED IDEOGRAPH+0x8BAC	0x5CE1	#CJK UNIFIED IDEOGRAPH+0x8BAD	0x5F37	#CJK UNIFIED IDEOGRAPH+0x8BAE	0x5F4A	#CJK UNIFIED IDEOGRAPH+0x8BAF	0x602F	#CJK UNIFIED IDEOGRAPH+0x8BB0	0x6050	#CJK UNIFIED IDEOGRAPH+0x8BB1	0x606D	#CJK UNIFIED IDEOGRAPH+0x8BB2	0x631F	#CJK UNIFIED IDEOGRAPH+0x8BB3	0x6559	#CJK UNIFIED IDEOGRAPH+0x8BB4	0x6A4B	#CJK UNIFIED IDEOGRAPH+0x8BB5	0x6CC1	#CJK UNIFIED IDEOGRAPH+0x8BB6	0x72C2	#CJK UNIFIED IDEOGRAPH+0x8BB7	0x72ED	#CJK UNIFIED IDEOGRAPH+0x8BB8	0x77EF	#CJK UNIFIED IDEOGRAPH+0x8BB9	0x80F8	#CJK UNIFIED IDEOGRAPH+0x8BBA	0x8105	#CJK UNIFIED IDEOGRAPH+0x8BBB	0x8208	#CJK UNIFIED IDEOGRAPH+0x8BBC	0x854E	#CJK UNIFIED IDEOGRAPH+0x8BBD	0x90F7	#CJK UNIFIED IDEOGRAPH+0x8BBE	0x93E1	#CJK UNIFIED IDEOGRAPH+0x8BBF	0x97FF	#CJK UNIFIED IDEOGRAPH+0x8BC0	0x9957	#CJK UNIFIED IDEOGRAPH+0x8BC1	0x9A5A	#CJK UNIFIED IDEOGRAPH+0x8BC2	0x4EF0	#CJK UNIFIED IDEOGRAPH+0x8BC3	0x51DD	#CJK UNIFIED IDEOGRAPH+0x8BC4	0x5C2D	#CJK UNIFIED IDEOGRAPH+0x8BC5	0x6681	#CJK UNIFIED IDEOGRAPH+0x8BC6	0x696D	#CJK UNIFIED IDEOGRAPH+0x8BC7	0x5C40	#CJK UNIFIED IDEOGRAPH+0x8BC8	0x66F2	#CJK UNIFIED IDEOGRAPH+0x8BC9	0x6975	#CJK UNIFIED IDEOGRAPH+0x8BCA	0x7389	#CJK UNIFIED IDEOGRAPH+0x8BCB	0x6850	#CJK UNIFIED IDEOGRAPH+0x8BCC	0x7C81	#CJK UNIFIED IDEOGRAPH+0x8BCD	0x50C5	#CJK UNIFIED IDEOGRAPH+0x8BCE	0x52E4	#CJK UNIFIED IDEOGRAPH+0x8BCF	0x5747	#CJK UNIFIED IDEOGRAPH+0x8BD0	0x5DFE	#CJK UNIFIED IDEOGRAPH+0x8BD1	0x9326	#CJK UNIFIED IDEOGRAPH+0x8BD2	0x65A4	#CJK UNIFIED IDEOGRAPH+0x8BD3	0x6B23	#CJK UNIFIED IDEOGRAPH+0x8BD4	0x6B3D	#CJK UNIFIED IDEOGRAPH+0x8BD5	0x7434	#CJK UNIFIED IDEOGRAPH+0x8BD6	0x7981	#CJK UNIFIED IDEOGRAPH+0x8BD7	0x79BD	#CJK UNIFIED IDEOGRAPH+0x8BD8	0x7B4B	#CJK UNIFIED IDEOGRAPH+0x8BD9	0x7DCA	#CJK UNIFIED IDEOGRAPH+0x8BDA	0x82B9	#CJK UNIFIED IDEOGRAPH+0x8BDB	0x83CC	#CJK UNIFIED IDEOGRAPH+0x8BDC	0x887F	#CJK UNIFIED IDEOGRAPH+0x8BDD	0x895F	#CJK UNIFIED IDEOGRAPH+0x8BDE	0x8B39	#CJK UNIFIED IDEOGRAPH+0x8BDF	0x8FD1	#CJK UNIFIED IDEOGRAPH+0x8BE0	0x91D1	#CJK UNIFIED IDEOGRAPH+0x8BE1	0x541F	#CJK UNIFIED IDEOGRAPH+0x8BE2	0x9280	#CJK UNIFIED IDEOGRAPH+0x8BE3	0x4E5D	#CJK UNIFIED IDEOGRAPH+0x8BE4	0x5036	#CJK UNIFIED IDEOGRAPH+0x8BE5	0x53E5	#CJK UNIFIED IDEOGRAPH+0x8BE6	0x533A	#CJK UNIFIED IDEOGRAPH+0x8BE7	0x72D7	#CJK UNIFIED IDEOGRAPH+0x8BE8	0x7396	#CJK UNIFIED IDEOGRAPH+0x8BE9	0x77E9	#CJK UNIFIED IDEOGRAPH+0x8BEA	0x82E6	#CJK UNIFIED IDEOGRAPH+0x8BEB	0x8EAF	#CJK UNIFIED IDEOGRAPH+0x8BEC	0x99C6	#CJK UNIFIED IDEOGRAPH+0x8BED	0x99C8	#CJK UNIFIED IDEOGRAPH+0x8BEE	0x99D2	#CJK UNIFIED IDEOGRAPH+0x8BEF	0x5177	#CJK UNIFIED IDEOGRAPH+0x8BF0	0x611A	#CJK UNIFIED IDEOGRAPH+0x8BF1	0x865E	#CJK UNIFIED IDEOGRAPH+0x8BF2	0x55B0	#CJK UNIFIED IDEOGRAPH+0x8BF3	0x7A7A	#CJK UNIFIED IDEOGRAPH+0x8BF4	0x5076	#CJK UNIFIED IDEOGRAPH+0x8BF5	0x5BD3	#CJK UNIFIED IDEOGRAPH+0x8BF6	0x9047	#CJK UNIFIED IDEOGRAPH+0x8BF7	0x9685	#CJK UNIFIED IDEOGRAPH+0x8BF8	0x4E32	#CJK UNIFIED IDEOGRAPH+0x8BF9	0x6ADB	#CJK UNIFIED IDEOGRAPH+0x8BFA	0x91E7	#CJK UNIFIED IDEOGRAPH+0x8BFB	0x5C51	#CJK UNIFIED IDEOGRAPH+0x8BFC	0x5C48	#CJK UNIFIED IDEOGRAPH+0x8C40	0x6398	#CJK UNIFIED IDEOGRAPH+0x8C41	0x7A9F	#CJK UNIFIED IDEOGRAPH+0x8C42	0x6C93	#CJK UNIFIED IDEOGRAPH+0x8C43	0x9774	#CJK UNIFIED IDEOGRAPH+0x8C44	0x8F61	#CJK UNIFIED IDEOGRAPH+0x8C45	0x7AAA	#CJK UNIFIED IDEOGRAPH+0x8C46	0x718A	#CJK UNIFIED IDEOGRAPH+0x8C47	0x9688	#CJK UNIFIED IDEOGRAPH+0x8C48	0x7C82	#CJK UNIFIED IDEOGRAPH+0x8C49	0x6817	#CJK UNIFIED IDEOGRAPH+0x8C4A	0x7E70	#CJK UNIFIED IDEOGRAPH+0x8C4B	0x6851	#CJK UNIFIED IDEOGRAPH+0x8C4C	0x936C	#CJK UNIFIED IDEOGRAPH+0x8C4D	0x52F2	#CJK UNIFIED IDEOGRAPH+0x8C4E	0x541B	#CJK UNIFIED IDEOGRAPH+0x8C4F	0x85AB	#CJK UNIFIED IDEOGRAPH+0x8C50	0x8A13	#CJK UNIFIED IDEOGRAPH+0x8C51	0x7FA4	#CJK UNIFIED IDEOGRAPH+0x8C52	0x8ECD	#CJK UNIFIED IDEOGRAPH+0x8C53	0x90E1	#CJK UNIFIED IDEOGRAPH+0x8C54	0x5366	#CJK UNIFIED IDEOGRAPH+0x8C55	0x8888	#CJK UNIFIED IDEOGRAPH+0x8C56	0x7941	#CJK UNIFIED IDEOGRAPH+0x8C57	0x4FC2	#CJK UNIFIED IDEOGRAPH+0x8C58	0x50BE	#CJK UNIFIED IDEOGRAPH+0x8C59	0x5211	#CJK UNIFIED IDEOGRAPH+0x8C5A	0x5144	#CJK UNIFIED IDEOGRAPH+0x8C5B	0x5553	#CJK UNIFIED IDEOGRAPH+0x8C5C	0x572D	#CJK UNIFIED IDEOGRAPH+0x8C5D	0x73EA	#CJK UNIFIED IDEOGRAPH+0x8C5E	0x578B	#CJK UNIFIED IDEOGRAPH+0x8C5F	0x5951	#CJK UNIFIED IDEOGRAPH+0x8C60	0x5F62	#CJK UNIFIED IDEOGRAPH+0x8C61	0x5F84	#CJK UNIFIED IDEOGRAPH+0x8C62	0x6075	#CJK UNIFIED IDEOGRAPH+0x8C63	0x6176	#CJK UNIFIED IDEOGRAPH+0x8C64	0x6167	#CJK UNIFIED IDEOGRAPH+0x8C65	0x61A9	#CJK UNIFIED IDEOGRAPH+0x8C66	0x63B2	#CJK UNIFIED IDEOGRAPH+0x8C67	0x643A	#CJK UNIFIED IDEOGRAPH+0x8C68	0x656C	#CJK UNIFIED IDEOGRAPH+0x8C69	0x666F	#CJK UNIFIED IDEOGRAPH+0x8C6A	0x6842	#CJK UNIFIED IDEOGRAPH+0x8C6B	0x6E13	#CJK UNIFIED IDEOGRAPH+0x8C6C	0x7566	#CJK UNIFIED IDEOGRAPH+0x8C6D	0x7A3D	#CJK UNIFIED IDEOGRAPH+0x8C6E	0x7CFB	#CJK UNIFIED IDEOGRAPH+0x8C6F	0x7D4C	#CJK UNIFIED IDEOGRAPH+0x8C70	0x7D99	#CJK UNIFIED IDEOGRAPH+0x8C71	0x7E4B	#CJK UNIFIED IDEOGRAPH+0x8C72	0x7F6B	#CJK UNIFIED IDEOGRAPH+0x8C73	0x830E	#CJK UNIFIED IDEOGRAPH+0x8C74	0x834A	#CJK UNIFIED IDEOGRAPH+0x8C75	0x86CD	#CJK UNIFIED IDEOGRAPH+0x8C76	0x8A08	#CJK UNIFIED IDEOGRAPH+0x8C77	0x8A63	#CJK UNIFIED IDEOGRAPH+0x8C78	0x8B66	#CJK UNIFIED IDEOGRAPH+0x8C79	0x8EFD	#CJK UNIFIED IDEOGRAPH+0x8C7A	0x981A	#CJK UNIFIED IDEOGRAPH+0x8C7B	0x9D8F	#CJK UNIFIED IDEOGRAPH+0x8C7C	0x82B8	#CJK UNIFIED IDEOGRAPH+0x8C7D	0x8FCE	#CJK UNIFIED IDEOGRAPH+0x8C7E	0x9BE8	#CJK UNIFIED IDEOGRAPH+0x8C80	0x5287	#CJK UNIFIED IDEOGRAPH+0x8C81	0x621F	#CJK UNIFIED IDEOGRAPH+0x8C82	0x6483	#CJK UNIFIED IDEOGRAPH+0x8C83	0x6FC0	#CJK UNIFIED IDEOGRAPH+0x8C84	0x9699	#CJK UNIFIED IDEOGRAPH+0x8C85	0x6841	#CJK UNIFIED IDEOGRAPH+0x8C86	0x5091	#CJK UNIFIED IDEOGRAPH+0x8C87	0x6B20	#CJK UNIFIED IDEOGRAPH+0x8C88	0x6C7A	#CJK UNIFIED IDEOGRAPH+0x8C89	0x6F54	#CJK UNIFIED IDEOGRAPH+0x8C8A	0x7A74	#CJK UNIFIED IDEOGRAPH+0x8C8B	0x7D50	#CJK UNIFIED IDEOGRAPH+0x8C8C	0x8840	#CJK UNIFIED IDEOGRAPH+0x8C8D	0x8A23	#CJK UNIFIED IDEOGRAPH+0x8C8E	0x6708	#CJK UNIFIED IDEOGRAPH+0x8C8F	0x4EF6	#CJK UNIFIED IDEOGRAPH+0x8C90	0x5039	#CJK UNIFIED IDEOGRAPH+0x8C91	0x5026	#CJK UNIFIED IDEOGRAPH+0x8C92	0x5065	#CJK UNIFIED IDEOGRAPH+0x8C93	0x517C	#CJK UNIFIED IDEOGRAPH+0x8C94	0x5238	#CJK UNIFIED IDEOGRAPH+0x8C95	0x5263	#CJK UNIFIED IDEOGRAPH+0x8C96	0x55A7	#CJK UNIFIED IDEOGRAPH+0x8C97	0x570F	#CJK UNIFIED IDEOGRAPH+0x8C98	0x5805	#CJK UNIFIED IDEOGRAPH+0x8C99	0x5ACC	#CJK UNIFIED IDEOGRAPH+0x8C9A	0x5EFA	#CJK UNIFIED IDEOGRAPH+0x8C9B	0x61B2	#CJK UNIFIED IDEOGRAPH+0x8C9C	0x61F8	#CJK UNIFIED IDEOGRAPH+0x8C9D	0x62F3	#CJK UNIFIED IDEOGRAPH+0x8C9E	0x6372	#CJK UNIFIED IDEOGRAPH+0x8C9F	0x691C	#CJK UNIFIED IDEOGRAPH+0x8CA0	0x6A29	#CJK UNIFIED IDEOGRAPH+0x8CA1	0x727D	#CJK UNIFIED IDEOGRAPH+0x8CA2	0x72AC	#CJK UNIFIED IDEOGRAPH+0x8CA3	0x732E	#CJK UNIFIED IDEOGRAPH+0x8CA4	0x7814	#CJK UNIFIED IDEOGRAPH+0x8CA5	0x786F	#CJK UNIFIED IDEOGRAPH+0x8CA6	0x7D79	#CJK UNIFIED IDEOGRAPH+0x8CA7	0x770C	#CJK UNIFIED IDEOGRAPH+0x8CA8	0x80A9	#CJK UNIFIED IDEOGRAPH+0x8CA9	0x898B	#CJK UNIFIED IDEOGRAPH+0x8CAA	0x8B19	#CJK UNIFIED IDEOGRAPH+0x8CAB	0x8CE2	#CJK UNIFIED IDEOGRAPH+0x8CAC	0x8ED2	#CJK UNIFIED IDEOGRAPH+0x8CAD	0x9063	#CJK UNIFIED IDEOGRAPH+0x8CAE	0x9375	#CJK UNIFIED IDEOGRAPH+0x8CAF	0x967A	#CJK UNIFIED IDEOGRAPH+0x8CB0	0x9855	#CJK UNIFIED IDEOGRAPH+0x8CB1	0x9A13	#CJK UNIFIED IDEOGRAPH+0x8CB2	0x9E78	#CJK UNIFIED IDEOGRAPH+0x8CB3	0x5143	#CJK UNIFIED IDEOGRAPH+0x8CB4	0x539F	#CJK UNIFIED IDEOGRAPH+0x8CB5	0x53B3	#CJK UNIFIED IDEOGRAPH+0x8CB6	0x5E7B	#CJK UNIFIED IDEOGRAPH+0x8CB7	0x5F26	#CJK UNIFIED IDEOGRAPH+0x8CB8	0x6E1B	#CJK UNIFIED IDEOGRAPH+0x8CB9	0x6E90	#CJK UNIFIED IDEOGRAPH+0x8CBA	0x7384	#CJK UNIFIED IDEOGRAPH+0x8CBB	0x73FE	#CJK UNIFIED IDEOGRAPH+0x8CBC	0x7D43	#CJK UNIFIED IDEOGRAPH+0x8CBD	0x8237	#CJK UNIFIED IDEOGRAPH+0x8CBE	0x8A00	#CJK UNIFIED IDEOGRAPH+0x8CBF	0x8AFA	#CJK UNIFIED IDEOGRAPH+0x8CC0	0x9650	#CJK UNIFIED IDEOGRAPH+0x8CC1	0x4E4E	#CJK UNIFIED IDEOGRAPH+0x8CC2	0x500B	#CJK UNIFIED IDEOGRAPH+0x8CC3	0x53E4	#CJK UNIFIED IDEOGRAPH+0x8CC4	0x547C	#CJK UNIFIED IDEOGRAPH+0x8CC5	0x56FA	#CJK UNIFIED IDEOGRAPH+0x8CC6	0x59D1	#CJK UNIFIED IDEOGRAPH+0x8CC7	0x5B64	#CJK UNIFIED IDEOGRAPH+0x8CC8	0x5DF1	#CJK UNIFIED IDEOGRAPH+0x8CC9	0x5EAB	#CJK UNIFIED IDEOGRAPH+0x8CCA	0x5F27	#CJK UNIFIED IDEOGRAPH+0x8CCB	0x6238	#CJK UNIFIED IDEOGRAPH+0x8CCC	0x6545	#CJK UNIFIED IDEOGRAPH+0x8CCD	0x67AF	#CJK UNIFIED IDEOGRAPH+0x8CCE	0x6E56	#CJK UNIFIED IDEOGRAPH+0x8CCF	0x72D0	#CJK UNIFIED IDEOGRAPH+0x8CD0	0x7CCA	#CJK UNIFIED IDEOGRAPH+0x8CD1	0x88B4	#CJK UNIFIED IDEOGRAPH+0x8CD2	0x80A1	#CJK UNIFIED IDEOGRAPH+0x8CD3	0x80E1	#CJK UNIFIED IDEOGRAPH+0x8CD4	0x83F0	#CJK UNIFIED IDEOGRAPH+0x8CD5	0x864E	#CJK UNIFIED IDEOGRAPH+0x8CD6	0x8A87	#CJK UNIFIED IDEOGRAPH+0x8CD7	0x8DE8	#CJK UNIFIED IDEOGRAPH+0x8CD8	0x9237	#CJK UNIFIED IDEOGRAPH+0x8CD9	0x96C7	#CJK UNIFIED IDEOGRAPH+0x8CDA	0x9867	#CJK UNIFIED IDEOGRAPH+0x8CDB	0x9F13	#CJK UNIFIED IDEOGRAPH+0x8CDC	0x4E94	#CJK UNIFIED IDEOGRAPH+0x8CDD	0x4E92	#CJK UNIFIED IDEOGRAPH+0x8CDE	0x4F0D	#CJK UNIFIED IDEOGRAPH+0x8CDF	0x5348	#CJK UNIFIED IDEOGRAPH+0x8CE0	0x5449	#CJK UNIFIED IDEOGRAPH+0x8CE1	0x543E	#CJK UNIFIED IDEOGRAPH+0x8CE2	0x5A2F	#CJK UNIFIED IDEOGRAPH+0x8CE3	0x5F8C	#CJK UNIFIED IDEOGRAPH+0x8CE4	0x5FA1	#CJK UNIFIED IDEOGRAPH+0x8CE5	0x609F	#CJK UNIFIED IDEOGRAPH+0x8CE6	0x68A7	#CJK UNIFIED IDEOGRAPH+0x8CE7	0x6A8E	#CJK UNIFIED IDEOGRAPH+0x8CE8	0x745A	#CJK UNIFIED IDEOGRAPH+0x8CE9	0x7881	#CJK UNIFIED IDEOGRAPH+0x8CEA	0x8A9E	#CJK UNIFIED IDEOGRAPH+0x8CEB	0x8AA4	#CJK UNIFIED IDEOGRAPH+0x8CEC	0x8B77	#CJK UNIFIED IDEOGRAPH+0x8CED	0x9190	#CJK UNIFIED IDEOGRAPH+0x8CEE	0x4E5E	#CJK UNIFIED IDEOGRAPH+0x8CEF	0x9BC9	#CJK UNIFIED IDEOGRAPH+0x8CF0	0x4EA4	#CJK UNIFIED IDEOGRAPH+0x8CF1	0x4F7C	#CJK UNIFIED IDEOGRAPH+0x8CF2	0x4FAF	#CJK UNIFIED IDEOGRAPH+0x8CF3	0x5019	#CJK UNIFIED IDEOGRAPH+0x8CF4	0x5016	#CJK UNIFIED IDEOGRAPH+0x8CF5	0x5149	#CJK UNIFIED IDEOGRAPH+0x8CF6	0x516C	#CJK UNIFIED IDEOGRAPH+0x8CF7	0x529F	#CJK UNIFIED IDEOGRAPH+0x8CF8	0x52B9	#CJK UNIFIED IDEOGRAPH+0x8CF9	0x52FE	#CJK UNIFIED IDEOGRAPH+0x8CFA	0x539A	#CJK UNIFIED IDEOGRAPH+0x8CFB	0x53E3	#CJK UNIFIED IDEOGRAPH+0x8CFC	0x5411	#CJK UNIFIED IDEOGRAPH+0x8D40	0x540E	#CJK UNIFIED IDEOGRAPH+0x8D41	0x5589	#CJK UNIFIED IDEOGRAPH+0x8D42	0x5751	#CJK UNIFIED IDEOGRAPH+0x8D43	0x57A2	#CJK UNIFIED IDEOGRAPH+0x8D44	0x597D	#CJK UNIFIED IDEOGRAPH+0x8D45	0x5B54	#CJK UNIFIED IDEOGRAPH+0x8D46	0x5B5D	#CJK UNIFIED IDEOGRAPH+0x8D47	0x5B8F	#CJK UNIFIED IDEOGRAPH+0x8D48	0x5DE5	#CJK UNIFIED IDEOGRAPH+0x8D49	0x5DE7	#CJK UNIFIED IDEOGRAPH+0x8D4A	0x5DF7	#CJK UNIFIED IDEOGRAPH+0x8D4B	0x5E78	#CJK UNIFIED IDEOGRAPH+0x8D4C	0x5E83	#CJK UNIFIED IDEOGRAPH+0x8D4D	0x5E9A	#CJK UNIFIED IDEOGRAPH+0x8D4E	0x5EB7	#CJK UNIFIED IDEOGRAPH+0x8D4F	0x5F18	#CJK UNIFIED IDEOGRAPH+0x8D50	0x6052	#CJK UNIFIED IDEOGRAPH+0x8D51	0x614C	#CJK UNIFIED IDEOGRAPH+0x8D52	0x6297	#CJK UNIFIED IDEOGRAPH+0x8D53	0x62D8	#CJK UNIFIED IDEOGRAPH+0x8D54	0x63A7	#CJK UNIFIED IDEOGRAPH+0x8D55	0x653B	#CJK UNIFIED IDEOGRAPH+0x8D56	0x6602	#CJK UNIFIED IDEOGRAPH+0x8D57	0x6643	#CJK UNIFIED IDEOGRAPH+0x8D58	0x66F4	#CJK UNIFIED IDEOGRAPH+0x8D59	0x676D	#CJK UNIFIED IDEOGRAPH+0x8D5A	0x6821	#CJK UNIFIED IDEOGRAPH+0x8D5B	0x6897	#CJK UNIFIED IDEOGRAPH+0x8D5C	0x69CB	#CJK UNIFIED IDEOGRAPH+0x8D5D	0x6C5F	#CJK UNIFIED IDEOGRAPH+0x8D5E	0x6D2A	#CJK UNIFIED IDEOGRAPH+0x8D5F	0x6D69	#CJK UNIFIED IDEOGRAPH+0x8D60	0x6E2F	#CJK UNIFIED IDEOGRAPH+0x8D61	0x6E9D	#CJK UNIFIED IDEOGRAPH+0x8D62	0x7532	#CJK UNIFIED IDEOGRAPH+0x8D63	0x7687	#CJK UNIFIED IDEOGRAPH+0x8D64	0x786C	#CJK UNIFIED IDEOGRAPH+0x8D65	0x7A3F	#CJK UNIFIED IDEOGRAPH+0x8D66	0x7CE0	#CJK UNIFIED IDEOGRAPH+0x8D67	0x7D05	#CJK UNIFIED IDEOGRAPH+0x8D68	0x7D18	#CJK UNIFIED IDEOGRAPH+0x8D69	0x7D5E	#CJK UNIFIED IDEOGRAPH+0x8D6A	0x7DB1	#CJK UNIFIED IDEOGRAPH+0x8D6B	0x8015	#CJK UNIFIED IDEOGRAPH+0x8D6C	0x8003	#CJK UNIFIED IDEOGRAPH+0x8D6D	0x80AF	#CJK UNIFIED IDEOGRAPH+0x8D6E	0x80B1	#CJK UNIFIED IDEOGRAPH+0x8D6F	0x8154	#CJK UNIFIED IDEOGRAPH+0x8D70	0x818F	#CJK UNIFIED IDEOGRAPH+0x8D71	0x822A	#CJK UNIFIED IDEOGRAPH+0x8D72	0x8352	#CJK UNIFIED IDEOGRAPH+0x8D73	0x884C	#CJK UNIFIED IDEOGRAPH+0x8D74	0x8861	#CJK UNIFIED IDEOGRAPH+0x8D75	0x8B1B	#CJK UNIFIED IDEOGRAPH+0x8D76	0x8CA2	#CJK UNIFIED IDEOGRAPH+0x8D77	0x8CFC	#CJK UNIFIED IDEOGRAPH+0x8D78	0x90CA	#CJK UNIFIED IDEOGRAPH+0x8D79	0x9175	#CJK UNIFIED IDEOGRAPH+0x8D7A	0x9271	#CJK UNIFIED IDEOGRAPH+0x8D7B	0x783F	#CJK UNIFIED IDEOGRAPH+0x8D7C	0x92FC	#CJK UNIFIED IDEOGRAPH+0x8D7D	0x95A4	#CJK UNIFIED IDEOGRAPH+0x8D7E	0x964D	#CJK UNIFIED IDEOGRAPH+0x8D80	0x9805	#CJK UNIFIED IDEOGRAPH+0x8D81	0x9999	#CJK UNIFIED IDEOGRAPH+0x8D82	0x9AD8	#CJK UNIFIED IDEOGRAPH+0x8D83	0x9D3B	#CJK UNIFIED IDEOGRAPH+0x8D84	0x525B	#CJK UNIFIED IDEOGRAPH+0x8D85	0x52AB	#CJK UNIFIED IDEOGRAPH+0x8D86	0x53F7	#CJK UNIFIED IDEOGRAPH+0x8D87	0x5408	#CJK UNIFIED IDEOGRAPH+0x8D88	0x58D5	#CJK UNIFIED IDEOGRAPH+0x8D89	0x62F7	#CJK UNIFIED IDEOGRAPH+0x8D8A	0x6FE0	#CJK UNIFIED IDEOGRAPH+0x8D8B	0x8C6A	#CJK UNIFIED IDEOGRAPH+0x8D8C	0x8F5F	#CJK UNIFIED IDEOGRAPH+0x8D8D	0x9EB9	#CJK UNIFIED IDEOGRAPH+0x8D8E	0x514B	#CJK UNIFIED IDEOGRAPH+0x8D8F	0x523B	#CJK UNIFIED IDEOGRAPH+0x8D90	0x544A	#CJK UNIFIED IDEOGRAPH+0x8D91	0x56FD	#CJK UNIFIED IDEOGRAPH+0x8D92	0x7A40	#CJK UNIFIED IDEOGRAPH+0x8D93	0x9177	#CJK UNIFIED IDEOGRAPH+0x8D94	0x9D60	#CJK UNIFIED IDEOGRAPH+0x8D95	0x9ED2	#CJK UNIFIED IDEOGRAPH+0x8D96	0x7344	#CJK UNIFIED IDEOGRAPH+0x8D97	0x6F09	#CJK UNIFIED IDEOGRAPH+0x8D98	0x8170	#CJK UNIFIED IDEOGRAPH+0x8D99	0x7511	#CJK UNIFIED IDEOGRAPH+0x8D9A	0x5FFD	#CJK UNIFIED IDEOGRAPH+0x8D9B	0x60DA	#CJK UNIFIED IDEOGRAPH+0x8D9C	0x9AA8	#CJK UNIFIED IDEOGRAPH+0x8D9D	0x72DB	#CJK UNIFIED IDEOGRAPH+0x8D9E	0x8FBC	#CJK UNIFIED IDEOGRAPH+0x8D9F	0x6B64	#CJK UNIFIED IDEOGRAPH+0x8DA0	0x9803	#CJK UNIFIED IDEOGRAPH+0x8DA1	0x4ECA	#CJK UNIFIED IDEOGRAPH+0x8DA2	0x56F0	#CJK UNIFIED IDEOGRAPH+0x8DA3	0x5764	#CJK UNIFIED IDEOGRAPH+0x8DA4	0x58BE	#CJK UNIFIED IDEOGRAPH+0x8DA5	0x5A5A	#CJK UNIFIED IDEOGRAPH+0x8DA6	0x6068	#CJK UNIFIED IDEOGRAPH+0x8DA7	0x61C7	#CJK UNIFIED IDEOGRAPH+0x8DA8	0x660F	#CJK UNIFIED IDEOGRAPH+0x8DA9	0x6606	#CJK UNIFIED IDEOGRAPH+0x8DAA	0x6839	#CJK UNIFIED IDEOGRAPH+0x8DAB	0x68B1	#CJK UNIFIED IDEOGRAPH+0x8DAC	0x6DF7	#CJK UNIFIED IDEOGRAPH+0x8DAD	0x75D5	#CJK UNIFIED IDEOGRAPH+0x8DAE	0x7D3A	#CJK UNIFIED IDEOGRAPH+0x8DAF	0x826E	#CJK UNIFIED IDEOGRAPH+0x8DB0	0x9B42	#CJK UNIFIED IDEOGRAPH+0x8DB1	0x4E9B	#CJK UNIFIED IDEOGRAPH+0x8DB2	0x4F50	#CJK UNIFIED IDEOGRAPH+0x8DB3	0x53C9	#CJK UNIFIED IDEOGRAPH+0x8DB4	0x5506	#CJK UNIFIED IDEOGRAPH+0x8DB5	0x5D6F	#CJK UNIFIED IDEOGRAPH+0x8DB6	0x5DE6	#CJK UNIFIED IDEOGRAPH+0x8DB7	0x5DEE	#CJK UNIFIED IDEOGRAPH+0x8DB8	0x67FB	#CJK UNIFIED IDEOGRAPH+0x8DB9	0x6C99	#CJK UNIFIED IDEOGRAPH+0x8DBA	0x7473	#CJK UNIFIED IDEOGRAPH+0x8DBB	0x7802	#CJK UNIFIED IDEOGRAPH+0x8DBC	0x8A50	#CJK UNIFIED IDEOGRAPH+0x8DBD	0x9396	#CJK UNIFIED IDEOGRAPH+0x8DBE	0x88DF	#CJK UNIFIED IDEOGRAPH+0x8DBF	0x5750	#CJK UNIFIED IDEOGRAPH+0x8DC0	0x5EA7	#CJK UNIFIED IDEOGRAPH+0x8DC1	0x632B	#CJK UNIFIED IDEOGRAPH+0x8DC2	0x50B5	#CJK UNIFIED IDEOGRAPH+0x8DC3	0x50AC	#CJK UNIFIED IDEOGRAPH+0x8DC4	0x518D	#CJK UNIFIED IDEOGRAPH+0x8DC5	0x6700	#CJK UNIFIED IDEOGRAPH+0x8DC6	0x54C9	#CJK UNIFIED IDEOGRAPH+0x8DC7	0x585E	#CJK UNIFIED IDEOGRAPH+0x8DC8	0x59BB	#CJK UNIFIED IDEOGRAPH+0x8DC9	0x5BB0	#CJK UNIFIED IDEOGRAPH+0x8DCA	0x5F69	#CJK UNIFIED IDEOGRAPH+0x8DCB	0x624D	#CJK UNIFIED IDEOGRAPH+0x8DCC	0x63A1	#CJK UNIFIED IDEOGRAPH+0x8DCD	0x683D	#CJK UNIFIED IDEOGRAPH+0x8DCE	0x6B73	#CJK UNIFIED IDEOGRAPH+0x8DCF	0x6E08	#CJK UNIFIED IDEOGRAPH+0x8DD0	0x707D	#CJK UNIFIED IDEOGRAPH+0x8DD1	0x91C7	#CJK UNIFIED IDEOGRAPH+0x8DD2	0x7280	#CJK UNIFIED IDEOGRAPH+0x8DD3	0x7815	#CJK UNIFIED IDEOGRAPH+0x8DD4	0x7826	#CJK UNIFIED IDEOGRAPH+0x8DD5	0x796D	#CJK UNIFIED IDEOGRAPH+0x8DD6	0x658E	#CJK UNIFIED IDEOGRAPH+0x8DD7	0x7D30	#CJK UNIFIED IDEOGRAPH+0x8DD8	0x83DC	#CJK UNIFIED IDEOGRAPH+0x8DD9	0x88C1	#CJK UNIFIED IDEOGRAPH+0x8DDA	0x8F09	#CJK UNIFIED IDEOGRAPH+0x8DDB	0x969B	#CJK UNIFIED IDEOGRAPH+0x8DDC	0x5264	#CJK UNIFIED IDEOGRAPH+0x8DDD	0x5728	#CJK UNIFIED IDEOGRAPH+0x8DDE	0x6750	#CJK UNIFIED IDEOGRAPH+0x8DDF	0x7F6A	#CJK UNIFIED IDEOGRAPH+0x8DE0	0x8CA1	#CJK UNIFIED IDEOGRAPH+0x8DE1	0x51B4	#CJK UNIFIED IDEOGRAPH+0x8DE2	0x5742	#CJK UNIFIED IDEOGRAPH+0x8DE3	0x962A	#CJK UNIFIED IDEOGRAPH+0x8DE4	0x583A	#CJK UNIFIED IDEOGRAPH+0x8DE5	0x698A	#CJK UNIFIED IDEOGRAPH+0x8DE6	0x80B4	#CJK UNIFIED IDEOGRAPH+0x8DE7	0x54B2	#CJK UNIFIED IDEOGRAPH+0x8DE8	0x5D0E	#CJK UNIFIED IDEOGRAPH+0x8DE9	0x57FC	#CJK UNIFIED IDEOGRAPH+0x8DEA	0x7895	#CJK UNIFIED IDEOGRAPH+0x8DEB	0x9DFA	#CJK UNIFIED IDEOGRAPH+0x8DEC	0x4F5C	#CJK UNIFIED IDEOGRAPH+0x8DED	0x524A	#CJK UNIFIED IDEOGRAPH+0x8DEE	0x548B	#CJK UNIFIED IDEOGRAPH+0x8DEF	0x643E	#CJK UNIFIED IDEOGRAPH+0x8DF0	0x6628	#CJK UNIFIED IDEOGRAPH+0x8DF1	0x6714	#CJK UNIFIED IDEOGRAPH+0x8DF2	0x67F5	#CJK UNIFIED IDEOGRAPH+0x8DF3	0x7A84	#CJK UNIFIED IDEOGRAPH+0x8DF4	0x7B56	#CJK UNIFIED IDEOGRAPH+0x8DF5	0x7D22	#CJK UNIFIED IDEOGRAPH+0x8DF6	0x932F	#CJK UNIFIED IDEOGRAPH+0x8DF7	0x685C	#CJK UNIFIED IDEOGRAPH+0x8DF8	0x9BAD	#CJK UNIFIED IDEOGRAPH+0x8DF9	0x7B39	#CJK UNIFIED IDEOGRAPH+0x8DFA	0x5319	#CJK UNIFIED IDEOGRAPH+0x8DFB	0x518A	#CJK UNIFIED IDEOGRAPH+0x8DFC	0x5237	#CJK UNIFIED IDEOGRAPH+0x8E40	0x5BDF	#CJK UNIFIED IDEOGRAPH+0x8E41	0x62F6	#CJK UNIFIED IDEOGRAPH+0x8E42	0x64AE	#CJK UNIFIED IDEOGRAPH+0x8E43	0x64E6	#CJK UNIFIED IDEOGRAPH+0x8E44	0x672D	#CJK UNIFIED IDEOGRAPH+0x8E45	0x6BBA	#CJK UNIFIED IDEOGRAPH+0x8E46	0x85A9	#CJK UNIFIED IDEOGRAPH+0x8E47	0x96D1	#CJK UNIFIED IDEOGRAPH+0x8E48	0x7690	#CJK UNIFIED IDEOGRAPH+0x8E49	0x9BD6	#CJK UNIFIED IDEOGRAPH+0x8E4A	0x634C	#CJK UNIFIED IDEOGRAPH+0x8E4B	0x9306	#CJK UNIFIED IDEOGRAPH+0x8E4C	0x9BAB	#CJK UNIFIED IDEOGRAPH+0x8E4D	0x76BF	#CJK UNIFIED IDEOGRAPH+0x8E4E	0x6652	#CJK UNIFIED IDEOGRAPH+0x8E4F	0x4E09	#CJK UNIFIED IDEOGRAPH+0x8E50	0x5098	#CJK UNIFIED IDEOGRAPH+0x8E51	0x53C2	#CJK UNIFIED IDEOGRAPH+0x8E52	0x5C71	#CJK UNIFIED IDEOGRAPH+0x8E53	0x60E8	#CJK UNIFIED IDEOGRAPH+0x8E54	0x6492	#CJK UNIFIED IDEOGRAPH+0x8E55	0x6563	#CJK UNIFIED IDEOGRAPH+0x8E56	0x685F	#CJK UNIFIED IDEOGRAPH+0x8E57	0x71E6	#CJK UNIFIED IDEOGRAPH+0x8E58	0x73CA	#CJK UNIFIED IDEOGRAPH+0x8E59	0x7523	#CJK UNIFIED IDEOGRAPH+0x8E5A	0x7B97	#CJK UNIFIED IDEOGRAPH+0x8E5B	0x7E82	#CJK UNIFIED IDEOGRAPH+0x8E5C	0x8695	#CJK UNIFIED IDEOGRAPH+0x8E5D	0x8B83	#CJK UNIFIED IDEOGRAPH+0x8E5E	0x8CDB	#CJK UNIFIED IDEOGRAPH+0x8E5F	0x9178	#CJK UNIFIED IDEOGRAPH+0x8E60	0x9910	#CJK UNIFIED IDEOGRAPH+0x8E61	0x65AC	#CJK UNIFIED IDEOGRAPH+0x8E62	0x66AB	#CJK UNIFIED IDEOGRAPH+0x8E63	0x6B8B	#CJK UNIFIED IDEOGRAPH+0x8E64	0x4ED5	#CJK UNIFIED IDEOGRAPH+0x8E65	0x4ED4	#CJK UNIFIED IDEOGRAPH+0x8E66	0x4F3A	#CJK UNIFIED IDEOGRAPH+0x8E67	0x4F7F	#CJK UNIFIED IDEOGRAPH+0x8E68	0x523A	#CJK UNIFIED IDEOGRAPH+0x8E69	0x53F8	#CJK UNIFIED IDEOGRAPH+0x8E6A	0x53F2	#CJK UNIFIED IDEOGRAPH+0x8E6B	0x55E3	#CJK UNIFIED IDEOGRAPH+0x8E6C	0x56DB	#CJK UNIFIED IDEOGRAPH+0x8E6D	0x58EB	#CJK UNIFIED IDEOGRAPH+0x8E6E	0x59CB	#CJK UNIFIED IDEOGRAPH+0x8E6F	0x59C9	#CJK UNIFIED IDEOGRAPH+0x8E70	0x59FF	#CJK UNIFIED IDEOGRAPH+0x8E71	0x5B50	#CJK UNIFIED IDEOGRAPH+0x8E72	0x5C4D	#CJK UNIFIED IDEOGRAPH+0x8E73	0x5E02	#CJK UNIFIED IDEOGRAPH+0x8E74	0x5E2B	#CJK UNIFIED IDEOGRAPH+0x8E75	0x5FD7	#CJK UNIFIED IDEOGRAPH+0x8E76	0x601D	#CJK UNIFIED IDEOGRAPH+0x8E77	0x6307	#CJK UNIFIED IDEOGRAPH+0x8E78	0x652F	#CJK UNIFIED IDEOGRAPH+0x8E79	0x5B5C	#CJK UNIFIED IDEOGRAPH+0x8E7A	0x65AF	#CJK UNIFIED IDEOGRAPH+0x8E7B	0x65BD	#CJK UNIFIED IDEOGRAPH+0x8E7C	0x65E8	#CJK UNIFIED IDEOGRAPH+0x8E7D	0x679D	#CJK UNIFIED IDEOGRAPH+0x8E7E	0x6B62	#CJK UNIFIED IDEOGRAPH+0x8E80	0x6B7B	#CJK UNIFIED IDEOGRAPH+0x8E81	0x6C0F	#CJK UNIFIED IDEOGRAPH+0x8E82	0x7345	#CJK UNIFIED IDEOGRAPH+0x8E83	0x7949	#CJK UNIFIED IDEOGRAPH+0x8E84	0x79C1	#CJK UNIFIED IDEOGRAPH+0x8E85	0x7CF8	#CJK UNIFIED IDEOGRAPH+0x8E86	0x7D19	#CJK UNIFIED IDEOGRAPH+0x8E87	0x7D2B	#CJK UNIFIED IDEOGRAPH+0x8E88	0x80A2	#CJK UNIFIED IDEOGRAPH+0x8E89	0x8102	#CJK UNIFIED IDEOGRAPH+0x8E8A	0x81F3	#CJK UNIFIED IDEOGRAPH+0x8E8B	0x8996	#CJK UNIFIED IDEOGRAPH+0x8E8C	0x8A5E	#CJK UNIFIED IDEOGRAPH+0x8E8D	0x8A69	#CJK UNIFIED IDEOGRAPH+0x8E8E	0x8A66	#CJK UNIFIED IDEOGRAPH+0x8E8F	0x8A8C	#CJK UNIFIED IDEOGRAPH+0x8E90	0x8AEE	#CJK UNIFIED IDEOGRAPH+0x8E91	0x8CC7	#CJK UNIFIED IDEOGRAPH+0x8E92	0x8CDC	#CJK UNIFIED IDEOGRAPH+0x8E93	0x96CC	#CJK UNIFIED IDEOGRAPH+0x8E94	0x98FC	#CJK UNIFIED IDEOGRAPH+0x8E95	0x6B6F	#CJK UNIFIED IDEOGRAPH+0x8E96	0x4E8B	#CJK UNIFIED IDEOGRAPH+0x8E97	0x4F3C	#CJK UNIFIED IDEOGRAPH+0x8E98	0x4F8D	#CJK UNIFIED IDEOGRAPH+0x8E99	0x5150	#CJK UNIFIED IDEOGRAPH+0x8E9A	0x5B57	#CJK UNIFIED IDEOGRAPH+0x8E9B	0x5BFA	#CJK UNIFIED IDEOGRAPH+0x8E9C	0x6148	#CJK UNIFIED IDEOGRAPH+0x8E9D	0x6301	#CJK UNIFIED IDEOGRAPH+0x8E9E	0x6642	#CJK UNIFIED IDEOGRAPH+0x8E9F	0x6B21	#CJK UNIFIED IDEOGRAPH+0x8EA0	0x6ECB	#CJK UNIFIED IDEOGRAPH+0x8EA1	0x6CBB	#CJK UNIFIED IDEOGRAPH+0x8EA2	0x723E	#CJK UNIFIED IDEOGRAPH+0x8EA3	0x74BD	#CJK UNIFIED IDEOGRAPH+0x8EA4	0x75D4	#CJK UNIFIED IDEOGRAPH+0x8EA5	0x78C1	#CJK UNIFIED IDEOGRAPH+0x8EA6	0x793A	#CJK UNIFIED IDEOGRAPH+0x8EA7	0x800C	#CJK UNIFIED IDEOGRAPH+0x8EA8	0x8033	#CJK UNIFIED IDEOGRAPH+0x8EA9	0x81EA	#CJK UNIFIED IDEOGRAPH+0x8EAA	0x8494	#CJK UNIFIED IDEOGRAPH+0x8EAB	0x8F9E	#CJK UNIFIED IDEOGRAPH+0x8EAC	0x6C50	#CJK UNIFIED IDEOGRAPH+0x8EAD	0x9E7F	#CJK UNIFIED IDEOGRAPH+0x8EAE	0x5F0F	#CJK UNIFIED IDEOGRAPH+0x8EAF	0x8B58	#CJK UNIFIED IDEOGRAPH+0x8EB0	0x9D2B	#CJK UNIFIED IDEOGRAPH+0x8EB1	0x7AFA	#CJK UNIFIED IDEOGRAPH+0x8EB2	0x8EF8	#CJK UNIFIED IDEOGRAPH+0x8EB3	0x5B8D	#CJK UNIFIED IDEOGRAPH+0x8EB4	0x96EB	#CJK UNIFIED IDEOGRAPH+0x8EB5	0x4E03	#CJK UNIFIED IDEOGRAPH+0x8EB6	0x53F1	#CJK UNIFIED IDEOGRAPH+0x8EB7	0x57F7	#CJK UNIFIED IDEOGRAPH+0x8EB8	0x5931	#CJK UNIFIED IDEOGRAPH+0x8EB9	0x5AC9	#CJK UNIFIED IDEOGRAPH+0x8EBA	0x5BA4	#CJK UNIFIED IDEOGRAPH+0x8EBB	0x6089	#CJK UNIFIED IDEOGRAPH+0x8EBC	0x6E7F	#CJK UNIFIED IDEOGRAPH+0x8EBD	0x6F06	#CJK UNIFIED IDEOGRAPH+0x8EBE	0x75BE	#CJK UNIFIED IDEOGRAPH+0x8EBF	0x8CEA	#CJK UNIFIED IDEOGRAPH+0x8EC0	0x5B9F	#CJK UNIFIED IDEOGRAPH+0x8EC1	0x8500	#CJK UNIFIED IDEOGRAPH+0x8EC2	0x7BE0	#CJK UNIFIED IDEOGRAPH+0x8EC3	0x5072	#CJK UNIFIED IDEOGRAPH+0x8EC4	0x67F4	#CJK UNIFIED IDEOGRAPH+0x8EC5	0x829D	#CJK UNIFIED IDEOGRAPH+0x8EC6	0x5C61	#CJK UNIFIED IDEOGRAPH+0x8EC7	0x854A	#CJK UNIFIED IDEOGRAPH+0x8EC8	0x7E1E	#CJK UNIFIED IDEOGRAPH+0x8EC9	0x820E	#CJK UNIFIED IDEOGRAPH+0x8ECA	0x5199	#CJK UNIFIED IDEOGRAPH+0x8ECB	0x5C04	#CJK UNIFIED IDEOGRAPH+0x8ECC	0x6368	#CJK UNIFIED IDEOGRAPH+0x8ECD	0x8D66	#CJK UNIFIED IDEOGRAPH+0x8ECE	0x659C	#CJK UNIFIED IDEOGRAPH+0x8ECF	0x716E	#CJK UNIFIED IDEOGRAPH+0x8ED0	0x793E	#CJK UNIFIED IDEOGRAPH+0x8ED1	0x7D17	#CJK UNIFIED IDEOGRAPH+0x8ED2	0x8005	#CJK UNIFIED IDEOGRAPH+0x8ED3	0x8B1D	#CJK UNIFIED IDEOGRAPH+0x8ED4	0x8ECA	#CJK UNIFIED IDEOGRAPH+0x8ED5	0x906E	#CJK UNIFIED IDEOGRAPH+0x8ED6	0x86C7	#CJK UNIFIED IDEOGRAPH+0x8ED7	0x90AA	#CJK UNIFIED IDEOGRAPH+0x8ED8	0x501F	#CJK UNIFIED IDEOGRAPH+0x8ED9	0x52FA	#CJK UNIFIED IDEOGRAPH+0x8EDA	0x5C3A	#CJK UNIFIED IDEOGRAPH+0x8EDB	0x6753	#CJK UNIFIED IDEOGRAPH+0x8EDC	0x707C	#CJK UNIFIED IDEOGRAPH+0x8EDD	0x7235	#CJK UNIFIED IDEOGRAPH+0x8EDE	0x914C	#CJK UNIFIED IDEOGRAPH+0x8EDF	0x91C8	#CJK UNIFIED IDEOGRAPH+0x8EE0	0x932B	#CJK UNIFIED IDEOGRAPH+0x8EE1	0x82E5	#CJK UNIFIED IDEOGRAPH+0x8EE2	0x5BC2	#CJK UNIFIED IDEOGRAPH+0x8EE3	0x5F31	#CJK UNIFIED IDEOGRAPH+0x8EE4	0x60F9	#CJK UNIFIED IDEOGRAPH+0x8EE5	0x4E3B	#CJK UNIFIED IDEOGRAPH+0x8EE6	0x53D6	#CJK UNIFIED IDEOGRAPH+0x8EE7	0x5B88	#CJK UNIFIED IDEOGRAPH+0x8EE8	0x624B	#CJK UNIFIED IDEOGRAPH+0x8EE9	0x6731	#CJK UNIFIED IDEOGRAPH+0x8EEA	0x6B8A	#CJK UNIFIED IDEOGRAPH+0x8EEB	0x72E9	#CJK UNIFIED IDEOGRAPH+0x8EEC	0x73E0	#CJK UNIFIED IDEOGRAPH+0x8EED	0x7A2E	#CJK UNIFIED IDEOGRAPH+0x8EEE	0x816B	#CJK UNIFIED IDEOGRAPH+0x8EEF	0x8DA3	#CJK UNIFIED IDEOGRAPH+0x8EF0	0x9152	#CJK UNIFIED IDEOGRAPH+0x8EF1	0x9996	#CJK UNIFIED IDEOGRAPH+0x8EF2	0x5112	#CJK UNIFIED IDEOGRAPH+0x8EF3	0x53D7	#CJK UNIFIED IDEOGRAPH+0x8EF4	0x546A	#CJK UNIFIED IDEOGRAPH+0x8EF5	0x5BFF	#CJK UNIFIED IDEOGRAPH+0x8EF6	0x6388	#CJK UNIFIED IDEOGRAPH+0x8EF7	0x6A39	#CJK UNIFIED IDEOGRAPH+0x8EF8	0x7DAC	#CJK UNIFIED IDEOGRAPH+0x8EF9	0x9700	#CJK UNIFIED IDEOGRAPH+0x8EFA	0x56DA	#CJK UNIFIED IDEOGRAPH+0x8EFB	0x53CE	#CJK UNIFIED IDEOGRAPH+0x8EFC	0x5468	#CJK UNIFIED IDEOGRAPH+0x8F40	0x5B97	#CJK UNIFIED IDEOGRAPH+0x8F41	0x5C31	#CJK UNIFIED IDEOGRAPH+0x8F42	0x5DDE	#CJK UNIFIED IDEOGRAPH+0x8F43	0x4FEE	#CJK UNIFIED IDEOGRAPH+0x8F44	0x6101	#CJK UNIFIED IDEOGRAPH+0x8F45	0x62FE	#CJK UNIFIED IDEOGRAPH+0x8F46	0x6D32	#CJK UNIFIED IDEOGRAPH+0x8F47	0x79C0	#CJK UNIFIED IDEOGRAPH+0x8F48	0x79CB	#CJK UNIFIED IDEOGRAPH+0x8F49	0x7D42	#CJK UNIFIED IDEOGRAPH+0x8F4A	0x7E4D	#CJK UNIFIED IDEOGRAPH+0x8F4B	0x7FD2	#CJK UNIFIED IDEOGRAPH+0x8F4C	0x81ED	#CJK UNIFIED IDEOGRAPH+0x8F4D	0x821F	#CJK UNIFIED IDEOGRAPH+0x8F4E	0x8490	#CJK UNIFIED IDEOGRAPH+0x8F4F	0x8846	#CJK UNIFIED IDEOGRAPH+0x8F50	0x8972	#CJK UNIFIED IDEOGRAPH+0x8F51	0x8B90	#CJK UNIFIED IDEOGRAPH+0x8F52	0x8E74	#CJK UNIFIED IDEOGRAPH+0x8F53	0x8F2F	#CJK UNIFIED IDEOGRAPH+0x8F54	0x9031	#CJK UNIFIED IDEOGRAPH+0x8F55	0x914B	#CJK UNIFIED IDEOGRAPH+0x8F56	0x916C	#CJK UNIFIED IDEOGRAPH+0x8F57	0x96C6	#CJK UNIFIED IDEOGRAPH+0x8F58	0x919C	#CJK UNIFIED IDEOGRAPH+0x8F59	0x4EC0	#CJK UNIFIED IDEOGRAPH+0x8F5A	0x4F4F	#CJK UNIFIED IDEOGRAPH+0x8F5B	0x5145	#CJK UNIFIED IDEOGRAPH+0x8F5C	0x5341	#CJK UNIFIED IDEOGRAPH+0x8F5D	0x5F93	#CJK UNIFIED IDEOGRAPH+0x8F5E	0x620E	#CJK UNIFIED IDEOGRAPH+0x8F5F	0x67D4	#CJK UNIFIED IDEOGRAPH+0x8F60	0x6C41	#CJK UNIFIED IDEOGRAPH+0x8F61	0x6E0B	#CJK UNIFIED IDEOGRAPH+0x8F62	0x7363	#CJK UNIFIED IDEOGRAPH+0x8F63	0x7E26	#CJK UNIFIED IDEOGRAPH+0x8F64	0x91CD	#CJK UNIFIED IDEOGRAPH+0x8F65	0x9283	#CJK UNIFIED IDEOGRAPH+0x8F66	0x53D4	#CJK UNIFIED IDEOGRAPH+0x8F67	0x5919	#CJK UNIFIED IDEOGRAPH+0x8F68	0x5BBF	#CJK UNIFIED IDEOGRAPH+0x8F69	0x6DD1	#CJK UNIFIED IDEOGRAPH+0x8F6A	0x795D	#CJK UNIFIED IDEOGRAPH+0x8F6B	0x7E2E	#CJK UNIFIED IDEOGRAPH+0x8F6C	0x7C9B	#CJK UNIFIED IDEOGRAPH+0x8F6D	0x587E	#CJK UNIFIED IDEOGRAPH+0x8F6E	0x719F	#CJK UNIFIED IDEOGRAPH+0x8F6F	0x51FA	#CJK UNIFIED IDEOGRAPH+0x8F70	0x8853	#CJK UNIFIED IDEOGRAPH+0x8F71	0x8FF0	#CJK UNIFIED IDEOGRAPH+0x8F72	0x4FCA	#CJK UNIFIED IDEOGRAPH+0x8F73	0x5CFB	#CJK UNIFIED IDEOGRAPH+0x8F74	0x6625	#CJK UNIFIED IDEOGRAPH+0x8F75	0x77AC	#CJK UNIFIED IDEOGRAPH+0x8F76	0x7AE3	#CJK UNIFIED IDEOGRAPH+0x8F77	0x821C	#CJK UNIFIED IDEOGRAPH+0x8F78	0x99FF	#CJK UNIFIED IDEOGRAPH+0x8F79	0x51C6	#CJK UNIFIED IDEOGRAPH+0x8F7A	0x5FAA	#CJK UNIFIED IDEOGRAPH+0x8F7B	0x65EC	#CJK UNIFIED IDEOGRAPH+0x8F7C	0x696F	#CJK UNIFIED IDEOGRAPH+0x8F7D	0x6B89	#CJK UNIFIED IDEOGRAPH+0x8F7E	0x6DF3	#CJK UNIFIED IDEOGRAPH+0x8F80	0x6E96	#CJK UNIFIED IDEOGRAPH+0x8F81	0x6F64	#CJK UNIFIED IDEOGRAPH+0x8F82	0x76FE	#CJK UNIFIED IDEOGRAPH+0x8F83	0x7D14	#CJK UNIFIED IDEOGRAPH+0x8F84	0x5DE1	#CJK UNIFIED IDEOGRAPH+0x8F85	0x9075	#CJK UNIFIED IDEOGRAPH+0x8F86	0x9187	#CJK UNIFIED IDEOGRAPH+0x8F87	0x9806	#CJK UNIFIED IDEOGRAPH+0x8F88	0x51E6	#CJK UNIFIED IDEOGRAPH+0x8F89	0x521D	#CJK UNIFIED IDEOGRAPH+0x8F8A	0x6240	#CJK UNIFIED IDEOGRAPH+0x8F8B	0x6691	#CJK UNIFIED IDEOGRAPH+0x8F8C	0x66D9	#CJK UNIFIED IDEOGRAPH+0x8F8D	0x6E1A	#CJK UNIFIED IDEOGRAPH+0x8F8E	0x5EB6	#CJK UNIFIED IDEOGRAPH+0x8F8F	0x7DD2	#CJK UNIFIED IDEOGRAPH+0x8F90	0x7F72	#CJK UNIFIED IDEOGRAPH+0x8F91	0x66F8	#CJK UNIFIED IDEOGRAPH+0x8F92	0x85AF	#CJK UNIFIED IDEOGRAPH+0x8F93	0x85F7	#CJK UNIFIED IDEOGRAPH+0x8F94	0x8AF8	#CJK UNIFIED IDEOGRAPH+0x8F95	0x52A9	#CJK UNIFIED IDEOGRAPH+0x8F96	0x53D9	#CJK UNIFIED IDEOGRAPH+0x8F97	0x5973	#CJK UNIFIED IDEOGRAPH+0x8F98	0x5E8F	#CJK UNIFIED IDEOGRAPH+0x8F99	0x5F90	#CJK UNIFIED IDEOGRAPH+0x8F9A	0x6055	#CJK UNIFIED IDEOGRAPH+0x8F9B	0x92E4	#CJK UNIFIED IDEOGRAPH+0x8F9C	0x9664	#CJK UNIFIED IDEOGRAPH+0x8F9D	0x50B7	#CJK UNIFIED IDEOGRAPH+0x8F9E	0x511F	#CJK UNIFIED IDEOGRAPH+0x8F9F	0x52DD	#CJK UNIFIED IDEOGRAPH+0x8FA0	0x5320	#CJK UNIFIED IDEOGRAPH+0x8FA1	0x5347	#CJK UNIFIED IDEOGRAPH+0x8FA2	0x53EC	#CJK UNIFIED IDEOGRAPH+0x8FA3	0x54E8	#CJK UNIFIED IDEOGRAPH+0x8FA4	0x5546	#CJK UNIFIED IDEOGRAPH+0x8FA5	0x5531	#CJK UNIFIED IDEOGRAPH+0x8FA6	0x5617	#CJK UNIFIED IDEOGRAPH+0x8FA7	0x5968	#CJK UNIFIED IDEOGRAPH+0x8FA8	0x59BE	#CJK UNIFIED IDEOGRAPH+0x8FA9	0x5A3C	#CJK UNIFIED IDEOGRAPH+0x8FAA	0x5BB5	#CJK UNIFIED IDEOGRAPH+0x8FAB	0x5C06	#CJK UNIFIED IDEOGRAPH+0x8FAC	0x5C0F	#CJK UNIFIED IDEOGRAPH+0x8FAD	0x5C11	#CJK UNIFIED IDEOGRAPH+0x8FAE	0x5C1A	#CJK UNIFIED IDEOGRAPH+0x8FAF	0x5E84	#CJK UNIFIED IDEOGRAPH+0x8FB0	0x5E8A	#CJK UNIFIED IDEOGRAPH+0x8FB1	0x5EE0	#CJK UNIFIED IDEOGRAPH+0x8FB2	0x5F70	#CJK UNIFIED IDEOGRAPH+0x8FB3	0x627F	#CJK UNIFIED IDEOGRAPH+0x8FB4	0x6284	#CJK UNIFIED IDEOGRAPH+0x8FB5	0x62DB	#CJK UNIFIED IDEOGRAPH+0x8FB6	0x638C	#CJK UNIFIED IDEOGRAPH+0x8FB7	0x6377	#CJK UNIFIED IDEOGRAPH+0x8FB8	0x6607	#CJK UNIFIED IDEOGRAPH+0x8FB9	0x660C	#CJK UNIFIED IDEOGRAPH+0x8FBA	0x662D	#CJK UNIFIED IDEOGRAPH+0x8FBB	0x6676	#CJK UNIFIED IDEOGRAPH+0x8FBC	0x677E	#CJK UNIFIED IDEOGRAPH+0x8FBD	0x68A2	#CJK UNIFIED IDEOGRAPH+0x8FBE	0x6A1F	#CJK UNIFIED IDEOGRAPH+0x8FBF	0x6A35	#CJK UNIFIED IDEOGRAPH+0x8FC0	0x6CBC	#CJK UNIFIED IDEOGRAPH+0x8FC1	0x6D88	#CJK UNIFIED IDEOGRAPH+0x8FC2	0x6E09	#CJK UNIFIED IDEOGRAPH+0x8FC3	0x6E58	#CJK UNIFIED IDEOGRAPH+0x8FC4	0x713C	#CJK UNIFIED IDEOGRAPH+0x8FC5	0x7126	#CJK UNIFIED IDEOGRAPH+0x8FC6	0x7167	#CJK UNIFIED IDEOGRAPH+0x8FC7	0x75C7	#CJK UNIFIED IDEOGRAPH+0x8FC8	0x7701	#CJK UNIFIED IDEOGRAPH+0x8FC9	0x785D	#CJK UNIFIED IDEOGRAPH+0x8FCA	0x7901	#CJK UNIFIED IDEOGRAPH+0x8FCB	0x7965	#CJK UNIFIED IDEOGRAPH+0x8FCC	0x79F0	#CJK UNIFIED IDEOGRAPH+0x8FCD	0x7AE0	#CJK UNIFIED IDEOGRAPH+0x8FCE	0x7B11	#CJK UNIFIED IDEOGRAPH+0x8FCF	0x7CA7	#CJK UNIFIED IDEOGRAPH+0x8FD0	0x7D39	#CJK UNIFIED IDEOGRAPH+0x8FD1	0x8096	#CJK UNIFIED IDEOGRAPH+0x8FD2	0x83D6	#CJK UNIFIED IDEOGRAPH+0x8FD3	0x848B	#CJK UNIFIED IDEOGRAPH+0x8FD4	0x8549	#CJK UNIFIED IDEOGRAPH+0x8FD5	0x885D	#CJK UNIFIED IDEOGRAPH+0x8FD6	0x88F3	#CJK UNIFIED IDEOGRAPH+0x8FD7	0x8A1F	#CJK UNIFIED IDEOGRAPH+0x8FD8	0x8A3C	#CJK UNIFIED IDEOGRAPH+0x8FD9	0x8A54	#CJK UNIFIED IDEOGRAPH+0x8FDA	0x8A73	#CJK UNIFIED IDEOGRAPH+0x8FDB	0x8C61	#CJK UNIFIED IDEOGRAPH+0x8FDC	0x8CDE	#CJK UNIFIED IDEOGRAPH+0x8FDD	0x91A4	#CJK UNIFIED IDEOGRAPH+0x8FDE	0x9266	#CJK UNIFIED IDEOGRAPH+0x8FDF	0x937E	#CJK UNIFIED IDEOGRAPH+0x8FE0	0x9418	#CJK UNIFIED IDEOGRAPH+0x8FE1	0x969C	#CJK UNIFIED IDEOGRAPH+0x8FE2	0x9798	#CJK UNIFIED IDEOGRAPH+0x8FE3	0x4E0A	#CJK UNIFIED IDEOGRAPH+0x8FE4	0x4E08	#CJK UNIFIED IDEOGRAPH+0x8FE5	0x4E1E	#CJK UNIFIED IDEOGRAPH+0x8FE6	0x4E57	#CJK UNIFIED IDEOGRAPH+0x8FE7	0x5197	#CJK UNIFIED IDEOGRAPH+0x8FE8	0x5270	#CJK UNIFIED IDEOGRAPH+0x8FE9	0x57CE	#CJK UNIFIED IDEOGRAPH+0x8FEA	0x5834	#CJK UNIFIED IDEOGRAPH+0x8FEB	0x58CC	#CJK UNIFIED IDEOGRAPH+0x8FEC	0x5B22	#CJK UNIFIED IDEOGRAPH+0x8FED	0x5E38	#CJK UNIFIED IDEOGRAPH+0x8FEE	0x60C5	#CJK UNIFIED IDEOGRAPH+0x8FEF	0x64FE	#CJK UNIFIED IDEOGRAPH+0x8FF0	0x6761	#CJK UNIFIED IDEOGRAPH+0x8FF1	0x6756	#CJK UNIFIED IDEOGRAPH+0x8FF2	0x6D44	#CJK UNIFIED IDEOGRAPH+0x8FF3	0x72B6	#CJK UNIFIED IDEOGRAPH+0x8FF4	0x7573	#CJK UNIFIED IDEOGRAPH+0x8FF5	0x7A63	#CJK UNIFIED IDEOGRAPH+0x8FF6	0x84B8	#CJK UNIFIED IDEOGRAPH+0x8FF7	0x8B72	#CJK UNIFIED IDEOGRAPH+0x8FF8	0x91B8	#CJK UNIFIED IDEOGRAPH+0x8FF9	0x9320	#CJK UNIFIED IDEOGRAPH+0x8FFA	0x5631	#CJK UNIFIED IDEOGRAPH+0x8FFB	0x57F4	#CJK UNIFIED IDEOGRAPH+0x8FFC	0x98FE	#CJK UNIFIED IDEOGRAPH+0x9040	0x62ED	#CJK UNIFIED IDEOGRAPH+0x9041	0x690D	#CJK UNIFIED IDEOGRAPH+0x9042	0x6B96	#CJK UNIFIED IDEOGRAPH+0x9043	0x71ED	#CJK UNIFIED IDEOGRAPH+0x9044	0x7E54	#CJK UNIFIED IDEOGRAPH+0x9045	0x8077	#CJK UNIFIED IDEOGRAPH+0x9046	0x8272	#CJK UNIFIED IDEOGRAPH+0x9047	0x89E6	#CJK UNIFIED IDEOGRAPH+0x9048	0x98DF	#CJK UNIFIED IDEOGRAPH+0x9049	0x8755	#CJK UNIFIED IDEOGRAPH+0x904A	0x8FB1	#CJK UNIFIED IDEOGRAPH+0x904B	0x5C3B	#CJK UNIFIED IDEOGRAPH+0x904C	0x4F38	#CJK UNIFIED IDEOGRAPH+0x904D	0x4FE1	#CJK UNIFIED IDEOGRAPH+0x904E	0x4FB5	#CJK UNIFIED IDEOGRAPH+0x904F	0x5507	#CJK UNIFIED IDEOGRAPH+0x9050	0x5A20	#CJK UNIFIED IDEOGRAPH+0x9051	0x5BDD	#CJK UNIFIED IDEOGRAPH+0x9052	0x5BE9	#CJK UNIFIED IDEOGRAPH+0x9053	0x5FC3	#CJK UNIFIED IDEOGRAPH+0x9054	0x614E	#CJK UNIFIED IDEOGRAPH+0x9055	0x632F	#CJK UNIFIED IDEOGRAPH+0x9056	0x65B0	#CJK UNIFIED IDEOGRAPH+0x9057	0x664B	#CJK UNIFIED IDEOGRAPH+0x9058	0x68EE	#CJK UNIFIED IDEOGRAPH+0x9059	0x699B	#CJK UNIFIED IDEOGRAPH+0x905A	0x6D78	#CJK UNIFIED IDEOGRAPH+0x905B	0x6DF1	#CJK UNIFIED IDEOGRAPH+0x905C	0x7533	#CJK UNIFIED IDEOGRAPH+0x905D	0x75B9	#CJK UNIFIED IDEOGRAPH+0x905E	0x771F	#CJK UNIFIED IDEOGRAPH+0x905F	0x795E	#CJK UNIFIED IDEOGRAPH+0x9060	0x79E6	#CJK UNIFIED IDEOGRAPH+0x9061	0x7D33	#CJK UNIFIED IDEOGRAPH+0x9062	0x81E3	#CJK UNIFIED IDEOGRAPH+0x9063	0x82AF	#CJK UNIFIED IDEOGRAPH+0x9064	0x85AA	#CJK UNIFIED IDEOGRAPH+0x9065	0x89AA	#CJK UNIFIED IDEOGRAPH+0x9066	0x8A3A	#CJK UNIFIED IDEOGRAPH+0x9067	0x8EAB	#CJK UNIFIED IDEOGRAPH+0x9068	0x8F9B	#CJK UNIFIED IDEOGRAPH+0x9069	0x9032	#CJK UNIFIED IDEOGRAPH+0x906A	0x91DD	#CJK UNIFIED IDEOGRAPH+0x906B	0x9707	#CJK UNIFIED IDEOGRAPH+0x906C	0x4EBA	#CJK UNIFIED IDEOGRAPH+0x906D	0x4EC1	#CJK UNIFIED IDEOGRAPH+0x906E	0x5203	#CJK UNIFIED IDEOGRAPH+0x906F	0x5875	#CJK UNIFIED IDEOGRAPH+0x9070	0x58EC	#CJK UNIFIED IDEOGRAPH+0x9071	0x5C0B	#CJK UNIFIED IDEOGRAPH+0x9072	0x751A	#CJK UNIFIED IDEOGRAPH+0x9073	0x5C3D	#CJK UNIFIED IDEOGRAPH+0x9074	0x814E	#CJK UNIFIED IDEOGRAPH+0x9075	0x8A0A	#CJK UNIFIED IDEOGRAPH+0x9076	0x8FC5	#CJK UNIFIED IDEOGRAPH+0x9077	0x9663	#CJK UNIFIED IDEOGRAPH+0x9078	0x976D	#CJK UNIFIED IDEOGRAPH+0x9079	0x7B25	#CJK UNIFIED IDEOGRAPH+0x907A	0x8ACF	#CJK UNIFIED IDEOGRAPH+0x907B	0x9808	#CJK UNIFIED IDEOGRAPH+0x907C	0x9162	#CJK UNIFIED IDEOGRAPH+0x907D	0x56F3	#CJK UNIFIED IDEOGRAPH+0x907E	0x53A8	#CJK UNIFIED IDEOGRAPH+0x9080	0x9017	#CJK UNIFIED IDEOGRAPH+0x9081	0x5439	#CJK UNIFIED IDEOGRAPH+0x9082	0x5782	#CJK UNIFIED IDEOGRAPH+0x9083	0x5E25	#CJK UNIFIED IDEOGRAPH+0x9084	0x63A8	#CJK UNIFIED IDEOGRAPH+0x9085	0x6C34	#CJK UNIFIED IDEOGRAPH+0x9086	0x708A	#CJK UNIFIED IDEOGRAPH+0x9087	0x7761	#CJK UNIFIED IDEOGRAPH+0x9088	0x7C8B	#CJK UNIFIED IDEOGRAPH+0x9089	0x7FE0	#CJK UNIFIED IDEOGRAPH+0x908A	0x8870	#CJK UNIFIED IDEOGRAPH+0x908B	0x9042	#CJK UNIFIED IDEOGRAPH+0x908C	0x9154	#CJK UNIFIED IDEOGRAPH+0x908D	0x9310	#CJK UNIFIED IDEOGRAPH+0x908E	0x9318	#CJK UNIFIED IDEOGRAPH+0x908F	0x968F	#CJK UNIFIED IDEOGRAPH+0x9090	0x745E	#CJK UNIFIED IDEOGRAPH+0x9091	0x9AC4	#CJK UNIFIED IDEOGRAPH+0x9092	0x5D07	#CJK UNIFIED IDEOGRAPH+0x9093	0x5D69	#CJK UNIFIED IDEOGRAPH+0x9094	0x6570	#CJK UNIFIED IDEOGRAPH+0x9095	0x67A2	#CJK UNIFIED IDEOGRAPH+0x9096	0x8DA8	#CJK UNIFIED IDEOGRAPH+0x9097	0x96DB	#CJK UNIFIED IDEOGRAPH+0x9098	0x636E	#CJK UNIFIED IDEOGRAPH+0x9099	0x6749	#CJK UNIFIED IDEOGRAPH+0x909A	0x6919	#CJK UNIFIED IDEOGRAPH+0x909B	0x83C5	#CJK UNIFIED IDEOGRAPH+0x909C	0x9817	#CJK UNIFIED IDEOGRAPH+0x909D	0x96C0	#CJK UNIFIED IDEOGRAPH+0x909E	0x88FE	#CJK UNIFIED IDEOGRAPH+0x909F	0x6F84	#CJK UNIFIED IDEOGRAPH+0x90A0	0x647A	#CJK UNIFIED IDEOGRAPH+0x90A1	0x5BF8	#CJK UNIFIED IDEOGRAPH+0x90A2	0x4E16	#CJK UNIFIED IDEOGRAPH+0x90A3	0x702C	#CJK UNIFIED IDEOGRAPH+0x90A4	0x755D	#CJK UNIFIED IDEOGRAPH+0x90A5	0x662F	#CJK UNIFIED IDEOGRAPH+0x90A6	0x51C4	#CJK UNIFIED IDEOGRAPH+0x90A7	0x5236	#CJK UNIFIED IDEOGRAPH+0x90A8	0x52E2	#CJK UNIFIED IDEOGRAPH+0x90A9	0x59D3	#CJK UNIFIED IDEOGRAPH+0x90AA	0x5F81	#CJK UNIFIED IDEOGRAPH+0x90AB	0x6027	#CJK UNIFIED IDEOGRAPH+0x90AC	0x6210	#CJK UNIFIED IDEOGRAPH+0x90AD	0x653F	#CJK UNIFIED IDEOGRAPH+0x90AE	0x6574	#CJK UNIFIED IDEOGRAPH+0x90AF	0x661F	#CJK UNIFIED IDEOGRAPH+0x90B0	0x6674	#CJK UNIFIED IDEOGRAPH+0x90B1	0x68F2	#CJK UNIFIED IDEOGRAPH+0x90B2	0x6816	#CJK UNIFIED IDEOGRAPH+0x90B3	0x6B63	#CJK UNIFIED IDEOGRAPH+0x90B4	0x6E05	#CJK UNIFIED IDEOGRAPH+0x90B5	0x7272	#CJK UNIFIED IDEOGRAPH+0x90B6	0x751F	#CJK UNIFIED IDEOGRAPH+0x90B7	0x76DB	#CJK UNIFIED IDEOGRAPH+0x90B8	0x7CBE	#CJK UNIFIED IDEOGRAPH+0x90B9	0x8056	#CJK UNIFIED IDEOGRAPH+0x90BA	0x58F0	#CJK UNIFIED IDEOGRAPH+0x90BB	0x88FD	#CJK UNIFIED IDEOGRAPH+0x90BC	0x897F	#CJK UNIFIED IDEOGRAPH+0x90BD	0x8AA0	#CJK UNIFIED IDEOGRAPH+0x90BE	0x8A93	#CJK UNIFIED IDEOGRAPH+0x90BF	0x8ACB	#CJK UNIFIED IDEOGRAPH+0x90C0	0x901D	#CJK UNIFIED IDEOGRAPH+0x90C1	0x9192	#CJK UNIFIED IDEOGRAPH+0x90C2	0x9752	#CJK UNIFIED IDEOGRAPH+0x90C3	0x9759	#CJK UNIFIED IDEOGRAPH+0x90C4	0x6589	#CJK UNIFIED IDEOGRAPH+0x90C5	0x7A0E	#CJK UNIFIED IDEOGRAPH+0x90C6	0x8106	#CJK UNIFIED IDEOGRAPH+0x90C7	0x96BB	#CJK UNIFIED IDEOGRAPH+0x90C8	0x5E2D	#CJK UNIFIED IDEOGRAPH+0x90C9	0x60DC	#CJK UNIFIED IDEOGRAPH+0x90CA	0x621A	#CJK UNIFIED IDEOGRAPH+0x90CB	0x65A5	#CJK UNIFIED IDEOGRAPH+0x90CC	0x6614	#CJK UNIFIED IDEOGRAPH+0x90CD	0x6790	#CJK UNIFIED IDEOGRAPH+0x90CE	0x77F3	#CJK UNIFIED IDEOGRAPH+0x90CF	0x7A4D	#CJK UNIFIED IDEOGRAPH+0x90D0	0x7C4D	#CJK UNIFIED IDEOGRAPH+0x90D1	0x7E3E	#CJK UNIFIED IDEOGRAPH+0x90D2	0x810A	#CJK UNIFIED IDEOGRAPH+0x90D3	0x8CAC	#CJK UNIFIED IDEOGRAPH+0x90D4	0x8D64	#CJK UNIFIED IDEOGRAPH+0x90D5	0x8DE1	#CJK UNIFIED IDEOGRAPH+0x90D6	0x8E5F	#CJK UNIFIED IDEOGRAPH+0x90D7	0x78A9	#CJK UNIFIED IDEOGRAPH+0x90D8	0x5207	#CJK UNIFIED IDEOGRAPH+0x90D9	0x62D9	#CJK UNIFIED IDEOGRAPH+0x90DA	0x63A5	#CJK UNIFIED IDEOGRAPH+0x90DB	0x6442	#CJK UNIFIED IDEOGRAPH+0x90DC	0x6298	#CJK UNIFIED IDEOGRAPH+0x90DD	0x8A2D	#CJK UNIFIED IDEOGRAPH+0x90DE	0x7A83	#CJK UNIFIED IDEOGRAPH+0x90DF	0x7BC0	#CJK UNIFIED IDEOGRAPH+0x90E0	0x8AAC	#CJK UNIFIED IDEOGRAPH+0x90E1	0x96EA	#CJK UNIFIED IDEOGRAPH+0x90E2	0x7D76	#CJK UNIFIED IDEOGRAPH+0x90E3	0x820C	#CJK UNIFIED IDEOGRAPH+0x90E4	0x8749	#CJK UNIFIED IDEOGRAPH+0x90E5	0x4ED9	#CJK UNIFIED IDEOGRAPH+0x90E6	0x5148	#CJK UNIFIED IDEOGRAPH+0x90E7	0x5343	#CJK UNIFIED IDEOGRAPH+0x90E8	0x5360	#CJK UNIFIED IDEOGRAPH+0x90E9	0x5BA3	#CJK UNIFIED IDEOGRAPH+0x90EA	0x5C02	#CJK UNIFIED IDEOGRAPH+0x90EB	0x5C16	#CJK UNIFIED IDEOGRAPH+0x90EC	0x5DDD	#CJK UNIFIED IDEOGRAPH+0x90ED	0x6226	#CJK UNIFIED IDEOGRAPH+0x90EE	0x6247	#CJK UNIFIED IDEOGRAPH+0x90EF	0x64B0	#CJK UNIFIED IDEOGRAPH+0x90F0	0x6813	#CJK UNIFIED IDEOGRAPH+0x90F1	0x6834	#CJK UNIFIED IDEOGRAPH+0x90F2	0x6CC9	#CJK UNIFIED IDEOGRAPH+0x90F3	0x6D45	#CJK UNIFIED IDEOGRAPH+0x90F4	0x6D17	#CJK UNIFIED IDEOGRAPH+0x90F5	0x67D3	#CJK UNIFIED IDEOGRAPH+0x90F6	0x6F5C	#CJK UNIFIED IDEOGRAPH+0x90F7	0x714E	#CJK UNIFIED IDEOGRAPH+0x90F8	0x717D	#CJK UNIFIED IDEOGRAPH+0x90F9	0x65CB	#CJK UNIFIED IDEOGRAPH+0x90FA	0x7A7F	#CJK UNIFIED IDEOGRAPH+0x90FB	0x7BAD	#CJK UNIFIED IDEOGRAPH+0x90FC	0x7DDA	#CJK UNIFIED IDEOGRAPH+0x9140	0x7E4A	#CJK UNIFIED IDEOGRAPH+0x9141	0x7FA8	#CJK UNIFIED IDEOGRAPH+0x9142	0x817A	#CJK UNIFIED IDEOGRAPH+0x9143	0x821B	#CJK UNIFIED IDEOGRAPH+0x9144	0x8239	#CJK UNIFIED IDEOGRAPH+0x9145	0x85A6	#CJK UNIFIED IDEOGRAPH+0x9146	0x8A6E	#CJK UNIFIED IDEOGRAPH+0x9147	0x8CCE	#CJK UNIFIED IDEOGRAPH+0x9148	0x8DF5	#CJK UNIFIED IDEOGRAPH+0x9149	0x9078	#CJK UNIFIED IDEOGRAPH+0x914A	0x9077	#CJK UNIFIED IDEOGRAPH+0x914B	0x92AD	#CJK UNIFIED IDEOGRAPH+0x914C	0x9291	#CJK UNIFIED IDEOGRAPH+0x914D	0x9583	#CJK UNIFIED IDEOGRAPH+0x914E	0x9BAE	#CJK UNIFIED IDEOGRAPH+0x914F	0x524D	#CJK UNIFIED IDEOGRAPH+0x9150	0x5584	#CJK UNIFIED IDEOGRAPH+0x9151	0x6F38	#CJK UNIFIED IDEOGRAPH+0x9152	0x7136	#CJK UNIFIED IDEOGRAPH+0x9153	0x5168	#CJK UNIFIED IDEOGRAPH+0x9154	0x7985	#CJK UNIFIED IDEOGRAPH+0x9155	0x7E55	#CJK UNIFIED IDEOGRAPH+0x9156	0x81B3	#CJK UNIFIED IDEOGRAPH+0x9157	0x7CCE	#CJK UNIFIED IDEOGRAPH+0x9158	0x564C	#CJK UNIFIED IDEOGRAPH+0x9159	0x5851	#CJK UNIFIED IDEOGRAPH+0x915A	0x5CA8	#CJK UNIFIED IDEOGRAPH+0x915B	0x63AA	#CJK UNIFIED IDEOGRAPH+0x915C	0x66FE	#CJK UNIFIED IDEOGRAPH+0x915D	0x66FD	#CJK UNIFIED IDEOGRAPH+0x915E	0x695A	#CJK UNIFIED IDEOGRAPH+0x915F	0x72D9	#CJK UNIFIED IDEOGRAPH+0x9160	0x758F	#CJK UNIFIED IDEOGRAPH+0x9161	0x758E	#CJK UNIFIED IDEOGRAPH+0x9162	0x790E	#CJK UNIFIED IDEOGRAPH+0x9163	0x7956	#CJK UNIFIED IDEOGRAPH+0x9164	0x79DF	#CJK UNIFIED IDEOGRAPH+0x9165	0x7C97	#CJK UNIFIED IDEOGRAPH+0x9166	0x7D20	#CJK UNIFIED IDEOGRAPH+0x9167	0x7D44	#CJK UNIFIED IDEOGRAPH+0x9168	0x8607	#CJK UNIFIED IDEOGRAPH+0x9169	0x8A34	#CJK UNIFIED IDEOGRAPH+0x916A	0x963B	#CJK UNIFIED IDEOGRAPH+0x916B	0x9061	#CJK UNIFIED IDEOGRAPH+0x916C	0x9F20	#CJK UNIFIED IDEOGRAPH+0x916D	0x50E7	#CJK UNIFIED IDEOGRAPH+0x916E	0x5275	#CJK UNIFIED IDEOGRAPH+0x916F	0x53CC	#CJK UNIFIED IDEOGRAPH+0x9170	0x53E2	#CJK UNIFIED IDEOGRAPH+0x9171	0x5009	#CJK UNIFIED IDEOGRAPH+0x9172	0x55AA	#CJK UNIFIED IDEOGRAPH+0x9173	0x58EE	#CJK UNIFIED IDEOGRAPH+0x9174	0x594F	#CJK UNIFIED IDEOGRAPH+0x9175	0x723D	#CJK UNIFIED IDEOGRAPH+0x9176	0x5B8B	#CJK UNIFIED IDEOGRAPH+0x9177	0x5C64	#CJK UNIFIED IDEOGRAPH+0x9178	0x531D	#CJK UNIFIED IDEOGRAPH+0x9179	0x60E3	#CJK UNIFIED IDEOGRAPH+0x917A	0x60F3	#CJK UNIFIED IDEOGRAPH+0x917B	0x635C	#CJK UNIFIED IDEOGRAPH+0x917C	0x6383	#CJK UNIFIED IDEOGRAPH+0x917D	0x633F	#CJK UNIFIED IDEOGRAPH+0x917E	0x63BB	#CJK UNIFIED IDEOGRAPH+0x9180	0x64CD	#CJK UNIFIED IDEOGRAPH+0x9181	0x65E9	#CJK UNIFIED IDEOGRAPH+0x9182	0x66F9	#CJK UNIFIED IDEOGRAPH+0x9183	0x5DE3	#CJK UNIFIED IDEOGRAPH+0x9184	0x69CD	#CJK UNIFIED IDEOGRAPH+0x9185	0x69FD	#CJK UNIFIED IDEOGRAPH+0x9186	0x6F15	#CJK UNIFIED IDEOGRAPH+0x9187	0x71E5	#CJK UNIFIED IDEOGRAPH+0x9188	0x4E89	#CJK UNIFIED IDEOGRAPH+0x9189	0x75E9	#CJK UNIFIED IDEOGRAPH+0x918A	0x76F8	#CJK UNIFIED IDEOGRAPH+0x918B	0x7A93	#CJK UNIFIED IDEOGRAPH+0x918C	0x7CDF	#CJK UNIFIED IDEOGRAPH+0x918D	0x7DCF	#CJK UNIFIED IDEOGRAPH+0x918E	0x7D9C	#CJK UNIFIED IDEOGRAPH+0x918F	0x8061	#CJK UNIFIED IDEOGRAPH+0x9190	0x8349	#CJK UNIFIED IDEOGRAPH+0x9191	0x8358	#CJK UNIFIED IDEOGRAPH+0x9192	0x846C	#CJK UNIFIED IDEOGRAPH+0x9193	0x84BC	#CJK UNIFIED IDEOGRAPH+0x9194	0x85FB	#CJK UNIFIED IDEOGRAPH+0x9195	0x88C5	#CJK UNIFIED IDEOGRAPH+0x9196	0x8D70	#CJK UNIFIED IDEOGRAPH+0x9197	0x9001	#CJK UNIFIED IDEOGRAPH+0x9198	0x906D	#CJK UNIFIED IDEOGRAPH+0x9199	0x9397	#CJK UNIFIED IDEOGRAPH+0x919A	0x971C	#CJK UNIFIED IDEOGRAPH+0x919B	0x9A12	#CJK UNIFIED IDEOGRAPH+0x919C	0x50CF	#CJK UNIFIED IDEOGRAPH+0x919D	0x5897	#CJK UNIFIED IDEOGRAPH+0x919E	0x618E	#CJK UNIFIED IDEOGRAPH+0x919F	0x81D3	#CJK UNIFIED IDEOGRAPH+0x91A0	0x8535	#CJK UNIFIED IDEOGRAPH+0x91A1	0x8D08	#CJK UNIFIED IDEOGRAPH+0x91A2	0x9020	#CJK UNIFIED IDEOGRAPH+0x91A3	0x4FC3	#CJK UNIFIED IDEOGRAPH+0x91A4	0x5074	#CJK UNIFIED IDEOGRAPH+0x91A5	0x5247	#CJK UNIFIED IDEOGRAPH+0x91A6	0x5373	#CJK UNIFIED IDEOGRAPH+0x91A7	0x606F	#CJK UNIFIED IDEOGRAPH+0x91A8	0x6349	#CJK UNIFIED IDEOGRAPH+0x91A9	0x675F	#CJK UNIFIED IDEOGRAPH+0x91AA	0x6E2C	#CJK UNIFIED IDEOGRAPH+0x91AB	0x8DB3	#CJK UNIFIED IDEOGRAPH+0x91AC	0x901F	#CJK UNIFIED IDEOGRAPH+0x91AD	0x4FD7	#CJK UNIFIED IDEOGRAPH+0x91AE	0x5C5E	#CJK UNIFIED IDEOGRAPH+0x91AF	0x8CCA	#CJK UNIFIED IDEOGRAPH+0x91B0	0x65CF	#CJK UNIFIED IDEOGRAPH+0x91B1	0x7D9A	#CJK UNIFIED IDEOGRAPH+0x91B2	0x5352	#CJK UNIFIED IDEOGRAPH+0x91B3	0x8896	#CJK UNIFIED IDEOGRAPH+0x91B4	0x5176	#CJK UNIFIED IDEOGRAPH+0x91B5	0x63C3	#CJK UNIFIED IDEOGRAPH+0x91B6	0x5B58	#CJK UNIFIED IDEOGRAPH+0x91B7	0x5B6B	#CJK UNIFIED IDEOGRAPH+0x91B8	0x5C0A	#CJK UNIFIED IDEOGRAPH+0x91B9	0x640D	#CJK UNIFIED IDEOGRAPH+0x91BA	0x6751	#CJK UNIFIED IDEOGRAPH+0x91BB	0x905C	#CJK UNIFIED IDEOGRAPH+0x91BC	0x4ED6	#CJK UNIFIED IDEOGRAPH+0x91BD	0x591A	#CJK UNIFIED IDEOGRAPH+0x91BE	0x592A	#CJK UNIFIED IDEOGRAPH+0x91BF	0x6C70	#CJK UNIFIED IDEOGRAPH+0x91C0	0x8A51	#CJK UNIFIED IDEOGRAPH+0x91C1	0x553E	#CJK UNIFIED IDEOGRAPH+0x91C2	0x5815	#CJK UNIFIED IDEOGRAPH+0x91C3	0x59A5	#CJK UNIFIED IDEOGRAPH+0x91C4	0x60F0	#CJK UNIFIED IDEOGRAPH+0x91C5	0x6253	#CJK UNIFIED IDEOGRAPH+0x91C6	0x67C1	#CJK UNIFIED IDEOGRAPH+0x91C7	0x8235	#CJK UNIFIED IDEOGRAPH+0x91C8	0x6955	#CJK UNIFIED IDEOGRAPH+0x91C9	0x9640	#CJK UNIFIED IDEOGRAPH+0x91CA	0x99C4	#CJK UNIFIED IDEOGRAPH+0x91CB	0x9A28	#CJK UNIFIED IDEOGRAPH+0x91CC	0x4F53	#CJK UNIFIED IDEOGRAPH+0x91CD	0x5806	#CJK UNIFIED IDEOGRAPH+0x91CE	0x5BFE	#CJK UNIFIED IDEOGRAPH+0x91CF	0x8010	#CJK UNIFIED IDEOGRAPH+0x91D0	0x5CB1	#CJK UNIFIED IDEOGRAPH+0x91D1	0x5E2F	#CJK UNIFIED IDEOGRAPH+0x91D2	0x5F85	#CJK UNIFIED IDEOGRAPH+0x91D3	0x6020	#CJK UNIFIED IDEOGRAPH+0x91D4	0x614B	#CJK UNIFIED IDEOGRAPH+0x91D5	0x6234	#CJK UNIFIED IDEOGRAPH+0x91D6	0x66FF	#CJK UNIFIED IDEOGRAPH+0x91D7	0x6CF0	#CJK UNIFIED IDEOGRAPH+0x91D8	0x6EDE	#CJK UNIFIED IDEOGRAPH+0x91D9	0x80CE	#CJK UNIFIED IDEOGRAPH+0x91DA	0x817F	#CJK UNIFIED IDEOGRAPH+0x91DB	0x82D4	#CJK UNIFIED IDEOGRAPH+0x91DC	0x888B	#CJK UNIFIED IDEOGRAPH+0x91DD	0x8CB8	#CJK UNIFIED IDEOGRAPH+0x91DE	0x9000	#CJK UNIFIED IDEOGRAPH+0x91DF	0x902E	#CJK UNIFIED IDEOGRAPH+0x91E0	0x968A	#CJK UNIFIED IDEOGRAPH+0x91E1	0x9EDB	#CJK UNIFIED IDEOGRAPH+0x91E2	0x9BDB	#CJK UNIFIED IDEOGRAPH+0x91E3	0x4EE3	#CJK UNIFIED IDEOGRAPH+0x91E4	0x53F0	#CJK UNIFIED IDEOGRAPH+0x91E5	0x5927	#CJK UNIFIED IDEOGRAPH+0x91E6	0x7B2C	#CJK UNIFIED IDEOGRAPH+0x91E7	0x918D	#CJK UNIFIED IDEOGRAPH+0x91E8	0x984C	#CJK UNIFIED IDEOGRAPH+0x91E9	0x9DF9	#CJK UNIFIED IDEOGRAPH+0x91EA	0x6EDD	#CJK UNIFIED IDEOGRAPH+0x91EB	0x7027	#CJK UNIFIED IDEOGRAPH+0x91EC	0x5353	#CJK UNIFIED IDEOGRAPH+0x91ED	0x5544	#CJK UNIFIED IDEOGRAPH+0x91EE	0x5B85	#CJK UNIFIED IDEOGRAPH+0x91EF	0x6258	#CJK UNIFIED IDEOGRAPH+0x91F0	0x629E	#CJK UNIFIED IDEOGRAPH+0x91F1	0x62D3	#CJK UNIFIED IDEOGRAPH+0x91F2	0x6CA2	#CJK UNIFIED IDEOGRAPH+0x91F3	0x6FEF	#CJK UNIFIED IDEOGRAPH+0x91F4	0x7422	#CJK UNIFIED IDEOGRAPH+0x91F5	0x8A17	#CJK UNIFIED IDEOGRAPH+0x91F6	0x9438	#CJK UNIFIED IDEOGRAPH+0x91F7	0x6FC1	#CJK UNIFIED IDEOGRAPH+0x91F8	0x8AFE	#CJK UNIFIED IDEOGRAPH+0x91F9	0x8338	#CJK UNIFIED IDEOGRAPH+0x91FA	0x51E7	#CJK UNIFIED IDEOGRAPH+0x91FB	0x86F8	#CJK UNIFIED IDEOGRAPH+0x91FC	0x53EA	#CJK UNIFIED IDEOGRAPH+0x9240	0x53E9	#CJK UNIFIED IDEOGRAPH+0x9241	0x4F46	#CJK UNIFIED IDEOGRAPH+0x9242	0x9054	#CJK UNIFIED IDEOGRAPH+0x9243	0x8FB0	#CJK UNIFIED IDEOGRAPH+0x9244	0x596A	#CJK UNIFIED IDEOGRAPH+0x9245	0x8131	#CJK UNIFIED IDEOGRAPH+0x9246	0x5DFD	#CJK UNIFIED IDEOGRAPH+0x9247	0x7AEA	#CJK UNIFIED IDEOGRAPH+0x9248	0x8FBF	#CJK UNIFIED IDEOGRAPH+0x9249	0x68DA	#CJK UNIFIED IDEOGRAPH+0x924A	0x8C37	#CJK UNIFIED IDEOGRAPH+0x924B	0x72F8	#CJK UNIFIED IDEOGRAPH+0x924C	0x9C48	#CJK UNIFIED IDEOGRAPH+0x924D	0x6A3D	#CJK UNIFIED IDEOGRAPH+0x924E	0x8AB0	#CJK UNIFIED IDEOGRAPH+0x924F	0x4E39	#CJK UNIFIED IDEOGRAPH+0x9250	0x5358	#CJK UNIFIED IDEOGRAPH+0x9251	0x5606	#CJK UNIFIED IDEOGRAPH+0x9252	0x5766	#CJK UNIFIED IDEOGRAPH+0x9253	0x62C5	#CJK UNIFIED IDEOGRAPH+0x9254	0x63A2	#CJK UNIFIED IDEOGRAPH+0x9255	0x65E6	#CJK UNIFIED IDEOGRAPH+0x9256	0x6B4E	#CJK UNIFIED IDEOGRAPH+0x9257	0x6DE1	#CJK UNIFIED IDEOGRAPH+0x9258	0x6E5B	#CJK UNIFIED IDEOGRAPH+0x9259	0x70AD	#CJK UNIFIED IDEOGRAPH+0x925A	0x77ED	#CJK UNIFIED IDEOGRAPH+0x925B	0x7AEF	#CJK UNIFIED IDEOGRAPH+0x925C	0x7BAA	#CJK UNIFIED IDEOGRAPH+0x925D	0x7DBB	#CJK UNIFIED IDEOGRAPH+0x925E	0x803D	#CJK UNIFIED IDEOGRAPH+0x925F	0x80C6	#CJK UNIFIED IDEOGRAPH+0x9260	0x86CB	#CJK UNIFIED IDEOGRAPH+0x9261	0x8A95	#CJK UNIFIED IDEOGRAPH+0x9262	0x935B	#CJK UNIFIED IDEOGRAPH+0x9263	0x56E3	#CJK UNIFIED IDEOGRAPH+0x9264	0x58C7	#CJK UNIFIED IDEOGRAPH+0x9265	0x5F3E	#CJK UNIFIED IDEOGRAPH+0x9266	0x65AD	#CJK UNIFIED IDEOGRAPH+0x9267	0x6696	#CJK UNIFIED IDEOGRAPH+0x9268	0x6A80	#CJK UNIFIED IDEOGRAPH+0x9269	0x6BB5	#CJK UNIFIED IDEOGRAPH+0x926A	0x7537	#CJK UNIFIED IDEOGRAPH+0x926B	0x8AC7	#CJK UNIFIED IDEOGRAPH+0x926C	0x5024	#CJK UNIFIED IDEOGRAPH+0x926D	0x77E5	#CJK UNIFIED IDEOGRAPH+0x926E	0x5730	#CJK UNIFIED IDEOGRAPH+0x926F	0x5F1B	#CJK UNIFIED IDEOGRAPH+0x9270	0x6065	#CJK UNIFIED IDEOGRAPH+0x9271	0x667A	#CJK UNIFIED IDEOGRAPH+0x9272	0x6C60	#CJK UNIFIED IDEOGRAPH+0x9273	0x75F4	#CJK UNIFIED IDEOGRAPH+0x9274	0x7A1A	#CJK UNIFIED IDEOGRAPH+0x9275	0x7F6E	#CJK UNIFIED IDEOGRAPH+0x9276	0x81F4	#CJK UNIFIED IDEOGRAPH+0x9277	0x8718	#CJK UNIFIED IDEOGRAPH+0x9278	0x9045	#CJK UNIFIED IDEOGRAPH+0x9279	0x99B3	#CJK UNIFIED IDEOGRAPH+0x927A	0x7BC9	#CJK UNIFIED IDEOGRAPH+0x927B	0x755C	#CJK UNIFIED IDEOGRAPH+0x927C	0x7AF9	#CJK UNIFIED IDEOGRAPH+0x927D	0x7B51	#CJK UNIFIED IDEOGRAPH+0x927E	0x84C4	#CJK UNIFIED IDEOGRAPH+0x9280	0x9010	#CJK UNIFIED IDEOGRAPH+0x9281	0x79E9	#CJK UNIFIED IDEOGRAPH+0x9282	0x7A92	#CJK UNIFIED IDEOGRAPH+0x9283	0x8336	#CJK UNIFIED IDEOGRAPH+0x9284	0x5AE1	#CJK UNIFIED IDEOGRAPH+0x9285	0x7740	#CJK UNIFIED IDEOGRAPH+0x9286	0x4E2D	#CJK UNIFIED IDEOGRAPH+0x9287	0x4EF2	#CJK UNIFIED IDEOGRAPH+0x9288	0x5B99	#CJK UNIFIED IDEOGRAPH+0x9289	0x5FE0	#CJK UNIFIED IDEOGRAPH+0x928A	0x62BD	#CJK UNIFIED IDEOGRAPH+0x928B	0x663C	#CJK UNIFIED IDEOGRAPH+0x928C	0x67F1	#CJK UNIFIED IDEOGRAPH+0x928D	0x6CE8	#CJK UNIFIED IDEOGRAPH+0x928E	0x866B	#CJK UNIFIED IDEOGRAPH+0x928F	0x8877	#CJK UNIFIED IDEOGRAPH+0x9290	0x8A3B	#CJK UNIFIED IDEOGRAPH+0x9291	0x914E	#CJK UNIFIED IDEOGRAPH+0x9292	0x92F3	#CJK UNIFIED IDEOGRAPH+0x9293	0x99D0	#CJK UNIFIED IDEOGRAPH+0x9294	0x6A17	#CJK UNIFIED IDEOGRAPH+0x9295	0x7026	#CJK UNIFIED IDEOGRAPH+0x9296	0x732A	#CJK UNIFIED IDEOGRAPH+0x9297	0x82E7	#CJK UNIFIED IDEOGRAPH+0x9298	0x8457	#CJK UNIFIED IDEOGRAPH+0x9299	0x8CAF	#CJK UNIFIED IDEOGRAPH+0x929A	0x4E01	#CJK UNIFIED IDEOGRAPH+0x929B	0x5146	#CJK UNIFIED IDEOGRAPH+0x929C	0x51CB	#CJK UNIFIED IDEOGRAPH+0x929D	0x558B	#CJK UNIFIED IDEOGRAPH+0x929E	0x5BF5	#CJK UNIFIED IDEOGRAPH+0x929F	0x5E16	#CJK UNIFIED IDEOGRAPH+0x92A0	0x5E33	#CJK UNIFIED IDEOGRAPH+0x92A1	0x5E81	#CJK UNIFIED IDEOGRAPH+0x92A2	0x5F14	#CJK UNIFIED IDEOGRAPH+0x92A3	0x5F35	#CJK UNIFIED IDEOGRAPH+0x92A4	0x5F6B	#CJK UNIFIED IDEOGRAPH+0x92A5	0x5FB4	#CJK UNIFIED IDEOGRAPH+0x92A6	0x61F2	#CJK UNIFIED IDEOGRAPH+0x92A7	0x6311	#CJK UNIFIED IDEOGRAPH+0x92A8	0x66A2	#CJK UNIFIED IDEOGRAPH+0x92A9	0x671D	#CJK UNIFIED IDEOGRAPH+0x92AA	0x6F6E	#CJK UNIFIED IDEOGRAPH+0x92AB	0x7252	#CJK UNIFIED IDEOGRAPH+0x92AC	0x753A	#CJK UNIFIED IDEOGRAPH+0x92AD	0x773A	#CJK UNIFIED IDEOGRAPH+0x92AE	0x8074	#CJK UNIFIED IDEOGRAPH+0x92AF	0x8139	#CJK UNIFIED IDEOGRAPH+0x92B0	0x8178	#CJK UNIFIED IDEOGRAPH+0x92B1	0x8776	#CJK UNIFIED IDEOGRAPH+0x92B2	0x8ABF	#CJK UNIFIED IDEOGRAPH+0x92B3	0x8ADC	#CJK UNIFIED IDEOGRAPH+0x92B4	0x8D85	#CJK UNIFIED IDEOGRAPH+0x92B5	0x8DF3	#CJK UNIFIED IDEOGRAPH+0x92B6	0x929A	#CJK UNIFIED IDEOGRAPH+0x92B7	0x9577	#CJK UNIFIED IDEOGRAPH+0x92B8	0x9802	#CJK UNIFIED IDEOGRAPH+0x92B9	0x9CE5	#CJK UNIFIED IDEOGRAPH+0x92BA	0x52C5	#CJK UNIFIED IDEOGRAPH+0x92BB	0x6357	#CJK UNIFIED IDEOGRAPH+0x92BC	0x76F4	#CJK UNIFIED IDEOGRAPH+0x92BD	0x6715	#CJK UNIFIED IDEOGRAPH+0x92BE	0x6C88	#CJK UNIFIED IDEOGRAPH+0x92BF	0x73CD	#CJK UNIFIED IDEOGRAPH+0x92C0	0x8CC3	#CJK UNIFIED IDEOGRAPH+0x92C1	0x93AE	#CJK UNIFIED IDEOGRAPH+0x92C2	0x9673	#CJK UNIFIED IDEOGRAPH+0x92C3	0x6D25	#CJK UNIFIED IDEOGRAPH+0x92C4	0x589C	#CJK UNIFIED IDEOGRAPH+0x92C5	0x690E	#CJK UNIFIED IDEOGRAPH+0x92C6	0x69CC	#CJK UNIFIED IDEOGRAPH+0x92C7	0x8FFD	#CJK UNIFIED IDEOGRAPH+0x92C8	0x939A	#CJK UNIFIED IDEOGRAPH+0x92C9	0x75DB	#CJK UNIFIED IDEOGRAPH+0x92CA	0x901A	#CJK UNIFIED IDEOGRAPH+0x92CB	0x585A	#CJK UNIFIED IDEOGRAPH+0x92CC	0x6802	#CJK UNIFIED IDEOGRAPH+0x92CD	0x63B4	#CJK UNIFIED IDEOGRAPH+0x92CE	0x69FB	#CJK UNIFIED IDEOGRAPH+0x92CF	0x4F43	#CJK UNIFIED IDEOGRAPH+0x92D0	0x6F2C	#CJK UNIFIED IDEOGRAPH+0x92D1	0x67D8	#CJK UNIFIED IDEOGRAPH+0x92D2	0x8FBB	#CJK UNIFIED IDEOGRAPH+0x92D3	0x8526	#CJK UNIFIED IDEOGRAPH+0x92D4	0x7DB4	#CJK UNIFIED IDEOGRAPH+0x92D5	0x9354	#CJK UNIFIED IDEOGRAPH+0x92D6	0x693F	#CJK UNIFIED IDEOGRAPH+0x92D7	0x6F70	#CJK UNIFIED IDEOGRAPH+0x92D8	0x576A	#CJK UNIFIED IDEOGRAPH+0x92D9	0x58F7	#CJK UNIFIED IDEOGRAPH+0x92DA	0x5B2C	#CJK UNIFIED IDEOGRAPH+0x92DB	0x7D2C	#CJK UNIFIED IDEOGRAPH+0x92DC	0x722A	#CJK UNIFIED IDEOGRAPH+0x92DD	0x540A	#CJK UNIFIED IDEOGRAPH+0x92DE	0x91E3	#CJK UNIFIED IDEOGRAPH+0x92DF	0x9DB4	#CJK UNIFIED IDEOGRAPH+0x92E0	0x4EAD	#CJK UNIFIED IDEOGRAPH+0x92E1	0x4F4E	#CJK UNIFIED IDEOGRAPH+0x92E2	0x505C	#CJK UNIFIED IDEOGRAPH+0x92E3	0x5075	#CJK UNIFIED IDEOGRAPH+0x92E4	0x5243	#CJK UNIFIED IDEOGRAPH+0x92E5	0x8C9E	#CJK UNIFIED IDEOGRAPH+0x92E6	0x5448	#CJK UNIFIED IDEOGRAPH+0x92E7	0x5824	#CJK UNIFIED IDEOGRAPH+0x92E8	0x5B9A	#CJK UNIFIED IDEOGRAPH+0x92E9	0x5E1D	#CJK UNIFIED IDEOGRAPH+0x92EA	0x5E95	#CJK UNIFIED IDEOGRAPH+0x92EB	0x5EAD	#CJK UNIFIED IDEOGRAPH+0x92EC	0x5EF7	#CJK UNIFIED IDEOGRAPH+0x92ED	0x5F1F	#CJK UNIFIED IDEOGRAPH+0x92EE	0x608C	#CJK UNIFIED IDEOGRAPH+0x92EF	0x62B5	#CJK UNIFIED IDEOGRAPH+0x92F0	0x633A	#CJK UNIFIED IDEOGRAPH+0x92F1	0x63D0	#CJK UNIFIED IDEOGRAPH+0x92F2	0x68AF	#CJK UNIFIED IDEOGRAPH+0x92F3	0x6C40	#CJK UNIFIED IDEOGRAPH+0x92F4	0x7887	#CJK UNIFIED IDEOGRAPH+0x92F5	0x798E	#CJK UNIFIED IDEOGRAPH+0x92F6	0x7A0B	#CJK UNIFIED IDEOGRAPH+0x92F7	0x7DE0	#CJK UNIFIED IDEOGRAPH+0x92F8	0x8247	#CJK UNIFIED IDEOGRAPH+0x92F9	0x8A02	#CJK UNIFIED IDEOGRAPH+0x92FA	0x8AE6	#CJK UNIFIED IDEOGRAPH+0x92FB	0x8E44	#CJK UNIFIED IDEOGRAPH+0x92FC	0x9013	#CJK UNIFIED IDEOGRAPH+0x9340	0x90B8	#CJK UNIFIED IDEOGRAPH+0x9341	0x912D	#CJK UNIFIED IDEOGRAPH+0x9342	0x91D8	#CJK UNIFIED IDEOGRAPH+0x9343	0x9F0E	#CJK UNIFIED IDEOGRAPH+0x9344	0x6CE5	#CJK UNIFIED IDEOGRAPH+0x9345	0x6458	#CJK UNIFIED IDEOGRAPH+0x9346	0x64E2	#CJK UNIFIED IDEOGRAPH+0x9347	0x6575	#CJK UNIFIED IDEOGRAPH+0x9348	0x6EF4	#CJK UNIFIED IDEOGRAPH+0x9349	0x7684	#CJK UNIFIED IDEOGRAPH+0x934A	0x7B1B	#CJK UNIFIED IDEOGRAPH+0x934B	0x9069	#CJK UNIFIED IDEOGRAPH+0x934C	0x93D1	#CJK UNIFIED IDEOGRAPH+0x934D	0x6EBA	#CJK UNIFIED IDEOGRAPH+0x934E	0x54F2	#CJK UNIFIED IDEOGRAPH+0x934F	0x5FB9	#CJK UNIFIED IDEOGRAPH+0x9350	0x64A4	#CJK UNIFIED IDEOGRAPH+0x9351	0x8F4D	#CJK UNIFIED IDEOGRAPH+0x9352	0x8FED	#CJK UNIFIED IDEOGRAPH+0x9353	0x9244	#CJK UNIFIED IDEOGRAPH+0x9354	0x5178	#CJK UNIFIED IDEOGRAPH+0x9355	0x586B	#CJK UNIFIED IDEOGRAPH+0x9356	0x5929	#CJK UNIFIED IDEOGRAPH+0x9357	0x5C55	#CJK UNIFIED IDEOGRAPH+0x9358	0x5E97	#CJK UNIFIED IDEOGRAPH+0x9359	0x6DFB	#CJK UNIFIED IDEOGRAPH+0x935A	0x7E8F	#CJK UNIFIED IDEOGRAPH+0x935B	0x751C	#CJK UNIFIED IDEOGRAPH+0x935C	0x8CBC	#CJK UNIFIED IDEOGRAPH+0x935D	0x8EE2	#CJK UNIFIED IDEOGRAPH+0x935E	0x985B	#CJK UNIFIED IDEOGRAPH+0x935F	0x70B9	#CJK UNIFIED IDEOGRAPH+0x9360	0x4F1D	#CJK UNIFIED IDEOGRAPH+0x9361	0x6BBF	#CJK UNIFIED IDEOGRAPH+0x9362	0x6FB1	#CJK UNIFIED IDEOGRAPH+0x9363	0x7530	#CJK UNIFIED IDEOGRAPH+0x9364	0x96FB	#CJK UNIFIED IDEOGRAPH+0x9365	0x514E	#CJK UNIFIED IDEOGRAPH+0x9366	0x5410	#CJK UNIFIED IDEOGRAPH+0x9367	0x5835	#CJK UNIFIED IDEOGRAPH+0x9368	0x5857	#CJK UNIFIED IDEOGRAPH+0x9369	0x59AC	#CJK UNIFIED IDEOGRAPH+0x936A	0x5C60	#CJK UNIFIED IDEOGRAPH+0x936B	0x5F92	#CJK UNIFIED IDEOGRAPH+0x936C	0x6597	#CJK UNIFIED IDEOGRAPH+0x936D	0x675C	#CJK UNIFIED IDEOGRAPH+0x936E	0x6E21	#CJK UNIFIED IDEOGRAPH+0x936F	0x767B	#CJK UNIFIED IDEOGRAPH+0x9370	0x83DF	#CJK UNIFIED IDEOGRAPH+0x9371	0x8CED	#CJK UNIFIED IDEOGRAPH+0x9372	0x9014	#CJK UNIFIED IDEOGRAPH+0x9373	0x90FD	#CJK UNIFIED IDEOGRAPH+0x9374	0x934D	#CJK UNIFIED IDEOGRAPH+0x9375	0x7825	#CJK UNIFIED IDEOGRAPH+0x9376	0x783A	#CJK UNIFIED IDEOGRAPH+0x9377	0x52AA	#CJK UNIFIED IDEOGRAPH+0x9378	0x5EA6	#CJK UNIFIED IDEOGRAPH+0x9379	0x571F	#CJK UNIFIED IDEOGRAPH+0x937A	0x5974	#CJK UNIFIED IDEOGRAPH+0x937B	0x6012	#CJK UNIFIED IDEOGRAPH+0x937C	0x5012	#CJK UNIFIED IDEOGRAPH+0x937D	0x515A	#CJK UNIFIED IDEOGRAPH+0x937E	0x51AC	#CJK UNIFIED IDEOGRAPH+0x9380	0x51CD	#CJK UNIFIED IDEOGRAPH+0x9381	0x5200	#CJK UNIFIED IDEOGRAPH+0x9382	0x5510	#CJK UNIFIED IDEOGRAPH+0x9383	0x5854	#CJK UNIFIED IDEOGRAPH+0x9384	0x5858	#CJK UNIFIED IDEOGRAPH+0x9385	0x5957	#CJK UNIFIED IDEOGRAPH+0x9386	0x5B95	#CJK UNIFIED IDEOGRAPH+0x9387	0x5CF6	#CJK UNIFIED IDEOGRAPH+0x9388	0x5D8B	#CJK UNIFIED IDEOGRAPH+0x9389	0x60BC	#CJK UNIFIED IDEOGRAPH+0x938A	0x6295	#CJK UNIFIED IDEOGRAPH+0x938B	0x642D	#CJK UNIFIED IDEOGRAPH+0x938C	0x6771	#CJK UNIFIED IDEOGRAPH+0x938D	0x6843	#CJK UNIFIED IDEOGRAPH+0x938E	0x68BC	#CJK UNIFIED IDEOGRAPH+0x938F	0x68DF	#CJK UNIFIED IDEOGRAPH+0x9390	0x76D7	#CJK UNIFIED IDEOGRAPH+0x9391	0x6DD8	#CJK UNIFIED IDEOGRAPH+0x9392	0x6E6F	#CJK UNIFIED IDEOGRAPH+0x9393	0x6D9B	#CJK UNIFIED IDEOGRAPH+0x9394	0x706F	#CJK UNIFIED IDEOGRAPH+0x9395	0x71C8	#CJK UNIFIED IDEOGRAPH+0x9396	0x5F53	#CJK UNIFIED IDEOGRAPH+0x9397	0x75D8	#CJK UNIFIED IDEOGRAPH+0x9398	0x7977	#CJK UNIFIED IDEOGRAPH+0x9399	0x7B49	#CJK UNIFIED IDEOGRAPH+0x939A	0x7B54	#CJK UNIFIED IDEOGRAPH+0x939B	0x7B52	#CJK UNIFIED IDEOGRAPH+0x939C	0x7CD6	#CJK UNIFIED IDEOGRAPH+0x939D	0x7D71	#CJK UNIFIED IDEOGRAPH+0x939E	0x5230	#CJK UNIFIED IDEOGRAPH+0x939F	0x8463	#CJK UNIFIED IDEOGRAPH+0x93A0	0x8569	#CJK UNIFIED IDEOGRAPH+0x93A1	0x85E4	#CJK UNIFIED IDEOGRAPH+0x93A2	0x8A0E	#CJK UNIFIED IDEOGRAPH+0x93A3	0x8B04	#CJK UNIFIED IDEOGRAPH+0x93A4	0x8C46	#CJK UNIFIED IDEOGRAPH+0x93A5	0x8E0F	#CJK UNIFIED IDEOGRAPH+0x93A6	0x9003	#CJK UNIFIED IDEOGRAPH+0x93A7	0x900F	#CJK UNIFIED IDEOGRAPH+0x93A8	0x9419	#CJK UNIFIED IDEOGRAPH+0x93A9	0x9676	#CJK UNIFIED IDEOGRAPH+0x93AA	0x982D	#CJK UNIFIED IDEOGRAPH+0x93AB	0x9A30	#CJK UNIFIED IDEOGRAPH+0x93AC	0x95D8	#CJK UNIFIED IDEOGRAPH+0x93AD	0x50CD	#CJK UNIFIED IDEOGRAPH+0x93AE	0x52D5	#CJK UNIFIED IDEOGRAPH+0x93AF	0x540C	#CJK UNIFIED IDEOGRAPH+0x93B0	0x5802	#CJK UNIFIED IDEOGRAPH+0x93B1	0x5C0E	#CJK UNIFIED IDEOGRAPH+0x93B2	0x61A7	#CJK UNIFIED IDEOGRAPH+0x93B3	0x649E	#CJK UNIFIED IDEOGRAPH+0x93B4	0x6D1E	#CJK UNIFIED IDEOGRAPH+0x93B5	0x77B3	#CJK UNIFIED IDEOGRAPH+0x93B6	0x7AE5	#CJK UNIFIED IDEOGRAPH+0x93B7	0x80F4	#CJK UNIFIED IDEOGRAPH+0x93B8	0x8404	#CJK UNIFIED IDEOGRAPH+0x93B9	0x9053	#CJK UNIFIED IDEOGRAPH+0x93BA	0x9285	#CJK UNIFIED IDEOGRAPH+0x93BB	0x5CE0	#CJK UNIFIED IDEOGRAPH+0x93BC	0x9D07	#CJK UNIFIED IDEOGRAPH+0x93BD	0x533F	#CJK UNIFIED IDEOGRAPH+0x93BE	0x5F97	#CJK UNIFIED IDEOGRAPH+0x93BF	0x5FB3	#CJK UNIFIED IDEOGRAPH+0x93C0	0x6D9C	#CJK UNIFIED IDEOGRAPH+0x93C1	0x7279	#CJK UNIFIED IDEOGRAPH+0x93C2	0x7763	#CJK UNIFIED IDEOGRAPH+0x93C3	0x79BF	#CJK UNIFIED IDEOGRAPH+0x93C4	0x7BE4	#CJK UNIFIED IDEOGRAPH+0x93C5	0x6BD2	#CJK UNIFIED IDEOGRAPH+0x93C6	0x72EC	#CJK UNIFIED IDEOGRAPH+0x93C7	0x8AAD	#CJK UNIFIED IDEOGRAPH+0x93C8	0x6803	#CJK UNIFIED IDEOGRAPH+0x93C9	0x6A61	#CJK UNIFIED IDEOGRAPH+0x93CA	0x51F8	#CJK UNIFIED IDEOGRAPH+0x93CB	0x7A81	#CJK UNIFIED IDEOGRAPH+0x93CC	0x6934	#CJK UNIFIED IDEOGRAPH+0x93CD	0x5C4A	#CJK UNIFIED IDEOGRAPH+0x93CE	0x9CF6	#CJK UNIFIED IDEOGRAPH+0x93CF	0x82EB	#CJK UNIFIED IDEOGRAPH+0x93D0	0x5BC5	#CJK UNIFIED IDEOGRAPH+0x93D1	0x9149	#CJK UNIFIED IDEOGRAPH+0x93D2	0x701E	#CJK UNIFIED IDEOGRAPH+0x93D3	0x5678	#CJK UNIFIED IDEOGRAPH+0x93D4	0x5C6F	#CJK UNIFIED IDEOGRAPH+0x93D5	0x60C7	#CJK UNIFIED IDEOGRAPH+0x93D6	0x6566	#CJK UNIFIED IDEOGRAPH+0x93D7	0x6C8C	#CJK UNIFIED IDEOGRAPH+0x93D8	0x8C5A	#CJK UNIFIED IDEOGRAPH+0x93D9	0x9041	#CJK UNIFIED IDEOGRAPH+0x93DA	0x9813	#CJK UNIFIED IDEOGRAPH+0x93DB	0x5451	#CJK UNIFIED IDEOGRAPH+0x93DC	0x66C7	#CJK UNIFIED IDEOGRAPH+0x93DD	0x920D	#CJK UNIFIED IDEOGRAPH+0x93DE	0x5948	#CJK UNIFIED IDEOGRAPH+0x93DF	0x90A3	#CJK UNIFIED IDEOGRAPH+0x93E0	0x5185	#CJK UNIFIED IDEOGRAPH+0x93E1	0x4E4D	#CJK UNIFIED IDEOGRAPH+0x93E2	0x51EA	#CJK UNIFIED IDEOGRAPH+0x93E3	0x8599	#CJK UNIFIED IDEOGRAPH+0x93E4	0x8B0E	#CJK UNIFIED IDEOGRAPH+0x93E5	0x7058	#CJK UNIFIED IDEOGRAPH+0x93E6	0x637A	#CJK UNIFIED IDEOGRAPH+0x93E7	0x934B	#CJK UNIFIED IDEOGRAPH+0x93E8	0x6962	#CJK UNIFIED IDEOGRAPH+0x93E9	0x99B4	#CJK UNIFIED IDEOGRAPH+0x93EA	0x7E04	#CJK UNIFIED IDEOGRAPH+0x93EB	0x7577	#CJK UNIFIED IDEOGRAPH+0x93EC	0x5357	#CJK UNIFIED IDEOGRAPH+0x93ED	0x6960	#CJK UNIFIED IDEOGRAPH+0x93EE	0x8EDF	#CJK UNIFIED IDEOGRAPH+0x93EF	0x96E3	#CJK UNIFIED IDEOGRAPH+0x93F0	0x6C5D	#CJK UNIFIED IDEOGRAPH+0x93F1	0x4E8C	#CJK UNIFIED IDEOGRAPH+0x93F2	0x5C3C	#CJK UNIFIED IDEOGRAPH+0x93F3	0x5F10	#CJK UNIFIED IDEOGRAPH+0x93F4	0x8FE9	#CJK UNIFIED IDEOGRAPH+0x93F5	0x5302	#CJK UNIFIED IDEOGRAPH+0x93F6	0x8CD1	#CJK UNIFIED IDEOGRAPH+0x93F7	0x8089	#CJK UNIFIED IDEOGRAPH+0x93F8	0x8679	#CJK UNIFIED IDEOGRAPH+0x93F9	0x5EFF	#CJK UNIFIED IDEOGRAPH+0x93FA	0x65E5	#CJK UNIFIED IDEOGRAPH+0x93FB	0x4E73	#CJK UNIFIED IDEOGRAPH+0x93FC	0x5165	#CJK UNIFIED IDEOGRAPH+0x9440	0x5982	#CJK UNIFIED IDEOGRAPH+0x9441	0x5C3F	#CJK UNIFIED IDEOGRAPH+0x9442	0x97EE	#CJK UNIFIED IDEOGRAPH+0x9443	0x4EFB	#CJK UNIFIED IDEOGRAPH+0x9444	0x598A	#CJK UNIFIED IDEOGRAPH+0x9445	0x5FCD	#CJK UNIFIED IDEOGRAPH+0x9446	0x8A8D	#CJK UNIFIED IDEOGRAPH+0x9447	0x6FE1	#CJK UNIFIED IDEOGRAPH+0x9448	0x79B0	#CJK UNIFIED IDEOGRAPH+0x9449	0x7962	#CJK UNIFIED IDEOGRAPH+0x944A	0x5BE7	#CJK UNIFIED IDEOGRAPH+0x944B	0x8471	#CJK UNIFIED IDEOGRAPH+0x944C	0x732B	#CJK UNIFIED IDEOGRAPH+0x944D	0x71B1	#CJK UNIFIED IDEOGRAPH+0x944E	0x5E74	#CJK UNIFIED IDEOGRAPH+0x944F	0x5FF5	#CJK UNIFIED IDEOGRAPH+0x9450	0x637B	#CJK UNIFIED IDEOGRAPH+0x9451	0x649A	#CJK UNIFIED IDEOGRAPH+0x9452	0x71C3	#CJK UNIFIED IDEOGRAPH+0x9453	0x7C98	#CJK UNIFIED IDEOGRAPH+0x9454	0x4E43	#CJK UNIFIED IDEOGRAPH+0x9455	0x5EFC	#CJK UNIFIED IDEOGRAPH+0x9456	0x4E4B	#CJK UNIFIED IDEOGRAPH+0x9457	0x57DC	#CJK UNIFIED IDEOGRAPH+0x9458	0x56A2	#CJK UNIFIED IDEOGRAPH+0x9459	0x60A9	#CJK UNIFIED IDEOGRAPH+0x945A	0x6FC3	#CJK UNIFIED IDEOGRAPH+0x945B	0x7D0D	#CJK UNIFIED IDEOGRAPH+0x945C	0x80FD	#CJK UNIFIED IDEOGRAPH+0x945D	0x8133	#CJK UNIFIED IDEOGRAPH+0x945E	0x81BF	#CJK UNIFIED IDEOGRAPH+0x945F	0x8FB2	#CJK UNIFIED IDEOGRAPH+0x9460	0x8997	#CJK UNIFIED IDEOGRAPH+0x9461	0x86A4	#CJK UNIFIED IDEOGRAPH+0x9462	0x5DF4	#CJK UNIFIED IDEOGRAPH+0x9463	0x628A	#CJK UNIFIED IDEOGRAPH+0x9464	0x64AD	#CJK UNIFIED IDEOGRAPH+0x9465	0x8987	#CJK UNIFIED IDEOGRAPH+0x9466	0x6777	#CJK UNIFIED IDEOGRAPH+0x9467	0x6CE2	#CJK UNIFIED IDEOGRAPH+0x9468	0x6D3E	#CJK UNIFIED IDEOGRAPH+0x9469	0x7436	#CJK UNIFIED IDEOGRAPH+0x946A	0x7834	#CJK UNIFIED IDEOGRAPH+0x946B	0x5A46	#CJK UNIFIED IDEOGRAPH+0x946C	0x7F75	#CJK UNIFIED IDEOGRAPH+0x946D	0x82AD	#CJK UNIFIED IDEOGRAPH+0x946E	0x99AC	#CJK UNIFIED IDEOGRAPH+0x946F	0x4FF3	#CJK UNIFIED IDEOGRAPH+0x9470	0x5EC3	#CJK UNIFIED IDEOGRAPH+0x9471	0x62DD	#CJK UNIFIED IDEOGRAPH+0x9472	0x6392	#CJK UNIFIED IDEOGRAPH+0x9473	0x6557	#CJK UNIFIED IDEOGRAPH+0x9474	0x676F	#CJK UNIFIED IDEOGRAPH+0x9475	0x76C3	#CJK UNIFIED IDEOGRAPH+0x9476	0x724C	#CJK UNIFIED IDEOGRAPH+0x9477	0x80CC	#CJK UNIFIED IDEOGRAPH+0x9478	0x80BA	#CJK UNIFIED IDEOGRAPH+0x9479	0x8F29	#CJK UNIFIED IDEOGRAPH+0x947A	0x914D	#CJK UNIFIED IDEOGRAPH+0x947B	0x500D	#CJK UNIFIED IDEOGRAPH+0x947C	0x57F9	#CJK UNIFIED IDEOGRAPH+0x947D	0x5A92	#CJK UNIFIED IDEOGRAPH+0x947E	0x6885	#CJK UNIFIED IDEOGRAPH+0x9480	0x6973	#CJK UNIFIED IDEOGRAPH+0x9481	0x7164	#CJK UNIFIED IDEOGRAPH+0x9482	0x72FD	#CJK UNIFIED IDEOGRAPH+0x9483	0x8CB7	#CJK UNIFIED IDEOGRAPH+0x9484	0x58F2	#CJK UNIFIED IDEOGRAPH+0x9485	0x8CE0	#CJK UNIFIED IDEOGRAPH+0x9486	0x966A	#CJK UNIFIED IDEOGRAPH+0x9487	0x9019	#CJK UNIFIED IDEOGRAPH+0x9488	0x877F	#CJK UNIFIED IDEOGRAPH+0x9489	0x79E4	#CJK UNIFIED IDEOGRAPH+0x948A	0x77E7	#CJK UNIFIED IDEOGRAPH+0x948B	0x8429	#CJK UNIFIED IDEOGRAPH+0x948C	0x4F2F	#CJK UNIFIED IDEOGRAPH+0x948D	0x5265	#CJK UNIFIED IDEOGRAPH+0x948E	0x535A	#CJK UNIFIED IDEOGRAPH+0x948F	0x62CD	#CJK UNIFIED IDEOGRAPH+0x9490	0x67CF	#CJK UNIFIED IDEOGRAPH+0x9491	0x6CCA	#CJK UNIFIED IDEOGRAPH+0x9492	0x767D	#CJK UNIFIED IDEOGRAPH+0x9493	0x7B94	#CJK UNIFIED IDEOGRAPH+0x9494	0x7C95	#CJK UNIFIED IDEOGRAPH+0x9495	0x8236	#CJK UNIFIED IDEOGRAPH+0x9496	0x8584	#CJK UNIFIED IDEOGRAPH+0x9497	0x8FEB	#CJK UNIFIED IDEOGRAPH+0x9498	0x66DD	#CJK UNIFIED IDEOGRAPH+0x9499	0x6F20	#CJK UNIFIED IDEOGRAPH+0x949A	0x7206	#CJK UNIFIED IDEOGRAPH+0x949B	0x7E1B	#CJK UNIFIED IDEOGRAPH+0x949C	0x83AB	#CJK UNIFIED IDEOGRAPH+0x949D	0x99C1	#CJK UNIFIED IDEOGRAPH+0x949E	0x9EA6	#CJK UNIFIED IDEOGRAPH+0x949F	0x51FD	#CJK UNIFIED IDEOGRAPH+0x94A0	0x7BB1	#CJK UNIFIED IDEOGRAPH+0x94A1	0x7872	#CJK UNIFIED IDEOGRAPH+0x94A2	0x7BB8	#CJK UNIFIED IDEOGRAPH+0x94A3	0x8087	#CJK UNIFIED IDEOGRAPH+0x94A4	0x7B48	#CJK UNIFIED IDEOGRAPH+0x94A5	0x6AE8	#CJK UNIFIED IDEOGRAPH+0x94A6	0x5E61	#CJK UNIFIED IDEOGRAPH+0x94A7	0x808C	#CJK UNIFIED IDEOGRAPH+0x94A8	0x7551	#CJK UNIFIED IDEOGRAPH+0x94A9	0x7560	#CJK UNIFIED IDEOGRAPH+0x94AA	0x516B	#CJK UNIFIED IDEOGRAPH+0x94AB	0x9262	#CJK UNIFIED IDEOGRAPH+0x94AC	0x6E8C	#CJK UNIFIED IDEOGRAPH+0x94AD	0x767A	#CJK UNIFIED IDEOGRAPH+0x94AE	0x9197	#CJK UNIFIED IDEOGRAPH+0x94AF	0x9AEA	#CJK UNIFIED IDEOGRAPH+0x94B0	0x4F10	#CJK UNIFIED IDEOGRAPH+0x94B1	0x7F70	#CJK UNIFIED IDEOGRAPH+0x94B2	0x629C	#CJK UNIFIED IDEOGRAPH+0x94B3	0x7B4F	#CJK UNIFIED IDEOGRAPH+0x94B4	0x95A5	#CJK UNIFIED IDEOGRAPH+0x94B5	0x9CE9	#CJK UNIFIED IDEOGRAPH+0x94B6	0x567A	#CJK UNIFIED IDEOGRAPH+0x94B7	0x5859	#CJK UNIFIED IDEOGRAPH+0x94B8	0x86E4	#CJK UNIFIED IDEOGRAPH+0x94B9	0x96BC	#CJK UNIFIED IDEOGRAPH+0x94BA	0x4F34	#CJK UNIFIED IDEOGRAPH+0x94BB	0x5224	#CJK UNIFIED IDEOGRAPH+0x94BC	0x534A	#CJK UNIFIED IDEOGRAPH+0x94BD	0x53CD	#CJK UNIFIED IDEOGRAPH+0x94BE	0x53DB	#CJK UNIFIED IDEOGRAPH+0x94BF	0x5E06	#CJK UNIFIED IDEOGRAPH+0x94C0	0x642C	#CJK UNIFIED IDEOGRAPH+0x94C1	0x6591	#CJK UNIFIED IDEOGRAPH+0x94C2	0x677F	#CJK UNIFIED IDEOGRAPH+0x94C3	0x6C3E	#CJK UNIFIED IDEOGRAPH+0x94C4	0x6C4E	#CJK UNIFIED IDEOGRAPH+0x94C5	0x7248	#CJK UNIFIED IDEOGRAPH+0x94C6	0x72AF	#CJK UNIFIED IDEOGRAPH+0x94C7	0x73ED	#CJK UNIFIED IDEOGRAPH+0x94C8	0x7554	#CJK UNIFIED IDEOGRAPH+0x94C9	0x7E41	#CJK UNIFIED IDEOGRAPH+0x94CA	0x822C	#CJK UNIFIED IDEOGRAPH+0x94CB	0x85E9	#CJK UNIFIED IDEOGRAPH+0x94CC	0x8CA9	#CJK UNIFIED IDEOGRAPH+0x94CD	0x7BC4	#CJK UNIFIED IDEOGRAPH+0x94CE	0x91C6	#CJK UNIFIED IDEOGRAPH+0x94CF	0x7169	#CJK UNIFIED IDEOGRAPH+0x94D0	0x9812	#CJK UNIFIED IDEOGRAPH+0x94D1	0x98EF	#CJK UNIFIED IDEOGRAPH+0x94D2	0x633D	#CJK UNIFIED IDEOGRAPH+0x94D3	0x6669	#CJK UNIFIED IDEOGRAPH+0x94D4	0x756A	#CJK UNIFIED IDEOGRAPH+0x94D5	0x76E4	#CJK UNIFIED IDEOGRAPH+0x94D6	0x78D0	#CJK UNIFIED IDEOGRAPH+0x94D7	0x8543	#CJK UNIFIED IDEOGRAPH+0x94D8	0x86EE	#CJK UNIFIED IDEOGRAPH+0x94D9	0x532A	#CJK UNIFIED IDEOGRAPH+0x94DA	0x5351	#CJK UNIFIED IDEOGRAPH+0x94DB	0x5426	#CJK UNIFIED IDEOGRAPH+0x94DC	0x5983	#CJK UNIFIED IDEOGRAPH+0x94DD	0x5E87	#CJK UNIFIED IDEOGRAPH+0x94DE	0x5F7C	#CJK UNIFIED IDEOGRAPH+0x94DF	0x60B2	#CJK UNIFIED IDEOGRAPH+0x94E0	0x6249	#CJK UNIFIED IDEOGRAPH+0x94E1	0x6279	#CJK UNIFIED IDEOGRAPH+0x94E2	0x62AB	#CJK UNIFIED IDEOGRAPH+0x94E3	0x6590	#CJK UNIFIED IDEOGRAPH+0x94E4	0x6BD4	#CJK UNIFIED IDEOGRAPH+0x94E5	0x6CCC	#CJK UNIFIED IDEOGRAPH+0x94E6	0x75B2	#CJK UNIFIED IDEOGRAPH+0x94E7	0x76AE	#CJK UNIFIED IDEOGRAPH+0x94E8	0x7891	#CJK UNIFIED IDEOGRAPH+0x94E9	0x79D8	#CJK UNIFIED IDEOGRAPH+0x94EA	0x7DCB	#CJK UNIFIED IDEOGRAPH+0x94EB	0x7F77	#CJK UNIFIED IDEOGRAPH+0x94EC	0x80A5	#CJK UNIFIED IDEOGRAPH+0x94ED	0x88AB	#CJK UNIFIED IDEOGRAPH+0x94EE	0x8AB9	#CJK UNIFIED IDEOGRAPH+0x94EF	0x8CBB	#CJK UNIFIED IDEOGRAPH+0x94F0	0x907F	#CJK UNIFIED IDEOGRAPH+0x94F1	0x975E	#CJK UNIFIED IDEOGRAPH+0x94F2	0x98DB	#CJK UNIFIED IDEOGRAPH+0x94F3	0x6A0B	#CJK UNIFIED IDEOGRAPH+0x94F4	0x7C38	#CJK UNIFIED IDEOGRAPH+0x94F5	0x5099	#CJK UNIFIED IDEOGRAPH+0x94F6	0x5C3E	#CJK UNIFIED IDEOGRAPH+0x94F7	0x5FAE	#CJK UNIFIED IDEOGRAPH+0x94F8	0x6787	#CJK UNIFIED IDEOGRAPH+0x94F9	0x6BD8	#CJK UNIFIED IDEOGRAPH+0x94FA	0x7435	#CJK UNIFIED IDEOGRAPH+0x94FB	0x7709	#CJK UNIFIED IDEOGRAPH+0x94FC	0x7F8E	#CJK UNIFIED IDEOGRAPH+0x9540	0x9F3B	#CJK UNIFIED IDEOGRAPH+0x9541	0x67CA	#CJK UNIFIED IDEOGRAPH+0x9542	0x7A17	#CJK UNIFIED IDEOGRAPH+0x9543	0x5339	#CJK UNIFIED IDEOGRAPH+0x9544	0x758B	#CJK UNIFIED IDEOGRAPH+0x9545	0x9AED	#CJK UNIFIED IDEOGRAPH+0x9546	0x5F66	#CJK UNIFIED IDEOGRAPH+0x9547	0x819D	#CJK UNIFIED IDEOGRAPH+0x9548	0x83F1	#CJK UNIFIED IDEOGRAPH+0x9549	0x8098	#CJK UNIFIED IDEOGRAPH+0x954A	0x5F3C	#CJK UNIFIED IDEOGRAPH+0x954B	0x5FC5	#CJK UNIFIED IDEOGRAPH+0x954C	0x7562	#CJK UNIFIED IDEOGRAPH+0x954D	0x7B46	#CJK UNIFIED IDEOGRAPH+0x954E	0x903C	#CJK UNIFIED IDEOGRAPH+0x954F	0x6867	#CJK UNIFIED IDEOGRAPH+0x9550	0x59EB	#CJK UNIFIED IDEOGRAPH+0x9551	0x5A9B	#CJK UNIFIED IDEOGRAPH+0x9552	0x7D10	#CJK UNIFIED IDEOGRAPH+0x9553	0x767E	#CJK UNIFIED IDEOGRAPH+0x9554	0x8B2C	#CJK UNIFIED IDEOGRAPH+0x9555	0x4FF5	#CJK UNIFIED IDEOGRAPH+0x9556	0x5F6A	#CJK UNIFIED IDEOGRAPH+0x9557	0x6A19	#CJK UNIFIED IDEOGRAPH+0x9558	0x6C37	#CJK UNIFIED IDEOGRAPH+0x9559	0x6F02	#CJK UNIFIED IDEOGRAPH+0x955A	0x74E2	#CJK UNIFIED IDEOGRAPH+0x955B	0x7968	#CJK UNIFIED IDEOGRAPH+0x955C	0x8868	#CJK UNIFIED IDEOGRAPH+0x955D	0x8A55	#CJK UNIFIED IDEOGRAPH+0x955E	0x8C79	#CJK UNIFIED IDEOGRAPH+0x955F	0x5EDF	#CJK UNIFIED IDEOGRAPH+0x9560	0x63CF	#CJK UNIFIED IDEOGRAPH+0x9561	0x75C5	#CJK UNIFIED IDEOGRAPH+0x9562	0x79D2	#CJK UNIFIED IDEOGRAPH+0x9563	0x82D7	#CJK UNIFIED IDEOGRAPH+0x9564	0x9328	#CJK UNIFIED IDEOGRAPH+0x9565	0x92F2	#CJK UNIFIED IDEOGRAPH+0x9566	0x849C	#CJK UNIFIED IDEOGRAPH+0x9567	0x86ED	#CJK UNIFIED IDEOGRAPH+0x9568	0x9C2D	#CJK UNIFIED IDEOGRAPH+0x9569	0x54C1	#CJK UNIFIED IDEOGRAPH+0x956A	0x5F6C	#CJK UNIFIED IDEOGRAPH+0x956B	0x658C	#CJK UNIFIED IDEOGRAPH+0x956C	0x6D5C	#CJK UNIFIED IDEOGRAPH+0x956D	0x7015	#CJK UNIFIED IDEOGRAPH+0x956E	0x8CA7	#CJK UNIFIED IDEOGRAPH+0x956F	0x8CD3	#CJK UNIFIED IDEOGRAPH+0x9570	0x983B	#CJK UNIFIED IDEOGRAPH+0x9571	0x654F	#CJK UNIFIED IDEOGRAPH+0x9572	0x74F6	#CJK UNIFIED IDEOGRAPH+0x9573	0x4E0D	#CJK UNIFIED IDEOGRAPH+0x9574	0x4ED8	#CJK UNIFIED IDEOGRAPH+0x9575	0x57E0	#CJK UNIFIED IDEOGRAPH+0x9576	0x592B	#CJK UNIFIED IDEOGRAPH+0x9577	0x5A66	#CJK UNIFIED IDEOGRAPH+0x9578	0x5BCC	#CJK UNIFIED IDEOGRAPH+0x9579	0x51A8	#CJK UNIFIED IDEOGRAPH+0x957A	0x5E03	#CJK UNIFIED IDEOGRAPH+0x957B	0x5E9C	#CJK UNIFIED IDEOGRAPH+0x957C	0x6016	#CJK UNIFIED IDEOGRAPH+0x957D	0x6276	#CJK UNIFIED IDEOGRAPH+0x957E	0x6577	#CJK UNIFIED IDEOGRAPH+0x9580	0x65A7	#CJK UNIFIED IDEOGRAPH+0x9581	0x666E	#CJK UNIFIED IDEOGRAPH+0x9582	0x6D6E	#CJK UNIFIED IDEOGRAPH+0x9583	0x7236	#CJK UNIFIED IDEOGRAPH+0x9584	0x7B26	#CJK UNIFIED IDEOGRAPH+0x9585	0x8150	#CJK UNIFIED IDEOGRAPH+0x9586	0x819A	#CJK UNIFIED IDEOGRAPH+0x9587	0x8299	#CJK UNIFIED IDEOGRAPH+0x9588	0x8B5C	#CJK UNIFIED IDEOGRAPH+0x9589	0x8CA0	#CJK UNIFIED IDEOGRAPH+0x958A	0x8CE6	#CJK UNIFIED IDEOGRAPH+0x958B	0x8D74	#CJK UNIFIED IDEOGRAPH+0x958C	0x961C	#CJK UNIFIED IDEOGRAPH+0x958D	0x9644	#CJK UNIFIED IDEOGRAPH+0x958E	0x4FAE	#CJK UNIFIED IDEOGRAPH+0x958F	0x64AB	#CJK UNIFIED IDEOGRAPH+0x9590	0x6B66	#CJK UNIFIED IDEOGRAPH+0x9591	0x821E	#CJK UNIFIED IDEOGRAPH+0x9592	0x8461	#CJK UNIFIED IDEOGRAPH+0x9593	0x856A	#CJK UNIFIED IDEOGRAPH+0x9594	0x90E8	#CJK UNIFIED IDEOGRAPH+0x9595	0x5C01	#CJK UNIFIED IDEOGRAPH+0x9596	0x6953	#CJK UNIFIED IDEOGRAPH+0x9597	0x98A8	#CJK UNIFIED IDEOGRAPH+0x9598	0x847A	#CJK UNIFIED IDEOGRAPH+0x9599	0x8557	#CJK UNIFIED IDEOGRAPH+0x959A	0x4F0F	#CJK UNIFIED IDEOGRAPH+0x959B	0x526F	#CJK UNIFIED IDEOGRAPH+0x959C	0x5FA9	#CJK UNIFIED IDEOGRAPH+0x959D	0x5E45	#CJK UNIFIED IDEOGRAPH+0x959E	0x670D	#CJK UNIFIED IDEOGRAPH+0x959F	0x798F	#CJK UNIFIED IDEOGRAPH+0x95A0	0x8179	#CJK UNIFIED IDEOGRAPH+0x95A1	0x8907	#CJK UNIFIED IDEOGRAPH+0x95A2	0x8986	#CJK UNIFIED IDEOGRAPH+0x95A3	0x6DF5	#CJK UNIFIED IDEOGRAPH+0x95A4	0x5F17	#CJK UNIFIED IDEOGRAPH+0x95A5	0x6255	#CJK UNIFIED IDEOGRAPH+0x95A6	0x6CB8	#CJK UNIFIED IDEOGRAPH+0x95A7	0x4ECF	#CJK UNIFIED IDEOGRAPH+0x95A8	0x7269	#CJK UNIFIED IDEOGRAPH+0x95A9	0x9B92	#CJK UNIFIED IDEOGRAPH+0x95AA	0x5206	#CJK UNIFIED IDEOGRAPH+0x95AB	0x543B	#CJK UNIFIED IDEOGRAPH+0x95AC	0x5674	#CJK UNIFIED IDEOGRAPH+0x95AD	0x58B3	#CJK UNIFIED IDEOGRAPH+0x95AE	0x61A4	#CJK UNIFIED IDEOGRAPH+0x95AF	0x626E	#CJK UNIFIED IDEOGRAPH+0x95B0	0x711A	#CJK UNIFIED IDEOGRAPH+0x95B1	0x596E	#CJK UNIFIED IDEOGRAPH+0x95B2	0x7C89	#CJK UNIFIED IDEOGRAPH+0x95B3	0x7CDE	#CJK UNIFIED IDEOGRAPH+0x95B4	0x7D1B	#CJK UNIFIED IDEOGRAPH+0x95B5	0x96F0	#CJK UNIFIED IDEOGRAPH+0x95B6	0x6587	#CJK UNIFIED IDEOGRAPH+0x95B7	0x805E	#CJK UNIFIED IDEOGRAPH+0x95B8	0x4E19	#CJK UNIFIED IDEOGRAPH+0x95B9	0x4F75	#CJK UNIFIED IDEOGRAPH+0x95BA	0x5175	#CJK UNIFIED IDEOGRAPH+0x95BB	0x5840	#CJK UNIFIED IDEOGRAPH+0x95BC	0x5E63	#CJK UNIFIED IDEOGRAPH+0x95BD	0x5E73	#CJK UNIFIED IDEOGRAPH+0x95BE	0x5F0A	#CJK UNIFIED IDEOGRAPH+0x95BF	0x67C4	#CJK UNIFIED IDEOGRAPH+0x95C0	0x4E26	#CJK UNIFIED IDEOGRAPH+0x95C1	0x853D	#CJK UNIFIED IDEOGRAPH+0x95C2	0x9589	#CJK UNIFIED IDEOGRAPH+0x95C3	0x965B	#CJK UNIFIED IDEOGRAPH+0x95C4	0x7C73	#CJK UNIFIED IDEOGRAPH+0x95C5	0x9801	#CJK UNIFIED IDEOGRAPH+0x95C6	0x50FB	#CJK UNIFIED IDEOGRAPH+0x95C7	0x58C1	#CJK UNIFIED IDEOGRAPH+0x95C8	0x7656	#CJK UNIFIED IDEOGRAPH+0x95C9	0x78A7	#CJK UNIFIED IDEOGRAPH+0x95CA	0x5225	#CJK UNIFIED IDEOGRAPH+0x95CB	0x77A5	#CJK UNIFIED IDEOGRAPH+0x95CC	0x8511	#CJK UNIFIED IDEOGRAPH+0x95CD	0x7B86	#CJK UNIFIED IDEOGRAPH+0x95CE	0x504F	#CJK UNIFIED IDEOGRAPH+0x95CF	0x5909	#CJK UNIFIED IDEOGRAPH+0x95D0	0x7247	#CJK UNIFIED IDEOGRAPH+0x95D1	0x7BC7	#CJK UNIFIED IDEOGRAPH+0x95D2	0x7DE8	#CJK UNIFIED IDEOGRAPH+0x95D3	0x8FBA	#CJK UNIFIED IDEOGRAPH+0x95D4	0x8FD4	#CJK UNIFIED IDEOGRAPH+0x95D5	0x904D	#CJK UNIFIED IDEOGRAPH+0x95D6	0x4FBF	#CJK UNIFIED IDEOGRAPH+0x95D7	0x52C9	#CJK UNIFIED IDEOGRAPH+0x95D8	0x5A29	#CJK UNIFIED IDEOGRAPH+0x95D9	0x5F01	#CJK UNIFIED IDEOGRAPH+0x95DA	0x97AD	#CJK UNIFIED IDEOGRAPH+0x95DB	0x4FDD	#CJK UNIFIED IDEOGRAPH+0x95DC	0x8217	#CJK UNIFIED IDEOGRAPH+0x95DD	0x92EA	#CJK UNIFIED IDEOGRAPH+0x95DE	0x5703	#CJK UNIFIED IDEOGRAPH+0x95DF	0x6355	#CJK UNIFIED IDEOGRAPH+0x95E0	0x6B69	#CJK UNIFIED IDEOGRAPH+0x95E1	0x752B	#CJK UNIFIED IDEOGRAPH+0x95E2	0x88DC	#CJK UNIFIED IDEOGRAPH+0x95E3	0x8F14	#CJK UNIFIED IDEOGRAPH+0x95E4	0x7A42	#CJK UNIFIED IDEOGRAPH+0x95E5	0x52DF	#CJK UNIFIED IDEOGRAPH+0x95E6	0x5893	#CJK UNIFIED IDEOGRAPH+0x95E7	0x6155	#CJK UNIFIED IDEOGRAPH+0x95E8	0x620A	#CJK UNIFIED IDEOGRAPH+0x95E9	0x66AE	#CJK UNIFIED IDEOGRAPH+0x95EA	0x6BCD	#CJK UNIFIED IDEOGRAPH+0x95EB	0x7C3F	#CJK UNIFIED IDEOGRAPH+0x95EC	0x83E9	#CJK UNIFIED IDEOGRAPH+0x95ED	0x5023	#CJK UNIFIED IDEOGRAPH+0x95EE	0x4FF8	#CJK UNIFIED IDEOGRAPH+0x95EF	0x5305	#CJK UNIFIED IDEOGRAPH+0x95F0	0x5446	#CJK UNIFIED IDEOGRAPH+0x95F1	0x5831	#CJK UNIFIED IDEOGRAPH+0x95F2	0x5949	#CJK UNIFIED IDEOGRAPH+0x95F3	0x5B9D	#CJK UNIFIED IDEOGRAPH+0x95F4	0x5CF0	#CJK UNIFIED IDEOGRAPH+0x95F5	0x5CEF	#CJK UNIFIED IDEOGRAPH+0x95F6	0x5D29	#CJK UNIFIED IDEOGRAPH+0x95F7	0x5E96	#CJK UNIFIED IDEOGRAPH+0x95F8	0x62B1	#CJK UNIFIED IDEOGRAPH+0x95F9	0x6367	#CJK UNIFIED IDEOGRAPH+0x95FA	0x653E	#CJK UNIFIED IDEOGRAPH+0x95FB	0x65B9	#CJK UNIFIED IDEOGRAPH+0x95FC	0x670B	#CJK UNIFIED IDEOGRAPH+0x9640	0x6CD5	#CJK UNIFIED IDEOGRAPH+0x9641	0x6CE1	#CJK UNIFIED IDEOGRAPH+0x9642	0x70F9	#CJK UNIFIED IDEOGRAPH+0x9643	0x7832	#CJK UNIFIED IDEOGRAPH+0x9644	0x7E2B	#CJK UNIFIED IDEOGRAPH+0x9645	0x80DE	#CJK UNIFIED IDEOGRAPH+0x9646	0x82B3	#CJK UNIFIED IDEOGRAPH+0x9647	0x840C	#CJK UNIFIED IDEOGRAPH+0x9648	0x84EC	#CJK UNIFIED IDEOGRAPH+0x9649	0x8702	#CJK UNIFIED IDEOGRAPH+0x964A	0x8912	#CJK UNIFIED IDEOGRAPH+0x964B	0x8A2A	#CJK UNIFIED IDEOGRAPH+0x964C	0x8C4A	#CJK UNIFIED IDEOGRAPH+0x964D	0x90A6	#CJK UNIFIED IDEOGRAPH+0x964E	0x92D2	#CJK UNIFIED IDEOGRAPH+0x964F	0x98FD	#CJK UNIFIED IDEOGRAPH+0x9650	0x9CF3	#CJK UNIFIED IDEOGRAPH+0x9651	0x9D6C	#CJK UNIFIED IDEOGRAPH+0x9652	0x4E4F	#CJK UNIFIED IDEOGRAPH+0x9653	0x4EA1	#CJK UNIFIED IDEOGRAPH+0x9654	0x508D	#CJK UNIFIED IDEOGRAPH+0x9655	0x5256	#CJK UNIFIED IDEOGRAPH+0x9656	0x574A	#CJK UNIFIED IDEOGRAPH+0x9657	0x59A8	#CJK UNIFIED IDEOGRAPH+0x9658	0x5E3D	#CJK UNIFIED IDEOGRAPH+0x9659	0x5FD8	#CJK UNIFIED IDEOGRAPH+0x965A	0x5FD9	#CJK UNIFIED IDEOGRAPH+0x965B	0x623F	#CJK UNIFIED IDEOGRAPH+0x965C	0x66B4	#CJK UNIFIED IDEOGRAPH+0x965D	0x671B	#CJK UNIFIED IDEOGRAPH+0x965E	0x67D0	#CJK UNIFIED IDEOGRAPH+0x965F	0x68D2	#CJK UNIFIED IDEOGRAPH+0x9660	0x5192	#CJK UNIFIED IDEOGRAPH+0x9661	0x7D21	#CJK UNIFIED IDEOGRAPH+0x9662	0x80AA	#CJK UNIFIED IDEOGRAPH+0x9663	0x81A8	#CJK UNIFIED IDEOGRAPH+0x9664	0x8B00	#CJK UNIFIED IDEOGRAPH+0x9665	0x8C8C	#CJK UNIFIED IDEOGRAPH+0x9666	0x8CBF	#CJK UNIFIED IDEOGRAPH+0x9667	0x927E	#CJK UNIFIED IDEOGRAPH+0x9668	0x9632	#CJK UNIFIED IDEOGRAPH+0x9669	0x5420	#CJK UNIFIED IDEOGRAPH+0x966A	0x982C	#CJK UNIFIED IDEOGRAPH+0x966B	0x5317	#CJK UNIFIED IDEOGRAPH+0x966C	0x50D5	#CJK UNIFIED IDEOGRAPH+0x966D	0x535C	#CJK UNIFIED IDEOGRAPH+0x966E	0x58A8	#CJK UNIFIED IDEOGRAPH+0x966F	0x64B2	#CJK UNIFIED IDEOGRAPH+0x9670	0x6734	#CJK UNIFIED IDEOGRAPH+0x9671	0x7267	#CJK UNIFIED IDEOGRAPH+0x9672	0x7766	#CJK UNIFIED IDEOGRAPH+0x9673	0x7A46	#CJK UNIFIED IDEOGRAPH+0x9674	0x91E6	#CJK UNIFIED IDEOGRAPH+0x9675	0x52C3	#CJK UNIFIED IDEOGRAPH+0x9676	0x6CA1	#CJK UNIFIED IDEOGRAPH+0x9677	0x6B86	#CJK UNIFIED IDEOGRAPH+0x9678	0x5800	#CJK UNIFIED IDEOGRAPH+0x9679	0x5E4C	#CJK UNIFIED IDEOGRAPH+0x967A	0x5954	#CJK UNIFIED IDEOGRAPH+0x967B	0x672C	#CJK UNIFIED IDEOGRAPH+0x967C	0x7FFB	#CJK UNIFIED IDEOGRAPH+0x967D	0x51E1	#CJK UNIFIED IDEOGRAPH+0x967E	0x76C6	#CJK UNIFIED IDEOGRAPH+0x9680	0x6469	#CJK UNIFIED IDEOGRAPH+0x9681	0x78E8	#CJK UNIFIED IDEOGRAPH+0x9682	0x9B54	#CJK UNIFIED IDEOGRAPH+0x9683	0x9EBB	#CJK UNIFIED IDEOGRAPH+0x9684	0x57CB	#CJK UNIFIED IDEOGRAPH+0x9685	0x59B9	#CJK UNIFIED IDEOGRAPH+0x9686	0x6627	#CJK UNIFIED IDEOGRAPH+0x9687	0x679A	#CJK UNIFIED IDEOGRAPH+0x9688	0x6BCE	#CJK UNIFIED IDEOGRAPH+0x9689	0x54E9	#CJK UNIFIED IDEOGRAPH+0x968A	0x69D9	#CJK UNIFIED IDEOGRAPH+0x968B	0x5E55	#CJK UNIFIED IDEOGRAPH+0x968C	0x819C	#CJK UNIFIED IDEOGRAPH+0x968D	0x6795	#CJK UNIFIED IDEOGRAPH+0x968E	0x9BAA	#CJK UNIFIED IDEOGRAPH+0x968F	0x67FE	#CJK UNIFIED IDEOGRAPH+0x9690	0x9C52	#CJK UNIFIED IDEOGRAPH+0x9691	0x685D	#CJK UNIFIED IDEOGRAPH+0x9692	0x4EA6	#CJK UNIFIED IDEOGRAPH+0x9693	0x4FE3	#CJK UNIFIED IDEOGRAPH+0x9694	0x53C8	#CJK UNIFIED IDEOGRAPH+0x9695	0x62B9	#CJK UNIFIED IDEOGRAPH+0x9696	0x672B	#CJK UNIFIED IDEOGRAPH+0x9697	0x6CAB	#CJK UNIFIED IDEOGRAPH+0x9698	0x8FC4	#CJK UNIFIED IDEOGRAPH+0x9699	0x4FAD	#CJK UNIFIED IDEOGRAPH+0x969A	0x7E6D	#CJK UNIFIED IDEOGRAPH+0x969B	0x9EBF	#CJK UNIFIED IDEOGRAPH+0x969C	0x4E07	#CJK UNIFIED IDEOGRAPH+0x969D	0x6162	#CJK UNIFIED IDEOGRAPH+0x969E	0x6E80	#CJK UNIFIED IDEOGRAPH+0x969F	0x6F2B	#CJK UNIFIED IDEOGRAPH+0x96A0	0x8513	#CJK UNIFIED IDEOGRAPH+0x96A1	0x5473	#CJK UNIFIED IDEOGRAPH+0x96A2	0x672A	#CJK UNIFIED IDEOGRAPH+0x96A3	0x9B45	#CJK UNIFIED IDEOGRAPH+0x96A4	0x5DF3	#CJK UNIFIED IDEOGRAPH+0x96A5	0x7B95	#CJK UNIFIED IDEOGRAPH+0x96A6	0x5CAC	#CJK UNIFIED IDEOGRAPH+0x96A7	0x5BC6	#CJK UNIFIED IDEOGRAPH+0x96A8	0x871C	#CJK UNIFIED IDEOGRAPH+0x96A9	0x6E4A	#CJK UNIFIED IDEOGRAPH+0x96AA	0x84D1	#CJK UNIFIED IDEOGRAPH+0x96AB	0x7A14	#CJK UNIFIED IDEOGRAPH+0x96AC	0x8108	#CJK UNIFIED IDEOGRAPH+0x96AD	0x5999	#CJK UNIFIED IDEOGRAPH+0x96AE	0x7C8D	#CJK UNIFIED IDEOGRAPH+0x96AF	0x6C11	#CJK UNIFIED IDEOGRAPH+0x96B0	0x7720	#CJK UNIFIED IDEOGRAPH+0x96B1	0x52D9	#CJK UNIFIED IDEOGRAPH+0x96B2	0x5922	#CJK UNIFIED IDEOGRAPH+0x96B3	0x7121	#CJK UNIFIED IDEOGRAPH+0x96B4	0x725F	#CJK UNIFIED IDEOGRAPH+0x96B5	0x77DB	#CJK UNIFIED IDEOGRAPH+0x96B6	0x9727	#CJK UNIFIED IDEOGRAPH+0x96B7	0x9D61	#CJK UNIFIED IDEOGRAPH+0x96B8	0x690B	#CJK UNIFIED IDEOGRAPH+0x96B9	0x5A7F	#CJK UNIFIED IDEOGRAPH+0x96BA	0x5A18	#CJK UNIFIED IDEOGRAPH+0x96BB	0x51A5	#CJK UNIFIED IDEOGRAPH+0x96BC	0x540D	#CJK UNIFIED IDEOGRAPH+0x96BD	0x547D	#CJK UNIFIED IDEOGRAPH+0x96BE	0x660E	#CJK UNIFIED IDEOGRAPH+0x96BF	0x76DF	#CJK UNIFIED IDEOGRAPH+0x96C0	0x8FF7	#CJK UNIFIED IDEOGRAPH+0x96C1	0x9298	#CJK UNIFIED IDEOGRAPH+0x96C2	0x9CF4	#CJK UNIFIED IDEOGRAPH+0x96C3	0x59EA	#CJK UNIFIED IDEOGRAPH+0x96C4	0x725D	#CJK UNIFIED IDEOGRAPH+0x96C5	0x6EC5	#CJK UNIFIED IDEOGRAPH+0x96C6	0x514D	#CJK UNIFIED IDEOGRAPH+0x96C7	0x68C9	#CJK UNIFIED IDEOGRAPH+0x96C8	0x7DBF	#CJK UNIFIED IDEOGRAPH+0x96C9	0x7DEC	#CJK UNIFIED IDEOGRAPH+0x96CA	0x9762	#CJK UNIFIED IDEOGRAPH+0x96CB	0x9EBA	#CJK UNIFIED IDEOGRAPH+0x96CC	0x6478	#CJK UNIFIED IDEOGRAPH+0x96CD	0x6A21	#CJK UNIFIED IDEOGRAPH+0x96CE	0x8302	#CJK UNIFIED IDEOGRAPH+0x96CF	0x5984	#CJK UNIFIED IDEOGRAPH+0x96D0	0x5B5F	#CJK UNIFIED IDEOGRAPH+0x96D1	0x6BDB	#CJK UNIFIED IDEOGRAPH+0x96D2	0x731B	#CJK UNIFIED IDEOGRAPH+0x96D3	0x76F2	#CJK UNIFIED IDEOGRAPH+0x96D4	0x7DB2	#CJK UNIFIED IDEOGRAPH+0x96D5	0x8017	#CJK UNIFIED IDEOGRAPH+0x96D6	0x8499	#CJK UNIFIED IDEOGRAPH+0x96D7	0x5132	#CJK UNIFIED IDEOGRAPH+0x96D8	0x6728	#CJK UNIFIED IDEOGRAPH+0x96D9	0x9ED9	#CJK UNIFIED IDEOGRAPH+0x96DA	0x76EE	#CJK UNIFIED IDEOGRAPH+0x96DB	0x6762	#CJK UNIFIED IDEOGRAPH+0x96DC	0x52FF	#CJK UNIFIED IDEOGRAPH+0x96DD	0x9905	#CJK UNIFIED IDEOGRAPH+0x96DE	0x5C24	#CJK UNIFIED IDEOGRAPH+0x96DF	0x623B	#CJK UNIFIED IDEOGRAPH+0x96E0	0x7C7E	#CJK UNIFIED IDEOGRAPH+0x96E1	0x8CB0	#CJK UNIFIED IDEOGRAPH+0x96E2	0x554F	#CJK UNIFIED IDEOGRAPH+0x96E3	0x60B6	#CJK UNIFIED IDEOGRAPH+0x96E4	0x7D0B	#CJK UNIFIED IDEOGRAPH+0x96E5	0x9580	#CJK UNIFIED IDEOGRAPH+0x96E6	0x5301	#CJK UNIFIED IDEOGRAPH+0x96E7	0x4E5F	#CJK UNIFIED IDEOGRAPH+0x96E8	0x51B6	#CJK UNIFIED IDEOGRAPH+0x96E9	0x591C	#CJK UNIFIED IDEOGRAPH+0x96EA	0x723A	#CJK UNIFIED IDEOGRAPH+0x96EB	0x8036	#CJK UNIFIED IDEOGRAPH+0x96EC	0x91CE	#CJK UNIFIED IDEOGRAPH+0x96ED	0x5F25	#CJK UNIFIED IDEOGRAPH+0x96EE	0x77E2	#CJK UNIFIED IDEOGRAPH+0x96EF	0x5384	#CJK UNIFIED IDEOGRAPH+0x96F0	0x5F79	#CJK UNIFIED IDEOGRAPH+0x96F1	0x7D04	#CJK UNIFIED IDEOGRAPH+0x96F2	0x85AC	#CJK UNIFIED IDEOGRAPH+0x96F3	0x8A33	#CJK UNIFIED IDEOGRAPH+0x96F4	0x8E8D	#CJK UNIFIED IDEOGRAPH+0x96F5	0x9756	#CJK UNIFIED IDEOGRAPH+0x96F6	0x67F3	#CJK UNIFIED IDEOGRAPH+0x96F7	0x85AE	#CJK UNIFIED IDEOGRAPH+0x96F8	0x9453	#CJK UNIFIED IDEOGRAPH+0x96F9	0x6109	#CJK UNIFIED IDEOGRAPH+0x96FA	0x6108	#CJK UNIFIED IDEOGRAPH+0x96FB	0x6CB9	#CJK UNIFIED IDEOGRAPH+0x96FC	0x7652	#CJK UNIFIED IDEOGRAPH+0x9740	0x8AED	#CJK UNIFIED IDEOGRAPH+0x9741	0x8F38	#CJK UNIFIED IDEOGRAPH+0x9742	0x552F	#CJK UNIFIED IDEOGRAPH+0x9743	0x4F51	#CJK UNIFIED IDEOGRAPH+0x9744	0x512A	#CJK UNIFIED IDEOGRAPH+0x9745	0x52C7	#CJK UNIFIED IDEOGRAPH+0x9746	0x53CB	#CJK UNIFIED IDEOGRAPH+0x9747	0x5BA5	#CJK UNIFIED IDEOGRAPH+0x9748	0x5E7D	#CJK UNIFIED IDEOGRAPH+0x9749	0x60A0	#CJK UNIFIED IDEOGRAPH+0x974A	0x6182	#CJK UNIFIED IDEOGRAPH+0x974B	0x63D6	#CJK UNIFIED IDEOGRAPH+0x974C	0x6709	#CJK UNIFIED IDEOGRAPH+0x974D	0x67DA	#CJK UNIFIED IDEOGRAPH+0x974E	0x6E67	#CJK UNIFIED IDEOGRAPH+0x974F	0x6D8C	#CJK UNIFIED IDEOGRAPH+0x9750	0x7336	#CJK UNIFIED IDEOGRAPH+0x9751	0x7337	#CJK UNIFIED IDEOGRAPH+0x9752	0x7531	#CJK UNIFIED IDEOGRAPH+0x9753	0x7950	#CJK UNIFIED IDEOGRAPH+0x9754	0x88D5	#CJK UNIFIED IDEOGRAPH+0x9755	0x8A98	#CJK UNIFIED IDEOGRAPH+0x9756	0x904A	#CJK UNIFIED IDEOGRAPH+0x9757	0x9091	#CJK UNIFIED IDEOGRAPH+0x9758	0x90F5	#CJK UNIFIED IDEOGRAPH+0x9759	0x96C4	#CJK UNIFIED IDEOGRAPH+0x975A	0x878D	#CJK UNIFIED IDEOGRAPH+0x975B	0x5915	#CJK UNIFIED IDEOGRAPH+0x975C	0x4E88	#CJK UNIFIED IDEOGRAPH+0x975D	0x4F59	#CJK UNIFIED IDEOGRAPH+0x975E	0x4E0E	#CJK UNIFIED IDEOGRAPH+0x975F	0x8A89	#CJK UNIFIED IDEOGRAPH+0x9760	0x8F3F	#CJK UNIFIED IDEOGRAPH+0x9761	0x9810	#CJK UNIFIED IDEOGRAPH+0x9762	0x50AD	#CJK UNIFIED IDEOGRAPH+0x9763	0x5E7C	#CJK UNIFIED IDEOGRAPH+0x9764	0x5996	#CJK UNIFIED IDEOGRAPH+0x9765	0x5BB9	#CJK UNIFIED IDEOGRAPH+0x9766	0x5EB8	#CJK UNIFIED IDEOGRAPH+0x9767	0x63DA	#CJK UNIFIED IDEOGRAPH+0x9768	0x63FA	#CJK UNIFIED IDEOGRAPH+0x9769	0x64C1	#CJK UNIFIED IDEOGRAPH+0x976A	0x66DC	#CJK UNIFIED IDEOGRAPH+0x976B	0x694A	#CJK UNIFIED IDEOGRAPH+0x976C	0x69D8	#CJK UNIFIED IDEOGRAPH+0x976D	0x6D0B	#CJK UNIFIED IDEOGRAPH+0x976E	0x6EB6	#CJK UNIFIED IDEOGRAPH+0x976F	0x7194	#CJK UNIFIED IDEOGRAPH+0x9770	0x7528	#CJK UNIFIED IDEOGRAPH+0x9771	0x7AAF	#CJK UNIFIED IDEOGRAPH+0x9772	0x7F8A	#CJK UNIFIED IDEOGRAPH+0x9773	0x8000	#CJK UNIFIED IDEOGRAPH+0x9774	0x8449	#CJK UNIFIED IDEOGRAPH+0x9775	0x84C9	#CJK UNIFIED IDEOGRAPH+0x9776	0x8981	#CJK UNIFIED IDEOGRAPH+0x9777	0x8B21	#CJK UNIFIED IDEOGRAPH+0x9778	0x8E0A	#CJK UNIFIED IDEOGRAPH+0x9779	0x9065	#CJK UNIFIED IDEOGRAPH+0x977A	0x967D	#CJK UNIFIED IDEOGRAPH+0x977B	0x990A	#CJK UNIFIED IDEOGRAPH+0x977C	0x617E	#CJK UNIFIED IDEOGRAPH+0x977D	0x6291	#CJK UNIFIED IDEOGRAPH+0x977E	0x6B32	#CJK UNIFIED IDEOGRAPH+0x9780	0x6C83	#CJK UNIFIED IDEOGRAPH+0x9781	0x6D74	#CJK UNIFIED IDEOGRAPH+0x9782	0x7FCC	#CJK UNIFIED IDEOGRAPH+0x9783	0x7FFC	#CJK UNIFIED IDEOGRAPH+0x9784	0x6DC0	#CJK UNIFIED IDEOGRAPH+0x9785	0x7F85	#CJK UNIFIED IDEOGRAPH+0x9786	0x87BA	#CJK UNIFIED IDEOGRAPH+0x9787	0x88F8	#CJK UNIFIED IDEOGRAPH+0x9788	0x6765	#CJK UNIFIED IDEOGRAPH+0x9789	0x83B1	#CJK UNIFIED IDEOGRAPH+0x978A	0x983C	#CJK UNIFIED IDEOGRAPH+0x978B	0x96F7	#CJK UNIFIED IDEOGRAPH+0x978C	0x6D1B	#CJK UNIFIED IDEOGRAPH+0x978D	0x7D61	#CJK UNIFIED IDEOGRAPH+0x978E	0x843D	#CJK UNIFIED IDEOGRAPH+0x978F	0x916A	#CJK UNIFIED IDEOGRAPH+0x9790	0x4E71	#CJK UNIFIED IDEOGRAPH+0x9791	0x5375	#CJK UNIFIED IDEOGRAPH+0x9792	0x5D50	#CJK UNIFIED IDEOGRAPH+0x9793	0x6B04	#CJK UNIFIED IDEOGRAPH+0x9794	0x6FEB	#CJK UNIFIED IDEOGRAPH+0x9795	0x85CD	#CJK UNIFIED IDEOGRAPH+0x9796	0x862D	#CJK UNIFIED IDEOGRAPH+0x9797	0x89A7	#CJK UNIFIED IDEOGRAPH+0x9798	0x5229	#CJK UNIFIED IDEOGRAPH+0x9799	0x540F	#CJK UNIFIED IDEOGRAPH+0x979A	0x5C65	#CJK UNIFIED IDEOGRAPH+0x979B	0x674E	#CJK UNIFIED IDEOGRAPH+0x979C	0x68A8	#CJK UNIFIED IDEOGRAPH+0x979D	0x7406	#CJK UNIFIED IDEOGRAPH+0x979E	0x7483	#CJK UNIFIED IDEOGRAPH+0x979F	0x75E2	#CJK UNIFIED IDEOGRAPH+0x97A0	0x88CF	#CJK UNIFIED IDEOGRAPH+0x97A1	0x88E1	#CJK UNIFIED IDEOGRAPH+0x97A2	0x91CC	#CJK UNIFIED IDEOGRAPH+0x97A3	0x96E2	#CJK UNIFIED IDEOGRAPH+0x97A4	0x9678	#CJK UNIFIED IDEOGRAPH+0x97A5	0x5F8B	#CJK UNIFIED IDEOGRAPH+0x97A6	0x7387	#CJK UNIFIED IDEOGRAPH+0x97A7	0x7ACB	#CJK UNIFIED IDEOGRAPH+0x97A8	0x844E	#CJK UNIFIED IDEOGRAPH+0x97A9	0x63A0	#CJK UNIFIED IDEOGRAPH+0x97AA	0x7565	#CJK UNIFIED IDEOGRAPH+0x97AB	0x5289	#CJK UNIFIED IDEOGRAPH+0x97AC	0x6D41	#CJK UNIFIED IDEOGRAPH+0x97AD	0x6E9C	#CJK UNIFIED IDEOGRAPH+0x97AE	0x7409	#CJK UNIFIED IDEOGRAPH+0x97AF	0x7559	#CJK UNIFIED IDEOGRAPH+0x97B0	0x786B	#CJK UNIFIED IDEOGRAPH+0x97B1	0x7C92	#CJK UNIFIED IDEOGRAPH+0x97B2	0x9686	#CJK UNIFIED IDEOGRAPH+0x97B3	0x7ADC	#CJK UNIFIED IDEOGRAPH+0x97B4	0x9F8D	#CJK UNIFIED IDEOGRAPH+0x97B5	0x4FB6	#CJK UNIFIED IDEOGRAPH+0x97B6	0x616E	#CJK UNIFIED IDEOGRAPH+0x97B7	0x65C5	#CJK UNIFIED IDEOGRAPH+0x97B8	0x865C	#CJK UNIFIED IDEOGRAPH+0x97B9	0x4E86	#CJK UNIFIED IDEOGRAPH+0x97BA	0x4EAE	#CJK UNIFIED IDEOGRAPH+0x97BB	0x50DA	#CJK UNIFIED IDEOGRAPH+0x97BC	0x4E21	#CJK UNIFIED IDEOGRAPH+0x97BD	0x51CC	#CJK UNIFIED IDEOGRAPH+0x97BE	0x5BEE	#CJK UNIFIED IDEOGRAPH+0x97BF	0x6599	#CJK UNIFIED IDEOGRAPH+0x97C0	0x6881	#CJK UNIFIED IDEOGRAPH+0x97C1	0x6DBC	#CJK UNIFIED IDEOGRAPH+0x97C2	0x731F	#CJK UNIFIED IDEOGRAPH+0x97C3	0x7642	#CJK UNIFIED IDEOGRAPH+0x97C4	0x77AD	#CJK UNIFIED IDEOGRAPH+0x97C5	0x7A1C	#CJK UNIFIED IDEOGRAPH+0x97C6	0x7CE7	#CJK UNIFIED IDEOGRAPH+0x97C7	0x826F	#CJK UNIFIED IDEOGRAPH+0x97C8	0x8AD2	#CJK UNIFIED IDEOGRAPH+0x97C9	0x907C	#CJK UNIFIED IDEOGRAPH+0x97CA	0x91CF	#CJK UNIFIED IDEOGRAPH+0x97CB	0x9675	#CJK UNIFIED IDEOGRAPH+0x97CC	0x9818	#CJK UNIFIED IDEOGRAPH+0x97CD	0x529B	#CJK UNIFIED IDEOGRAPH+0x97CE	0x7DD1	#CJK UNIFIED IDEOGRAPH+0x97CF	0x502B	#CJK UNIFIED IDEOGRAPH+0x97D0	0x5398	#CJK UNIFIED IDEOGRAPH+0x97D1	0x6797	#CJK UNIFIED IDEOGRAPH+0x97D2	0x6DCB	#CJK UNIFIED IDEOGRAPH+0x97D3	0x71D0	#CJK UNIFIED IDEOGRAPH+0x97D4	0x7433	#CJK UNIFIED IDEOGRAPH+0x97D5	0x81E8	#CJK UNIFIED IDEOGRAPH+0x97D6	0x8F2A	#CJK UNIFIED IDEOGRAPH+0x97D7	0x96A3	#CJK UNIFIED IDEOGRAPH+0x97D8	0x9C57	#CJK UNIFIED IDEOGRAPH+0x97D9	0x9E9F	#CJK UNIFIED IDEOGRAPH+0x97DA	0x7460	#CJK UNIFIED IDEOGRAPH+0x97DB	0x5841	#CJK UNIFIED IDEOGRAPH+0x97DC	0x6D99	#CJK UNIFIED IDEOGRAPH+0x97DD	0x7D2F	#CJK UNIFIED IDEOGRAPH+0x97DE	0x985E	#CJK UNIFIED IDEOGRAPH+0x97DF	0x4EE4	#CJK UNIFIED IDEOGRAPH+0x97E0	0x4F36	#CJK UNIFIED IDEOGRAPH+0x97E1	0x4F8B	#CJK UNIFIED IDEOGRAPH+0x97E2	0x51B7	#CJK UNIFIED IDEOGRAPH+0x97E3	0x52B1	#CJK UNIFIED IDEOGRAPH+0x97E4	0x5DBA	#CJK UNIFIED IDEOGRAPH+0x97E5	0x601C	#CJK UNIFIED IDEOGRAPH+0x97E6	0x73B2	#CJK UNIFIED IDEOGRAPH+0x97E7	0x793C	#CJK UNIFIED IDEOGRAPH+0x97E8	0x82D3	#CJK UNIFIED IDEOGRAPH+0x97E9	0x9234	#CJK UNIFIED IDEOGRAPH+0x97EA	0x96B7	#CJK UNIFIED IDEOGRAPH+0x97EB	0x96F6	#CJK UNIFIED IDEOGRAPH+0x97EC	0x970A	#CJK UNIFIED IDEOGRAPH+0x97ED	0x9E97	#CJK UNIFIED IDEOGRAPH+0x97EE	0x9F62	#CJK UNIFIED IDEOGRAPH+0x97EF	0x66A6	#CJK UNIFIED IDEOGRAPH+0x97F0	0x6B74	#CJK UNIFIED IDEOGRAPH+0x97F1	0x5217	#CJK UNIFIED IDEOGRAPH+0x97F2	0x52A3	#CJK UNIFIED IDEOGRAPH+0x97F3	0x70C8	#CJK UNIFIED IDEOGRAPH+0x97F4	0x88C2	#CJK UNIFIED IDEOGRAPH+0x97F5	0x5EC9	#CJK UNIFIED IDEOGRAPH+0x97F6	0x604B	#CJK UNIFIED IDEOGRAPH+0x97F7	0x6190	#CJK UNIFIED IDEOGRAPH+0x97F8	0x6F23	#CJK UNIFIED IDEOGRAPH+0x97F9	0x7149	#CJK UNIFIED IDEOGRAPH+0x97FA	0x7C3E	#CJK UNIFIED IDEOGRAPH+0x97FB	0x7DF4	#CJK UNIFIED IDEOGRAPH+0x97FC	0x806F	#CJK UNIFIED IDEOGRAPH+0x9840	0x84EE	#CJK UNIFIED IDEOGRAPH+0x9841	0x9023	#CJK UNIFIED IDEOGRAPH+0x9842	0x932C	#CJK UNIFIED IDEOGRAPH+0x9843	0x5442	#CJK UNIFIED IDEOGRAPH+0x9844	0x9B6F	#CJK UNIFIED IDEOGRAPH+0x9845	0x6AD3	#CJK UNIFIED IDEOGRAPH+0x9846	0x7089	#CJK UNIFIED IDEOGRAPH+0x9847	0x8CC2	#CJK UNIFIED IDEOGRAPH+0x9848	0x8DEF	#CJK UNIFIED IDEOGRAPH+0x9849	0x9732	#CJK UNIFIED IDEOGRAPH+0x984A	0x52B4	#CJK UNIFIED IDEOGRAPH+0x984B	0x5A41	#CJK UNIFIED IDEOGRAPH+0x984C	0x5ECA	#CJK UNIFIED IDEOGRAPH+0x984D	0x5F04	#CJK UNIFIED IDEOGRAPH+0x984E	0x6717	#CJK UNIFIED IDEOGRAPH+0x984F	0x697C	#CJK UNIFIED IDEOGRAPH+0x9850	0x6994	#CJK UNIFIED IDEOGRAPH+0x9851	0x6D6A	#CJK UNIFIED IDEOGRAPH+0x9852	0x6F0F	#CJK UNIFIED IDEOGRAPH+0x9853	0x7262	#CJK UNIFIED IDEOGRAPH+0x9854	0x72FC	#CJK UNIFIED IDEOGRAPH+0x9855	0x7BED	#CJK UNIFIED IDEOGRAPH+0x9856	0x8001	#CJK UNIFIED IDEOGRAPH+0x9857	0x807E	#CJK UNIFIED IDEOGRAPH+0x9858	0x874B	#CJK UNIFIED IDEOGRAPH+0x9859	0x90CE	#CJK UNIFIED IDEOGRAPH+0x985A	0x516D	#CJK UNIFIED IDEOGRAPH+0x985B	0x9E93	#CJK UNIFIED IDEOGRAPH+0x985C	0x7984	#CJK UNIFIED IDEOGRAPH+0x985D	0x808B	#CJK UNIFIED IDEOGRAPH+0x985E	0x9332	#CJK UNIFIED IDEOGRAPH+0x985F	0x8AD6	#CJK UNIFIED IDEOGRAPH+0x9860	0x502D	#CJK UNIFIED IDEOGRAPH+0x9861	0x548C	#CJK UNIFIED IDEOGRAPH+0x9862	0x8A71	#CJK UNIFIED IDEOGRAPH+0x9863	0x6B6A	#CJK UNIFIED IDEOGRAPH+0x9864	0x8CC4	#CJK UNIFIED IDEOGRAPH+0x9865	0x8107	#CJK UNIFIED IDEOGRAPH+0x9866	0x60D1	#CJK UNIFIED IDEOGRAPH+0x9867	0x67A0	#CJK UNIFIED IDEOGRAPH+0x9868	0x9DF2	#CJK UNIFIED IDEOGRAPH+0x9869	0x4E99	#CJK UNIFIED IDEOGRAPH+0x986A	0x4E98	#CJK UNIFIED IDEOGRAPH+0x986B	0x9C10	#CJK UNIFIED IDEOGRAPH+0x986C	0x8A6B	#CJK UNIFIED IDEOGRAPH+0x986D	0x85C1	#CJK UNIFIED IDEOGRAPH+0x986E	0x8568	#CJK UNIFIED IDEOGRAPH+0x986F	0x6900	#CJK UNIFIED IDEOGRAPH+0x9870	0x6E7E	#CJK UNIFIED IDEOGRAPH+0x9871	0x7897	#CJK UNIFIED IDEOGRAPH+0x9872	0x8155	#CJK UNIFIED IDEOGRAPH+0x989F	0x5F0C	#CJK UNIFIED IDEOGRAPH+0x98A0	0x4E10	#CJK UNIFIED IDEOGRAPH+0x98A1	0x4E15	#CJK UNIFIED IDEOGRAPH+0x98A2	0x4E2A	#CJK UNIFIED IDEOGRAPH+0x98A3	0x4E31	#CJK UNIFIED IDEOGRAPH+0x98A4	0x4E36	#CJK UNIFIED IDEOGRAPH+0x98A5	0x4E3C	#CJK UNIFIED IDEOGRAPH+0x98A6	0x4E3F	#CJK UNIFIED IDEOGRAPH+0x98A7	0x4E42	#CJK UNIFIED IDEOGRAPH+0x98A8	0x4E56	#CJK UNIFIED IDEOGRAPH+0x98A9	0x4E58	#CJK UNIFIED IDEOGRAPH+0x98AA	0x4E82	#CJK UNIFIED IDEOGRAPH+0x98AB	0x4E85	#CJK UNIFIED IDEOGRAPH+0x98AC	0x8C6B	#CJK UNIFIED IDEOGRAPH+0x98AD	0x4E8A	#CJK UNIFIED IDEOGRAPH+0x98AE	0x8212	#CJK UNIFIED IDEOGRAPH+0x98AF	0x5F0D	#CJK UNIFIED IDEOGRAPH+0x98B0	0x4E8E	#CJK UNIFIED IDEOGRAPH+0x98B1	0x4E9E	#CJK UNIFIED IDEOGRAPH+0x98B2	0x4E9F	#CJK UNIFIED IDEOGRAPH+0x98B3	0x4EA0	#CJK UNIFIED IDEOGRAPH+0x98B4	0x4EA2	#CJK UNIFIED IDEOGRAPH+0x98B5	0x4EB0	#CJK UNIFIED IDEOGRAPH+0x98B6	0x4EB3	#CJK UNIFIED IDEOGRAPH+0x98B7	0x4EB6	#CJK UNIFIED IDEOGRAPH+0x98B8	0x4ECE	#CJK UNIFIED IDEOGRAPH+0x98B9	0x4ECD	#CJK UNIFIED IDEOGRAPH+0x98BA	0x4EC4	#CJK UNIFIED IDEOGRAPH+0x98BB	0x4EC6	#CJK UNIFIED IDEOGRAPH+0x98BC	0x4EC2	#CJK UNIFIED IDEOGRAPH+0x98BD	0x4ED7	#CJK UNIFIED IDEOGRAPH+0x98BE	0x4EDE	#CJK UNIFIED IDEOGRAPH+0x98BF	0x4EED	#CJK UNIFIED IDEOGRAPH+0x98C0	0x4EDF	#CJK UNIFIED IDEOGRAPH+0x98C1	0x4EF7	#CJK UNIFIED IDEOGRAPH+0x98C2	0x4F09	#CJK UNIFIED IDEOGRAPH+0x98C3	0x4F5A	#CJK UNIFIED IDEOGRAPH+0x98C4	0x4F30	#CJK UNIFIED IDEOGRAPH+0x98C5	0x4F5B	#CJK UNIFIED IDEOGRAPH+0x98C6	0x4F5D	#CJK UNIFIED IDEOGRAPH+0x98C7	0x4F57	#CJK UNIFIED IDEOGRAPH+0x98C8	0x4F47	#CJK UNIFIED IDEOGRAPH+0x98C9	0x4F76	#CJK UNIFIED IDEOGRAPH+0x98CA	0x4F88	#CJK UNIFIED IDEOGRAPH+0x98CB	0x4F8F	#CJK UNIFIED IDEOGRAPH+0x98CC	0x4F98	#CJK UNIFIED IDEOGRAPH+0x98CD	0x4F7B	#CJK UNIFIED IDEOGRAPH+0x98CE	0x4F69	#CJK UNIFIED IDEOGRAPH+0x98CF	0x4F70	#CJK UNIFIED IDEOGRAPH+0x98D0	0x4F91	#CJK UNIFIED IDEOGRAPH+0x98D1	0x4F6F	#CJK UNIFIED IDEOGRAPH+0x98D2	0x4F86	#CJK UNIFIED IDEOGRAPH+0x98D3	0x4F96	#CJK UNIFIED IDEOGRAPH+0x98D4	0x5118	#CJK UNIFIED IDEOGRAPH+0x98D5	0x4FD4	#CJK UNIFIED IDEOGRAPH+0x98D6	0x4FDF	#CJK UNIFIED IDEOGRAPH+0x98D7	0x4FCE	#CJK UNIFIED IDEOGRAPH+0x98D8	0x4FD8	#CJK UNIFIED IDEOGRAPH+0x98D9	0x4FDB	#CJK UNIFIED IDEOGRAPH+0x98DA	0x4FD1	#CJK UNIFIED IDEOGRAPH+0x98DB	0x4FDA	#CJK UNIFIED IDEOGRAPH+0x98DC	0x4FD0	#CJK UNIFIED IDEOGRAPH+0x98DD	0x4FE4	#CJK UNIFIED IDEOGRAPH+0x98DE	0x4FE5	#CJK UNIFIED IDEOGRAPH+0x98DF	0x501A	#CJK UNIFIED IDEOGRAPH+0x98E0	0x5028	#CJK UNIFIED IDEOGRAPH+0x98E1	0x5014	#CJK UNIFIED IDEOGRAPH+0x98E2	0x502A	#CJK UNIFIED IDEOGRAPH+0x98E3	0x5025	#CJK UNIFIED IDEOGRAPH+0x98E4	0x5005	#CJK UNIFIED IDEOGRAPH+0x98E5	0x4F1C	#CJK UNIFIED IDEOGRAPH+0x98E6	0x4FF6	#CJK UNIFIED IDEOGRAPH+0x98E7	0x5021	#CJK UNIFIED IDEOGRAPH+0x98E8	0x5029	#CJK UNIFIED IDEOGRAPH+0x98E9	0x502C	#CJK UNIFIED IDEOGRAPH+0x98EA	0x4FFE	#CJK UNIFIED IDEOGRAPH+0x98EB	0x4FEF	#CJK UNIFIED IDEOGRAPH+0x98EC	0x5011	#CJK UNIFIED IDEOGRAPH+0x98ED	0x5006	#CJK UNIFIED IDEOGRAPH+0x98EE	0x5043	#CJK UNIFIED IDEOGRAPH+0x98EF	0x5047	#CJK UNIFIED IDEOGRAPH+0x98F0	0x6703	#CJK UNIFIED IDEOGRAPH+0x98F1	0x5055	#CJK UNIFIED IDEOGRAPH+0x98F2	0x5050	#CJK UNIFIED IDEOGRAPH+0x98F3	0x5048	#CJK UNIFIED IDEOGRAPH+0x98F4	0x505A	#CJK UNIFIED IDEOGRAPH+0x98F5	0x5056	#CJK UNIFIED IDEOGRAPH+0x98F6	0x506C	#CJK UNIFIED IDEOGRAPH+0x98F7	0x5078	#CJK UNIFIED IDEOGRAPH+0x98F8	0x5080	#CJK UNIFIED IDEOGRAPH+0x98F9	0x509A	#CJK UNIFIED IDEOGRAPH+0x98FA	0x5085	#CJK UNIFIED IDEOGRAPH+0x98FB	0x50B4	#CJK UNIFIED IDEOGRAPH+0x98FC	0x50B2	#CJK UNIFIED IDEOGRAPH+0x9940	0x50C9	#CJK UNIFIED IDEOGRAPH+0x9941	0x50CA	#CJK UNIFIED IDEOGRAPH+0x9942	0x50B3	#CJK UNIFIED IDEOGRAPH+0x9943	0x50C2	#CJK UNIFIED IDEOGRAPH+0x9944	0x50D6	#CJK UNIFIED IDEOGRAPH+0x9945	0x50DE	#CJK UNIFIED IDEOGRAPH+0x9946	0x50E5	#CJK UNIFIED IDEOGRAPH+0x9947	0x50ED	#CJK UNIFIED IDEOGRAPH+0x9948	0x50E3	#CJK UNIFIED IDEOGRAPH+0x9949	0x50EE	#CJK UNIFIED IDEOGRAPH+0x994A	0x50F9	#CJK UNIFIED IDEOGRAPH+0x994B	0x50F5	#CJK UNIFIED IDEOGRAPH+0x994C	0x5109	#CJK UNIFIED IDEOGRAPH+0x994D	0x5101	#CJK UNIFIED IDEOGRAPH+0x994E	0x5102	#CJK UNIFIED IDEOGRAPH+0x994F	0x5116	#CJK UNIFIED IDEOGRAPH+0x9950	0x5115	#CJK UNIFIED IDEOGRAPH+0x9951	0x5114	#CJK UNIFIED IDEOGRAPH+0x9952	0x511A	#CJK UNIFIED IDEOGRAPH+0x9953	0x5121	#CJK UNIFIED IDEOGRAPH+0x9954	0x513A	#CJK UNIFIED IDEOGRAPH+0x9955	0x5137	#CJK UNIFIED IDEOGRAPH+0x9956	0x513C	#CJK UNIFIED IDEOGRAPH+0x9957	0x513B	#CJK UNIFIED IDEOGRAPH+0x9958	0x513F	#CJK UNIFIED IDEOGRAPH+0x9959	0x5140	#CJK UNIFIED IDEOGRAPH+0x995A	0x5152	#CJK UNIFIED IDEOGRAPH+0x995B	0x514C	#CJK UNIFIED IDEOGRAPH+0x995C	0x5154	#CJK UNIFIED IDEOGRAPH+0x995D	0x5162	#CJK UNIFIED IDEOGRAPH+0x995E	0x7AF8	#CJK UNIFIED IDEOGRAPH+0x995F	0x5169	#CJK UNIFIED IDEOGRAPH+0x9960	0x516A	#CJK UNIFIED IDEOGRAPH+0x9961	0x516E	#CJK UNIFIED IDEOGRAPH+0x9962	0x5180	#CJK UNIFIED IDEOGRAPH+0x9963	0x5182	#CJK UNIFIED IDEOGRAPH+0x9964	0x56D8	#CJK UNIFIED IDEOGRAPH+0x9965	0x518C	#CJK UNIFIED IDEOGRAPH+0x9966	0x5189	#CJK UNIFIED IDEOGRAPH+0x9967	0x518F	#CJK UNIFIED IDEOGRAPH+0x9968	0x5191	#CJK UNIFIED IDEOGRAPH+0x9969	0x5193	#CJK UNIFIED IDEOGRAPH+0x996A	0x5195	#CJK UNIFIED IDEOGRAPH+0x996B	0x5196	#CJK UNIFIED IDEOGRAPH+0x996C	0x51A4	#CJK UNIFIED IDEOGRAPH+0x996D	0x51A6	#CJK UNIFIED IDEOGRAPH+0x996E	0x51A2	#CJK UNIFIED IDEOGRAPH+0x996F	0x51A9	#CJK UNIFIED IDEOGRAPH+0x9970	0x51AA	#CJK UNIFIED IDEOGRAPH+0x9971	0x51AB	#CJK UNIFIED IDEOGRAPH+0x9972	0x51B3	#CJK UNIFIED IDEOGRAPH+0x9973	0x51B1	#CJK UNIFIED IDEOGRAPH+0x9974	0x51B2	#CJK UNIFIED IDEOGRAPH+0x9975	0x51B0	#CJK UNIFIED IDEOGRAPH+0x9976	0x51B5	#CJK UNIFIED IDEOGRAPH+0x9977	0x51BD	#CJK UNIFIED IDEOGRAPH+0x9978	0x51C5	#CJK UNIFIED IDEOGRAPH+0x9979	0x51C9	#CJK UNIFIED IDEOGRAPH+0x997A	0x51DB	#CJK UNIFIED IDEOGRAPH+0x997B	0x51E0	#CJK UNIFIED IDEOGRAPH+0x997C	0x8655	#CJK UNIFIED IDEOGRAPH+0x997D	0x51E9	#CJK UNIFIED IDEOGRAPH+0x997E	0x51ED	#CJK UNIFIED IDEOGRAPH+0x9980	0x51F0	#CJK UNIFIED IDEOGRAPH+0x9981	0x51F5	#CJK UNIFIED IDEOGRAPH+0x9982	0x51FE	#CJK UNIFIED IDEOGRAPH+0x9983	0x5204	#CJK UNIFIED IDEOGRAPH+0x9984	0x520B	#CJK UNIFIED IDEOGRAPH+0x9985	0x5214	#CJK UNIFIED IDEOGRAPH+0x9986	0x520E	#CJK UNIFIED IDEOGRAPH+0x9987	0x5227	#CJK UNIFIED IDEOGRAPH+0x9988	0x522A	#CJK UNIFIED IDEOGRAPH+0x9989	0x522E	#CJK UNIFIED IDEOGRAPH+0x998A	0x5233	#CJK UNIFIED IDEOGRAPH+0x998B	0x5239	#CJK UNIFIED IDEOGRAPH+0x998C	0x524F	#CJK UNIFIED IDEOGRAPH+0x998D	0x5244	#CJK UNIFIED IDEOGRAPH+0x998E	0x524B	#CJK UNIFIED IDEOGRAPH+0x998F	0x524C	#CJK UNIFIED IDEOGRAPH+0x9990	0x525E	#CJK UNIFIED IDEOGRAPH+0x9991	0x5254	#CJK UNIFIED IDEOGRAPH+0x9992	0x526A	#CJK UNIFIED IDEOGRAPH+0x9993	0x5274	#CJK UNIFIED IDEOGRAPH+0x9994	0x5269	#CJK UNIFIED IDEOGRAPH+0x9995	0x5273	#CJK UNIFIED IDEOGRAPH+0x9996	0x527F	#CJK UNIFIED IDEOGRAPH+0x9997	0x527D	#CJK UNIFIED IDEOGRAPH+0x9998	0x528D	#CJK UNIFIED IDEOGRAPH+0x9999	0x5294	#CJK UNIFIED IDEOGRAPH+0x999A	0x5292	#CJK UNIFIED IDEOGRAPH+0x999B	0x5271	#CJK UNIFIED IDEOGRAPH+0x999C	0x5288	#CJK UNIFIED IDEOGRAPH+0x999D	0x5291	#CJK UNIFIED IDEOGRAPH+0x999E	0x8FA8	#CJK UNIFIED IDEOGRAPH+0x999F	0x8FA7	#CJK UNIFIED IDEOGRAPH+0x99A0	0x52AC	#CJK UNIFIED IDEOGRAPH+0x99A1	0x52AD	#CJK UNIFIED IDEOGRAPH+0x99A2	0x52BC	#CJK UNIFIED IDEOGRAPH+0x99A3	0x52B5	#CJK UNIFIED IDEOGRAPH+0x99A4	0x52C1	#CJK UNIFIED IDEOGRAPH+0x99A5	0x52CD	#CJK UNIFIED IDEOGRAPH+0x99A6	0x52D7	#CJK UNIFIED IDEOGRAPH+0x99A7	0x52DE	#CJK UNIFIED IDEOGRAPH+0x99A8	0x52E3	#CJK UNIFIED IDEOGRAPH+0x99A9	0x52E6	#CJK UNIFIED IDEOGRAPH+0x99AA	0x98ED	#CJK UNIFIED IDEOGRAPH+0x99AB	0x52E0	#CJK UNIFIED IDEOGRAPH+0x99AC	0x52F3	#CJK UNIFIED IDEOGRAPH+0x99AD	0x52F5	#CJK UNIFIED IDEOGRAPH+0x99AE	0x52F8	#CJK UNIFIED IDEOGRAPH+0x99AF	0x52F9	#CJK UNIFIED IDEOGRAPH+0x99B0	0x5306	#CJK UNIFIED IDEOGRAPH+0x99B1	0x5308	#CJK UNIFIED IDEOGRAPH+0x99B2	0x7538	#CJK UNIFIED IDEOGRAPH+0x99B3	0x530D	#CJK UNIFIED IDEOGRAPH+0x99B4	0x5310	#CJK UNIFIED IDEOGRAPH+0x99B5	0x530F	#CJK UNIFIED IDEOGRAPH+0x99B6	0x5315	#CJK UNIFIED IDEOGRAPH+0x99B7	0x531A	#CJK UNIFIED IDEOGRAPH+0x99B8	0x5323	#CJK UNIFIED IDEOGRAPH+0x99B9	0x532F	#CJK UNIFIED IDEOGRAPH+0x99BA	0x5331	#CJK UNIFIED IDEOGRAPH+0x99BB	0x5333	#CJK UNIFIED IDEOGRAPH+0x99BC	0x5338	#CJK UNIFIED IDEOGRAPH+0x99BD	0x5340	#CJK UNIFIED IDEOGRAPH+0x99BE	0x5346	#CJK UNIFIED IDEOGRAPH+0x99BF	0x5345	#CJK UNIFIED IDEOGRAPH+0x99C0	0x4E17	#CJK UNIFIED IDEOGRAPH+0x99C1	0x5349	#CJK UNIFIED IDEOGRAPH+0x99C2	0x534D	#CJK UNIFIED IDEOGRAPH+0x99C3	0x51D6	#CJK UNIFIED IDEOGRAPH+0x99C4	0x535E	#CJK UNIFIED IDEOGRAPH+0x99C5	0x5369	#CJK UNIFIED IDEOGRAPH+0x99C6	0x536E	#CJK UNIFIED IDEOGRAPH+0x99C7	0x5918	#CJK UNIFIED IDEOGRAPH+0x99C8	0x537B	#CJK UNIFIED IDEOGRAPH+0x99C9	0x5377	#CJK UNIFIED IDEOGRAPH+0x99CA	0x5382	#CJK UNIFIED IDEOGRAPH+0x99CB	0x5396	#CJK UNIFIED IDEOGRAPH+0x99CC	0x53A0	#CJK UNIFIED IDEOGRAPH+0x99CD	0x53A6	#CJK UNIFIED IDEOGRAPH+0x99CE	0x53A5	#CJK UNIFIED IDEOGRAPH+0x99CF	0x53AE	#CJK UNIFIED IDEOGRAPH+0x99D0	0x53B0	#CJK UNIFIED IDEOGRAPH+0x99D1	0x53B6	#CJK UNIFIED IDEOGRAPH+0x99D2	0x53C3	#CJK UNIFIED IDEOGRAPH+0x99D3	0x7C12	#CJK UNIFIED IDEOGRAPH+0x99D4	0x96D9	#CJK UNIFIED IDEOGRAPH+0x99D5	0x53DF	#CJK UNIFIED IDEOGRAPH+0x99D6	0x66FC	#CJK UNIFIED IDEOGRAPH+0x99D7	0x71EE	#CJK UNIFIED IDEOGRAPH+0x99D8	0x53EE	#CJK UNIFIED IDEOGRAPH+0x99D9	0x53E8	#CJK UNIFIED IDEOGRAPH+0x99DA	0x53ED	#CJK UNIFIED IDEOGRAPH+0x99DB	0x53FA	#CJK UNIFIED IDEOGRAPH+0x99DC	0x5401	#CJK UNIFIED IDEOGRAPH+0x99DD	0x543D	#CJK UNIFIED IDEOGRAPH+0x99DE	0x5440	#CJK UNIFIED IDEOGRAPH+0x99DF	0x542C	#CJK UNIFIED IDEOGRAPH+0x99E0	0x542D	#CJK UNIFIED IDEOGRAPH+0x99E1	0x543C	#CJK UNIFIED IDEOGRAPH+0x99E2	0x542E	#CJK UNIFIED IDEOGRAPH+0x99E3	0x5436	#CJK UNIFIED IDEOGRAPH+0x99E4	0x5429	#CJK UNIFIED IDEOGRAPH+0x99E5	0x541D	#CJK UNIFIED IDEOGRAPH+0x99E6	0x544E	#CJK UNIFIED IDEOGRAPH+0x99E7	0x548F	#CJK UNIFIED IDEOGRAPH+0x99E8	0x5475	#CJK UNIFIED IDEOGRAPH+0x99E9	0x548E	#CJK UNIFIED IDEOGRAPH+0x99EA	0x545F	#CJK UNIFIED IDEOGRAPH+0x99EB	0x5471	#CJK UNIFIED IDEOGRAPH+0x99EC	0x5477	#CJK UNIFIED IDEOGRAPH+0x99ED	0x5470	#CJK UNIFIED IDEOGRAPH+0x99EE	0x5492	#CJK UNIFIED IDEOGRAPH+0x99EF	0x547B	#CJK UNIFIED IDEOGRAPH+0x99F0	0x5480	#CJK UNIFIED IDEOGRAPH+0x99F1	0x5476	#CJK UNIFIED IDEOGRAPH+0x99F2	0x5484	#CJK UNIFIED IDEOGRAPH+0x99F3	0x5490	#CJK UNIFIED IDEOGRAPH+0x99F4	0x5486	#CJK UNIFIED IDEOGRAPH+0x99F5	0x54C7	#CJK UNIFIED IDEOGRAPH+0x99F6	0x54A2	#CJK UNIFIED IDEOGRAPH+0x99F7	0x54B8	#CJK UNIFIED IDEOGRAPH+0x99F8	0x54A5	#CJK UNIFIED IDEOGRAPH+0x99F9	0x54AC	#CJK UNIFIED IDEOGRAPH+0x99FA	0x54C4	#CJK UNIFIED IDEOGRAPH+0x99FB	0x54C8	#CJK UNIFIED IDEOGRAPH+0x99FC	0x54A8	#CJK UNIFIED IDEOGRAPH+0x9A40	0x54AB	#CJK UNIFIED IDEOGRAPH+0x9A41	0x54C2	#CJK UNIFIED IDEOGRAPH+0x9A42	0x54A4	#CJK UNIFIED IDEOGRAPH+0x9A43	0x54BE	#CJK UNIFIED IDEOGRAPH+0x9A44	0x54BC	#CJK UNIFIED IDEOGRAPH+0x9A45	0x54D8	#CJK UNIFIED IDEOGRAPH+0x9A46	0x54E5	#CJK UNIFIED IDEOGRAPH+0x9A47	0x54E6	#CJK UNIFIED IDEOGRAPH+0x9A48	0x550F	#CJK UNIFIED IDEOGRAPH+0x9A49	0x5514	#CJK UNIFIED IDEOGRAPH+0x9A4A	0x54FD	#CJK UNIFIED IDEOGRAPH+0x9A4B	0x54EE	#CJK UNIFIED IDEOGRAPH+0x9A4C	0x54ED	#CJK UNIFIED IDEOGRAPH+0x9A4D	0x54FA	#CJK UNIFIED IDEOGRAPH+0x9A4E	0x54E2	#CJK UNIFIED IDEOGRAPH+0x9A4F	0x5539	#CJK UNIFIED IDEOGRAPH+0x9A50	0x5540	#CJK UNIFIED IDEOGRAPH+0x9A51	0x5563	#CJK UNIFIED IDEOGRAPH+0x9A52	0x554C	#CJK UNIFIED IDEOGRAPH+0x9A53	0x552E	#CJK UNIFIED IDEOGRAPH+0x9A54	0x555C	#CJK UNIFIED IDEOGRAPH+0x9A55	0x5545	#CJK UNIFIED IDEOGRAPH+0x9A56	0x5556	#CJK UNIFIED IDEOGRAPH+0x9A57	0x5557	#CJK UNIFIED IDEOGRAPH+0x9A58	0x5538	#CJK UNIFIED IDEOGRAPH+0x9A59	0x5533	#CJK UNIFIED IDEOGRAPH+0x9A5A	0x555D	#CJK UNIFIED IDEOGRAPH+0x9A5B	0x5599	#CJK UNIFIED IDEOGRAPH+0x9A5C	0x5580	#CJK UNIFIED IDEOGRAPH+0x9A5D	0x54AF	#CJK UNIFIED IDEOGRAPH+0x9A5E	0x558A	#CJK UNIFIED IDEOGRAPH+0x9A5F	0x559F	#CJK UNIFIED IDEOGRAPH+0x9A60	0x557B	#CJK UNIFIED IDEOGRAPH+0x9A61	0x557E	#CJK UNIFIED IDEOGRAPH+0x9A62	0x5598	#CJK UNIFIED IDEOGRAPH+0x9A63	0x559E	#CJK UNIFIED IDEOGRAPH+0x9A64	0x55AE	#CJK UNIFIED IDEOGRAPH+0x9A65	0x557C	#CJK UNIFIED IDEOGRAPH+0x9A66	0x5583	#CJK UNIFIED IDEOGRAPH+0x9A67	0x55A9	#CJK UNIFIED IDEOGRAPH+0x9A68	0x5587	#CJK UNIFIED IDEOGRAPH+0x9A69	0x55A8	#CJK UNIFIED IDEOGRAPH+0x9A6A	0x55DA	#CJK UNIFIED IDEOGRAPH+0x9A6B	0x55C5	#CJK UNIFIED IDEOGRAPH+0x9A6C	0x55DF	#CJK UNIFIED IDEOGRAPH+0x9A6D	0x55C4	#CJK UNIFIED IDEOGRAPH+0x9A6E	0x55DC	#CJK UNIFIED IDEOGRAPH+0x9A6F	0x55E4	#CJK UNIFIED IDEOGRAPH+0x9A70	0x55D4	#CJK UNIFIED IDEOGRAPH+0x9A71	0x5614	#CJK UNIFIED IDEOGRAPH+0x9A72	0x55F7	#CJK UNIFIED IDEOGRAPH+0x9A73	0x5616	#CJK UNIFIED IDEOGRAPH+0x9A74	0x55FE	#CJK UNIFIED IDEOGRAPH+0x9A75	0x55FD	#CJK UNIFIED IDEOGRAPH+0x9A76	0x561B	#CJK UNIFIED IDEOGRAPH+0x9A77	0x55F9	#CJK UNIFIED IDEOGRAPH+0x9A78	0x564E	#CJK UNIFIED IDEOGRAPH+0x9A79	0x5650	#CJK UNIFIED IDEOGRAPH+0x9A7A	0x71DF	#CJK UNIFIED IDEOGRAPH+0x9A7B	0x5634	#CJK UNIFIED IDEOGRAPH+0x9A7C	0x5636	#CJK UNIFIED IDEOGRAPH+0x9A7D	0x5632	#CJK UNIFIED IDEOGRAPH+0x9A7E	0x5638	#CJK UNIFIED IDEOGRAPH+0x9A80	0x566B	#CJK UNIFIED IDEOGRAPH+0x9A81	0x5664	#CJK UNIFIED IDEOGRAPH+0x9A82	0x562F	#CJK UNIFIED IDEOGRAPH+0x9A83	0x566C	#CJK UNIFIED IDEOGRAPH+0x9A84	0x566A	#CJK UNIFIED IDEOGRAPH+0x9A85	0x5686	#CJK UNIFIED IDEOGRAPH+0x9A86	0x5680	#CJK UNIFIED IDEOGRAPH+0x9A87	0x568A	#CJK UNIFIED IDEOGRAPH+0x9A88	0x56A0	#CJK UNIFIED IDEOGRAPH+0x9A89	0x5694	#CJK UNIFIED IDEOGRAPH+0x9A8A	0x568F	#CJK UNIFIED IDEOGRAPH+0x9A8B	0x56A5	#CJK UNIFIED IDEOGRAPH+0x9A8C	0x56AE	#CJK UNIFIED IDEOGRAPH+0x9A8D	0x56B6	#CJK UNIFIED IDEOGRAPH+0x9A8E	0x56B4	#CJK UNIFIED IDEOGRAPH+0x9A8F	0x56C2	#CJK UNIFIED IDEOGRAPH+0x9A90	0x56BC	#CJK UNIFIED IDEOGRAPH+0x9A91	0x56C1	#CJK UNIFIED IDEOGRAPH+0x9A92	0x56C3	#CJK UNIFIED IDEOGRAPH+0x9A93	0x56C0	#CJK UNIFIED IDEOGRAPH+0x9A94	0x56C8	#CJK UNIFIED IDEOGRAPH+0x9A95	0x56CE	#CJK UNIFIED IDEOGRAPH+0x9A96	0x56D1	#CJK UNIFIED IDEOGRAPH+0x9A97	0x56D3	#CJK UNIFIED IDEOGRAPH+0x9A98	0x56D7	#CJK UNIFIED IDEOGRAPH+0x9A99	0x56EE	#CJK UNIFIED IDEOGRAPH+0x9A9A	0x56F9	#CJK UNIFIED IDEOGRAPH+0x9A9B	0x5700	#CJK UNIFIED IDEOGRAPH+0x9A9C	0x56FF	#CJK UNIFIED IDEOGRAPH+0x9A9D	0x5704	#CJK UNIFIED IDEOGRAPH+0x9A9E	0x5709	#CJK UNIFIED IDEOGRAPH+0x9A9F	0x5708	#CJK UNIFIED IDEOGRAPH+0x9AA0	0x570B	#CJK UNIFIED IDEOGRAPH+0x9AA1	0x570D	#CJK UNIFIED IDEOGRAPH+0x9AA2	0x5713	#CJK UNIFIED IDEOGRAPH+0x9AA3	0x5718	#CJK UNIFIED IDEOGRAPH+0x9AA4	0x5716	#CJK UNIFIED IDEOGRAPH+0x9AA5	0x55C7	#CJK UNIFIED IDEOGRAPH+0x9AA6	0x571C	#CJK UNIFIED IDEOGRAPH+0x9AA7	0x5726	#CJK UNIFIED IDEOGRAPH+0x9AA8	0x5737	#CJK UNIFIED IDEOGRAPH+0x9AA9	0x5738	#CJK UNIFIED IDEOGRAPH+0x9AAA	0x574E	#CJK UNIFIED IDEOGRAPH+0x9AAB	0x573B	#CJK UNIFIED IDEOGRAPH+0x9AAC	0x5740	#CJK UNIFIED IDEOGRAPH+0x9AAD	0x574F	#CJK UNIFIED IDEOGRAPH+0x9AAE	0x5769	#CJK UNIFIED IDEOGRAPH+0x9AAF	0x57C0	#CJK UNIFIED IDEOGRAPH+0x9AB0	0x5788	#CJK UNIFIED IDEOGRAPH+0x9AB1	0x5761	#CJK UNIFIED IDEOGRAPH+0x9AB2	0x577F	#CJK UNIFIED IDEOGRAPH+0x9AB3	0x5789	#CJK UNIFIED IDEOGRAPH+0x9AB4	0x5793	#CJK UNIFIED IDEOGRAPH+0x9AB5	0x57A0	#CJK UNIFIED IDEOGRAPH+0x9AB6	0x57B3	#CJK UNIFIED IDEOGRAPH+0x9AB7	0x57A4	#CJK UNIFIED IDEOGRAPH+0x9AB8	0x57AA	#CJK UNIFIED IDEOGRAPH+0x9AB9	0x57B0	#CJK UNIFIED IDEOGRAPH+0x9ABA	0x57C3	#CJK UNIFIED IDEOGRAPH+0x9ABB	0x57C6	#CJK UNIFIED IDEOGRAPH+0x9ABC	0x57D4	#CJK UNIFIED IDEOGRAPH+0x9ABD	0x57D2	#CJK UNIFIED IDEOGRAPH+0x9ABE	0x57D3	#CJK UNIFIED IDEOGRAPH+0x9ABF	0x580A	#CJK UNIFIED IDEOGRAPH+0x9AC0	0x57D6	#CJK UNIFIED IDEOGRAPH+0x9AC1	0x57E3	#CJK UNIFIED IDEOGRAPH+0x9AC2	0x580B	#CJK UNIFIED IDEOGRAPH+0x9AC3	0x5819	#CJK UNIFIED IDEOGRAPH+0x9AC4	0x581D	#CJK UNIFIED IDEOGRAPH+0x9AC5	0x5872	#CJK UNIFIED IDEOGRAPH+0x9AC6	0x5821	#CJK UNIFIED IDEOGRAPH+0x9AC7	0x5862	#CJK UNIFIED IDEOGRAPH+0x9AC8	0x584B	#CJK UNIFIED IDEOGRAPH+0x9AC9	0x5870	#CJK UNIFIED IDEOGRAPH+0x9ACA	0x6BC0	#CJK UNIFIED IDEOGRAPH+0x9ACB	0x5852	#CJK UNIFIED IDEOGRAPH+0x9ACC	0x583D	#CJK UNIFIED IDEOGRAPH+0x9ACD	0x5879	#CJK UNIFIED IDEOGRAPH+0x9ACE	0x5885	#CJK UNIFIED IDEOGRAPH+0x9ACF	0x58B9	#CJK UNIFIED IDEOGRAPH+0x9AD0	0x589F	#CJK UNIFIED IDEOGRAPH+0x9AD1	0x58AB	#CJK UNIFIED IDEOGRAPH+0x9AD2	0x58BA	#CJK UNIFIED IDEOGRAPH+0x9AD3	0x58DE	#CJK UNIFIED IDEOGRAPH+0x9AD4	0x58BB	#CJK UNIFIED IDEOGRAPH+0x9AD5	0x58B8	#CJK UNIFIED IDEOGRAPH+0x9AD6	0x58AE	#CJK UNIFIED IDEOGRAPH+0x9AD7	0x58C5	#CJK UNIFIED IDEOGRAPH+0x9AD8	0x58D3	#CJK UNIFIED IDEOGRAPH+0x9AD9	0x58D1	#CJK UNIFIED IDEOGRAPH+0x9ADA	0x58D7	#CJK UNIFIED IDEOGRAPH+0x9ADB	0x58D9	#CJK UNIFIED IDEOGRAPH+0x9ADC	0x58D8	#CJK UNIFIED IDEOGRAPH+0x9ADD	0x58E5	#CJK UNIFIED IDEOGRAPH+0x9ADE	0x58DC	#CJK UNIFIED IDEOGRAPH+0x9ADF	0x58E4	#CJK UNIFIED IDEOGRAPH+0x9AE0	0x58DF	#CJK UNIFIED IDEOGRAPH+0x9AE1	0x58EF	#CJK UNIFIED IDEOGRAPH+0x9AE2	0x58FA	#CJK UNIFIED IDEOGRAPH+0x9AE3	0x58F9	#CJK UNIFIED IDEOGRAPH+0x9AE4	0x58FB	#CJK UNIFIED IDEOGRAPH+0x9AE5	0x58FC	#CJK UNIFIED IDEOGRAPH+0x9AE6	0x58FD	#CJK UNIFIED IDEOGRAPH+0x9AE7	0x5902	#CJK UNIFIED IDEOGRAPH+0x9AE8	0x590A	#CJK UNIFIED IDEOGRAPH+0x9AE9	0x5910	#CJK UNIFIED IDEOGRAPH+0x9AEA	0x591B	#CJK UNIFIED IDEOGRAPH+0x9AEB	0x68A6	#CJK UNIFIED IDEOGRAPH+0x9AEC	0x5925	#CJK UNIFIED IDEOGRAPH+0x9AED	0x592C	#CJK UNIFIED IDEOGRAPH+0x9AEE	0x592D	#CJK UNIFIED IDEOGRAPH+0x9AEF	0x5932	#CJK UNIFIED IDEOGRAPH+0x9AF0	0x5938	#CJK UNIFIED IDEOGRAPH+0x9AF1	0x593E	#CJK UNIFIED IDEOGRAPH+0x9AF2	0x7AD2	#CJK UNIFIED IDEOGRAPH+0x9AF3	0x5955	#CJK UNIFIED IDEOGRAPH+0x9AF4	0x5950	#CJK UNIFIED IDEOGRAPH+0x9AF5	0x594E	#CJK UNIFIED IDEOGRAPH+0x9AF6	0x595A	#CJK UNIFIED IDEOGRAPH+0x9AF7	0x5958	#CJK UNIFIED IDEOGRAPH+0x9AF8	0x5962	#CJK UNIFIED IDEOGRAPH+0x9AF9	0x5960	#CJK UNIFIED IDEOGRAPH+0x9AFA	0x5967	#CJK UNIFIED IDEOGRAPH+0x9AFB	0x596C	#CJK UNIFIED IDEOGRAPH+0x9AFC	0x5969	#CJK UNIFIED IDEOGRAPH+0x9B40	0x5978	#CJK UNIFIED IDEOGRAPH+0x9B41	0x5981	#CJK UNIFIED IDEOGRAPH+0x9B42	0x599D	#CJK UNIFIED IDEOGRAPH+0x9B43	0x4F5E	#CJK UNIFIED IDEOGRAPH+0x9B44	0x4FAB	#CJK UNIFIED IDEOGRAPH+0x9B45	0x59A3	#CJK UNIFIED IDEOGRAPH+0x9B46	0x59B2	#CJK UNIFIED IDEOGRAPH+0x9B47	0x59C6	#CJK UNIFIED IDEOGRAPH+0x9B48	0x59E8	#CJK UNIFIED IDEOGRAPH+0x9B49	0x59DC	#CJK UNIFIED IDEOGRAPH+0x9B4A	0x598D	#CJK UNIFIED IDEOGRAPH+0x9B4B	0x59D9	#CJK UNIFIED IDEOGRAPH+0x9B4C	0x59DA	#CJK UNIFIED IDEOGRAPH+0x9B4D	0x5A25	#CJK UNIFIED IDEOGRAPH+0x9B4E	0x5A1F	#CJK UNIFIED IDEOGRAPH+0x9B4F	0x5A11	#CJK UNIFIED IDEOGRAPH+0x9B50	0x5A1C	#CJK UNIFIED IDEOGRAPH+0x9B51	0x5A09	#CJK UNIFIED IDEOGRAPH+0x9B52	0x5A1A	#CJK UNIFIED IDEOGRAPH+0x9B53	0x5A40	#CJK UNIFIED IDEOGRAPH+0x9B54	0x5A6C	#CJK UNIFIED IDEOGRAPH+0x9B55	0x5A49	#CJK UNIFIED IDEOGRAPH+0x9B56	0x5A35	#CJK UNIFIED IDEOGRAPH+0x9B57	0x5A36	#CJK UNIFIED IDEOGRAPH+0x9B58	0x5A62	#CJK UNIFIED IDEOGRAPH+0x9B59	0x5A6A	#CJK UNIFIED IDEOGRAPH+0x9B5A	0x5A9A	#CJK UNIFIED IDEOGRAPH+0x9B5B	0x5ABC	#CJK UNIFIED IDEOGRAPH+0x9B5C	0x5ABE	#CJK UNIFIED IDEOGRAPH+0x9B5D	0x5ACB	#CJK UNIFIED IDEOGRAPH+0x9B5E	0x5AC2	#CJK UNIFIED IDEOGRAPH+0x9B5F	0x5ABD	#CJK UNIFIED IDEOGRAPH+0x9B60	0x5AE3	#CJK UNIFIED IDEOGRAPH+0x9B61	0x5AD7	#CJK UNIFIED IDEOGRAPH+0x9B62	0x5AE6	#CJK UNIFIED IDEOGRAPH+0x9B63	0x5AE9	#CJK UNIFIED IDEOGRAPH+0x9B64	0x5AD6	#CJK UNIFIED IDEOGRAPH+0x9B65	0x5AFA	#CJK UNIFIED IDEOGRAPH+0x9B66	0x5AFB	#CJK UNIFIED IDEOGRAPH+0x9B67	0x5B0C	#CJK UNIFIED IDEOGRAPH+0x9B68	0x5B0B	#CJK UNIFIED IDEOGRAPH+0x9B69	0x5B16	#CJK UNIFIED IDEOGRAPH+0x9B6A	0x5B32	#CJK UNIFIED IDEOGRAPH+0x9B6B	0x5AD0	#CJK UNIFIED IDEOGRAPH+0x9B6C	0x5B2A	#CJK UNIFIED IDEOGRAPH+0x9B6D	0x5B36	#CJK UNIFIED IDEOGRAPH+0x9B6E	0x5B3E	#CJK UNIFIED IDEOGRAPH+0x9B6F	0x5B43	#CJK UNIFIED IDEOGRAPH+0x9B70	0x5B45	#CJK UNIFIED IDEOGRAPH+0x9B71	0x5B40	#CJK UNIFIED IDEOGRAPH+0x9B72	0x5B51	#CJK UNIFIED IDEOGRAPH+0x9B73	0x5B55	#CJK UNIFIED IDEOGRAPH+0x9B74	0x5B5A	#CJK UNIFIED IDEOGRAPH+0x9B75	0x5B5B	#CJK UNIFIED IDEOGRAPH+0x9B76	0x5B65	#CJK UNIFIED IDEOGRAPH+0x9B77	0x5B69	#CJK UNIFIED IDEOGRAPH+0x9B78	0x5B70	#CJK UNIFIED IDEOGRAPH+0x9B79	0x5B73	#CJK UNIFIED IDEOGRAPH+0x9B7A	0x5B75	#CJK UNIFIED IDEOGRAPH+0x9B7B	0x5B78	#CJK UNIFIED IDEOGRAPH+0x9B7C	0x6588	#CJK UNIFIED IDEOGRAPH+0x9B7D	0x5B7A	#CJK UNIFIED IDEOGRAPH+0x9B7E	0x5B80	#CJK UNIFIED IDEOGRAPH+0x9B80	0x5B83	#CJK UNIFIED IDEOGRAPH+0x9B81	0x5BA6	#CJK UNIFIED IDEOGRAPH+0x9B82	0x5BB8	#CJK UNIFIED IDEOGRAPH+0x9B83	0x5BC3	#CJK UNIFIED IDEOGRAPH+0x9B84	0x5BC7	#CJK UNIFIED IDEOGRAPH+0x9B85	0x5BC9	#CJK UNIFIED IDEOGRAPH+0x9B86	0x5BD4	#CJK UNIFIED IDEOGRAPH+0x9B87	0x5BD0	#CJK UNIFIED IDEOGRAPH+0x9B88	0x5BE4	#CJK UNIFIED IDEOGRAPH+0x9B89	0x5BE6	#CJK UNIFIED IDEOGRAPH+0x9B8A	0x5BE2	#CJK UNIFIED IDEOGRAPH+0x9B8B	0x5BDE	#CJK UNIFIED IDEOGRAPH+0x9B8C	0x5BE5	#CJK UNIFIED IDEOGRAPH+0x9B8D	0x5BEB	#CJK UNIFIED IDEOGRAPH+0x9B8E	0x5BF0	#CJK UNIFIED IDEOGRAPH+0x9B8F	0x5BF6	#CJK UNIFIED IDEOGRAPH+0x9B90	0x5BF3	#CJK UNIFIED IDEOGRAPH+0x9B91	0x5C05	#CJK UNIFIED IDEOGRAPH+0x9B92	0x5C07	#CJK UNIFIED IDEOGRAPH+0x9B93	0x5C08	#CJK UNIFIED IDEOGRAPH+0x9B94	0x5C0D	#CJK UNIFIED IDEOGRAPH+0x9B95	0x5C13	#CJK UNIFIED IDEOGRAPH+0x9B96	0x5C20	#CJK UNIFIED IDEOGRAPH+0x9B97	0x5C22	#CJK UNIFIED IDEOGRAPH+0x9B98	0x5C28	#CJK UNIFIED IDEOGRAPH+0x9B99	0x5C38	#CJK UNIFIED IDEOGRAPH+0x9B9A	0x5C39	#CJK UNIFIED IDEOGRAPH+0x9B9B	0x5C41	#CJK UNIFIED IDEOGRAPH+0x9B9C	0x5C46	#CJK UNIFIED IDEOGRAPH+0x9B9D	0x5C4E	#CJK UNIFIED IDEOGRAPH+0x9B9E	0x5C53	#CJK UNIFIED IDEOGRAPH+0x9B9F	0x5C50	#CJK UNIFIED IDEOGRAPH+0x9BA0	0x5C4F	#CJK UNIFIED IDEOGRAPH+0x9BA1	0x5B71	#CJK UNIFIED IDEOGRAPH+0x9BA2	0x5C6C	#CJK UNIFIED IDEOGRAPH+0x9BA3	0x5C6E	#CJK UNIFIED IDEOGRAPH+0x9BA4	0x4E62	#CJK UNIFIED IDEOGRAPH+0x9BA5	0x5C76	#CJK UNIFIED IDEOGRAPH+0x9BA6	0x5C79	#CJK UNIFIED IDEOGRAPH+0x9BA7	0x5C8C	#CJK UNIFIED IDEOGRAPH+0x9BA8	0x5C91	#CJK UNIFIED IDEOGRAPH+0x9BA9	0x5C94	#CJK UNIFIED IDEOGRAPH+0x9BAA	0x599B	#CJK UNIFIED IDEOGRAPH+0x9BAB	0x5CAB	#CJK UNIFIED IDEOGRAPH+0x9BAC	0x5CBB	#CJK UNIFIED IDEOGRAPH+0x9BAD	0x5CB6	#CJK UNIFIED IDEOGRAPH+0x9BAE	0x5CBC	#CJK UNIFIED IDEOGRAPH+0x9BAF	0x5CB7	#CJK UNIFIED IDEOGRAPH+0x9BB0	0x5CC5	#CJK UNIFIED IDEOGRAPH+0x9BB1	0x5CBE	#CJK UNIFIED IDEOGRAPH+0x9BB2	0x5CC7	#CJK UNIFIED IDEOGRAPH+0x9BB3	0x5CD9	#CJK UNIFIED IDEOGRAPH+0x9BB4	0x5CE9	#CJK UNIFIED IDEOGRAPH+0x9BB5	0x5CFD	#CJK UNIFIED IDEOGRAPH+0x9BB6	0x5CFA	#CJK UNIFIED IDEOGRAPH+0x9BB7	0x5CED	#CJK UNIFIED IDEOGRAPH+0x9BB8	0x5D8C	#CJK UNIFIED IDEOGRAPH+0x9BB9	0x5CEA	#CJK UNIFIED IDEOGRAPH+0x9BBA	0x5D0B	#CJK UNIFIED IDEOGRAPH+0x9BBB	0x5D15	#CJK UNIFIED IDEOGRAPH+0x9BBC	0x5D17	#CJK UNIFIED IDEOGRAPH+0x9BBD	0x5D5C	#CJK UNIFIED IDEOGRAPH+0x9BBE	0x5D1F	#CJK UNIFIED IDEOGRAPH+0x9BBF	0x5D1B	#CJK UNIFIED IDEOGRAPH+0x9BC0	0x5D11	#CJK UNIFIED IDEOGRAPH+0x9BC1	0x5D14	#CJK UNIFIED IDEOGRAPH+0x9BC2	0x5D22	#CJK UNIFIED IDEOGRAPH+0x9BC3	0x5D1A	#CJK UNIFIED IDEOGRAPH+0x9BC4	0x5D19	#CJK UNIFIED IDEOGRAPH+0x9BC5	0x5D18	#CJK UNIFIED IDEOGRAPH+0x9BC6	0x5D4C	#CJK UNIFIED IDEOGRAPH+0x9BC7	0x5D52	#CJK UNIFIED IDEOGRAPH+0x9BC8	0x5D4E	#CJK UNIFIED IDEOGRAPH+0x9BC9	0x5D4B	#CJK UNIFIED IDEOGRAPH+0x9BCA	0x5D6C	#CJK UNIFIED IDEOGRAPH+0x9BCB	0x5D73	#CJK UNIFIED IDEOGRAPH+0x9BCC	0x5D76	#CJK UNIFIED IDEOGRAPH+0x9BCD	0x5D87	#CJK UNIFIED IDEOGRAPH+0x9BCE	0x5D84	#CJK UNIFIED IDEOGRAPH+0x9BCF	0x5D82	#CJK UNIFIED IDEOGRAPH+0x9BD0	0x5DA2	#CJK UNIFIED IDEOGRAPH+0x9BD1	0x5D9D	#CJK UNIFIED IDEOGRAPH+0x9BD2	0x5DAC	#CJK UNIFIED IDEOGRAPH+0x9BD3	0x5DAE	#CJK UNIFIED IDEOGRAPH+0x9BD4	0x5DBD	#CJK UNIFIED IDEOGRAPH+0x9BD5	0x5D90	#CJK UNIFIED IDEOGRAPH+0x9BD6	0x5DB7	#CJK UNIFIED IDEOGRAPH+0x9BD7	0x5DBC	#CJK UNIFIED IDEOGRAPH+0x9BD8	0x5DC9	#CJK UNIFIED IDEOGRAPH+0x9BD9	0x5DCD	#CJK UNIFIED IDEOGRAPH+0x9BDA	0x5DD3	#CJK UNIFIED IDEOGRAPH+0x9BDB	0x5DD2	#CJK UNIFIED IDEOGRAPH+0x9BDC	0x5DD6	#CJK UNIFIED IDEOGRAPH+0x9BDD	0x5DDB	#CJK UNIFIED IDEOGRAPH+0x9BDE	0x5DEB	#CJK UNIFIED IDEOGRAPH+0x9BDF	0x5DF2	#CJK UNIFIED IDEOGRAPH+0x9BE0	0x5DF5	#CJK UNIFIED IDEOGRAPH+0x9BE1	0x5E0B	#CJK UNIFIED IDEOGRAPH+0x9BE2	0x5E1A	#CJK UNIFIED IDEOGRAPH+0x9BE3	0x5E19	#CJK UNIFIED IDEOGRAPH+0x9BE4	0x5E11	#CJK UNIFIED IDEOGRAPH+0x9BE5	0x5E1B	#CJK UNIFIED IDEOGRAPH+0x9BE6	0x5E36	#CJK UNIFIED IDEOGRAPH+0x9BE7	0x5E37	#CJK UNIFIED IDEOGRAPH+0x9BE8	0x5E44	#CJK UNIFIED IDEOGRAPH+0x9BE9	0x5E43	#CJK UNIFIED IDEOGRAPH+0x9BEA	0x5E40	#CJK UNIFIED IDEOGRAPH+0x9BEB	0x5E4E	#CJK UNIFIED IDEOGRAPH+0x9BEC	0x5E57	#CJK UNIFIED IDEOGRAPH+0x9BED	0x5E54	#CJK UNIFIED IDEOGRAPH+0x9BEE	0x5E5F	#CJK UNIFIED IDEOGRAPH+0x9BEF	0x5E62	#CJK UNIFIED IDEOGRAPH+0x9BF0	0x5E64	#CJK UNIFIED IDEOGRAPH+0x9BF1	0x5E47	#CJK UNIFIED IDEOGRAPH+0x9BF2	0x5E75	#CJK UNIFIED IDEOGRAPH+0x9BF3	0x5E76	#CJK UNIFIED IDEOGRAPH+0x9BF4	0x5E7A	#CJK UNIFIED IDEOGRAPH+0x9BF5	0x9EBC	#CJK UNIFIED IDEOGRAPH+0x9BF6	0x5E7F	#CJK UNIFIED IDEOGRAPH+0x9BF7	0x5EA0	#CJK UNIFIED IDEOGRAPH+0x9BF8	0x5EC1	#CJK UNIFIED IDEOGRAPH+0x9BF9	0x5EC2	#CJK UNIFIED IDEOGRAPH+0x9BFA	0x5EC8	#CJK UNIFIED IDEOGRAPH+0x9BFB	0x5ED0	#CJK UNIFIED IDEOGRAPH+0x9BFC	0x5ECF	#CJK UNIFIED IDEOGRAPH+0x9C40	0x5ED6	#CJK UNIFIED IDEOGRAPH+0x9C41	0x5EE3	#CJK UNIFIED IDEOGRAPH+0x9C42	0x5EDD	#CJK UNIFIED IDEOGRAPH+0x9C43	0x5EDA	#CJK UNIFIED IDEOGRAPH+0x9C44	0x5EDB	#CJK UNIFIED IDEOGRAPH+0x9C45	0x5EE2	#CJK UNIFIED IDEOGRAPH+0x9C46	0x5EE1	#CJK UNIFIED IDEOGRAPH+0x9C47	0x5EE8	#CJK UNIFIED IDEOGRAPH+0x9C48	0x5EE9	#CJK UNIFIED IDEOGRAPH+0x9C49	0x5EEC	#CJK UNIFIED IDEOGRAPH+0x9C4A	0x5EF1	#CJK UNIFIED IDEOGRAPH+0x9C4B	0x5EF3	#CJK UNIFIED IDEOGRAPH+0x9C4C	0x5EF0	#CJK UNIFIED IDEOGRAPH+0x9C4D	0x5EF4	#CJK UNIFIED IDEOGRAPH+0x9C4E	0x5EF8	#CJK UNIFIED IDEOGRAPH+0x9C4F	0x5EFE	#CJK UNIFIED IDEOGRAPH+0x9C50	0x5F03	#CJK UNIFIED IDEOGRAPH+0x9C51	0x5F09	#CJK UNIFIED IDEOGRAPH+0x9C52	0x5F5D	#CJK UNIFIED IDEOGRAPH+0x9C53	0x5F5C	#CJK UNIFIED IDEOGRAPH+0x9C54	0x5F0B	#CJK UNIFIED IDEOGRAPH+0x9C55	0x5F11	#CJK UNIFIED IDEOGRAPH+0x9C56	0x5F16	#CJK UNIFIED IDEOGRAPH+0x9C57	0x5F29	#CJK UNIFIED IDEOGRAPH+0x9C58	0x5F2D	#CJK UNIFIED IDEOGRAPH+0x9C59	0x5F38	#CJK UNIFIED IDEOGRAPH+0x9C5A	0x5F41	#CJK UNIFIED IDEOGRAPH+0x9C5B	0x5F48	#CJK UNIFIED IDEOGRAPH+0x9C5C	0x5F4C	#CJK UNIFIED IDEOGRAPH+0x9C5D	0x5F4E	#CJK UNIFIED IDEOGRAPH+0x9C5E	0x5F2F	#CJK UNIFIED IDEOGRAPH+0x9C5F	0x5F51	#CJK UNIFIED IDEOGRAPH+0x9C60	0x5F56	#CJK UNIFIED IDEOGRAPH+0x9C61	0x5F57	#CJK UNIFIED IDEOGRAPH+0x9C62	0x5F59	#CJK UNIFIED IDEOGRAPH+0x9C63	0x5F61	#CJK UNIFIED IDEOGRAPH+0x9C64	0x5F6D	#CJK UNIFIED IDEOGRAPH+0x9C65	0x5F73	#CJK UNIFIED IDEOGRAPH+0x9C66	0x5F77	#CJK UNIFIED IDEOGRAPH+0x9C67	0x5F83	#CJK UNIFIED IDEOGRAPH+0x9C68	0x5F82	#CJK UNIFIED IDEOGRAPH+0x9C69	0x5F7F	#CJK UNIFIED IDEOGRAPH+0x9C6A	0x5F8A	#CJK UNIFIED IDEOGRAPH+0x9C6B	0x5F88	#CJK UNIFIED IDEOGRAPH+0x9C6C	0x5F91	#CJK UNIFIED IDEOGRAPH+0x9C6D	0x5F87	#CJK UNIFIED IDEOGRAPH+0x9C6E	0x5F9E	#CJK UNIFIED IDEOGRAPH+0x9C6F	0x5F99	#CJK UNIFIED IDEOGRAPH+0x9C70	0x5F98	#CJK UNIFIED IDEOGRAPH+0x9C71	0x5FA0	#CJK UNIFIED IDEOGRAPH+0x9C72	0x5FA8	#CJK UNIFIED IDEOGRAPH+0x9C73	0x5FAD	#CJK UNIFIED IDEOGRAPH+0x9C74	0x5FBC	#CJK UNIFIED IDEOGRAPH+0x9C75	0x5FD6	#CJK UNIFIED IDEOGRAPH+0x9C76	0x5FFB	#CJK UNIFIED IDEOGRAPH+0x9C77	0x5FE4	#CJK UNIFIED IDEOGRAPH+0x9C78	0x5FF8	#CJK UNIFIED IDEOGRAPH+0x9C79	0x5FF1	#CJK UNIFIED IDEOGRAPH+0x9C7A	0x5FDD	#CJK UNIFIED IDEOGRAPH+0x9C7B	0x60B3	#CJK UNIFIED IDEOGRAPH+0x9C7C	0x5FFF	#CJK UNIFIED IDEOGRAPH+0x9C7D	0x6021	#CJK UNIFIED IDEOGRAPH+0x9C7E	0x6060	#CJK UNIFIED IDEOGRAPH+0x9C80	0x6019	#CJK UNIFIED IDEOGRAPH+0x9C81	0x6010	#CJK UNIFIED IDEOGRAPH+0x9C82	0x6029	#CJK UNIFIED IDEOGRAPH+0x9C83	0x600E	#CJK UNIFIED IDEOGRAPH+0x9C84	0x6031	#CJK UNIFIED IDEOGRAPH+0x9C85	0x601B	#CJK UNIFIED IDEOGRAPH+0x9C86	0x6015	#CJK UNIFIED IDEOGRAPH+0x9C87	0x602B	#CJK UNIFIED IDEOGRAPH+0x9C88	0x6026	#CJK UNIFIED IDEOGRAPH+0x9C89	0x600F	#CJK UNIFIED IDEOGRAPH+0x9C8A	0x603A	#CJK UNIFIED IDEOGRAPH+0x9C8B	0x605A	#CJK UNIFIED IDEOGRAPH+0x9C8C	0x6041	#CJK UNIFIED IDEOGRAPH+0x9C8D	0x606A	#CJK UNIFIED IDEOGRAPH+0x9C8E	0x6077	#CJK UNIFIED IDEOGRAPH+0x9C8F	0x605F	#CJK UNIFIED IDEOGRAPH+0x9C90	0x604A	#CJK UNIFIED IDEOGRAPH+0x9C91	0x6046	#CJK UNIFIED IDEOGRAPH+0x9C92	0x604D	#CJK UNIFIED IDEOGRAPH+0x9C93	0x6063	#CJK UNIFIED IDEOGRAPH+0x9C94	0x6043	#CJK UNIFIED IDEOGRAPH+0x9C95	0x6064	#CJK UNIFIED IDEOGRAPH+0x9C96	0x6042	#CJK UNIFIED IDEOGRAPH+0x9C97	0x606C	#CJK UNIFIED IDEOGRAPH+0x9C98	0x606B	#CJK UNIFIED IDEOGRAPH+0x9C99	0x6059	#CJK UNIFIED IDEOGRAPH+0x9C9A	0x6081	#CJK UNIFIED IDEOGRAPH+0x9C9B	0x608D	#CJK UNIFIED IDEOGRAPH+0x9C9C	0x60E7	#CJK UNIFIED IDEOGRAPH+0x9C9D	0x6083	#CJK UNIFIED IDEOGRAPH+0x9C9E	0x609A	#CJK UNIFIED IDEOGRAPH+0x9C9F	0x6084	#CJK UNIFIED IDEOGRAPH+0x9CA0	0x609B	#CJK UNIFIED IDEOGRAPH+0x9CA1	0x6096	#CJK UNIFIED IDEOGRAPH+0x9CA2	0x6097	#CJK UNIFIED IDEOGRAPH+0x9CA3	0x6092	#CJK UNIFIED IDEOGRAPH+0x9CA4	0x60A7	#CJK UNIFIED IDEOGRAPH+0x9CA5	0x608B	#CJK UNIFIED IDEOGRAPH+0x9CA6	0x60E1	#CJK UNIFIED IDEOGRAPH+0x9CA7	0x60B8	#CJK UNIFIED IDEOGRAPH+0x9CA8	0x60E0	#CJK UNIFIED IDEOGRAPH+0x9CA9	0x60D3	#CJK UNIFIED IDEOGRAPH+0x9CAA	0x60B4	#CJK UNIFIED IDEOGRAPH+0x9CAB	0x5FF0	#CJK UNIFIED IDEOGRAPH+0x9CAC	0x60BD	#CJK UNIFIED IDEOGRAPH+0x9CAD	0x60C6	#CJK UNIFIED IDEOGRAPH+0x9CAE	0x60B5	#CJK UNIFIED IDEOGRAPH+0x9CAF	0x60D8	#CJK UNIFIED IDEOGRAPH+0x9CB0	0x614D	#CJK UNIFIED IDEOGRAPH+0x9CB1	0x6115	#CJK UNIFIED IDEOGRAPH+0x9CB2	0x6106	#CJK UNIFIED IDEOGRAPH+0x9CB3	0x60F6	#CJK UNIFIED IDEOGRAPH+0x9CB4	0x60F7	#CJK UNIFIED IDEOGRAPH+0x9CB5	0x6100	#CJK UNIFIED IDEOGRAPH+0x9CB6	0x60F4	#CJK UNIFIED IDEOGRAPH+0x9CB7	0x60FA	#CJK UNIFIED IDEOGRAPH+0x9CB8	0x6103	#CJK UNIFIED IDEOGRAPH+0x9CB9	0x6121	#CJK UNIFIED IDEOGRAPH+0x9CBA	0x60FB	#CJK UNIFIED IDEOGRAPH+0x9CBB	0x60F1	#CJK UNIFIED IDEOGRAPH+0x9CBC	0x610D	#CJK UNIFIED IDEOGRAPH+0x9CBD	0x610E	#CJK UNIFIED IDEOGRAPH+0x9CBE	0x6147	#CJK UNIFIED IDEOGRAPH+0x9CBF	0x613E	#CJK UNIFIED IDEOGRAPH+0x9CC0	0x6128	#CJK UNIFIED IDEOGRAPH+0x9CC1	0x6127	#CJK UNIFIED IDEOGRAPH+0x9CC2	0x614A	#CJK UNIFIED IDEOGRAPH+0x9CC3	0x613F	#CJK UNIFIED IDEOGRAPH+0x9CC4	0x613C	#CJK UNIFIED IDEOGRAPH+0x9CC5	0x612C	#CJK UNIFIED IDEOGRAPH+0x9CC6	0x6134	#CJK UNIFIED IDEOGRAPH+0x9CC7	0x613D	#CJK UNIFIED IDEOGRAPH+0x9CC8	0x6142	#CJK UNIFIED IDEOGRAPH+0x9CC9	0x6144	#CJK UNIFIED IDEOGRAPH+0x9CCA	0x6173	#CJK UNIFIED IDEOGRAPH+0x9CCB	0x6177	#CJK UNIFIED IDEOGRAPH+0x9CCC	0x6158	#CJK UNIFIED IDEOGRAPH+0x9CCD	0x6159	#CJK UNIFIED IDEOGRAPH+0x9CCE	0x615A	#CJK UNIFIED IDEOGRAPH+0x9CCF	0x616B	#CJK UNIFIED IDEOGRAPH+0x9CD0	0x6174	#CJK UNIFIED IDEOGRAPH+0x9CD1	0x616F	#CJK UNIFIED IDEOGRAPH+0x9CD2	0x6165	#CJK UNIFIED IDEOGRAPH+0x9CD3	0x6171	#CJK UNIFIED IDEOGRAPH+0x9CD4	0x615F	#CJK UNIFIED IDEOGRAPH+0x9CD5	0x615D	#CJK UNIFIED IDEOGRAPH+0x9CD6	0x6153	#CJK UNIFIED IDEOGRAPH+0x9CD7	0x6175	#CJK UNIFIED IDEOGRAPH+0x9CD8	0x6199	#CJK UNIFIED IDEOGRAPH+0x9CD9	0x6196	#CJK UNIFIED IDEOGRAPH+0x9CDA	0x6187	#CJK UNIFIED IDEOGRAPH+0x9CDB	0x61AC	#CJK UNIFIED IDEOGRAPH+0x9CDC	0x6194	#CJK UNIFIED IDEOGRAPH+0x9CDD	0x619A	#CJK UNIFIED IDEOGRAPH+0x9CDE	0x618A	#CJK UNIFIED IDEOGRAPH+0x9CDF	0x6191	#CJK UNIFIED IDEOGRAPH+0x9CE0	0x61AB	#CJK UNIFIED IDEOGRAPH+0x9CE1	0x61AE	#CJK UNIFIED IDEOGRAPH+0x9CE2	0x61CC	#CJK UNIFIED IDEOGRAPH+0x9CE3	0x61CA	#CJK UNIFIED IDEOGRAPH+0x9CE4	0x61C9	#CJK UNIFIED IDEOGRAPH+0x9CE5	0x61F7	#CJK UNIFIED IDEOGRAPH+0x9CE6	0x61C8	#CJK UNIFIED IDEOGRAPH+0x9CE7	0x61C3	#CJK UNIFIED IDEOGRAPH+0x9CE8	0x61C6	#CJK UNIFIED IDEOGRAPH+0x9CE9	0x61BA	#CJK UNIFIED IDEOGRAPH+0x9CEA	0x61CB	#CJK UNIFIED IDEOGRAPH+0x9CEB	0x7F79	#CJK UNIFIED IDEOGRAPH+0x9CEC	0x61CD	#CJK UNIFIED IDEOGRAPH+0x9CED	0x61E6	#CJK UNIFIED IDEOGRAPH+0x9CEE	0x61E3	#CJK UNIFIED IDEOGRAPH+0x9CEF	0x61F6	#CJK UNIFIED IDEOGRAPH+0x9CF0	0x61FA	#CJK UNIFIED IDEOGRAPH+0x9CF1	0x61F4	#CJK UNIFIED IDEOGRAPH+0x9CF2	0x61FF	#CJK UNIFIED IDEOGRAPH+0x9CF3	0x61FD	#CJK UNIFIED IDEOGRAPH+0x9CF4	0x61FC	#CJK UNIFIED IDEOGRAPH+0x9CF5	0x61FE	#CJK UNIFIED IDEOGRAPH+0x9CF6	0x6200	#CJK UNIFIED IDEOGRAPH+0x9CF7	0x6208	#CJK UNIFIED IDEOGRAPH+0x9CF8	0x6209	#CJK UNIFIED IDEOGRAPH+0x9CF9	0x620D	#CJK UNIFIED IDEOGRAPH+0x9CFA	0x620C	#CJK UNIFIED IDEOGRAPH+0x9CFB	0x6214	#CJK UNIFIED IDEOGRAPH+0x9CFC	0x621B	#CJK UNIFIED IDEOGRAPH+0x9D40	0x621E	#CJK UNIFIED IDEOGRAPH+0x9D41	0x6221	#CJK UNIFIED IDEOGRAPH+0x9D42	0x622A	#CJK UNIFIED IDEOGRAPH+0x9D43	0x622E	#CJK UNIFIED IDEOGRAPH+0x9D44	0x6230	#CJK UNIFIED IDEOGRAPH+0x9D45	0x6232	#CJK UNIFIED IDEOGRAPH+0x9D46	0x6233	#CJK UNIFIED IDEOGRAPH+0x9D47	0x6241	#CJK UNIFIED IDEOGRAPH+0x9D48	0x624E	#CJK UNIFIED IDEOGRAPH+0x9D49	0x625E	#CJK UNIFIED IDEOGRAPH+0x9D4A	0x6263	#CJK UNIFIED IDEOGRAPH+0x9D4B	0x625B	#CJK UNIFIED IDEOGRAPH+0x9D4C	0x6260	#CJK UNIFIED IDEOGRAPH+0x9D4D	0x6268	#CJK UNIFIED IDEOGRAPH+0x9D4E	0x627C	#CJK UNIFIED IDEOGRAPH+0x9D4F	0x6282	#CJK UNIFIED IDEOGRAPH+0x9D50	0x6289	#CJK UNIFIED IDEOGRAPH+0x9D51	0x627E	#CJK UNIFIED IDEOGRAPH+0x9D52	0x6292	#CJK UNIFIED IDEOGRAPH+0x9D53	0x6293	#CJK UNIFIED IDEOGRAPH+0x9D54	0x6296	#CJK UNIFIED IDEOGRAPH+0x9D55	0x62D4	#CJK UNIFIED IDEOGRAPH+0x9D56	0x6283	#CJK UNIFIED IDEOGRAPH+0x9D57	0x6294	#CJK UNIFIED IDEOGRAPH+0x9D58	0x62D7	#CJK UNIFIED IDEOGRAPH+0x9D59	0x62D1	#CJK UNIFIED IDEOGRAPH+0x9D5A	0x62BB	#CJK UNIFIED IDEOGRAPH+0x9D5B	0x62CF	#CJK UNIFIED IDEOGRAPH+0x9D5C	0x62FF	#CJK UNIFIED IDEOGRAPH+0x9D5D	0x62C6	#CJK UNIFIED IDEOGRAPH+0x9D5E	0x64D4	#CJK UNIFIED IDEOGRAPH+0x9D5F	0x62C8	#CJK UNIFIED IDEOGRAPH+0x9D60	0x62DC	#CJK UNIFIED IDEOGRAPH+0x9D61	0x62CC	#CJK UNIFIED IDEOGRAPH+0x9D62	0x62CA	#CJK UNIFIED IDEOGRAPH+0x9D63	0x62C2	#CJK UNIFIED IDEOGRAPH+0x9D64	0x62C7	#CJK UNIFIED IDEOGRAPH+0x9D65	0x629B	#CJK UNIFIED IDEOGRAPH+0x9D66	0x62C9	#CJK UNIFIED IDEOGRAPH+0x9D67	0x630C	#CJK UNIFIED IDEOGRAPH+0x9D68	0x62EE	#CJK UNIFIED IDEOGRAPH+0x9D69	0x62F1	#CJK UNIFIED IDEOGRAPH+0x9D6A	0x6327	#CJK UNIFIED IDEOGRAPH+0x9D6B	0x6302	#CJK UNIFIED IDEOGRAPH+0x9D6C	0x6308	#CJK UNIFIED IDEOGRAPH+0x9D6D	0x62EF	#CJK UNIFIED IDEOGRAPH+0x9D6E	0x62F5	#CJK UNIFIED IDEOGRAPH+0x9D6F	0x6350	#CJK UNIFIED IDEOGRAPH+0x9D70	0x633E	#CJK UNIFIED IDEOGRAPH+0x9D71	0x634D	#CJK UNIFIED IDEOGRAPH+0x9D72	0x641C	#CJK UNIFIED IDEOGRAPH+0x9D73	0x634F	#CJK UNIFIED IDEOGRAPH+0x9D74	0x6396	#CJK UNIFIED IDEOGRAPH+0x9D75	0x638E	#CJK UNIFIED IDEOGRAPH+0x9D76	0x6380	#CJK UNIFIED IDEOGRAPH+0x9D77	0x63AB	#CJK UNIFIED IDEOGRAPH+0x9D78	0x6376	#CJK UNIFIED IDEOGRAPH+0x9D79	0x63A3	#CJK UNIFIED IDEOGRAPH+0x9D7A	0x638F	#CJK UNIFIED IDEOGRAPH+0x9D7B	0x6389	#CJK UNIFIED IDEOGRAPH+0x9D7C	0x639F	#CJK UNIFIED IDEOGRAPH+0x9D7D	0x63B5	#CJK UNIFIED IDEOGRAPH+0x9D7E	0x636B	#CJK UNIFIED IDEOGRAPH+0x9D80	0x6369	#CJK UNIFIED IDEOGRAPH+0x9D81	0x63BE	#CJK UNIFIED IDEOGRAPH+0x9D82	0x63E9	#CJK UNIFIED IDEOGRAPH+0x9D83	0x63C0	#CJK UNIFIED IDEOGRAPH+0x9D84	0x63C6	#CJK UNIFIED IDEOGRAPH+0x9D85	0x63E3	#CJK UNIFIED IDEOGRAPH+0x9D86	0x63C9	#CJK UNIFIED IDEOGRAPH+0x9D87	0x63D2	#CJK UNIFIED IDEOGRAPH+0x9D88	0x63F6	#CJK UNIFIED IDEOGRAPH+0x9D89	0x63C4	#CJK UNIFIED IDEOGRAPH+0x9D8A	0x6416	#CJK UNIFIED IDEOGRAPH+0x9D8B	0x6434	#CJK UNIFIED IDEOGRAPH+0x9D8C	0x6406	#CJK UNIFIED IDEOGRAPH+0x9D8D	0x6413	#CJK UNIFIED IDEOGRAPH+0x9D8E	0x6426	#CJK UNIFIED IDEOGRAPH+0x9D8F	0x6436	#CJK UNIFIED IDEOGRAPH+0x9D90	0x651D	#CJK UNIFIED IDEOGRAPH+0x9D91	0x6417	#CJK UNIFIED IDEOGRAPH+0x9D92	0x6428	#CJK UNIFIED IDEOGRAPH+0x9D93	0x640F	#CJK UNIFIED IDEOGRAPH+0x9D94	0x6467	#CJK UNIFIED IDEOGRAPH+0x9D95	0x646F	#CJK UNIFIED IDEOGRAPH+0x9D96	0x6476	#CJK UNIFIED IDEOGRAPH+0x9D97	0x644E	#CJK UNIFIED IDEOGRAPH+0x9D98	0x652A	#CJK UNIFIED IDEOGRAPH+0x9D99	0x6495	#CJK UNIFIED IDEOGRAPH+0x9D9A	0x6493	#CJK UNIFIED IDEOGRAPH+0x9D9B	0x64A5	#CJK UNIFIED IDEOGRAPH+0x9D9C	0x64A9	#CJK UNIFIED IDEOGRAPH+0x9D9D	0x6488	#CJK UNIFIED IDEOGRAPH+0x9D9E	0x64BC	#CJK UNIFIED IDEOGRAPH+0x9D9F	0x64DA	#CJK UNIFIED IDEOGRAPH+0x9DA0	0x64D2	#CJK UNIFIED IDEOGRAPH+0x9DA1	0x64C5	#CJK UNIFIED IDEOGRAPH+0x9DA2	0x64C7	#CJK UNIFIED IDEOGRAPH+0x9DA3	0x64BB	#CJK UNIFIED IDEOGRAPH+0x9DA4	0x64D8	#CJK UNIFIED IDEOGRAPH+0x9DA5	0x64C2	#CJK UNIFIED IDEOGRAPH+0x9DA6	0x64F1	#CJK UNIFIED IDEOGRAPH+0x9DA7	0x64E7	#CJK UNIFIED IDEOGRAPH+0x9DA8	0x8209	#CJK UNIFIED IDEOGRAPH+0x9DA9	0x64E0	#CJK UNIFIED IDEOGRAPH+0x9DAA	0x64E1	#CJK UNIFIED IDEOGRAPH+0x9DAB	0x62AC	#CJK UNIFIED IDEOGRAPH+0x9DAC	0x64E3	#CJK UNIFIED IDEOGRAPH+0x9DAD	0x64EF	#CJK UNIFIED IDEOGRAPH+0x9DAE	0x652C	#CJK UNIFIED IDEOGRAPH+0x9DAF	0x64F6	#CJK UNIFIED IDEOGRAPH+0x9DB0	0x64F4	#CJK UNIFIED IDEOGRAPH+0x9DB1	0x64F2	#CJK UNIFIED IDEOGRAPH+0x9DB2	0x64FA	#CJK UNIFIED IDEOGRAPH+0x9DB3	0x6500	#CJK UNIFIED IDEOGRAPH+0x9DB4	0x64FD	#CJK UNIFIED IDEOGRAPH+0x9DB5	0x6518	#CJK UNIFIED IDEOGRAPH+0x9DB6	0x651C	#CJK UNIFIED IDEOGRAPH+0x9DB7	0x6505	#CJK UNIFIED IDEOGRAPH+0x9DB8	0x6524	#CJK UNIFIED IDEOGRAPH+0x9DB9	0x6523	#CJK UNIFIED IDEOGRAPH+0x9DBA	0x652B	#CJK UNIFIED IDEOGRAPH+0x9DBB	0x6534	#CJK UNIFIED IDEOGRAPH+0x9DBC	0x6535	#CJK UNIFIED IDEOGRAPH+0x9DBD	0x6537	#CJK UNIFIED IDEOGRAPH+0x9DBE	0x6536	#CJK UNIFIED IDEOGRAPH+0x9DBF	0x6538	#CJK UNIFIED IDEOGRAPH+0x9DC0	0x754B	#CJK UNIFIED IDEOGRAPH+0x9DC1	0x6548	#CJK UNIFIED IDEOGRAPH+0x9DC2	0x6556	#CJK UNIFIED IDEOGRAPH+0x9DC3	0x6555	#CJK UNIFIED IDEOGRAPH+0x9DC4	0x654D	#CJK UNIFIED IDEOGRAPH+0x9DC5	0x6558	#CJK UNIFIED IDEOGRAPH+0x9DC6	0x655E	#CJK UNIFIED IDEOGRAPH+0x9DC7	0x655D	#CJK UNIFIED IDEOGRAPH+0x9DC8	0x6572	#CJK UNIFIED IDEOGRAPH+0x9DC9	0x6578	#CJK UNIFIED IDEOGRAPH+0x9DCA	0x6582	#CJK UNIFIED IDEOGRAPH+0x9DCB	0x6583	#CJK UNIFIED IDEOGRAPH+0x9DCC	0x8B8A	#CJK UNIFIED IDEOGRAPH+0x9DCD	0x659B	#CJK UNIFIED IDEOGRAPH+0x9DCE	0x659F	#CJK UNIFIED IDEOGRAPH+0x9DCF	0x65AB	#CJK UNIFIED IDEOGRAPH+0x9DD0	0x65B7	#CJK UNIFIED IDEOGRAPH+0x9DD1	0x65C3	#CJK UNIFIED IDEOGRAPH+0x9DD2	0x65C6	#CJK UNIFIED IDEOGRAPH+0x9DD3	0x65C1	#CJK UNIFIED IDEOGRAPH+0x9DD4	0x65C4	#CJK UNIFIED IDEOGRAPH+0x9DD5	0x65CC	#CJK UNIFIED IDEOGRAPH+0x9DD6	0x65D2	#CJK UNIFIED IDEOGRAPH+0x9DD7	0x65DB	#CJK UNIFIED IDEOGRAPH+0x9DD8	0x65D9	#CJK UNIFIED IDEOGRAPH+0x9DD9	0x65E0	#CJK UNIFIED IDEOGRAPH+0x9DDA	0x65E1	#CJK UNIFIED IDEOGRAPH+0x9DDB	0x65F1	#CJK UNIFIED IDEOGRAPH+0x9DDC	0x6772	#CJK UNIFIED IDEOGRAPH+0x9DDD	0x660A	#CJK UNIFIED IDEOGRAPH+0x9DDE	0x6603	#CJK UNIFIED IDEOGRAPH+0x9DDF	0x65FB	#CJK UNIFIED IDEOGRAPH+0x9DE0	0x6773	#CJK UNIFIED IDEOGRAPH+0x9DE1	0x6635	#CJK UNIFIED IDEOGRAPH+0x9DE2	0x6636	#CJK UNIFIED IDEOGRAPH+0x9DE3	0x6634	#CJK UNIFIED IDEOGRAPH+0x9DE4	0x661C	#CJK UNIFIED IDEOGRAPH+0x9DE5	0x664F	#CJK UNIFIED IDEOGRAPH+0x9DE6	0x6644	#CJK UNIFIED IDEOGRAPH+0x9DE7	0x6649	#CJK UNIFIED IDEOGRAPH+0x9DE8	0x6641	#CJK UNIFIED IDEOGRAPH+0x9DE9	0x665E	#CJK UNIFIED IDEOGRAPH+0x9DEA	0x665D	#CJK UNIFIED IDEOGRAPH+0x9DEB	0x6664	#CJK UNIFIED IDEOGRAPH+0x9DEC	0x6667	#CJK UNIFIED IDEOGRAPH+0x9DED	0x6668	#CJK UNIFIED IDEOGRAPH+0x9DEE	0x665F	#CJK UNIFIED IDEOGRAPH+0x9DEF	0x6662	#CJK UNIFIED IDEOGRAPH+0x9DF0	0x6670	#CJK UNIFIED IDEOGRAPH+0x9DF1	0x6683	#CJK UNIFIED IDEOGRAPH+0x9DF2	0x6688	#CJK UNIFIED IDEOGRAPH+0x9DF3	0x668E	#CJK UNIFIED IDEOGRAPH+0x9DF4	0x6689	#CJK UNIFIED IDEOGRAPH+0x9DF5	0x6684	#CJK UNIFIED IDEOGRAPH+0x9DF6	0x6698	#CJK UNIFIED IDEOGRAPH+0x9DF7	0x669D	#CJK UNIFIED IDEOGRAPH+0x9DF8	0x66C1	#CJK UNIFIED IDEOGRAPH+0x9DF9	0x66B9	#CJK UNIFIED IDEOGRAPH+0x9DFA	0x66C9	#CJK UNIFIED IDEOGRAPH+0x9DFB	0x66BE	#CJK UNIFIED IDEOGRAPH+0x9DFC	0x66BC	#CJK UNIFIED IDEOGRAPH+0x9E40	0x66C4	#CJK UNIFIED IDEOGRAPH+0x9E41	0x66B8	#CJK UNIFIED IDEOGRAPH+0x9E42	0x66D6	#CJK UNIFIED IDEOGRAPH+0x9E43	0x66DA	#CJK UNIFIED IDEOGRAPH+0x9E44	0x66E0	#CJK UNIFIED IDEOGRAPH+0x9E45	0x663F	#CJK UNIFIED IDEOGRAPH+0x9E46	0x66E6	#CJK UNIFIED IDEOGRAPH+0x9E47	0x66E9	#CJK UNIFIED IDEOGRAPH+0x9E48	0x66F0	#CJK UNIFIED IDEOGRAPH+0x9E49	0x66F5	#CJK UNIFIED IDEOGRAPH+0x9E4A	0x66F7	#CJK UNIFIED IDEOGRAPH+0x9E4B	0x670F	#CJK UNIFIED IDEOGRAPH+0x9E4C	0x6716	#CJK UNIFIED IDEOGRAPH+0x9E4D	0x671E	#CJK UNIFIED IDEOGRAPH+0x9E4E	0x6726	#CJK UNIFIED IDEOGRAPH+0x9E4F	0x6727	#CJK UNIFIED IDEOGRAPH+0x9E50	0x9738	#CJK UNIFIED IDEOGRAPH+0x9E51	0x672E	#CJK UNIFIED IDEOGRAPH+0x9E52	0x673F	#CJK UNIFIED IDEOGRAPH+0x9E53	0x6736	#CJK UNIFIED IDEOGRAPH+0x9E54	0x6741	#CJK UNIFIED IDEOGRAPH+0x9E55	0x6738	#CJK UNIFIED IDEOGRAPH+0x9E56	0x6737	#CJK UNIFIED IDEOGRAPH+0x9E57	0x6746	#CJK UNIFIED IDEOGRAPH+0x9E58	0x675E	#CJK UNIFIED IDEOGRAPH+0x9E59	0x6760	#CJK UNIFIED IDEOGRAPH+0x9E5A	0x6759	#CJK UNIFIED IDEOGRAPH+0x9E5B	0x6763	#CJK UNIFIED IDEOGRAPH+0x9E5C	0x6764	#CJK UNIFIED IDEOGRAPH+0x9E5D	0x6789	#CJK UNIFIED IDEOGRAPH+0x9E5E	0x6770	#CJK UNIFIED IDEOGRAPH+0x9E5F	0x67A9	#CJK UNIFIED IDEOGRAPH+0x9E60	0x677C	#CJK UNIFIED IDEOGRAPH+0x9E61	0x676A	#CJK UNIFIED IDEOGRAPH+0x9E62	0x678C	#CJK UNIFIED IDEOGRAPH+0x9E63	0x678B	#CJK UNIFIED IDEOGRAPH+0x9E64	0x67A6	#CJK UNIFIED IDEOGRAPH+0x9E65	0x67A1	#CJK UNIFIED IDEOGRAPH+0x9E66	0x6785	#CJK UNIFIED IDEOGRAPH+0x9E67	0x67B7	#CJK UNIFIED IDEOGRAPH+0x9E68	0x67EF	#CJK UNIFIED IDEOGRAPH+0x9E69	0x67B4	#CJK UNIFIED IDEOGRAPH+0x9E6A	0x67EC	#CJK UNIFIED IDEOGRAPH+0x9E6B	0x67B3	#CJK UNIFIED IDEOGRAPH+0x9E6C	0x67E9	#CJK UNIFIED IDEOGRAPH+0x9E6D	0x67B8	#CJK UNIFIED IDEOGRAPH+0x9E6E	0x67E4	#CJK UNIFIED IDEOGRAPH+0x9E6F	0x67DE	#CJK UNIFIED IDEOGRAPH+0x9E70	0x67DD	#CJK UNIFIED IDEOGRAPH+0x9E71	0x67E2	#CJK UNIFIED IDEOGRAPH+0x9E72	0x67EE	#CJK UNIFIED IDEOGRAPH+0x9E73	0x67B9	#CJK UNIFIED IDEOGRAPH+0x9E74	0x67CE	#CJK UNIFIED IDEOGRAPH+0x9E75	0x67C6	#CJK UNIFIED IDEOGRAPH+0x9E76	0x67E7	#CJK UNIFIED IDEOGRAPH+0x9E77	0x6A9C	#CJK UNIFIED IDEOGRAPH+0x9E78	0x681E	#CJK UNIFIED IDEOGRAPH+0x9E79	0x6846	#CJK UNIFIED IDEOGRAPH+0x9E7A	0x6829	#CJK UNIFIED IDEOGRAPH+0x9E7B	0x6840	#CJK UNIFIED IDEOGRAPH+0x9E7C	0x684D	#CJK UNIFIED IDEOGRAPH+0x9E7D	0x6832	#CJK UNIFIED IDEOGRAPH+0x9E7E	0x684E	#CJK UNIFIED IDEOGRAPH+0x9E80	0x68B3	#CJK UNIFIED IDEOGRAPH+0x9E81	0x682B	#CJK UNIFIED IDEOGRAPH+0x9E82	0x6859	#CJK UNIFIED IDEOGRAPH+0x9E83	0x6863	#CJK UNIFIED IDEOGRAPH+0x9E84	0x6877	#CJK UNIFIED IDEOGRAPH+0x9E85	0x687F	#CJK UNIFIED IDEOGRAPH+0x9E86	0x689F	#CJK UNIFIED IDEOGRAPH+0x9E87	0x688F	#CJK UNIFIED IDEOGRAPH+0x9E88	0x68AD	#CJK UNIFIED IDEOGRAPH+0x9E89	0x6894	#CJK UNIFIED IDEOGRAPH+0x9E8A	0x689D	#CJK UNIFIED IDEOGRAPH+0x9E8B	0x689B	#CJK UNIFIED IDEOGRAPH+0x9E8C	0x6883	#CJK UNIFIED IDEOGRAPH+0x9E8D	0x6AAE	#CJK UNIFIED IDEOGRAPH+0x9E8E	0x68B9	#CJK UNIFIED IDEOGRAPH+0x9E8F	0x6874	#CJK UNIFIED IDEOGRAPH+0x9E90	0x68B5	#CJK UNIFIED IDEOGRAPH+0x9E91	0x68A0	#CJK UNIFIED IDEOGRAPH+0x9E92	0x68BA	#CJK UNIFIED IDEOGRAPH+0x9E93	0x690F	#CJK UNIFIED IDEOGRAPH+0x9E94	0x688D	#CJK UNIFIED IDEOGRAPH+0x9E95	0x687E	#CJK UNIFIED IDEOGRAPH+0x9E96	0x6901	#CJK UNIFIED IDEOGRAPH+0x9E97	0x68CA	#CJK UNIFIED IDEOGRAPH+0x9E98	0x6908	#CJK UNIFIED IDEOGRAPH+0x9E99	0x68D8	#CJK UNIFIED IDEOGRAPH+0x9E9A	0x6922	#CJK UNIFIED IDEOGRAPH+0x9E9B	0x6926	#CJK UNIFIED IDEOGRAPH+0x9E9C	0x68E1	#CJK UNIFIED IDEOGRAPH+0x9E9D	0x690C	#CJK UNIFIED IDEOGRAPH+0x9E9E	0x68CD	#CJK UNIFIED IDEOGRAPH+0x9E9F	0x68D4	#CJK UNIFIED IDEOGRAPH+0x9EA0	0x68E7	#CJK UNIFIED IDEOGRAPH+0x9EA1	0x68D5	#CJK UNIFIED IDEOGRAPH+0x9EA2	0x6936	#CJK UNIFIED IDEOGRAPH+0x9EA3	0x6912	#CJK UNIFIED IDEOGRAPH+0x9EA4	0x6904	#CJK UNIFIED IDEOGRAPH+0x9EA5	0x68D7	#CJK UNIFIED IDEOGRAPH+0x9EA6	0x68E3	#CJK UNIFIED IDEOGRAPH+0x9EA7	0x6925	#CJK UNIFIED IDEOGRAPH+0x9EA8	0x68F9	#CJK UNIFIED IDEOGRAPH+0x9EA9	0x68E0	#CJK UNIFIED IDEOGRAPH+0x9EAA	0x68EF	#CJK UNIFIED IDEOGRAPH+0x9EAB	0x6928	#CJK UNIFIED IDEOGRAPH+0x9EAC	0x692A	#CJK UNIFIED IDEOGRAPH+0x9EAD	0x691A	#CJK UNIFIED IDEOGRAPH+0x9EAE	0x6923	#CJK UNIFIED IDEOGRAPH+0x9EAF	0x6921	#CJK UNIFIED IDEOGRAPH+0x9EB0	0x68C6	#CJK UNIFIED IDEOGRAPH+0x9EB1	0x6979	#CJK UNIFIED IDEOGRAPH+0x9EB2	0x6977	#CJK UNIFIED IDEOGRAPH+0x9EB3	0x695C	#CJK UNIFIED IDEOGRAPH+0x9EB4	0x6978	#CJK UNIFIED IDEOGRAPH+0x9EB5	0x696B	#CJK UNIFIED IDEOGRAPH+0x9EB6	0x6954	#CJK UNIFIED IDEOGRAPH+0x9EB7	0x697E	#CJK UNIFIED IDEOGRAPH+0x9EB8	0x696E	#CJK UNIFIED IDEOGRAPH+0x9EB9	0x6939	#CJK UNIFIED IDEOGRAPH+0x9EBA	0x6974	#CJK UNIFIED IDEOGRAPH+0x9EBB	0x693D	#CJK UNIFIED IDEOGRAPH+0x9EBC	0x6959	#CJK UNIFIED IDEOGRAPH+0x9EBD	0x6930	#CJK UNIFIED IDEOGRAPH+0x9EBE	0x6961	#CJK UNIFIED IDEOGRAPH+0x9EBF	0x695E	#CJK UNIFIED IDEOGRAPH+0x9EC0	0x695D	#CJK UNIFIED IDEOGRAPH+0x9EC1	0x6981	#CJK UNIFIED IDEOGRAPH+0x9EC2	0x696A	#CJK UNIFIED IDEOGRAPH+0x9EC3	0x69B2	#CJK UNIFIED IDEOGRAPH+0x9EC4	0x69AE	#CJK UNIFIED IDEOGRAPH+0x9EC5	0x69D0	#CJK UNIFIED IDEOGRAPH+0x9EC6	0x69BF	#CJK UNIFIED IDEOGRAPH+0x9EC7	0x69C1	#CJK UNIFIED IDEOGRAPH+0x9EC8	0x69D3	#CJK UNIFIED IDEOGRAPH+0x9EC9	0x69BE	#CJK UNIFIED IDEOGRAPH+0x9ECA	0x69CE	#CJK UNIFIED IDEOGRAPH+0x9ECB	0x5BE8	#CJK UNIFIED IDEOGRAPH+0x9ECC	0x69CA	#CJK UNIFIED IDEOGRAPH+0x9ECD	0x69DD	#CJK UNIFIED IDEOGRAPH+0x9ECE	0x69BB	#CJK UNIFIED IDEOGRAPH+0x9ECF	0x69C3	#CJK UNIFIED IDEOGRAPH+0x9ED0	0x69A7	#CJK UNIFIED IDEOGRAPH+0x9ED1	0x6A2E	#CJK UNIFIED IDEOGRAPH+0x9ED2	0x6991	#CJK UNIFIED IDEOGRAPH+0x9ED3	0x69A0	#CJK UNIFIED IDEOGRAPH+0x9ED4	0x699C	#CJK UNIFIED IDEOGRAPH+0x9ED5	0x6995	#CJK UNIFIED IDEOGRAPH+0x9ED6	0x69B4	#CJK UNIFIED IDEOGRAPH+0x9ED7	0x69DE	#CJK UNIFIED IDEOGRAPH+0x9ED8	0x69E8	#CJK UNIFIED IDEOGRAPH+0x9ED9	0x6A02	#CJK UNIFIED IDEOGRAPH+0x9EDA	0x6A1B	#CJK UNIFIED IDEOGRAPH+0x9EDB	0x69FF	#CJK UNIFIED IDEOGRAPH+0x9EDC	0x6B0A	#CJK UNIFIED IDEOGRAPH+0x9EDD	0x69F9	#CJK UNIFIED IDEOGRAPH+0x9EDE	0x69F2	#CJK UNIFIED IDEOGRAPH+0x9EDF	0x69E7	#CJK UNIFIED IDEOGRAPH+0x9EE0	0x6A05	#CJK UNIFIED IDEOGRAPH+0x9EE1	0x69B1	#CJK UNIFIED IDEOGRAPH+0x9EE2	0x6A1E	#CJK UNIFIED IDEOGRAPH+0x9EE3	0x69ED	#CJK UNIFIED IDEOGRAPH+0x9EE4	0x6A14	#CJK UNIFIED IDEOGRAPH+0x9EE5	0x69EB	#CJK UNIFIED IDEOGRAPH+0x9EE6	0x6A0A	#CJK UNIFIED IDEOGRAPH+0x9EE7	0x6A12	#CJK UNIFIED IDEOGRAPH+0x9EE8	0x6AC1	#CJK UNIFIED IDEOGRAPH+0x9EE9	0x6A23	#CJK UNIFIED IDEOGRAPH+0x9EEA	0x6A13	#CJK UNIFIED IDEOGRAPH+0x9EEB	0x6A44	#CJK UNIFIED IDEOGRAPH+0x9EEC	0x6A0C	#CJK UNIFIED IDEOGRAPH+0x9EED	0x6A72	#CJK UNIFIED IDEOGRAPH+0x9EEE	0x6A36	#CJK UNIFIED IDEOGRAPH+0x9EEF	0x6A78	#CJK UNIFIED IDEOGRAPH+0x9EF0	0x6A47	#CJK UNIFIED IDEOGRAPH+0x9EF1	0x6A62	#CJK UNIFIED IDEOGRAPH+0x9EF2	0x6A59	#CJK UNIFIED IDEOGRAPH+0x9EF3	0x6A66	#CJK UNIFIED IDEOGRAPH+0x9EF4	0x6A48	#CJK UNIFIED IDEOGRAPH+0x9EF5	0x6A38	#CJK UNIFIED IDEOGRAPH+0x9EF6	0x6A22	#CJK UNIFIED IDEOGRAPH+0x9EF7	0x6A90	#CJK UNIFIED IDEOGRAPH+0x9EF8	0x6A8D	#CJK UNIFIED IDEOGRAPH+0x9EF9	0x6AA0	#CJK UNIFIED IDEOGRAPH+0x9EFA	0x6A84	#CJK UNIFIED IDEOGRAPH+0x9EFB	0x6AA2	#CJK UNIFIED IDEOGRAPH+0x9EFC	0x6AA3	#CJK UNIFIED IDEOGRAPH+0x9F40	0x6A97	#CJK UNIFIED IDEOGRAPH+0x9F41	0x8617	#CJK UNIFIED IDEOGRAPH+0x9F42	0x6ABB	#CJK UNIFIED IDEOGRAPH+0x9F43	0x6AC3	#CJK UNIFIED IDEOGRAPH+0x9F44	0x6AC2	#CJK UNIFIED IDEOGRAPH+0x9F45	0x6AB8	#CJK UNIFIED IDEOGRAPH+0x9F46	0x6AB3	#CJK UNIFIED IDEOGRAPH+0x9F47	0x6AAC	#CJK UNIFIED IDEOGRAPH+0x9F48	0x6ADE	#CJK UNIFIED IDEOGRAPH+0x9F49	0x6AD1	#CJK UNIFIED IDEOGRAPH+0x9F4A	0x6ADF	#CJK UNIFIED IDEOGRAPH+0x9F4B	0x6AAA	#CJK UNIFIED IDEOGRAPH+0x9F4C	0x6ADA	#CJK UNIFIED IDEOGRAPH+0x9F4D	0x6AEA	#CJK UNIFIED IDEOGRAPH+0x9F4E	0x6AFB	#CJK UNIFIED IDEOGRAPH+0x9F4F	0x6B05	#CJK UNIFIED IDEOGRAPH+0x9F50	0x8616	#CJK UNIFIED IDEOGRAPH+0x9F51	0x6AFA	#CJK UNIFIED IDEOGRAPH+0x9F52	0x6B12	#CJK UNIFIED IDEOGRAPH+0x9F53	0x6B16	#CJK UNIFIED IDEOGRAPH+0x9F54	0x9B31	#CJK UNIFIED IDEOGRAPH+0x9F55	0x6B1F	#CJK UNIFIED IDEOGRAPH+0x9F56	0x6B38	#CJK UNIFIED IDEOGRAPH+0x9F57	0x6B37	#CJK UNIFIED IDEOGRAPH+0x9F58	0x76DC	#CJK UNIFIED IDEOGRAPH+0x9F59	0x6B39	#CJK UNIFIED IDEOGRAPH+0x9F5A	0x98EE	#CJK UNIFIED IDEOGRAPH+0x9F5B	0x6B47	#CJK UNIFIED IDEOGRAPH+0x9F5C	0x6B43	#CJK UNIFIED IDEOGRAPH+0x9F5D	0x6B49	#CJK UNIFIED IDEOGRAPH+0x9F5E	0x6B50	#CJK UNIFIED IDEOGRAPH+0x9F5F	0x6B59	#CJK UNIFIED IDEOGRAPH+0x9F60	0x6B54	#CJK UNIFIED IDEOGRAPH+0x9F61	0x6B5B	#CJK UNIFIED IDEOGRAPH+0x9F62	0x6B5F	#CJK UNIFIED IDEOGRAPH+0x9F63	0x6B61	#CJK UNIFIED IDEOGRAPH+0x9F64	0x6B78	#CJK UNIFIED IDEOGRAPH+0x9F65	0x6B79	#CJK UNIFIED IDEOGRAPH+0x9F66	0x6B7F	#CJK UNIFIED IDEOGRAPH+0x9F67	0x6B80	#CJK UNIFIED IDEOGRAPH+0x9F68	0x6B84	#CJK UNIFIED IDEOGRAPH+0x9F69	0x6B83	#CJK UNIFIED IDEOGRAPH+0x9F6A	0x6B8D	#CJK UNIFIED IDEOGRAPH+0x9F6B	0x6B98	#CJK UNIFIED IDEOGRAPH+0x9F6C	0x6B95	#CJK UNIFIED IDEOGRAPH+0x9F6D	0x6B9E	#CJK UNIFIED IDEOGRAPH+0x9F6E	0x6BA4	#CJK UNIFIED IDEOGRAPH+0x9F6F	0x6BAA	#CJK UNIFIED IDEOGRAPH+0x9F70	0x6BAB	#CJK UNIFIED IDEOGRAPH+0x9F71	0x6BAF	#CJK UNIFIED IDEOGRAPH+0x9F72	0x6BB2	#CJK UNIFIED IDEOGRAPH+0x9F73	0x6BB1	#CJK UNIFIED IDEOGRAPH+0x9F74	0x6BB3	#CJK UNIFIED IDEOGRAPH+0x9F75	0x6BB7	#CJK UNIFIED IDEOGRAPH+0x9F76	0x6BBC	#CJK UNIFIED IDEOGRAPH+0x9F77	0x6BC6	#CJK UNIFIED IDEOGRAPH+0x9F78	0x6BCB	#CJK UNIFIED IDEOGRAPH+0x9F79	0x6BD3	#CJK UNIFIED IDEOGRAPH+0x9F7A	0x6BDF	#CJK UNIFIED IDEOGRAPH+0x9F7B	0x6BEC	#CJK UNIFIED IDEOGRAPH+0x9F7C	0x6BEB	#CJK UNIFIED IDEOGRAPH+0x9F7D	0x6BF3	#CJK UNIFIED IDEOGRAPH+0x9F7E	0x6BEF	#CJK UNIFIED IDEOGRAPH+0x9F80	0x9EBE	#CJK UNIFIED IDEOGRAPH+0x9F81	0x6C08	#CJK UNIFIED IDEOGRAPH+0x9F82	0x6C13	#CJK UNIFIED IDEOGRAPH+0x9F83	0x6C14	#CJK UNIFIED IDEOGRAPH+0x9F84	0x6C1B	#CJK UNIFIED IDEOGRAPH+0x9F85	0x6C24	#CJK UNIFIED IDEOGRAPH+0x9F86	0x6C23	#CJK UNIFIED IDEOGRAPH+0x9F87	0x6C5E	#CJK UNIFIED IDEOGRAPH+0x9F88	0x6C55	#CJK UNIFIED IDEOGRAPH+0x9F89	0x6C62	#CJK UNIFIED IDEOGRAPH+0x9F8A	0x6C6A	#CJK UNIFIED IDEOGRAPH+0x9F8B	0x6C82	#CJK UNIFIED IDEOGRAPH+0x9F8C	0x6C8D	#CJK UNIFIED IDEOGRAPH+0x9F8D	0x6C9A	#CJK UNIFIED IDEOGRAPH+0x9F8E	0x6C81	#CJK UNIFIED IDEOGRAPH+0x9F8F	0x6C9B	#CJK UNIFIED IDEOGRAPH+0x9F90	0x6C7E	#CJK UNIFIED IDEOGRAPH+0x9F91	0x6C68	#CJK UNIFIED IDEOGRAPH+0x9F92	0x6C73	#CJK UNIFIED IDEOGRAPH+0x9F93	0x6C92	#CJK UNIFIED IDEOGRAPH+0x9F94	0x6C90	#CJK UNIFIED IDEOGRAPH+0x9F95	0x6CC4	#CJK UNIFIED IDEOGRAPH+0x9F96	0x6CF1	#CJK UNIFIED IDEOGRAPH+0x9F97	0x6CD3	#CJK UNIFIED IDEOGRAPH+0x9F98	0x6CBD	#CJK UNIFIED IDEOGRAPH+0x9F99	0x6CD7	#CJK UNIFIED IDEOGRAPH+0x9F9A	0x6CC5	#CJK UNIFIED IDEOGRAPH+0x9F9B	0x6CDD	#CJK UNIFIED IDEOGRAPH+0x9F9C	0x6CAE	#CJK UNIFIED IDEOGRAPH+0x9F9D	0x6CB1	#CJK UNIFIED IDEOGRAPH+0x9F9E	0x6CBE	#CJK UNIFIED IDEOGRAPH+0x9F9F	0x6CBA	#CJK UNIFIED IDEOGRAPH+0x9FA0	0x6CDB	#CJK UNIFIED IDEOGRAPH+0x9FA1	0x6CEF	#CJK UNIFIED IDEOGRAPH+0x9FA2	0x6CD9	#CJK UNIFIED IDEOGRAPH+0x9FA3	0x6CEA	#CJK UNIFIED IDEOGRAPH+0x9FA4	0x6D1F	#CJK UNIFIED IDEOGRAPH+0x9FA5	0x884D	#CJK UNIFIED IDEOGRAPH+0x9FA6	0x6D36	#CJK UNIFIED IDEOGRAPH+0x9FA7	0x6D2B	#CJK UNIFIED IDEOGRAPH+0x9FA8	0x6D3D	#CJK UNIFIED IDEOGRAPH+0x9FA9	0x6D38	#CJK UNIFIED IDEOGRAPH+0x9FAA	0x6D19	#CJK UNIFIED IDEOGRAPH+0x9FAB	0x6D35	#CJK UNIFIED IDEOGRAPH+0x9FAC	0x6D33	#CJK UNIFIED IDEOGRAPH+0x9FAD	0x6D12	#CJK UNIFIED IDEOGRAPH+0x9FAE	0x6D0C	#CJK UNIFIED IDEOGRAPH+0x9FAF	0x6D63	#CJK UNIFIED IDEOGRAPH+0x9FB0	0x6D93	#CJK UNIFIED IDEOGRAPH+0x9FB1	0x6D64	#CJK UNIFIED IDEOGRAPH+0x9FB2	0x6D5A	#CJK UNIFIED IDEOGRAPH+0x9FB3	0x6D79	#CJK UNIFIED IDEOGRAPH+0x9FB4	0x6D59	#CJK UNIFIED IDEOGRAPH+0x9FB5	0x6D8E	#CJK UNIFIED IDEOGRAPH+0x9FB6	0x6D95	#CJK UNIFIED IDEOGRAPH+0x9FB7	0x6FE4	#CJK UNIFIED IDEOGRAPH+0x9FB8	0x6D85	#CJK UNIFIED IDEOGRAPH+0x9FB9	0x6DF9	#CJK UNIFIED IDEOGRAPH+0x9FBA	0x6E15	#CJK UNIFIED IDEOGRAPH+0x9FBB	0x6E0A	#CJK UNIFIED IDEOGRAPH+0x9FBC	0x6DB5	#CJK UNIFIED IDEOGRAPH+0x9FBD	0x6DC7	#CJK UNIFIED IDEOGRAPH+0x9FBE	0x6DE6	#CJK UNIFIED IDEOGRAPH+0x9FBF	0x6DB8	#CJK UNIFIED IDEOGRAPH+0x9FC0	0x6DC6	#CJK UNIFIED IDEOGRAPH+0x9FC1	0x6DEC	#CJK UNIFIED IDEOGRAPH+0x9FC2	0x6DDE	#CJK UNIFIED IDEOGRAPH+0x9FC3	0x6DCC	#CJK UNIFIED IDEOGRAPH+0x9FC4	0x6DE8	#CJK UNIFIED IDEOGRAPH+0x9FC5	0x6DD2	#CJK UNIFIED IDEOGRAPH+0x9FC6	0x6DC5	#CJK UNIFIED IDEOGRAPH+0x9FC7	0x6DFA	#CJK UNIFIED IDEOGRAPH+0x9FC8	0x6DD9	#CJK UNIFIED IDEOGRAPH+0x9FC9	0x6DE4	#CJK UNIFIED IDEOGRAPH+0x9FCA	0x6DD5	#CJK UNIFIED IDEOGRAPH+0x9FCB	0x6DEA	#CJK UNIFIED IDEOGRAPH+0x9FCC	0x6DEE	#CJK UNIFIED IDEOGRAPH+0x9FCD	0x6E2D	#CJK UNIFIED IDEOGRAPH+0x9FCE	0x6E6E	#CJK UNIFIED IDEOGRAPH+0x9FCF	0x6E2E	#CJK UNIFIED IDEOGRAPH+0x9FD0	0x6E19	#CJK UNIFIED IDEOGRAPH+0x9FD1	0x6E72	#CJK UNIFIED IDEOGRAPH+0x9FD2	0x6E5F	#CJK UNIFIED IDEOGRAPH+0x9FD3	0x6E3E	#CJK UNIFIED IDEOGRAPH+0x9FD4	0x6E23	#CJK UNIFIED IDEOGRAPH+0x9FD5	0x6E6B	#CJK UNIFIED IDEOGRAPH+0x9FD6	0x6E2B	#CJK UNIFIED IDEOGRAPH+0x9FD7	0x6E76	#CJK UNIFIED IDEOGRAPH+0x9FD8	0x6E4D	#CJK UNIFIED IDEOGRAPH+0x9FD9	0x6E1F	#CJK UNIFIED IDEOGRAPH+0x9FDA	0x6E43	#CJK UNIFIED IDEOGRAPH+0x9FDB	0x6E3A	#CJK UNIFIED IDEOGRAPH+0x9FDC	0x6E4E	#CJK UNIFIED IDEOGRAPH+0x9FDD	0x6E24	#CJK UNIFIED IDEOGRAPH+0x9FDE	0x6EFF	#CJK UNIFIED IDEOGRAPH+0x9FDF	0x6E1D	#CJK UNIFIED IDEOGRAPH+0x9FE0	0x6E38	#CJK UNIFIED IDEOGRAPH+0x9FE1	0x6E82	#CJK UNIFIED IDEOGRAPH+0x9FE2	0x6EAA	#CJK UNIFIED IDEOGRAPH+0x9FE3	0x6E98	#CJK UNIFIED IDEOGRAPH+0x9FE4	0x6EC9	#CJK UNIFIED IDEOGRAPH+0x9FE5	0x6EB7	#CJK UNIFIED IDEOGRAPH+0x9FE6	0x6ED3	#CJK UNIFIED IDEOGRAPH+0x9FE7	0x6EBD	#CJK UNIFIED IDEOGRAPH+0x9FE8	0x6EAF	#CJK UNIFIED IDEOGRAPH+0x9FE9	0x6EC4	#CJK UNIFIED IDEOGRAPH+0x9FEA	0x6EB2	#CJK UNIFIED IDEOGRAPH+0x9FEB	0x6ED4	#CJK UNIFIED IDEOGRAPH+0x9FEC	0x6ED5	#CJK UNIFIED IDEOGRAPH+0x9FED	0x6E8F	#CJK UNIFIED IDEOGRAPH+0x9FEE	0x6EA5	#CJK UNIFIED IDEOGRAPH+0x9FEF	0x6EC2	#CJK UNIFIED IDEOGRAPH+0x9FF0	0x6E9F	#CJK UNIFIED IDEOGRAPH+0x9FF1	0x6F41	#CJK UNIFIED IDEOGRAPH+0x9FF2	0x6F11	#CJK UNIFIED IDEOGRAPH+0x9FF3	0x704C	#CJK UNIFIED IDEOGRAPH+0x9FF4	0x6EEC	#CJK UNIFIED IDEOGRAPH+0x9FF5	0x6EF8	#CJK UNIFIED IDEOGRAPH+0x9FF6	0x6EFE	#CJK UNIFIED IDEOGRAPH+0x9FF7	0x6F3F	#CJK UNIFIED IDEOGRAPH+0x9FF8	0x6EF2	#CJK UNIFIED IDEOGRAPH+0x9FF9	0x6F31	#CJK UNIFIED IDEOGRAPH+0x9FFA	0x6EEF	#CJK UNIFIED IDEOGRAPH+0x9FFB	0x6F32	#CJK UNIFIED IDEOGRAPH+0x9FFC	0x6ECC	#CJK UNIFIED IDEOGRAPH+0xE040	0x6F3E	#CJK UNIFIED IDEOGRAPH+0xE041	0x6F13	#CJK UNIFIED IDEOGRAPH+0xE042	0x6EF7	#CJK UNIFIED IDEOGRAPH+0xE043	0x6F86	#CJK UNIFIED IDEOGRAPH+0xE044	0x6F7A	#CJK UNIFIED IDEOGRAPH+0xE045	0x6F78	#CJK UNIFIED IDEOGRAPH+0xE046	0x6F81	#CJK UNIFIED IDEOGRAPH+0xE047	0x6F80	#CJK UNIFIED IDEOGRAPH+0xE048	0x6F6F	#CJK UNIFIED IDEOGRAPH+0xE049	0x6F5B	#CJK UNIFIED IDEOGRAPH+0xE04A	0x6FF3	#CJK UNIFIED IDEOGRAPH+0xE04B	0x6F6D	#CJK UNIFIED IDEOGRAPH+0xE04C	0x6F82	#CJK UNIFIED IDEOGRAPH+0xE04D	0x6F7C	#CJK UNIFIED IDEOGRAPH+0xE04E	0x6F58	#CJK UNIFIED IDEOGRAPH+0xE04F	0x6F8E	#CJK UNIFIED IDEOGRAPH+0xE050	0x6F91	#CJK UNIFIED IDEOGRAPH+0xE051	0x6FC2	#CJK UNIFIED IDEOGRAPH+0xE052	0x6F66	#CJK UNIFIED IDEOGRAPH+0xE053	0x6FB3	#CJK UNIFIED IDEOGRAPH+0xE054	0x6FA3	#CJK UNIFIED IDEOGRAPH+0xE055	0x6FA1	#CJK UNIFIED IDEOGRAPH+0xE056	0x6FA4	#CJK UNIFIED IDEOGRAPH+0xE057	0x6FB9	#CJK UNIFIED IDEOGRAPH+0xE058	0x6FC6	#CJK UNIFIED IDEOGRAPH+0xE059	0x6FAA	#CJK UNIFIED IDEOGRAPH+0xE05A	0x6FDF	#CJK UNIFIED IDEOGRAPH+0xE05B	0x6FD5	#CJK UNIFIED IDEOGRAPH+0xE05C	0x6FEC	#CJK UNIFIED IDEOGRAPH+0xE05D	0x6FD4	#CJK UNIFIED IDEOGRAPH+0xE05E	0x6FD8	#CJK UNIFIED IDEOGRAPH+0xE05F	0x6FF1	#CJK UNIFIED IDEOGRAPH+0xE060	0x6FEE	#CJK UNIFIED IDEOGRAPH+0xE061	0x6FDB	#CJK UNIFIED IDEOGRAPH+0xE062	0x7009	#CJK UNIFIED IDEOGRAPH+0xE063	0x700B	#CJK UNIFIED IDEOGRAPH+0xE064	0x6FFA	#CJK UNIFIED IDEOGRAPH+0xE065	0x7011	#CJK UNIFIED IDEOGRAPH+0xE066	0x7001	#CJK UNIFIED IDEOGRAPH+0xE067	0x700F	#CJK UNIFIED IDEOGRAPH+0xE068	0x6FFE	#CJK UNIFIED IDEOGRAPH+0xE069	0x701B	#CJK UNIFIED IDEOGRAPH+0xE06A	0x701A	#CJK UNIFIED IDEOGRAPH+0xE06B	0x6F74	#CJK UNIFIED IDEOGRAPH+0xE06C	0x701D	#CJK UNIFIED IDEOGRAPH+0xE06D	0x7018	#CJK UNIFIED IDEOGRAPH+0xE06E	0x701F	#CJK UNIFIED IDEOGRAPH+0xE06F	0x7030	#CJK UNIFIED IDEOGRAPH+0xE070	0x703E	#CJK UNIFIED IDEOGRAPH+0xE071	0x7032	#CJK UNIFIED IDEOGRAPH+0xE072	0x7051	#CJK UNIFIED IDEOGRAPH+0xE073	0x7063	#CJK UNIFIED IDEOGRAPH+0xE074	0x7099	#CJK UNIFIED IDEOGRAPH+0xE075	0x7092	#CJK UNIFIED IDEOGRAPH+0xE076	0x70AF	#CJK UNIFIED IDEOGRAPH+0xE077	0x70F1	#CJK UNIFIED IDEOGRAPH+0xE078	0x70AC	#CJK UNIFIED IDEOGRAPH+0xE079	0x70B8	#CJK UNIFIED IDEOGRAPH+0xE07A	0x70B3	#CJK UNIFIED IDEOGRAPH+0xE07B	0x70AE	#CJK UNIFIED IDEOGRAPH+0xE07C	0x70DF	#CJK UNIFIED IDEOGRAPH+0xE07D	0x70CB	#CJK UNIFIED IDEOGRAPH+0xE07E	0x70DD	#CJK UNIFIED IDEOGRAPH+0xE080	0x70D9	#CJK UNIFIED IDEOGRAPH+0xE081	0x7109	#CJK UNIFIED IDEOGRAPH+0xE082	0x70FD	#CJK UNIFIED IDEOGRAPH+0xE083	0x711C	#CJK UNIFIED IDEOGRAPH+0xE084	0x7119	#CJK UNIFIED IDEOGRAPH+0xE085	0x7165	#CJK UNIFIED IDEOGRAPH+0xE086	0x7155	#CJK UNIFIED IDEOGRAPH+0xE087	0x7188	#CJK UNIFIED IDEOGRAPH+0xE088	0x7166	#CJK UNIFIED IDEOGRAPH+0xE089	0x7162	#CJK UNIFIED IDEOGRAPH+0xE08A	0x714C	#CJK UNIFIED IDEOGRAPH+0xE08B	0x7156	#CJK UNIFIED IDEOGRAPH+0xE08C	0x716C	#CJK UNIFIED IDEOGRAPH+0xE08D	0x718F	#CJK UNIFIED IDEOGRAPH+0xE08E	0x71FB	#CJK UNIFIED IDEOGRAPH+0xE08F	0x7184	#CJK UNIFIED IDEOGRAPH+0xE090	0x7195	#CJK UNIFIED IDEOGRAPH+0xE091	0x71A8	#CJK UNIFIED IDEOGRAPH+0xE092	0x71AC	#CJK UNIFIED IDEOGRAPH+0xE093	0x71D7	#CJK UNIFIED IDEOGRAPH+0xE094	0x71B9	#CJK UNIFIED IDEOGRAPH+0xE095	0x71BE	#CJK UNIFIED IDEOGRAPH+0xE096	0x71D2	#CJK UNIFIED IDEOGRAPH+0xE097	0x71C9	#CJK UNIFIED IDEOGRAPH+0xE098	0x71D4	#CJK UNIFIED IDEOGRAPH+0xE099	0x71CE	#CJK UNIFIED IDEOGRAPH+0xE09A	0x71E0	#CJK UNIFIED IDEOGRAPH+0xE09B	0x71EC	#CJK UNIFIED IDEOGRAPH+0xE09C	0x71E7	#CJK UNIFIED IDEOGRAPH+0xE09D	0x71F5	#CJK UNIFIED IDEOGRAPH+0xE09E	0x71FC	#CJK UNIFIED IDEOGRAPH+0xE09F	0x71F9	#CJK UNIFIED IDEOGRAPH+0xE0A0	0x71FF	#CJK UNIFIED IDEOGRAPH+0xE0A1	0x720D	#CJK UNIFIED IDEOGRAPH+0xE0A2	0x7210	#CJK UNIFIED IDEOGRAPH+0xE0A3	0x721B	#CJK UNIFIED IDEOGRAPH+0xE0A4	0x7228	#CJK UNIFIED IDEOGRAPH+0xE0A5	0x722D	#CJK UNIFIED IDEOGRAPH+0xE0A6	0x722C	#CJK UNIFIED IDEOGRAPH+0xE0A7	0x7230	#CJK UNIFIED IDEOGRAPH+0xE0A8	0x7232	#CJK UNIFIED IDEOGRAPH+0xE0A9	0x723B	#CJK UNIFIED IDEOGRAPH+0xE0AA	0x723C	#CJK UNIFIED IDEOGRAPH+0xE0AB	0x723F	#CJK UNIFIED IDEOGRAPH+0xE0AC	0x7240	#CJK UNIFIED IDEOGRAPH+0xE0AD	0x7246	#CJK UNIFIED IDEOGRAPH+0xE0AE	0x724B	#CJK UNIFIED IDEOGRAPH+0xE0AF	0x7258	#CJK UNIFIED IDEOGRAPH+0xE0B0	0x7274	#CJK UNIFIED IDEOGRAPH+0xE0B1	0x727E	#CJK UNIFIED IDEOGRAPH+0xE0B2	0x7282	#CJK UNIFIED IDEOGRAPH+0xE0B3	0x7281	#CJK UNIFIED IDEOGRAPH+0xE0B4	0x7287	#CJK UNIFIED IDEOGRAPH+0xE0B5	0x7292	#CJK UNIFIED IDEOGRAPH+0xE0B6	0x7296	#CJK UNIFIED IDEOGRAPH+0xE0B7	0x72A2	#CJK UNIFIED IDEOGRAPH+0xE0B8	0x72A7	#CJK UNIFIED IDEOGRAPH+0xE0B9	0x72B9	#CJK UNIFIED IDEOGRAPH+0xE0BA	0x72B2	#CJK UNIFIED IDEOGRAPH+0xE0BB	0x72C3	#CJK UNIFIED IDEOGRAPH+0xE0BC	0x72C6	#CJK UNIFIED IDEOGRAPH+0xE0BD	0x72C4	#CJK UNIFIED IDEOGRAPH+0xE0BE	0x72CE	#CJK UNIFIED IDEOGRAPH+0xE0BF	0x72D2	#CJK UNIFIED IDEOGRAPH+0xE0C0	0x72E2	#CJK UNIFIED IDEOGRAPH+0xE0C1	0x72E0	#CJK UNIFIED IDEOGRAPH+0xE0C2	0x72E1	#CJK UNIFIED IDEOGRAPH+0xE0C3	0x72F9	#CJK UNIFIED IDEOGRAPH+0xE0C4	0x72F7	#CJK UNIFIED IDEOGRAPH+0xE0C5	0x500F	#CJK UNIFIED IDEOGRAPH+0xE0C6	0x7317	#CJK UNIFIED IDEOGRAPH+0xE0C7	0x730A	#CJK UNIFIED IDEOGRAPH+0xE0C8	0x731C	#CJK UNIFIED IDEOGRAPH+0xE0C9	0x7316	#CJK UNIFIED IDEOGRAPH+0xE0CA	0x731D	#CJK UNIFIED IDEOGRAPH+0xE0CB	0x7334	#CJK UNIFIED IDEOGRAPH+0xE0CC	0x732F	#CJK UNIFIED IDEOGRAPH+0xE0CD	0x7329	#CJK UNIFIED IDEOGRAPH+0xE0CE	0x7325	#CJK UNIFIED IDEOGRAPH+0xE0CF	0x733E	#CJK UNIFIED IDEOGRAPH+0xE0D0	0x734E	#CJK UNIFIED IDEOGRAPH+0xE0D1	0x734F	#CJK UNIFIED IDEOGRAPH+0xE0D2	0x9ED8	#CJK UNIFIED IDEOGRAPH+0xE0D3	0x7357	#CJK UNIFIED IDEOGRAPH+0xE0D4	0x736A	#CJK UNIFIED IDEOGRAPH+0xE0D5	0x7368	#CJK UNIFIED IDEOGRAPH+0xE0D6	0x7370	#CJK UNIFIED IDEOGRAPH+0xE0D7	0x7378	#CJK UNIFIED IDEOGRAPH+0xE0D8	0x7375	#CJK UNIFIED IDEOGRAPH+0xE0D9	0x737B	#CJK UNIFIED IDEOGRAPH+0xE0DA	0x737A	#CJK UNIFIED IDEOGRAPH+0xE0DB	0x73C8	#CJK UNIFIED IDEOGRAPH+0xE0DC	0x73B3	#CJK UNIFIED IDEOGRAPH+0xE0DD	0x73CE	#CJK UNIFIED IDEOGRAPH+0xE0DE	0x73BB	#CJK UNIFIED IDEOGRAPH+0xE0DF	0x73C0	#CJK UNIFIED IDEOGRAPH+0xE0E0	0x73E5	#CJK UNIFIED IDEOGRAPH+0xE0E1	0x73EE	#CJK UNIFIED IDEOGRAPH+0xE0E2	0x73DE	#CJK UNIFIED IDEOGRAPH+0xE0E3	0x74A2	#CJK UNIFIED IDEOGRAPH+0xE0E4	0x7405	#CJK UNIFIED IDEOGRAPH+0xE0E5	0x746F	#CJK UNIFIED IDEOGRAPH+0xE0E6	0x7425	#CJK UNIFIED IDEOGRAPH+0xE0E7	0x73F8	#CJK UNIFIED IDEOGRAPH+0xE0E8	0x7432	#CJK UNIFIED IDEOGRAPH+0xE0E9	0x743A	#CJK UNIFIED IDEOGRAPH+0xE0EA	0x7455	#CJK UNIFIED IDEOGRAPH+0xE0EB	0x743F	#CJK UNIFIED IDEOGRAPH+0xE0EC	0x745F	#CJK UNIFIED IDEOGRAPH+0xE0ED	0x7459	#CJK UNIFIED IDEOGRAPH+0xE0EE	0x7441	#CJK UNIFIED IDEOGRAPH+0xE0EF	0x745C	#CJK UNIFIED IDEOGRAPH+0xE0F0	0x7469	#CJK UNIFIED IDEOGRAPH+0xE0F1	0x7470	#CJK UNIFIED IDEOGRAPH+0xE0F2	0x7463	#CJK UNIFIED IDEOGRAPH+0xE0F3	0x746A	#CJK UNIFIED IDEOGRAPH+0xE0F4	0x7476	#CJK UNIFIED IDEOGRAPH+0xE0F5	0x747E	#CJK UNIFIED IDEOGRAPH+0xE0F6	0x748B	#CJK UNIFIED IDEOGRAPH+0xE0F7	0x749E	#CJK UNIFIED IDEOGRAPH+0xE0F8	0x74A7	#CJK UNIFIED IDEOGRAPH+0xE0F9	0x74CA	#CJK UNIFIED IDEOGRAPH+0xE0FA	0x74CF	#CJK UNIFIED IDEOGRAPH+0xE0FB	0x74D4	#CJK UNIFIED IDEOGRAPH+0xE0FC	0x73F1	#CJK UNIFIED IDEOGRAPH+0xE140	0x74E0	#CJK UNIFIED IDEOGRAPH+0xE141	0x74E3	#CJK UNIFIED IDEOGRAPH+0xE142	0x74E7	#CJK UNIFIED IDEOGRAPH+0xE143	0x74E9	#CJK UNIFIED IDEOGRAPH+0xE144	0x74EE	#CJK UNIFIED IDEOGRAPH+0xE145	0x74F2	#CJK UNIFIED IDEOGRAPH+0xE146	0x74F0	#CJK UNIFIED IDEOGRAPH+0xE147	0x74F1	#CJK UNIFIED IDEOGRAPH+0xE148	0x74F8	#CJK UNIFIED IDEOGRAPH+0xE149	0x74F7	#CJK UNIFIED IDEOGRAPH+0xE14A	0x7504	#CJK UNIFIED IDEOGRAPH+0xE14B	0x7503	#CJK UNIFIED IDEOGRAPH+0xE14C	0x7505	#CJK UNIFIED IDEOGRAPH+0xE14D	0x750C	#CJK UNIFIED IDEOGRAPH+0xE14E	0x750E	#CJK UNIFIED IDEOGRAPH+0xE14F	0x750D	#CJK UNIFIED IDEOGRAPH+0xE150	0x7515	#CJK UNIFIED IDEOGRAPH+0xE151	0x7513	#CJK UNIFIED IDEOGRAPH+0xE152	0x751E	#CJK UNIFIED IDEOGRAPH+0xE153	0x7526	#CJK UNIFIED IDEOGRAPH+0xE154	0x752C	#CJK UNIFIED IDEOGRAPH+0xE155	0x753C	#CJK UNIFIED IDEOGRAPH+0xE156	0x7544	#CJK UNIFIED IDEOGRAPH+0xE157	0x754D	#CJK UNIFIED IDEOGRAPH+0xE158	0x754A	#CJK UNIFIED IDEOGRAPH+0xE159	0x7549	#CJK UNIFIED IDEOGRAPH+0xE15A	0x755B	#CJK UNIFIED IDEOGRAPH+0xE15B	0x7546	#CJK UNIFIED IDEOGRAPH+0xE15C	0x755A	#CJK UNIFIED IDEOGRAPH+0xE15D	0x7569	#CJK UNIFIED IDEOGRAPH+0xE15E	0x7564	#CJK UNIFIED IDEOGRAPH+0xE15F	0x7567	#CJK UNIFIED IDEOGRAPH+0xE160	0x756B	#CJK UNIFIED IDEOGRAPH+0xE161	0x756D	#CJK UNIFIED IDEOGRAPH+0xE162	0x7578	#CJK UNIFIED IDEOGRAPH+0xE163	0x7576	#CJK UNIFIED IDEOGRAPH+0xE164	0x7586	#CJK UNIFIED IDEOGRAPH+0xE165	0x7587	#CJK UNIFIED IDEOGRAPH+0xE166	0x7574	#CJK UNIFIED IDEOGRAPH+0xE167	0x758A	#CJK UNIFIED IDEOGRAPH+0xE168	0x7589	#CJK UNIFIED IDEOGRAPH+0xE169	0x7582	#CJK UNIFIED IDEOGRAPH+0xE16A	0x7594	#CJK UNIFIED IDEOGRAPH+0xE16B	0x759A	#CJK UNIFIED IDEOGRAPH+0xE16C	0x759D	#CJK UNIFIED IDEOGRAPH+0xE16D	0x75A5	#CJK UNIFIED IDEOGRAPH+0xE16E	0x75A3	#CJK UNIFIED IDEOGRAPH+0xE16F	0x75C2	#CJK UNIFIED IDEOGRAPH+0xE170	0x75B3	#CJK UNIFIED IDEOGRAPH+0xE171	0x75C3	#CJK UNIFIED IDEOGRAPH+0xE172	0x75B5	#CJK UNIFIED IDEOGRAPH+0xE173	0x75BD	#CJK UNIFIED IDEOGRAPH+0xE174	0x75B8	#CJK UNIFIED IDEOGRAPH+0xE175	0x75BC	#CJK UNIFIED IDEOGRAPH+0xE176	0x75B1	#CJK UNIFIED IDEOGRAPH+0xE177	0x75CD	#CJK UNIFIED IDEOGRAPH+0xE178	0x75CA	#CJK UNIFIED IDEOGRAPH+0xE179	0x75D2	#CJK UNIFIED IDEOGRAPH+0xE17A	0x75D9	#CJK UNIFIED IDEOGRAPH+0xE17B	0x75E3	#CJK UNIFIED IDEOGRAPH+0xE17C	0x75DE	#CJK UNIFIED IDEOGRAPH+0xE17D	0x75FE	#CJK UNIFIED IDEOGRAPH+0xE17E	0x75FF	#CJK UNIFIED IDEOGRAPH+0xE180	0x75FC	#CJK UNIFIED IDEOGRAPH+0xE181	0x7601	#CJK UNIFIED IDEOGRAPH+0xE182	0x75F0	#CJK UNIFIED IDEOGRAPH+0xE183	0x75FA	#CJK UNIFIED IDEOGRAPH+0xE184	0x75F2	#CJK UNIFIED IDEOGRAPH+0xE185	0x75F3	#CJK UNIFIED IDEOGRAPH+0xE186	0x760B	#CJK UNIFIED IDEOGRAPH+0xE187	0x760D	#CJK UNIFIED IDEOGRAPH+0xE188	0x7609	#CJK UNIFIED IDEOGRAPH+0xE189	0x761F	#CJK UNIFIED IDEOGRAPH+0xE18A	0x7627	#CJK UNIFIED IDEOGRAPH+0xE18B	0x7620	#CJK UNIFIED IDEOGRAPH+0xE18C	0x7621	#CJK UNIFIED IDEOGRAPH+0xE18D	0x7622	#CJK UNIFIED IDEOGRAPH+0xE18E	0x7624	#CJK UNIFIED IDEOGRAPH+0xE18F	0x7634	#CJK UNIFIED IDEOGRAPH+0xE190	0x7630	#CJK UNIFIED IDEOGRAPH+0xE191	0x763B	#CJK UNIFIED IDEOGRAPH+0xE192	0x7647	#CJK UNIFIED IDEOGRAPH+0xE193	0x7648	#CJK UNIFIED IDEOGRAPH+0xE194	0x7646	#CJK UNIFIED IDEOGRAPH+0xE195	0x765C	#CJK UNIFIED IDEOGRAPH+0xE196	0x7658	#CJK UNIFIED IDEOGRAPH+0xE197	0x7661	#CJK UNIFIED IDEOGRAPH+0xE198	0x7662	#CJK UNIFIED IDEOGRAPH+0xE199	0x7668	#CJK UNIFIED IDEOGRAPH+0xE19A	0x7669	#CJK UNIFIED IDEOGRAPH+0xE19B	0x766A	#CJK UNIFIED IDEOGRAPH+0xE19C	0x7667	#CJK UNIFIED IDEOGRAPH+0xE19D	0x766C	#CJK UNIFIED IDEOGRAPH+0xE19E	0x7670	#CJK UNIFIED IDEOGRAPH+0xE19F	0x7672	#CJK UNIFIED IDEOGRAPH+0xE1A0	0x7676	#CJK UNIFIED IDEOGRAPH+0xE1A1	0x7678	#CJK UNIFIED IDEOGRAPH+0xE1A2	0x767C	#CJK UNIFIED IDEOGRAPH+0xE1A3	0x7680	#CJK UNIFIED IDEOGRAPH+0xE1A4	0x7683	#CJK UNIFIED IDEOGRAPH+0xE1A5	0x7688	#CJK UNIFIED IDEOGRAPH+0xE1A6	0x768B	#CJK UNIFIED IDEOGRAPH+0xE1A7	0x768E	#CJK UNIFIED IDEOGRAPH+0xE1A8	0x7696	#CJK UNIFIED IDEOGRAPH+0xE1A9	0x7693	#CJK UNIFIED IDEOGRAPH+0xE1AA	0x7699	#CJK UNIFIED IDEOGRAPH+0xE1AB	0x769A	#CJK UNIFIED IDEOGRAPH+0xE1AC	0x76B0	#CJK UNIFIED IDEOGRAPH+0xE1AD	0x76B4	#CJK UNIFIED IDEOGRAPH+0xE1AE	0x76B8	#CJK UNIFIED IDEOGRAPH+0xE1AF	0x76B9	#CJK UNIFIED IDEOGRAPH+0xE1B0	0x76BA	#CJK UNIFIED IDEOGRAPH+0xE1B1	0x76C2	#CJK UNIFIED IDEOGRAPH+0xE1B2	0x76CD	#CJK UNIFIED IDEOGRAPH+0xE1B3	0x76D6	#CJK UNIFIED IDEOGRAPH+0xE1B4	0x76D2	#CJK UNIFIED IDEOGRAPH+0xE1B5	0x76DE	#CJK UNIFIED IDEOGRAPH+0xE1B6	0x76E1	#CJK UNIFIED IDEOGRAPH+0xE1B7	0x76E5	#CJK UNIFIED IDEOGRAPH+0xE1B8	0x76E7	#CJK UNIFIED IDEOGRAPH+0xE1B9	0x76EA	#CJK UNIFIED IDEOGRAPH+0xE1BA	0x862F	#CJK UNIFIED IDEOGRAPH+0xE1BB	0x76FB	#CJK UNIFIED IDEOGRAPH+0xE1BC	0x7708	#CJK UNIFIED IDEOGRAPH+0xE1BD	0x7707	#CJK UNIFIED IDEOGRAPH+0xE1BE	0x7704	#CJK UNIFIED IDEOGRAPH+0xE1BF	0x7729	#CJK UNIFIED IDEOGRAPH+0xE1C0	0x7724	#CJK UNIFIED IDEOGRAPH+0xE1C1	0x771E	#CJK UNIFIED IDEOGRAPH+0xE1C2	0x7725	#CJK UNIFIED IDEOGRAPH+0xE1C3	0x7726	#CJK UNIFIED IDEOGRAPH+0xE1C4	0x771B	#CJK UNIFIED IDEOGRAPH+0xE1C5	0x7737	#CJK UNIFIED IDEOGRAPH+0xE1C6	0x7738	#CJK UNIFIED IDEOGRAPH+0xE1C7	0x7747	#CJK UNIFIED IDEOGRAPH+0xE1C8	0x775A	#CJK UNIFIED IDEOGRAPH+0xE1C9	0x7768	#CJK UNIFIED IDEOGRAPH+0xE1CA	0x776B	#CJK UNIFIED IDEOGRAPH+0xE1CB	0x775B	#CJK UNIFIED IDEOGRAPH+0xE1CC	0x7765	#CJK UNIFIED IDEOGRAPH+0xE1CD	0x777F	#CJK UNIFIED IDEOGRAPH+0xE1CE	0x777E	#CJK UNIFIED IDEOGRAPH+0xE1CF	0x7779	#CJK UNIFIED IDEOGRAPH+0xE1D0	0x778E	#CJK UNIFIED IDEOGRAPH+0xE1D1	0x778B	#CJK UNIFIED IDEOGRAPH+0xE1D2	0x7791	#CJK UNIFIED IDEOGRAPH+0xE1D3	0x77A0	#CJK UNIFIED IDEOGRAPH+0xE1D4	0x779E	#CJK UNIFIED IDEOGRAPH+0xE1D5	0x77B0	#CJK UNIFIED IDEOGRAPH+0xE1D6	0x77B6	#CJK UNIFIED IDEOGRAPH+0xE1D7	0x77B9	#CJK UNIFIED IDEOGRAPH+0xE1D8	0x77BF	#CJK UNIFIED IDEOGRAPH+0xE1D9	0x77BC	#CJK UNIFIED IDEOGRAPH+0xE1DA	0x77BD	#CJK UNIFIED IDEOGRAPH+0xE1DB	0x77BB	#CJK UNIFIED IDEOGRAPH+0xE1DC	0x77C7	#CJK UNIFIED IDEOGRAPH+0xE1DD	0x77CD	#CJK UNIFIED IDEOGRAPH+0xE1DE	0x77D7	#CJK UNIFIED IDEOGRAPH+0xE1DF	0x77DA	#CJK UNIFIED IDEOGRAPH+0xE1E0	0x77DC	#CJK UNIFIED IDEOGRAPH+0xE1E1	0x77E3	#CJK UNIFIED IDEOGRAPH+0xE1E2	0x77EE	#CJK UNIFIED IDEOGRAPH+0xE1E3	0x77FC	#CJK UNIFIED IDEOGRAPH+0xE1E4	0x780C	#CJK UNIFIED IDEOGRAPH+0xE1E5	0x7812	#CJK UNIFIED IDEOGRAPH+0xE1E6	0x7926	#CJK UNIFIED IDEOGRAPH+0xE1E7	0x7820	#CJK UNIFIED IDEOGRAPH+0xE1E8	0x792A	#CJK UNIFIED IDEOGRAPH+0xE1E9	0x7845	#CJK UNIFIED IDEOGRAPH+0xE1EA	0x788E	#CJK UNIFIED IDEOGRAPH+0xE1EB	0x7874	#CJK UNIFIED IDEOGRAPH+0xE1EC	0x7886	#CJK UNIFIED IDEOGRAPH+0xE1ED	0x787C	#CJK UNIFIED IDEOGRAPH+0xE1EE	0x789A	#CJK UNIFIED IDEOGRAPH+0xE1EF	0x788C	#CJK UNIFIED IDEOGRAPH+0xE1F0	0x78A3	#CJK UNIFIED IDEOGRAPH+0xE1F1	0x78B5	#CJK UNIFIED IDEOGRAPH+0xE1F2	0x78AA	#CJK UNIFIED IDEOGRAPH+0xE1F3	0x78AF	#CJK UNIFIED IDEOGRAPH+0xE1F4	0x78D1	#CJK UNIFIED IDEOGRAPH+0xE1F5	0x78C6	#CJK UNIFIED IDEOGRAPH+0xE1F6	0x78CB	#CJK UNIFIED IDEOGRAPH+0xE1F7	0x78D4	#CJK UNIFIED IDEOGRAPH+0xE1F8	0x78BE	#CJK UNIFIED IDEOGRAPH+0xE1F9	0x78BC	#CJK UNIFIED IDEOGRAPH+0xE1FA	0x78C5	#CJK UNIFIED IDEOGRAPH+0xE1FB	0x78CA	#CJK UNIFIED IDEOGRAPH+0xE1FC	0x78EC	#CJK UNIFIED IDEOGRAPH+0xE240	0x78E7	#CJK UNIFIED IDEOGRAPH+0xE241	0x78DA	#CJK UNIFIED IDEOGRAPH+0xE242	0x78FD	#CJK UNIFIED IDEOGRAPH+0xE243	0x78F4	#CJK UNIFIED IDEOGRAPH+0xE244	0x7907	#CJK UNIFIED IDEOGRAPH+0xE245	0x7912	#CJK UNIFIED IDEOGRAPH+0xE246	0x7911	#CJK UNIFIED IDEOGRAPH+0xE247	0x7919	#CJK UNIFIED IDEOGRAPH+0xE248	0x792C	#CJK UNIFIED IDEOGRAPH+0xE249	0x792B	#CJK UNIFIED IDEOGRAPH+0xE24A	0x7940	#CJK UNIFIED IDEOGRAPH+0xE24B	0x7960	#CJK UNIFIED IDEOGRAPH+0xE24C	0x7957	#CJK UNIFIED IDEOGRAPH+0xE24D	0x795F	#CJK UNIFIED IDEOGRAPH+0xE24E	0x795A	#CJK UNIFIED IDEOGRAPH+0xE24F	0x7955	#CJK UNIFIED IDEOGRAPH+0xE250	0x7953	#CJK UNIFIED IDEOGRAPH+0xE251	0x797A	#CJK UNIFIED IDEOGRAPH+0xE252	0x797F	#CJK UNIFIED IDEOGRAPH+0xE253	0x798A	#CJK UNIFIED IDEOGRAPH+0xE254	0x799D	#CJK UNIFIED IDEOGRAPH+0xE255	0x79A7	#CJK UNIFIED IDEOGRAPH+0xE256	0x9F4B	#CJK UNIFIED IDEOGRAPH+0xE257	0x79AA	#CJK UNIFIED IDEOGRAPH+0xE258	0x79AE	#CJK UNIFIED IDEOGRAPH+0xE259	0x79B3	#CJK UNIFIED IDEOGRAPH+0xE25A	0x79B9	#CJK UNIFIED IDEOGRAPH+0xE25B	0x79BA	#CJK UNIFIED IDEOGRAPH+0xE25C	0x79C9	#CJK UNIFIED IDEOGRAPH+0xE25D	0x79D5	#CJK UNIFIED IDEOGRAPH+0xE25E	0x79E7	#CJK UNIFIED IDEOGRAPH+0xE25F	0x79EC	#CJK UNIFIED IDEOGRAPH+0xE260	0x79E1	#CJK UNIFIED IDEOGRAPH+0xE261	0x79E3	#CJK UNIFIED IDEOGRAPH+0xE262	0x7A08	#CJK UNIFIED IDEOGRAPH+0xE263	0x7A0D	#CJK UNIFIED IDEOGRAPH+0xE264	0x7A18	#CJK UNIFIED IDEOGRAPH+0xE265	0x7A19	#CJK UNIFIED IDEOGRAPH+0xE266	0x7A20	#CJK UNIFIED IDEOGRAPH+0xE267	0x7A1F	#CJK UNIFIED IDEOGRAPH+0xE268	0x7980	#CJK UNIFIED IDEOGRAPH+0xE269	0x7A31	#CJK UNIFIED IDEOGRAPH+0xE26A	0x7A3B	#CJK UNIFIED IDEOGRAPH+0xE26B	0x7A3E	#CJK UNIFIED IDEOGRAPH+0xE26C	0x7A37	#CJK UNIFIED IDEOGRAPH+0xE26D	0x7A43	#CJK UNIFIED IDEOGRAPH+0xE26E	0x7A57	#CJK UNIFIED IDEOGRAPH+0xE26F	0x7A49	#CJK UNIFIED IDEOGRAPH+0xE270	0x7A61	#CJK UNIFIED IDEOGRAPH+0xE271	0x7A62	#CJK UNIFIED IDEOGRAPH+0xE272	0x7A69	#CJK UNIFIED IDEOGRAPH+0xE273	0x9F9D	#CJK UNIFIED IDEOGRAPH+0xE274	0x7A70	#CJK UNIFIED IDEOGRAPH+0xE275	0x7A79	#CJK UNIFIED IDEOGRAPH+0xE276	0x7A7D	#CJK UNIFIED IDEOGRAPH+0xE277	0x7A88	#CJK UNIFIED IDEOGRAPH+0xE278	0x7A97	#CJK UNIFIED IDEOGRAPH+0xE279	0x7A95	#CJK UNIFIED IDEOGRAPH+0xE27A	0x7A98	#CJK UNIFIED IDEOGRAPH+0xE27B	0x7A96	#CJK UNIFIED IDEOGRAPH+0xE27C	0x7AA9	#CJK UNIFIED IDEOGRAPH+0xE27D	0x7AC8	#CJK UNIFIED IDEOGRAPH+0xE27E	0x7AB0	#CJK UNIFIED IDEOGRAPH+0xE280	0x7AB6	#CJK UNIFIED IDEOGRAPH+0xE281	0x7AC5	#CJK UNIFIED IDEOGRAPH+0xE282	0x7AC4	#CJK UNIFIED IDEOGRAPH+0xE283	0x7ABF	#CJK UNIFIED IDEOGRAPH+0xE284	0x9083	#CJK UNIFIED IDEOGRAPH+0xE285	0x7AC7	#CJK UNIFIED IDEOGRAPH+0xE286	0x7ACA	#CJK UNIFIED IDEOGRAPH+0xE287	0x7ACD	#CJK UNIFIED IDEOGRAPH+0xE288	0x7ACF	#CJK UNIFIED IDEOGRAPH+0xE289	0x7AD5	#CJK UNIFIED IDEOGRAPH+0xE28A	0x7AD3	#CJK UNIFIED IDEOGRAPH+0xE28B	0x7AD9	#CJK UNIFIED IDEOGRAPH+0xE28C	0x7ADA	#CJK UNIFIED IDEOGRAPH+0xE28D	0x7ADD	#CJK UNIFIED IDEOGRAPH+0xE28E	0x7AE1	#CJK UNIFIED IDEOGRAPH+0xE28F	0x7AE2	#CJK UNIFIED IDEOGRAPH+0xE290	0x7AE6	#CJK UNIFIED IDEOGRAPH+0xE291	0x7AED	#CJK UNIFIED IDEOGRAPH+0xE292	0x7AF0	#CJK UNIFIED IDEOGRAPH+0xE293	0x7B02	#CJK UNIFIED IDEOGRAPH+0xE294	0x7B0F	#CJK UNIFIED IDEOGRAPH+0xE295	0x7B0A	#CJK UNIFIED IDEOGRAPH+0xE296	0x7B06	#CJK UNIFIED IDEOGRAPH+0xE297	0x7B33	#CJK UNIFIED IDEOGRAPH+0xE298	0x7B18	#CJK UNIFIED IDEOGRAPH+0xE299	0x7B19	#CJK UNIFIED IDEOGRAPH+0xE29A	0x7B1E	#CJK UNIFIED IDEOGRAPH+0xE29B	0x7B35	#CJK UNIFIED IDEOGRAPH+0xE29C	0x7B28	#CJK UNIFIED IDEOGRAPH+0xE29D	0x7B36	#CJK UNIFIED IDEOGRAPH+0xE29E	0x7B50	#CJK UNIFIED IDEOGRAPH+0xE29F	0x7B7A	#CJK UNIFIED IDEOGRAPH+0xE2A0	0x7B04	#CJK UNIFIED IDEOGRAPH+0xE2A1	0x7B4D	#CJK UNIFIED IDEOGRAPH+0xE2A2	0x7B0B	#CJK UNIFIED IDEOGRAPH+0xE2A3	0x7B4C	#CJK UNIFIED IDEOGRAPH+0xE2A4	0x7B45	#CJK UNIFIED IDEOGRAPH+0xE2A5	0x7B75	#CJK UNIFIED IDEOGRAPH+0xE2A6	0x7B65	#CJK UNIFIED IDEOGRAPH+0xE2A7	0x7B74	#CJK UNIFIED IDEOGRAPH+0xE2A8	0x7B67	#CJK UNIFIED IDEOGRAPH+0xE2A9	0x7B70	#CJK UNIFIED IDEOGRAPH+0xE2AA	0x7B71	#CJK UNIFIED IDEOGRAPH+0xE2AB	0x7B6C	#CJK UNIFIED IDEOGRAPH+0xE2AC	0x7B6E	#CJK UNIFIED IDEOGRAPH+0xE2AD	0x7B9D	#CJK UNIFIED IDEOGRAPH+0xE2AE	0x7B98	#CJK UNIFIED IDEOGRAPH+0xE2AF	0x7B9F	#CJK UNIFIED IDEOGRAPH+0xE2B0	0x7B8D	#CJK UNIFIED IDEOGRAPH+0xE2B1	0x7B9C	#CJK UNIFIED IDEOGRAPH+0xE2B2	0x7B9A	#CJK UNIFIED IDEOGRAPH+0xE2B3	0x7B8B	#CJK UNIFIED IDEOGRAPH+0xE2B4	0x7B92	#CJK UNIFIED IDEOGRAPH+0xE2B5	0x7B8F	#CJK UNIFIED IDEOGRAPH+0xE2B6	0x7B5D	#CJK UNIFIED IDEOGRAPH+0xE2B7	0x7B99	#CJK UNIFIED IDEOGRAPH+0xE2B8	0x7BCB	#CJK UNIFIED IDEOGRAPH+0xE2B9	0x7BC1	#CJK UNIFIED IDEOGRAPH+0xE2BA	0x7BCC	#CJK UNIFIED IDEOGRAPH+0xE2BB	0x7BCF	#CJK UNIFIED IDEOGRAPH+0xE2BC	0x7BB4	#CJK UNIFIED IDEOGRAPH+0xE2BD	0x7BC6	#CJK UNIFIED IDEOGRAPH+0xE2BE	0x7BDD	#CJK UNIFIED IDEOGRAPH+0xE2BF	0x7BE9	#CJK UNIFIED IDEOGRAPH+0xE2C0	0x7C11	#CJK UNIFIED IDEOGRAPH+0xE2C1	0x7C14	#CJK UNIFIED IDEOGRAPH+0xE2C2	0x7BE6	#CJK UNIFIED IDEOGRAPH+0xE2C3	0x7BE5	#CJK UNIFIED IDEOGRAPH+0xE2C4	0x7C60	#CJK UNIFIED IDEOGRAPH+0xE2C5	0x7C00	#CJK UNIFIED IDEOGRAPH+0xE2C6	0x7C07	#CJK UNIFIED IDEOGRAPH+0xE2C7	0x7C13	#CJK UNIFIED IDEOGRAPH+0xE2C8	0x7BF3	#CJK UNIFIED IDEOGRAPH+0xE2C9	0x7BF7	#CJK UNIFIED IDEOGRAPH+0xE2CA	0x7C17	#CJK UNIFIED IDEOGRAPH+0xE2CB	0x7C0D	#CJK UNIFIED IDEOGRAPH+0xE2CC	0x7BF6	#CJK UNIFIED IDEOGRAPH+0xE2CD	0x7C23	#CJK UNIFIED IDEOGRAPH+0xE2CE	0x7C27	#CJK UNIFIED IDEOGRAPH+0xE2CF	0x7C2A	#CJK UNIFIED IDEOGRAPH+0xE2D0	0x7C1F	#CJK UNIFIED IDEOGRAPH+0xE2D1	0x7C37	#CJK UNIFIED IDEOGRAPH+0xE2D2	0x7C2B	#CJK UNIFIED IDEOGRAPH+0xE2D3	0x7C3D	#CJK UNIFIED IDEOGRAPH+0xE2D4	0x7C4C	#CJK UNIFIED IDEOGRAPH+0xE2D5	0x7C43	#CJK UNIFIED IDEOGRAPH+0xE2D6	0x7C54	#CJK UNIFIED IDEOGRAPH+0xE2D7	0x7C4F	#CJK UNIFIED IDEOGRAPH+0xE2D8	0x7C40	#CJK UNIFIED IDEOGRAPH+0xE2D9	0x7C50	#CJK UNIFIED IDEOGRAPH+0xE2DA	0x7C58	#CJK UNIFIED IDEOGRAPH+0xE2DB	0x7C5F	#CJK UNIFIED IDEOGRAPH+0xE2DC	0x7C64	#CJK UNIFIED IDEOGRAPH+0xE2DD	0x7C56	#CJK UNIFIED IDEOGRAPH+0xE2DE	0x7C65	#CJK UNIFIED IDEOGRAPH+0xE2DF	0x7C6C	#CJK UNIFIED IDEOGRAPH+0xE2E0	0x7C75	#CJK UNIFIED IDEOGRAPH+0xE2E1	0x7C83	#CJK UNIFIED IDEOGRAPH+0xE2E2	0x7C90	#CJK UNIFIED IDEOGRAPH+0xE2E3	0x7CA4	#CJK UNIFIED IDEOGRAPH+0xE2E4	0x7CAD	#CJK UNIFIED IDEOGRAPH+0xE2E5	0x7CA2	#CJK UNIFIED IDEOGRAPH+0xE2E6	0x7CAB	#CJK UNIFIED IDEOGRAPH+0xE2E7	0x7CA1	#CJK UNIFIED IDEOGRAPH+0xE2E8	0x7CA8	#CJK UNIFIED IDEOGRAPH+0xE2E9	0x7CB3	#CJK UNIFIED IDEOGRAPH+0xE2EA	0x7CB2	#CJK UNIFIED IDEOGRAPH+0xE2EB	0x7CB1	#CJK UNIFIED IDEOGRAPH+0xE2EC	0x7CAE	#CJK UNIFIED IDEOGRAPH+0xE2ED	0x7CB9	#CJK UNIFIED IDEOGRAPH+0xE2EE	0x7CBD	#CJK UNIFIED IDEOGRAPH+0xE2EF	0x7CC0	#CJK UNIFIED IDEOGRAPH+0xE2F0	0x7CC5	#CJK UNIFIED IDEOGRAPH+0xE2F1	0x7CC2	#CJK UNIFIED IDEOGRAPH+0xE2F2	0x7CD8	#CJK UNIFIED IDEOGRAPH+0xE2F3	0x7CD2	#CJK UNIFIED IDEOGRAPH+0xE2F4	0x7CDC	#CJK UNIFIED IDEOGRAPH+0xE2F5	0x7CE2	#CJK UNIFIED IDEOGRAPH+0xE2F6	0x9B3B	#CJK UNIFIED IDEOGRAPH+0xE2F7	0x7CEF	#CJK UNIFIED IDEOGRAPH+0xE2F8	0x7CF2	#CJK UNIFIED IDEOGRAPH+0xE2F9	0x7CF4	#CJK UNIFIED IDEOGRAPH+0xE2FA	0x7CF6	#CJK UNIFIED IDEOGRAPH+0xE2FB	0x7CFA	#CJK UNIFIED IDEOGRAPH+0xE2FC	0x7D06	#CJK UNIFIED IDEOGRAPH+0xE340	0x7D02	#CJK UNIFIED IDEOGRAPH+0xE341	0x7D1C	#CJK UNIFIED IDEOGRAPH+0xE342	0x7D15	#CJK UNIFIED IDEOGRAPH+0xE343	0x7D0A	#CJK UNIFIED IDEOGRAPH+0xE344	0x7D45	#CJK UNIFIED IDEOGRAPH+0xE345	0x7D4B	#CJK UNIFIED IDEOGRAPH+0xE346	0x7D2E	#CJK UNIFIED IDEOGRAPH+0xE347	0x7D32	#CJK UNIFIED IDEOGRAPH+0xE348	0x7D3F	#CJK UNIFIED IDEOGRAPH+0xE349	0x7D35	#CJK UNIFIED IDEOGRAPH+0xE34A	0x7D46	#CJK UNIFIED IDEOGRAPH+0xE34B	0x7D73	#CJK UNIFIED IDEOGRAPH+0xE34C	0x7D56	#CJK UNIFIED IDEOGRAPH+0xE34D	0x7D4E	#CJK UNIFIED IDEOGRAPH+0xE34E	0x7D72	#CJK UNIFIED IDEOGRAPH+0xE34F	0x7D68	#CJK UNIFIED IDEOGRAPH+0xE350	0x7D6E	#CJK UNIFIED IDEOGRAPH+0xE351	0x7D4F	#CJK UNIFIED IDEOGRAPH+0xE352	0x7D63	#CJK UNIFIED IDEOGRAPH+0xE353	0x7D93	#CJK UNIFIED IDEOGRAPH+0xE354	0x7D89	#CJK UNIFIED IDEOGRAPH+0xE355	0x7D5B	#CJK UNIFIED IDEOGRAPH+0xE356	0x7D8F	#CJK UNIFIED IDEOGRAPH+0xE357	0x7D7D	#CJK UNIFIED IDEOGRAPH+0xE358	0x7D9B	#CJK UNIFIED IDEOGRAPH+0xE359	0x7DBA	#CJK UNIFIED IDEOGRAPH+0xE35A	0x7DAE	#CJK UNIFIED IDEOGRAPH+0xE35B	0x7DA3	#CJK UNIFIED IDEOGRAPH+0xE35C	0x7DB5	#CJK UNIFIED IDEOGRAPH+0xE35D	0x7DC7	#CJK UNIFIED IDEOGRAPH+0xE35E	0x7DBD	#CJK UNIFIED IDEOGRAPH+0xE35F	0x7DAB	#CJK UNIFIED IDEOGRAPH+0xE360	0x7E3D	#CJK UNIFIED IDEOGRAPH+0xE361	0x7DA2	#CJK UNIFIED IDEOGRAPH+0xE362	0x7DAF	#CJK UNIFIED IDEOGRAPH+0xE363	0x7DDC	#CJK UNIFIED IDEOGRAPH+0xE364	0x7DB8	#CJK UNIFIED IDEOGRAPH+0xE365	0x7D9F	#CJK UNIFIED IDEOGRAPH+0xE366	0x7DB0	#CJK UNIFIED IDEOGRAPH+0xE367	0x7DD8	#CJK UNIFIED IDEOGRAPH+0xE368	0x7DDD	#CJK UNIFIED IDEOGRAPH+0xE369	0x7DE4	#CJK UNIFIED IDEOGRAPH+0xE36A	0x7DDE	#CJK UNIFIED IDEOGRAPH+0xE36B	0x7DFB	#CJK UNIFIED IDEOGRAPH+0xE36C	0x7DF2	#CJK UNIFIED IDEOGRAPH+0xE36D	0x7DE1	#CJK UNIFIED IDEOGRAPH+0xE36E	0x7E05	#CJK UNIFIED IDEOGRAPH+0xE36F	0x7E0A	#CJK UNIFIED IDEOGRAPH+0xE370	0x7E23	#CJK UNIFIED IDEOGRAPH+0xE371	0x7E21	#CJK UNIFIED IDEOGRAPH+0xE372	0x7E12	#CJK UNIFIED IDEOGRAPH+0xE373	0x7E31	#CJK UNIFIED IDEOGRAPH+0xE374	0x7E1F	#CJK UNIFIED IDEOGRAPH+0xE375	0x7E09	#CJK UNIFIED IDEOGRAPH+0xE376	0x7E0B	#CJK UNIFIED IDEOGRAPH+0xE377	0x7E22	#CJK UNIFIED IDEOGRAPH+0xE378	0x7E46	#CJK UNIFIED IDEOGRAPH+0xE379	0x7E66	#CJK UNIFIED IDEOGRAPH+0xE37A	0x7E3B	#CJK UNIFIED IDEOGRAPH+0xE37B	0x7E35	#CJK UNIFIED IDEOGRAPH+0xE37C	0x7E39	#CJK UNIFIED IDEOGRAPH+0xE37D	0x7E43	#CJK UNIFIED IDEOGRAPH+0xE37E	0x7E37	#CJK UNIFIED IDEOGRAPH+0xE380	0x7E32	#CJK UNIFIED IDEOGRAPH+0xE381	0x7E3A	#CJK UNIFIED IDEOGRAPH+0xE382	0x7E67	#CJK UNIFIED IDEOGRAPH+0xE383	0x7E5D	#CJK UNIFIED IDEOGRAPH+0xE384	0x7E56	#CJK UNIFIED IDEOGRAPH+0xE385	0x7E5E	#CJK UNIFIED IDEOGRAPH+0xE386	0x7E59	#CJK UNIFIED IDEOGRAPH+0xE387	0x7E5A	#CJK UNIFIED IDEOGRAPH+0xE388	0x7E79	#CJK UNIFIED IDEOGRAPH+0xE389	0x7E6A	#CJK UNIFIED IDEOGRAPH+0xE38A	0x7E69	#CJK UNIFIED IDEOGRAPH+0xE38B	0x7E7C	#CJK UNIFIED IDEOGRAPH+0xE38C	0x7E7B	#CJK UNIFIED IDEOGRAPH+0xE38D	0x7E83	#CJK UNIFIED IDEOGRAPH+0xE38E	0x7DD5	#CJK UNIFIED IDEOGRAPH+0xE38F	0x7E7D	#CJK UNIFIED IDEOGRAPH+0xE390	0x8FAE	#CJK UNIFIED IDEOGRAPH+0xE391	0x7E7F	#CJK UNIFIED IDEOGRAPH+0xE392	0x7E88	#CJK UNIFIED IDEOGRAPH+0xE393	0x7E89	#CJK UNIFIED IDEOGRAPH+0xE394	0x7E8C	#CJK UNIFIED IDEOGRAPH+0xE395	0x7E92	#CJK UNIFIED IDEOGRAPH+0xE396	0x7E90	#CJK UNIFIED IDEOGRAPH+0xE397	0x7E93	#CJK UNIFIED IDEOGRAPH+0xE398	0x7E94	#CJK UNIFIED IDEOGRAPH+0xE399	0x7E96	#CJK UNIFIED IDEOGRAPH+0xE39A	0x7E8E	#CJK UNIFIED IDEOGRAPH+0xE39B	0x7E9B	#CJK UNIFIED IDEOGRAPH+0xE39C	0x7E9C	#CJK UNIFIED IDEOGRAPH+0xE39D	0x7F38	#CJK UNIFIED IDEOGRAPH+0xE39E	0x7F3A	#CJK UNIFIED IDEOGRAPH+0xE39F	0x7F45	#CJK UNIFIED IDEOGRAPH+0xE3A0	0x7F4C	#CJK UNIFIED IDEOGRAPH+0xE3A1	0x7F4D	#CJK UNIFIED IDEOGRAPH+0xE3A2	0x7F4E	#CJK UNIFIED IDEOGRAPH+0xE3A3	0x7F50	#CJK UNIFIED IDEOGRAPH+0xE3A4	0x7F51	#CJK UNIFIED IDEOGRAPH+0xE3A5	0x7F55	#CJK UNIFIED IDEOGRAPH+0xE3A6	0x7F54	#CJK UNIFIED IDEOGRAPH+0xE3A7	0x7F58	#CJK UNIFIED IDEOGRAPH+0xE3A8	0x7F5F	#CJK UNIFIED IDEOGRAPH+0xE3A9	0x7F60	#CJK UNIFIED IDEOGRAPH+0xE3AA	0x7F68	#CJK UNIFIED IDEOGRAPH+0xE3AB	0x7F69	#CJK UNIFIED IDEOGRAPH+0xE3AC	0x7F67	#CJK UNIFIED IDEOGRAPH+0xE3AD	0x7F78	#CJK UNIFIED IDEOGRAPH+0xE3AE	0x7F82	#CJK UNIFIED IDEOGRAPH+0xE3AF	0x7F86	#CJK UNIFIED IDEOGRAPH+0xE3B0	0x7F83	#CJK UNIFIED IDEOGRAPH+0xE3B1	0x7F88	#CJK UNIFIED IDEOGRAPH+0xE3B2	0x7F87	#CJK UNIFIED IDEOGRAPH+0xE3B3	0x7F8C	#CJK UNIFIED IDEOGRAPH+0xE3B4	0x7F94	#CJK UNIFIED IDEOGRAPH+0xE3B5	0x7F9E	#CJK UNIFIED IDEOGRAPH+0xE3B6	0x7F9D	#CJK UNIFIED IDEOGRAPH+0xE3B7	0x7F9A	#CJK UNIFIED IDEOGRAPH+0xE3B8	0x7FA3	#CJK UNIFIED IDEOGRAPH+0xE3B9	0x7FAF	#CJK UNIFIED IDEOGRAPH+0xE3BA	0x7FB2	#CJK UNIFIED IDEOGRAPH+0xE3BB	0x7FB9	#CJK UNIFIED IDEOGRAPH+0xE3BC	0x7FAE	#CJK UNIFIED IDEOGRAPH+0xE3BD	0x7FB6	#CJK UNIFIED IDEOGRAPH+0xE3BE	0x7FB8	#CJK UNIFIED IDEOGRAPH+0xE3BF	0x8B71	#CJK UNIFIED IDEOGRAPH+0xE3C0	0x7FC5	#CJK UNIFIED IDEOGRAPH+0xE3C1	0x7FC6	#CJK UNIFIED IDEOGRAPH+0xE3C2	0x7FCA	#CJK UNIFIED IDEOGRAPH+0xE3C3	0x7FD5	#CJK UNIFIED IDEOGRAPH+0xE3C4	0x7FD4	#CJK UNIFIED IDEOGRAPH+0xE3C5	0x7FE1	#CJK UNIFIED IDEOGRAPH+0xE3C6	0x7FE6	#CJK UNIFIED IDEOGRAPH+0xE3C7	0x7FE9	#CJK UNIFIED IDEOGRAPH+0xE3C8	0x7FF3	#CJK UNIFIED IDEOGRAPH+0xE3C9	0x7FF9	#CJK UNIFIED IDEOGRAPH+0xE3CA	0x98DC	#CJK UNIFIED IDEOGRAPH+0xE3CB	0x8006	#CJK UNIFIED IDEOGRAPH+0xE3CC	0x8004	#CJK UNIFIED IDEOGRAPH+0xE3CD	0x800B	#CJK UNIFIED IDEOGRAPH+0xE3CE	0x8012	#CJK UNIFIED IDEOGRAPH+0xE3CF	0x8018	#CJK UNIFIED IDEOGRAPH+0xE3D0	0x8019	#CJK UNIFIED IDEOGRAPH+0xE3D1	0x801C	#CJK UNIFIED IDEOGRAPH+0xE3D2	0x8021	#CJK UNIFIED IDEOGRAPH+0xE3D3	0x8028	#CJK UNIFIED IDEOGRAPH+0xE3D4	0x803F	#CJK UNIFIED IDEOGRAPH+0xE3D5	0x803B	#CJK UNIFIED IDEOGRAPH+0xE3D6	0x804A	#CJK UNIFIED IDEOGRAPH+0xE3D7	0x8046	#CJK UNIFIED IDEOGRAPH+0xE3D8	0x8052	#CJK UNIFIED IDEOGRAPH+0xE3D9	0x8058	#CJK UNIFIED IDEOGRAPH+0xE3DA	0x805A	#CJK UNIFIED IDEOGRAPH+0xE3DB	0x805F	#CJK UNIFIED IDEOGRAPH+0xE3DC	0x8062	#CJK UNIFIED IDEOGRAPH+0xE3DD	0x8068	#CJK UNIFIED IDEOGRAPH+0xE3DE	0x8073	#CJK UNIFIED IDEOGRAPH+0xE3DF	0x8072	#CJK UNIFIED IDEOGRAPH+0xE3E0	0x8070	#CJK UNIFIED IDEOGRAPH+0xE3E1	0x8076	#CJK UNIFIED IDEOGRAPH+0xE3E2	0x8079	#CJK UNIFIED IDEOGRAPH+0xE3E3	0x807D	#CJK UNIFIED IDEOGRAPH+0xE3E4	0x807F	#CJK UNIFIED IDEOGRAPH+0xE3E5	0x8084	#CJK UNIFIED IDEOGRAPH+0xE3E6	0x8086	#CJK UNIFIED IDEOGRAPH+0xE3E7	0x8085	#CJK UNIFIED IDEOGRAPH+0xE3E8	0x809B	#CJK UNIFIED IDEOGRAPH+0xE3E9	0x8093	#CJK UNIFIED IDEOGRAPH+0xE3EA	0x809A	#CJK UNIFIED IDEOGRAPH+0xE3EB	0x80AD	#CJK UNIFIED IDEOGRAPH+0xE3EC	0x5190	#CJK UNIFIED IDEOGRAPH+0xE3ED	0x80AC	#CJK UNIFIED IDEOGRAPH+0xE3EE	0x80DB	#CJK UNIFIED IDEOGRAPH+0xE3EF	0x80E5	#CJK UNIFIED IDEOGRAPH+0xE3F0	0x80D9	#CJK UNIFIED IDEOGRAPH+0xE3F1	0x80DD	#CJK UNIFIED IDEOGRAPH+0xE3F2	0x80C4	#CJK UNIFIED IDEOGRAPH+0xE3F3	0x80DA	#CJK UNIFIED IDEOGRAPH+0xE3F4	0x80D6	#CJK UNIFIED IDEOGRAPH+0xE3F5	0x8109	#CJK UNIFIED IDEOGRAPH+0xE3F6	0x80EF	#CJK UNIFIED IDEOGRAPH+0xE3F7	0x80F1	#CJK UNIFIED IDEOGRAPH+0xE3F8	0x811B	#CJK UNIFIED IDEOGRAPH+0xE3F9	0x8129	#CJK UNIFIED IDEOGRAPH+0xE3FA	0x8123	#CJK UNIFIED IDEOGRAPH+0xE3FB	0x812F	#CJK UNIFIED IDEOGRAPH+0xE3FC	0x814B	#CJK UNIFIED IDEOGRAPH+0xE440	0x968B	#CJK UNIFIED IDEOGRAPH+0xE441	0x8146	#CJK UNIFIED IDEOGRAPH+0xE442	0x813E	#CJK UNIFIED IDEOGRAPH+0xE443	0x8153	#CJK UNIFIED IDEOGRAPH+0xE444	0x8151	#CJK UNIFIED IDEOGRAPH+0xE445	0x80FC	#CJK UNIFIED IDEOGRAPH+0xE446	0x8171	#CJK UNIFIED IDEOGRAPH+0xE447	0x816E	#CJK UNIFIED IDEOGRAPH+0xE448	0x8165	#CJK UNIFIED IDEOGRAPH+0xE449	0x8166	#CJK UNIFIED IDEOGRAPH+0xE44A	0x8174	#CJK UNIFIED IDEOGRAPH+0xE44B	0x8183	#CJK UNIFIED IDEOGRAPH+0xE44C	0x8188	#CJK UNIFIED IDEOGRAPH+0xE44D	0x818A	#CJK UNIFIED IDEOGRAPH+0xE44E	0x8180	#CJK UNIFIED IDEOGRAPH+0xE44F	0x8182	#CJK UNIFIED IDEOGRAPH+0xE450	0x81A0	#CJK UNIFIED IDEOGRAPH+0xE451	0x8195	#CJK UNIFIED IDEOGRAPH+0xE452	0x81A4	#CJK UNIFIED IDEOGRAPH+0xE453	0x81A3	#CJK UNIFIED IDEOGRAPH+0xE454	0x815F	#CJK UNIFIED IDEOGRAPH+0xE455	0x8193	#CJK UNIFIED IDEOGRAPH+0xE456	0x81A9	#CJK UNIFIED IDEOGRAPH+0xE457	0x81B0	#CJK UNIFIED IDEOGRAPH+0xE458	0x81B5	#CJK UNIFIED IDEOGRAPH+0xE459	0x81BE	#CJK UNIFIED IDEOGRAPH+0xE45A	0x81B8	#CJK UNIFIED IDEOGRAPH+0xE45B	0x81BD	#CJK UNIFIED IDEOGRAPH+0xE45C	0x81C0	#CJK UNIFIED IDEOGRAPH+0xE45D	0x81C2	#CJK UNIFIED IDEOGRAPH+0xE45E	0x81BA	#CJK UNIFIED IDEOGRAPH+0xE45F	0x81C9	#CJK UNIFIED IDEOGRAPH+0xE460	0x81CD	#CJK UNIFIED IDEOGRAPH+0xE461	0x81D1	#CJK UNIFIED IDEOGRAPH+0xE462	0x81D9	#CJK UNIFIED IDEOGRAPH+0xE463	0x81D8	#CJK UNIFIED IDEOGRAPH+0xE464	0x81C8	#CJK UNIFIED IDEOGRAPH+0xE465	0x81DA	#CJK UNIFIED IDEOGRAPH+0xE466	0x81DF	#CJK UNIFIED IDEOGRAPH+0xE467	0x81E0	#CJK UNIFIED IDEOGRAPH+0xE468	0x81E7	#CJK UNIFIED IDEOGRAPH+0xE469	0x81FA	#CJK UNIFIED IDEOGRAPH+0xE46A	0x81FB	#CJK UNIFIED IDEOGRAPH+0xE46B	0x81FE	#CJK UNIFIED IDEOGRAPH+0xE46C	0x8201	#CJK UNIFIED IDEOGRAPH+0xE46D	0x8202	#CJK UNIFIED IDEOGRAPH+0xE46E	0x8205	#CJK UNIFIED IDEOGRAPH+0xE46F	0x8207	#CJK UNIFIED IDEOGRAPH+0xE470	0x820A	#CJK UNIFIED IDEOGRAPH+0xE471	0x820D	#CJK UNIFIED IDEOGRAPH+0xE472	0x8210	#CJK UNIFIED IDEOGRAPH+0xE473	0x8216	#CJK UNIFIED IDEOGRAPH+0xE474	0x8229	#CJK UNIFIED IDEOGRAPH+0xE475	0x822B	#CJK UNIFIED IDEOGRAPH+0xE476	0x8238	#CJK UNIFIED IDEOGRAPH+0xE477	0x8233	#CJK UNIFIED IDEOGRAPH+0xE478	0x8240	#CJK UNIFIED IDEOGRAPH+0xE479	0x8259	#CJK UNIFIED IDEOGRAPH+0xE47A	0x8258	#CJK UNIFIED IDEOGRAPH+0xE47B	0x825D	#CJK UNIFIED IDEOGRAPH+0xE47C	0x825A	#CJK UNIFIED IDEOGRAPH+0xE47D	0x825F	#CJK UNIFIED IDEOGRAPH+0xE47E	0x8264	#CJK UNIFIED IDEOGRAPH+0xE480	0x8262	#CJK UNIFIED IDEOGRAPH+0xE481	0x8268	#CJK UNIFIED IDEOGRAPH+0xE482	0x826A	#CJK UNIFIED IDEOGRAPH+0xE483	0x826B	#CJK UNIFIED IDEOGRAPH+0xE484	0x822E	#CJK UNIFIED IDEOGRAPH+0xE485	0x8271	#CJK UNIFIED IDEOGRAPH+0xE486	0x8277	#CJK UNIFIED IDEOGRAPH+0xE487	0x8278	#CJK UNIFIED IDEOGRAPH+0xE488	0x827E	#CJK UNIFIED IDEOGRAPH+0xE489	0x828D	#CJK UNIFIED IDEOGRAPH+0xE48A	0x8292	#CJK UNIFIED IDEOGRAPH+0xE48B	0x82AB	#CJK UNIFIED IDEOGRAPH+0xE48C	0x829F	#CJK UNIFIED IDEOGRAPH+0xE48D	0x82BB	#CJK UNIFIED IDEOGRAPH+0xE48E	0x82AC	#CJK UNIFIED IDEOGRAPH+0xE48F	0x82E1	#CJK UNIFIED IDEOGRAPH+0xE490	0x82E3	#CJK UNIFIED IDEOGRAPH+0xE491	0x82DF	#CJK UNIFIED IDEOGRAPH+0xE492	0x82D2	#CJK UNIFIED IDEOGRAPH+0xE493	0x82F4	#CJK UNIFIED IDEOGRAPH+0xE494	0x82F3	#CJK UNIFIED IDEOGRAPH+0xE495	0x82FA	#CJK UNIFIED IDEOGRAPH+0xE496	0x8393	#CJK UNIFIED IDEOGRAPH+0xE497	0x8303	#CJK UNIFIED IDEOGRAPH+0xE498	0x82FB	#CJK UNIFIED IDEOGRAPH+0xE499	0x82F9	#CJK UNIFIED IDEOGRAPH+0xE49A	0x82DE	#CJK UNIFIED IDEOGRAPH+0xE49B	0x8306	#CJK UNIFIED IDEOGRAPH+0xE49C	0x82DC	#CJK UNIFIED IDEOGRAPH+0xE49D	0x8309	#CJK UNIFIED IDEOGRAPH+0xE49E	0x82D9	#CJK UNIFIED IDEOGRAPH+0xE49F	0x8335	#CJK UNIFIED IDEOGRAPH+0xE4A0	0x8334	#CJK UNIFIED IDEOGRAPH+0xE4A1	0x8316	#CJK UNIFIED IDEOGRAPH+0xE4A2	0x8332	#CJK UNIFIED IDEOGRAPH+0xE4A3	0x8331	#CJK UNIFIED IDEOGRAPH+0xE4A4	0x8340	#CJK UNIFIED IDEOGRAPH+0xE4A5	0x8339	#CJK UNIFIED IDEOGRAPH+0xE4A6	0x8350	#CJK UNIFIED IDEOGRAPH+0xE4A7	0x8345	#CJK UNIFIED IDEOGRAPH+0xE4A8	0x832F	#CJK UNIFIED IDEOGRAPH+0xE4A9	0x832B	#CJK UNIFIED IDEOGRAPH+0xE4AA	0x8317	#CJK UNIFIED IDEOGRAPH+0xE4AB	0x8318	#CJK UNIFIED IDEOGRAPH+0xE4AC	0x8385	#CJK UNIFIED IDEOGRAPH+0xE4AD	0x839A	#CJK UNIFIED IDEOGRAPH+0xE4AE	0x83AA	#CJK UNIFIED IDEOGRAPH+0xE4AF	0x839F	#CJK UNIFIED IDEOGRAPH+0xE4B0	0x83A2	#CJK UNIFIED IDEOGRAPH+0xE4B1	0x8396	#CJK UNIFIED IDEOGRAPH+0xE4B2	0x8323	#CJK UNIFIED IDEOGRAPH+0xE4B3	0x838E	#CJK UNIFIED IDEOGRAPH+0xE4B4	0x8387	#CJK UNIFIED IDEOGRAPH+0xE4B5	0x838A	#CJK UNIFIED IDEOGRAPH+0xE4B6	0x837C	#CJK UNIFIED IDEOGRAPH+0xE4B7	0x83B5	#CJK UNIFIED IDEOGRAPH+0xE4B8	0x8373	#CJK UNIFIED IDEOGRAPH+0xE4B9	0x8375	#CJK UNIFIED IDEOGRAPH+0xE4BA	0x83A0	#CJK UNIFIED IDEOGRAPH+0xE4BB	0x8389	#CJK UNIFIED IDEOGRAPH+0xE4BC	0x83A8	#CJK UNIFIED IDEOGRAPH+0xE4BD	0x83F4	#CJK UNIFIED IDEOGRAPH+0xE4BE	0x8413	#CJK UNIFIED IDEOGRAPH+0xE4BF	0x83EB	#CJK UNIFIED IDEOGRAPH+0xE4C0	0x83CE	#CJK UNIFIED IDEOGRAPH+0xE4C1	0x83FD	#CJK UNIFIED IDEOGRAPH+0xE4C2	0x8403	#CJK UNIFIED IDEOGRAPH+0xE4C3	0x83D8	#CJK UNIFIED IDEOGRAPH+0xE4C4	0x840B	#CJK UNIFIED IDEOGRAPH+0xE4C5	0x83C1	#CJK UNIFIED IDEOGRAPH+0xE4C6	0x83F7	#CJK UNIFIED IDEOGRAPH+0xE4C7	0x8407	#CJK UNIFIED IDEOGRAPH+0xE4C8	0x83E0	#CJK UNIFIED IDEOGRAPH+0xE4C9	0x83F2	#CJK UNIFIED IDEOGRAPH+0xE4CA	0x840D	#CJK UNIFIED IDEOGRAPH+0xE4CB	0x8422	#CJK UNIFIED IDEOGRAPH+0xE4CC	0x8420	#CJK UNIFIED IDEOGRAPH+0xE4CD	0x83BD	#CJK UNIFIED IDEOGRAPH+0xE4CE	0x8438	#CJK UNIFIED IDEOGRAPH+0xE4CF	0x8506	#CJK UNIFIED IDEOGRAPH+0xE4D0	0x83FB	#CJK UNIFIED IDEOGRAPH+0xE4D1	0x846D	#CJK UNIFIED IDEOGRAPH+0xE4D2	0x842A	#CJK UNIFIED IDEOGRAPH+0xE4D3	0x843C	#CJK UNIFIED IDEOGRAPH+0xE4D4	0x855A	#CJK UNIFIED IDEOGRAPH+0xE4D5	0x8484	#CJK UNIFIED IDEOGRAPH+0xE4D6	0x8477	#CJK UNIFIED IDEOGRAPH+0xE4D7	0x846B	#CJK UNIFIED IDEOGRAPH+0xE4D8	0x84AD	#CJK UNIFIED IDEOGRAPH+0xE4D9	0x846E	#CJK UNIFIED IDEOGRAPH+0xE4DA	0x8482	#CJK UNIFIED IDEOGRAPH+0xE4DB	0x8469	#CJK UNIFIED IDEOGRAPH+0xE4DC	0x8446	#CJK UNIFIED IDEOGRAPH+0xE4DD	0x842C	#CJK UNIFIED IDEOGRAPH+0xE4DE	0x846F	#CJK UNIFIED IDEOGRAPH+0xE4DF	0x8479	#CJK UNIFIED IDEOGRAPH+0xE4E0	0x8435	#CJK UNIFIED IDEOGRAPH+0xE4E1	0x84CA	#CJK UNIFIED IDEOGRAPH+0xE4E2	0x8462	#CJK UNIFIED IDEOGRAPH+0xE4E3	0x84B9	#CJK UNIFIED IDEOGRAPH+0xE4E4	0x84BF	#CJK UNIFIED IDEOGRAPH+0xE4E5	0x849F	#CJK UNIFIED IDEOGRAPH+0xE4E6	0x84D9	#CJK UNIFIED IDEOGRAPH+0xE4E7	0x84CD	#CJK UNIFIED IDEOGRAPH+0xE4E8	0x84BB	#CJK UNIFIED IDEOGRAPH+0xE4E9	0x84DA	#CJK UNIFIED IDEOGRAPH+0xE4EA	0x84D0	#CJK UNIFIED IDEOGRAPH+0xE4EB	0x84C1	#CJK UNIFIED IDEOGRAPH+0xE4EC	0x84C6	#CJK UNIFIED IDEOGRAPH+0xE4ED	0x84D6	#CJK UNIFIED IDEOGRAPH+0xE4EE	0x84A1	#CJK UNIFIED IDEOGRAPH+0xE4EF	0x8521	#CJK UNIFIED IDEOGRAPH+0xE4F0	0x84FF	#CJK UNIFIED IDEOGRAPH+0xE4F1	0x84F4	#CJK UNIFIED IDEOGRAPH+0xE4F2	0x8517	#CJK UNIFIED IDEOGRAPH+0xE4F3	0x8518	#CJK UNIFIED IDEOGRAPH+0xE4F4	0x852C	#CJK UNIFIED IDEOGRAPH+0xE4F5	0x851F	#CJK UNIFIED IDEOGRAPH+0xE4F6	0x8515	#CJK UNIFIED IDEOGRAPH+0xE4F7	0x8514	#CJK UNIFIED IDEOGRAPH+0xE4F8	0x84FC	#CJK UNIFIED IDEOGRAPH+0xE4F9	0x8540	#CJK UNIFIED IDEOGRAPH+0xE4FA	0x8563	#CJK UNIFIED IDEOGRAPH+0xE4FB	0x8558	#CJK UNIFIED IDEOGRAPH+0xE4FC	0x8548	#CJK UNIFIED IDEOGRAPH+0xE540	0x8541	#CJK UNIFIED IDEOGRAPH+0xE541	0x8602	#CJK UNIFIED IDEOGRAPH+0xE542	0x854B	#CJK UNIFIED IDEOGRAPH+0xE543	0x8555	#CJK UNIFIED IDEOGRAPH+0xE544	0x8580	#CJK UNIFIED IDEOGRAPH+0xE545	0x85A4	#CJK UNIFIED IDEOGRAPH+0xE546	0x8588	#CJK UNIFIED IDEOGRAPH+0xE547	0x8591	#CJK UNIFIED IDEOGRAPH+0xE548	0x858A	#CJK UNIFIED IDEOGRAPH+0xE549	0x85A8	#CJK UNIFIED IDEOGRAPH+0xE54A	0x856D	#CJK UNIFIED IDEOGRAPH+0xE54B	0x8594	#CJK UNIFIED IDEOGRAPH+0xE54C	0x859B	#CJK UNIFIED IDEOGRAPH+0xE54D	0x85EA	#CJK UNIFIED IDEOGRAPH+0xE54E	0x8587	#CJK UNIFIED IDEOGRAPH+0xE54F	0x859C	#CJK UNIFIED IDEOGRAPH+0xE550	0x8577	#CJK UNIFIED IDEOGRAPH+0xE551	0x857E	#CJK UNIFIED IDEOGRAPH+0xE552	0x8590	#CJK UNIFIED IDEOGRAPH+0xE553	0x85C9	#CJK UNIFIED IDEOGRAPH+0xE554	0x85BA	#CJK UNIFIED IDEOGRAPH+0xE555	0x85CF	#CJK UNIFIED IDEOGRAPH+0xE556	0x85B9	#CJK UNIFIED IDEOGRAPH+0xE557	0x85D0	#CJK UNIFIED IDEOGRAPH+0xE558	0x85D5	#CJK UNIFIED IDEOGRAPH+0xE559	0x85DD	#CJK UNIFIED IDEOGRAPH+0xE55A	0x85E5	#CJK UNIFIED IDEOGRAPH+0xE55B	0x85DC	#CJK UNIFIED IDEOGRAPH+0xE55C	0x85F9	#CJK UNIFIED IDEOGRAPH+0xE55D	0x860A	#CJK UNIFIED IDEOGRAPH+0xE55E	0x8613	#CJK UNIFIED IDEOGRAPH+0xE55F	0x860B	#CJK UNIFIED IDEOGRAPH+0xE560	0x85FE	#CJK UNIFIED IDEOGRAPH+0xE561	0x85FA	#CJK UNIFIED IDEOGRAPH+0xE562	0x8606	#CJK UNIFIED IDEOGRAPH+0xE563	0x8622	#CJK UNIFIED IDEOGRAPH+0xE564	0x861A	#CJK UNIFIED IDEOGRAPH+0xE565	0x8630	#CJK UNIFIED IDEOGRAPH+0xE566	0x863F	#CJK UNIFIED IDEOGRAPH+0xE567	0x864D	#CJK UNIFIED IDEOGRAPH+0xE568	0x4E55	#CJK UNIFIED IDEOGRAPH+0xE569	0x8654	#CJK UNIFIED IDEOGRAPH+0xE56A	0x865F	#CJK UNIFIED IDEOGRAPH+0xE56B	0x8667	#CJK UNIFIED IDEOGRAPH+0xE56C	0x8671	#CJK UNIFIED IDEOGRAPH+0xE56D	0x8693	#CJK UNIFIED IDEOGRAPH+0xE56E	0x86A3	#CJK UNIFIED IDEOGRAPH+0xE56F	0x86A9	#CJK UNIFIED IDEOGRAPH+0xE570	0x86AA	#CJK UNIFIED IDEOGRAPH+0xE571	0x868B	#CJK UNIFIED IDEOGRAPH+0xE572	0x868C	#CJK UNIFIED IDEOGRAPH+0xE573	0x86B6	#CJK UNIFIED IDEOGRAPH+0xE574	0x86AF	#CJK UNIFIED IDEOGRAPH+0xE575	0x86C4	#CJK UNIFIED IDEOGRAPH+0xE576	0x86C6	#CJK UNIFIED IDEOGRAPH+0xE577	0x86B0	#CJK UNIFIED IDEOGRAPH+0xE578	0x86C9	#CJK UNIFIED IDEOGRAPH+0xE579	0x8823	#CJK UNIFIED IDEOGRAPH+0xE57A	0x86AB	#CJK UNIFIED IDEOGRAPH+0xE57B	0x86D4	#CJK UNIFIED IDEOGRAPH+0xE57C	0x86DE	#CJK UNIFIED IDEOGRAPH+0xE57D	0x86E9	#CJK UNIFIED IDEOGRAPH+0xE57E	0x86EC	#CJK UNIFIED IDEOGRAPH+0xE580	0x86DF	#CJK UNIFIED IDEOGRAPH+0xE581	0x86DB	#CJK UNIFIED IDEOGRAPH+0xE582	0x86EF	#CJK UNIFIED IDEOGRAPH+0xE583	0x8712	#CJK UNIFIED IDEOGRAPH+0xE584	0x8706	#CJK UNIFIED IDEOGRAPH+0xE585	0x8708	#CJK UNIFIED IDEOGRAPH+0xE586	0x8700	#CJK UNIFIED IDEOGRAPH+0xE587	0x8703	#CJK UNIFIED IDEOGRAPH+0xE588	0x86FB	#CJK UNIFIED IDEOGRAPH+0xE589	0x8711	#CJK UNIFIED IDEOGRAPH+0xE58A	0x8709	#CJK UNIFIED IDEOGRAPH+0xE58B	0x870D	#CJK UNIFIED IDEOGRAPH+0xE58C	0x86F9	#CJK UNIFIED IDEOGRAPH+0xE58D	0x870A	#CJK UNIFIED IDEOGRAPH+0xE58E	0x8734	#CJK UNIFIED IDEOGRAPH+0xE58F	0x873F	#CJK UNIFIED IDEOGRAPH+0xE590	0x8737	#CJK UNIFIED IDEOGRAPH+0xE591	0x873B	#CJK UNIFIED IDEOGRAPH+0xE592	0x8725	#CJK UNIFIED IDEOGRAPH+0xE593	0x8729	#CJK UNIFIED IDEOGRAPH+0xE594	0x871A	#CJK UNIFIED IDEOGRAPH+0xE595	0x8760	#CJK UNIFIED IDEOGRAPH+0xE596	0x875F	#CJK UNIFIED IDEOGRAPH+0xE597	0x8778	#CJK UNIFIED IDEOGRAPH+0xE598	0x874C	#CJK UNIFIED IDEOGRAPH+0xE599	0x874E	#CJK UNIFIED IDEOGRAPH+0xE59A	0x8774	#CJK UNIFIED IDEOGRAPH+0xE59B	0x8757	#CJK UNIFIED IDEOGRAPH+0xE59C	0x8768	#CJK UNIFIED IDEOGRAPH+0xE59D	0x876E	#CJK UNIFIED IDEOGRAPH+0xE59E	0x8759	#CJK UNIFIED IDEOGRAPH+0xE59F	0x8753	#CJK UNIFIED IDEOGRAPH+0xE5A0	0x8763	#CJK UNIFIED IDEOGRAPH+0xE5A1	0x876A	#CJK UNIFIED IDEOGRAPH+0xE5A2	0x8805	#CJK UNIFIED IDEOGRAPH+0xE5A3	0x87A2	#CJK UNIFIED IDEOGRAPH+0xE5A4	0x879F	#CJK UNIFIED IDEOGRAPH+0xE5A5	0x8782	#CJK UNIFIED IDEOGRAPH+0xE5A6	0x87AF	#CJK UNIFIED IDEOGRAPH+0xE5A7	0x87CB	#CJK UNIFIED IDEOGRAPH+0xE5A8	0x87BD	#CJK UNIFIED IDEOGRAPH+0xE5A9	0x87C0	#CJK UNIFIED IDEOGRAPH+0xE5AA	0x87D0	#CJK UNIFIED IDEOGRAPH+0xE5AB	0x96D6	#CJK UNIFIED IDEOGRAPH+0xE5AC	0x87AB	#CJK UNIFIED IDEOGRAPH+0xE5AD	0x87C4	#CJK UNIFIED IDEOGRAPH+0xE5AE	0x87B3	#CJK UNIFIED IDEOGRAPH+0xE5AF	0x87C7	#CJK UNIFIED IDEOGRAPH+0xE5B0	0x87C6	#CJK UNIFIED IDEOGRAPH+0xE5B1	0x87BB	#CJK UNIFIED IDEOGRAPH+0xE5B2	0x87EF	#CJK UNIFIED IDEOGRAPH+0xE5B3	0x87F2	#CJK UNIFIED IDEOGRAPH+0xE5B4	0x87E0	#CJK UNIFIED IDEOGRAPH+0xE5B5	0x880F	#CJK UNIFIED IDEOGRAPH+0xE5B6	0x880D	#CJK UNIFIED IDEOGRAPH+0xE5B7	0x87FE	#CJK UNIFIED IDEOGRAPH+0xE5B8	0x87F6	#CJK UNIFIED IDEOGRAPH+0xE5B9	0x87F7	#CJK UNIFIED IDEOGRAPH+0xE5BA	0x880E	#CJK UNIFIED IDEOGRAPH+0xE5BB	0x87D2	#CJK UNIFIED IDEOGRAPH+0xE5BC	0x8811	#CJK UNIFIED IDEOGRAPH+0xE5BD	0x8816	#CJK UNIFIED IDEOGRAPH+0xE5BE	0x8815	#CJK UNIFIED IDEOGRAPH+0xE5BF	0x8822	#CJK UNIFIED IDEOGRAPH+0xE5C0	0x8821	#CJK UNIFIED IDEOGRAPH+0xE5C1	0x8831	#CJK UNIFIED IDEOGRAPH+0xE5C2	0x8836	#CJK UNIFIED IDEOGRAPH+0xE5C3	0x8839	#CJK UNIFIED IDEOGRAPH+0xE5C4	0x8827	#CJK UNIFIED IDEOGRAPH+0xE5C5	0x883B	#CJK UNIFIED IDEOGRAPH+0xE5C6	0x8844	#CJK UNIFIED IDEOGRAPH+0xE5C7	0x8842	#CJK UNIFIED IDEOGRAPH+0xE5C8	0x8852	#CJK UNIFIED IDEOGRAPH+0xE5C9	0x8859	#CJK UNIFIED IDEOGRAPH+0xE5CA	0x885E	#CJK UNIFIED IDEOGRAPH+0xE5CB	0x8862	#CJK UNIFIED IDEOGRAPH+0xE5CC	0x886B	#CJK UNIFIED IDEOGRAPH+0xE5CD	0x8881	#CJK UNIFIED IDEOGRAPH+0xE5CE	0x887E	#CJK UNIFIED IDEOGRAPH+0xE5CF	0x889E	#CJK UNIFIED IDEOGRAPH+0xE5D0	0x8875	#CJK UNIFIED IDEOGRAPH+0xE5D1	0x887D	#CJK UNIFIED IDEOGRAPH+0xE5D2	0x88B5	#CJK UNIFIED IDEOGRAPH+0xE5D3	0x8872	#CJK UNIFIED IDEOGRAPH+0xE5D4	0x8882	#CJK UNIFIED IDEOGRAPH+0xE5D5	0x8897	#CJK UNIFIED IDEOGRAPH+0xE5D6	0x8892	#CJK UNIFIED IDEOGRAPH+0xE5D7	0x88AE	#CJK UNIFIED IDEOGRAPH+0xE5D8	0x8899	#CJK UNIFIED IDEOGRAPH+0xE5D9	0x88A2	#CJK UNIFIED IDEOGRAPH+0xE5DA	0x888D	#CJK UNIFIED IDEOGRAPH+0xE5DB	0x88A4	#CJK UNIFIED IDEOGRAPH+0xE5DC	0x88B0	#CJK UNIFIED IDEOGRAPH+0xE5DD	0x88BF	#CJK UNIFIED IDEOGRAPH+0xE5DE	0x88B1	#CJK UNIFIED IDEOGRAPH+0xE5DF	0x88C3	#CJK UNIFIED IDEOGRAPH+0xE5E0	0x88C4	#CJK UNIFIED IDEOGRAPH+0xE5E1	0x88D4	#CJK UNIFIED IDEOGRAPH+0xE5E2	0x88D8	#CJK UNIFIED IDEOGRAPH+0xE5E3	0x88D9	#CJK UNIFIED IDEOGRAPH+0xE5E4	0x88DD	#CJK UNIFIED IDEOGRAPH+0xE5E5	0x88F9	#CJK UNIFIED IDEOGRAPH+0xE5E6	0x8902	#CJK UNIFIED IDEOGRAPH+0xE5E7	0x88FC	#CJK UNIFIED IDEOGRAPH+0xE5E8	0x88F4	#CJK UNIFIED IDEOGRAPH+0xE5E9	0x88E8	#CJK UNIFIED IDEOGRAPH+0xE5EA	0x88F2	#CJK UNIFIED IDEOGRAPH+0xE5EB	0x8904	#CJK UNIFIED IDEOGRAPH+0xE5EC	0x890C	#CJK UNIFIED IDEOGRAPH+0xE5ED	0x890A	#CJK UNIFIED IDEOGRAPH+0xE5EE	0x8913	#CJK UNIFIED IDEOGRAPH+0xE5EF	0x8943	#CJK UNIFIED IDEOGRAPH+0xE5F0	0x891E	#CJK UNIFIED IDEOGRAPH+0xE5F1	0x8925	#CJK UNIFIED IDEOGRAPH+0xE5F2	0x892A	#CJK UNIFIED IDEOGRAPH+0xE5F3	0x892B	#CJK UNIFIED IDEOGRAPH+0xE5F4	0x8941	#CJK UNIFIED IDEOGRAPH+0xE5F5	0x8944	#CJK UNIFIED IDEOGRAPH+0xE5F6	0x893B	#CJK UNIFIED IDEOGRAPH+0xE5F7	0x8936	#CJK UNIFIED IDEOGRAPH+0xE5F8	0x8938	#CJK UNIFIED IDEOGRAPH+0xE5F9	0x894C	#CJK UNIFIED IDEOGRAPH+0xE5FA	0x891D	#CJK UNIFIED IDEOGRAPH+0xE5FB	0x8960	#CJK UNIFIED IDEOGRAPH+0xE5FC	0x895E	#CJK UNIFIED IDEOGRAPH+0xE640	0x8966	#CJK UNIFIED IDEOGRAPH+0xE641	0x8964	#CJK UNIFIED IDEOGRAPH+0xE642	0x896D	#CJK UNIFIED IDEOGRAPH+0xE643	0x896A	#CJK UNIFIED IDEOGRAPH+0xE644	0x896F	#CJK UNIFIED IDEOGRAPH+0xE645	0x8974	#CJK UNIFIED IDEOGRAPH+0xE646	0x8977	#CJK UNIFIED IDEOGRAPH+0xE647	0x897E	#CJK UNIFIED IDEOGRAPH+0xE648	0x8983	#CJK UNIFIED IDEOGRAPH+0xE649	0x8988	#CJK UNIFIED IDEOGRAPH+0xE64A	0x898A	#CJK UNIFIED IDEOGRAPH+0xE64B	0x8993	#CJK UNIFIED IDEOGRAPH+0xE64C	0x8998	#CJK UNIFIED IDEOGRAPH+0xE64D	0x89A1	#CJK UNIFIED IDEOGRAPH+0xE64E	0x89A9	#CJK UNIFIED IDEOGRAPH+0xE64F	0x89A6	#CJK UNIFIED IDEOGRAPH+0xE650	0x89AC	#CJK UNIFIED IDEOGRAPH+0xE651	0x89AF	#CJK UNIFIED IDEOGRAPH+0xE652	0x89B2	#CJK UNIFIED IDEOGRAPH+0xE653	0x89BA	#CJK UNIFIED IDEOGRAPH+0xE654	0x89BD	#CJK UNIFIED IDEOGRAPH+0xE655	0x89BF	#CJK UNIFIED IDEOGRAPH+0xE656	0x89C0	#CJK UNIFIED IDEOGRAPH+0xE657	0x89DA	#CJK UNIFIED IDEOGRAPH+0xE658	0x89DC	#CJK UNIFIED IDEOGRAPH+0xE659	0x89DD	#CJK UNIFIED IDEOGRAPH+0xE65A	0x89E7	#CJK UNIFIED IDEOGRAPH+0xE65B	0x89F4	#CJK UNIFIED IDEOGRAPH+0xE65C	0x89F8	#CJK UNIFIED IDEOGRAPH+0xE65D	0x8A03	#CJK UNIFIED IDEOGRAPH+0xE65E	0x8A16	#CJK UNIFIED IDEOGRAPH+0xE65F	0x8A10	#CJK UNIFIED IDEOGRAPH+0xE660	0x8A0C	#CJK UNIFIED IDEOGRAPH+0xE661	0x8A1B	#CJK UNIFIED IDEOGRAPH+0xE662	0x8A1D	#CJK UNIFIED IDEOGRAPH+0xE663	0x8A25	#CJK UNIFIED IDEOGRAPH+0xE664	0x8A36	#CJK UNIFIED IDEOGRAPH+0xE665	0x8A41	#CJK UNIFIED IDEOGRAPH+0xE666	0x8A5B	#CJK UNIFIED IDEOGRAPH+0xE667	0x8A52	#CJK UNIFIED IDEOGRAPH+0xE668	0x8A46	#CJK UNIFIED IDEOGRAPH+0xE669	0x8A48	#CJK UNIFIED IDEOGRAPH+0xE66A	0x8A7C	#CJK UNIFIED IDEOGRAPH+0xE66B	0x8A6D	#CJK UNIFIED IDEOGRAPH+0xE66C	0x8A6C	#CJK UNIFIED IDEOGRAPH+0xE66D	0x8A62	#CJK UNIFIED IDEOGRAPH+0xE66E	0x8A85	#CJK UNIFIED IDEOGRAPH+0xE66F	0x8A82	#CJK UNIFIED IDEOGRAPH+0xE670	0x8A84	#CJK UNIFIED IDEOGRAPH+0xE671	0x8AA8	#CJK UNIFIED IDEOGRAPH+0xE672	0x8AA1	#CJK UNIFIED IDEOGRAPH+0xE673	0x8A91	#CJK UNIFIED IDEOGRAPH+0xE674	0x8AA5	#CJK UNIFIED IDEOGRAPH+0xE675	0x8AA6	#CJK UNIFIED IDEOGRAPH+0xE676	0x8A9A	#CJK UNIFIED IDEOGRAPH+0xE677	0x8AA3	#CJK UNIFIED IDEOGRAPH+0xE678	0x8AC4	#CJK UNIFIED IDEOGRAPH+0xE679	0x8ACD	#CJK UNIFIED IDEOGRAPH+0xE67A	0x8AC2	#CJK UNIFIED IDEOGRAPH+0xE67B	0x8ADA	#CJK UNIFIED IDEOGRAPH+0xE67C	0x8AEB	#CJK UNIFIED IDEOGRAPH+0xE67D	0x8AF3	#CJK UNIFIED IDEOGRAPH+0xE67E	0x8AE7	#CJK UNIFIED IDEOGRAPH+0xE680	0x8AE4	#CJK UNIFIED IDEOGRAPH+0xE681	0x8AF1	#CJK UNIFIED IDEOGRAPH+0xE682	0x8B14	#CJK UNIFIED IDEOGRAPH+0xE683	0x8AE0	#CJK UNIFIED IDEOGRAPH+0xE684	0x8AE2	#CJK UNIFIED IDEOGRAPH+0xE685	0x8AF7	#CJK UNIFIED IDEOGRAPH+0xE686	0x8ADE	#CJK UNIFIED IDEOGRAPH+0xE687	0x8ADB	#CJK UNIFIED IDEOGRAPH+0xE688	0x8B0C	#CJK UNIFIED IDEOGRAPH+0xE689	0x8B07	#CJK UNIFIED IDEOGRAPH+0xE68A	0x8B1A	#CJK UNIFIED IDEOGRAPH+0xE68B	0x8AE1	#CJK UNIFIED IDEOGRAPH+0xE68C	0x8B16	#CJK UNIFIED IDEOGRAPH+0xE68D	0x8B10	#CJK UNIFIED IDEOGRAPH+0xE68E	0x8B17	#CJK UNIFIED IDEOGRAPH+0xE68F	0x8B20	#CJK UNIFIED IDEOGRAPH+0xE690	0x8B33	#CJK UNIFIED IDEOGRAPH+0xE691	0x97AB	#CJK UNIFIED IDEOGRAPH+0xE692	0x8B26	#CJK UNIFIED IDEOGRAPH+0xE693	0x8B2B	#CJK UNIFIED IDEOGRAPH+0xE694	0x8B3E	#CJK UNIFIED IDEOGRAPH+0xE695	0x8B28	#CJK UNIFIED IDEOGRAPH+0xE696	0x8B41	#CJK UNIFIED IDEOGRAPH+0xE697	0x8B4C	#CJK UNIFIED IDEOGRAPH+0xE698	0x8B4F	#CJK UNIFIED IDEOGRAPH+0xE699	0x8B4E	#CJK UNIFIED IDEOGRAPH+0xE69A	0x8B49	#CJK UNIFIED IDEOGRAPH+0xE69B	0x8B56	#CJK UNIFIED IDEOGRAPH+0xE69C	0x8B5B	#CJK UNIFIED IDEOGRAPH+0xE69D	0x8B5A	#CJK UNIFIED IDEOGRAPH+0xE69E	0x8B6B	#CJK UNIFIED IDEOGRAPH+0xE69F	0x8B5F	#CJK UNIFIED IDEOGRAPH+0xE6A0	0x8B6C	#CJK UNIFIED IDEOGRAPH+0xE6A1	0x8B6F	#CJK UNIFIED IDEOGRAPH+0xE6A2	0x8B74	#CJK UNIFIED IDEOGRAPH+0xE6A3	0x8B7D	#CJK UNIFIED IDEOGRAPH+0xE6A4	0x8B80	#CJK UNIFIED IDEOGRAPH+0xE6A5	0x8B8C	#CJK UNIFIED IDEOGRAPH+0xE6A6	0x8B8E	#CJK UNIFIED IDEOGRAPH+0xE6A7	0x8B92	#CJK UNIFIED IDEOGRAPH+0xE6A8	0x8B93	#CJK UNIFIED IDEOGRAPH+0xE6A9	0x8B96	#CJK UNIFIED IDEOGRAPH+0xE6AA	0x8B99	#CJK UNIFIED IDEOGRAPH+0xE6AB	0x8B9A	#CJK UNIFIED IDEOGRAPH+0xE6AC	0x8C3A	#CJK UNIFIED IDEOGRAPH+0xE6AD	0x8C41	#CJK UNIFIED IDEOGRAPH+0xE6AE	0x8C3F	#CJK UNIFIED IDEOGRAPH+0xE6AF	0x8C48	#CJK UNIFIED IDEOGRAPH+0xE6B0	0x8C4C	#CJK UNIFIED IDEOGRAPH+0xE6B1	0x8C4E	#CJK UNIFIED IDEOGRAPH+0xE6B2	0x8C50	#CJK UNIFIED IDEOGRAPH+0xE6B3	0x8C55	#CJK UNIFIED IDEOGRAPH+0xE6B4	0x8C62	#CJK UNIFIED IDEOGRAPH+0xE6B5	0x8C6C	#CJK UNIFIED IDEOGRAPH+0xE6B6	0x8C78	#CJK UNIFIED IDEOGRAPH+0xE6B7	0x8C7A	#CJK UNIFIED IDEOGRAPH+0xE6B8	0x8C82	#CJK UNIFIED IDEOGRAPH+0xE6B9	0x8C89	#CJK UNIFIED IDEOGRAPH+0xE6BA	0x8C85	#CJK UNIFIED IDEOGRAPH+0xE6BB	0x8C8A	#CJK UNIFIED IDEOGRAPH+0xE6BC	0x8C8D	#CJK UNIFIED IDEOGRAPH+0xE6BD	0x8C8E	#CJK UNIFIED IDEOGRAPH+0xE6BE	0x8C94	#CJK UNIFIED IDEOGRAPH+0xE6BF	0x8C7C	#CJK UNIFIED IDEOGRAPH+0xE6C0	0x8C98	#CJK UNIFIED IDEOGRAPH+0xE6C1	0x621D	#CJK UNIFIED IDEOGRAPH+0xE6C2	0x8CAD	#CJK UNIFIED IDEOGRAPH+0xE6C3	0x8CAA	#CJK UNIFIED IDEOGRAPH+0xE6C4	0x8CBD	#CJK UNIFIED IDEOGRAPH+0xE6C5	0x8CB2	#CJK UNIFIED IDEOGRAPH+0xE6C6	0x8CB3	#CJK UNIFIED IDEOGRAPH+0xE6C7	0x8CAE	#CJK UNIFIED IDEOGRAPH+0xE6C8	0x8CB6	#CJK UNIFIED IDEOGRAPH+0xE6C9	0x8CC8	#CJK UNIFIED IDEOGRAPH+0xE6CA	0x8CC1	#CJK UNIFIED IDEOGRAPH+0xE6CB	0x8CE4	#CJK UNIFIED IDEOGRAPH+0xE6CC	0x8CE3	#CJK UNIFIED IDEOGRAPH+0xE6CD	0x8CDA	#CJK UNIFIED IDEOGRAPH+0xE6CE	0x8CFD	#CJK UNIFIED IDEOGRAPH+0xE6CF	0x8CFA	#CJK UNIFIED IDEOGRAPH+0xE6D0	0x8CFB	#CJK UNIFIED IDEOGRAPH+0xE6D1	0x8D04	#CJK UNIFIED IDEOGRAPH+0xE6D2	0x8D05	#CJK UNIFIED IDEOGRAPH+0xE6D3	0x8D0A	#CJK UNIFIED IDEOGRAPH+0xE6D4	0x8D07	#CJK UNIFIED IDEOGRAPH+0xE6D5	0x8D0F	#CJK UNIFIED IDEOGRAPH+0xE6D6	0x8D0D	#CJK UNIFIED IDEOGRAPH+0xE6D7	0x8D10	#CJK UNIFIED IDEOGRAPH+0xE6D8	0x9F4E	#CJK UNIFIED IDEOGRAPH+0xE6D9	0x8D13	#CJK UNIFIED IDEOGRAPH+0xE6DA	0x8CCD	#CJK UNIFIED IDEOGRAPH+0xE6DB	0x8D14	#CJK UNIFIED IDEOGRAPH+0xE6DC	0x8D16	#CJK UNIFIED IDEOGRAPH+0xE6DD	0x8D67	#CJK UNIFIED IDEOGRAPH+0xE6DE	0x8D6D	#CJK UNIFIED IDEOGRAPH+0xE6DF	0x8D71	#CJK UNIFIED IDEOGRAPH+0xE6E0	0x8D73	#CJK UNIFIED IDEOGRAPH+0xE6E1	0x8D81	#CJK UNIFIED IDEOGRAPH+0xE6E2	0x8D99	#CJK UNIFIED IDEOGRAPH+0xE6E3	0x8DC2	#CJK UNIFIED IDEOGRAPH+0xE6E4	0x8DBE	#CJK UNIFIED IDEOGRAPH+0xE6E5	0x8DBA	#CJK UNIFIED IDEOGRAPH+0xE6E6	0x8DCF	#CJK UNIFIED IDEOGRAPH+0xE6E7	0x8DDA	#CJK UNIFIED IDEOGRAPH+0xE6E8	0x8DD6	#CJK UNIFIED IDEOGRAPH+0xE6E9	0x8DCC	#CJK UNIFIED IDEOGRAPH+0xE6EA	0x8DDB	#CJK UNIFIED IDEOGRAPH+0xE6EB	0x8DCB	#CJK UNIFIED IDEOGRAPH+0xE6EC	0x8DEA	#CJK UNIFIED IDEOGRAPH+0xE6ED	0x8DEB	#CJK UNIFIED IDEOGRAPH+0xE6EE	0x8DDF	#CJK UNIFIED IDEOGRAPH+0xE6EF	0x8DE3	#CJK UNIFIED IDEOGRAPH+0xE6F0	0x8DFC	#CJK UNIFIED IDEOGRAPH+0xE6F1	0x8E08	#CJK UNIFIED IDEOGRAPH+0xE6F2	0x8E09	#CJK UNIFIED IDEOGRAPH+0xE6F3	0x8DFF	#CJK UNIFIED IDEOGRAPH+0xE6F4	0x8E1D	#CJK UNIFIED IDEOGRAPH+0xE6F5	0x8E1E	#CJK UNIFIED IDEOGRAPH+0xE6F6	0x8E10	#CJK UNIFIED IDEOGRAPH+0xE6F7	0x8E1F	#CJK UNIFIED IDEOGRAPH+0xE6F8	0x8E42	#CJK UNIFIED IDEOGRAPH+0xE6F9	0x8E35	#CJK UNIFIED IDEOGRAPH+0xE6FA	0x8E30	#CJK UNIFIED IDEOGRAPH+0xE6FB	0x8E34	#CJK UNIFIED IDEOGRAPH+0xE6FC	0x8E4A	#CJK UNIFIED IDEOGRAPH+0xE740	0x8E47	#CJK UNIFIED IDEOGRAPH+0xE741	0x8E49	#CJK UNIFIED IDEOGRAPH+0xE742	0x8E4C	#CJK UNIFIED IDEOGRAPH+0xE743	0x8E50	#CJK UNIFIED IDEOGRAPH+0xE744	0x8E48	#CJK UNIFIED IDEOGRAPH+0xE745	0x8E59	#CJK UNIFIED IDEOGRAPH+0xE746	0x8E64	#CJK UNIFIED IDEOGRAPH+0xE747	0x8E60	#CJK UNIFIED IDEOGRAPH+0xE748	0x8E2A	#CJK UNIFIED IDEOGRAPH+0xE749	0x8E63	#CJK UNIFIED IDEOGRAPH+0xE74A	0x8E55	#CJK UNIFIED IDEOGRAPH+0xE74B	0x8E76	#CJK UNIFIED IDEOGRAPH+0xE74C	0x8E72	#CJK UNIFIED IDEOGRAPH+0xE74D	0x8E7C	#CJK UNIFIED IDEOGRAPH+0xE74E	0x8E81	#CJK UNIFIED IDEOGRAPH+0xE74F	0x8E87	#CJK UNIFIED IDEOGRAPH+0xE750	0x8E85	#CJK UNIFIED IDEOGRAPH+0xE751	0x8E84	#CJK UNIFIED IDEOGRAPH+0xE752	0x8E8B	#CJK UNIFIED IDEOGRAPH+0xE753	0x8E8A	#CJK UNIFIED IDEOGRAPH+0xE754	0x8E93	#CJK UNIFIED IDEOGRAPH+0xE755	0x8E91	#CJK UNIFIED IDEOGRAPH+0xE756	0x8E94	#CJK UNIFIED IDEOGRAPH+0xE757	0x8E99	#CJK UNIFIED IDEOGRAPH+0xE758	0x8EAA	#CJK UNIFIED IDEOGRAPH+0xE759	0x8EA1	#CJK UNIFIED IDEOGRAPH+0xE75A	0x8EAC	#CJK UNIFIED IDEOGRAPH+0xE75B	0x8EB0	#CJK UNIFIED IDEOGRAPH+0xE75C	0x8EC6	#CJK UNIFIED IDEOGRAPH+0xE75D	0x8EB1	#CJK UNIFIED IDEOGRAPH+0xE75E	0x8EBE	#CJK UNIFIED IDEOGRAPH+0xE75F	0x8EC5	#CJK UNIFIED IDEOGRAPH+0xE760	0x8EC8	#CJK UNIFIED IDEOGRAPH+0xE761	0x8ECB	#CJK UNIFIED IDEOGRAPH+0xE762	0x8EDB	#CJK UNIFIED IDEOGRAPH+0xE763	0x8EE3	#CJK UNIFIED IDEOGRAPH+0xE764	0x8EFC	#CJK UNIFIED IDEOGRAPH+0xE765	0x8EFB	#CJK UNIFIED IDEOGRAPH+0xE766	0x8EEB	#CJK UNIFIED IDEOGRAPH+0xE767	0x8EFE	#CJK UNIFIED IDEOGRAPH+0xE768	0x8F0A	#CJK UNIFIED IDEOGRAPH+0xE769	0x8F05	#CJK UNIFIED IDEOGRAPH+0xE76A	0x8F15	#CJK UNIFIED IDEOGRAPH+0xE76B	0x8F12	#CJK UNIFIED IDEOGRAPH+0xE76C	0x8F19	#CJK UNIFIED IDEOGRAPH+0xE76D	0x8F13	#CJK UNIFIED IDEOGRAPH+0xE76E	0x8F1C	#CJK UNIFIED IDEOGRAPH+0xE76F	0x8F1F	#CJK UNIFIED IDEOGRAPH+0xE770	0x8F1B	#CJK UNIFIED IDEOGRAPH+0xE771	0x8F0C	#CJK UNIFIED IDEOGRAPH+0xE772	0x8F26	#CJK UNIFIED IDEOGRAPH+0xE773	0x8F33	#CJK UNIFIED IDEOGRAPH+0xE774	0x8F3B	#CJK UNIFIED IDEOGRAPH+0xE775	0x8F39	#CJK UNIFIED IDEOGRAPH+0xE776	0x8F45	#CJK UNIFIED IDEOGRAPH+0xE777	0x8F42	#CJK UNIFIED IDEOGRAPH+0xE778	0x8F3E	#CJK UNIFIED IDEOGRAPH+0xE779	0x8F4C	#CJK UNIFIED IDEOGRAPH+0xE77A	0x8F49	#CJK UNIFIED IDEOGRAPH+0xE77B	0x8F46	#CJK UNIFIED IDEOGRAPH+0xE77C	0x8F4E	#CJK UNIFIED IDEOGRAPH+0xE77D	0x8F57	#CJK UNIFIED IDEOGRAPH+0xE77E	0x8F5C	#CJK UNIFIED IDEOGRAPH+0xE780	0x8F62	#CJK UNIFIED IDEOGRAPH+0xE781	0x8F63	#CJK UNIFIED IDEOGRAPH+0xE782	0x8F64	#CJK UNIFIED IDEOGRAPH+0xE783	0x8F9C	#CJK UNIFIED IDEOGRAPH+0xE784	0x8F9F	#CJK UNIFIED IDEOGRAPH+0xE785	0x8FA3	#CJK UNIFIED IDEOGRAPH+0xE786	0x8FAD	#CJK UNIFIED IDEOGRAPH+0xE787	0x8FAF	#CJK UNIFIED IDEOGRAPH+0xE788	0x8FB7	#CJK UNIFIED IDEOGRAPH+0xE789	0x8FDA	#CJK UNIFIED IDEOGRAPH+0xE78A	0x8FE5	#CJK UNIFIED IDEOGRAPH+0xE78B	0x8FE2	#CJK UNIFIED IDEOGRAPH+0xE78C	0x8FEA	#CJK UNIFIED IDEOGRAPH+0xE78D	0x8FEF	#CJK UNIFIED IDEOGRAPH+0xE78E	0x9087	#CJK UNIFIED IDEOGRAPH+0xE78F	0x8FF4	#CJK UNIFIED IDEOGRAPH+0xE790	0x9005	#CJK UNIFIED IDEOGRAPH+0xE791	0x8FF9	#CJK UNIFIED IDEOGRAPH+0xE792	0x8FFA	#CJK UNIFIED IDEOGRAPH+0xE793	0x9011	#CJK UNIFIED IDEOGRAPH+0xE794	0x9015	#CJK UNIFIED IDEOGRAPH+0xE795	0x9021	#CJK UNIFIED IDEOGRAPH+0xE796	0x900D	#CJK UNIFIED IDEOGRAPH+0xE797	0x901E	#CJK UNIFIED IDEOGRAPH+0xE798	0x9016	#CJK UNIFIED IDEOGRAPH+0xE799	0x900B	#CJK UNIFIED IDEOGRAPH+0xE79A	0x9027	#CJK UNIFIED IDEOGRAPH+0xE79B	0x9036	#CJK UNIFIED IDEOGRAPH+0xE79C	0x9035	#CJK UNIFIED IDEOGRAPH+0xE79D	0x9039	#CJK UNIFIED IDEOGRAPH+0xE79E	0x8FF8	#CJK UNIFIED IDEOGRAPH+0xE79F	0x904F	#CJK UNIFIED IDEOGRAPH+0xE7A0	0x9050	#CJK UNIFIED IDEOGRAPH+0xE7A1	0x9051	#CJK UNIFIED IDEOGRAPH+0xE7A2	0x9052	#CJK UNIFIED IDEOGRAPH+0xE7A3	0x900E	#CJK UNIFIED IDEOGRAPH+0xE7A4	0x9049	#CJK UNIFIED IDEOGRAPH+0xE7A5	0x903E	#CJK UNIFIED IDEOGRAPH+0xE7A6	0x9056	#CJK UNIFIED IDEOGRAPH+0xE7A7	0x9058	#CJK UNIFIED IDEOGRAPH+0xE7A8	0x905E	#CJK UNIFIED IDEOGRAPH+0xE7A9	0x9068	#CJK UNIFIED IDEOGRAPH+0xE7AA	0x906F	#CJK UNIFIED IDEOGRAPH+0xE7AB	0x9076	#CJK UNIFIED IDEOGRAPH+0xE7AC	0x96A8	#CJK UNIFIED IDEOGRAPH+0xE7AD	0x9072	#CJK UNIFIED IDEOGRAPH+0xE7AE	0x9082	#CJK UNIFIED IDEOGRAPH+0xE7AF	0x907D	#CJK UNIFIED IDEOGRAPH+0xE7B0	0x9081	#CJK UNIFIED IDEOGRAPH+0xE7B1	0x9080	#CJK UNIFIED IDEOGRAPH+0xE7B2	0x908A	#CJK UNIFIED IDEOGRAPH+0xE7B3	0x9089	#CJK UNIFIED IDEOGRAPH+0xE7B4	0x908F	#CJK UNIFIED IDEOGRAPH+0xE7B5	0x90A8	#CJK UNIFIED IDEOGRAPH+0xE7B6	0x90AF	#CJK UNIFIED IDEOGRAPH+0xE7B7	0x90B1	#CJK UNIFIED IDEOGRAPH+0xE7B8	0x90B5	#CJK UNIFIED IDEOGRAPH+0xE7B9	0x90E2	#CJK UNIFIED IDEOGRAPH+0xE7BA	0x90E4	#CJK UNIFIED IDEOGRAPH+0xE7BB	0x6248	#CJK UNIFIED IDEOGRAPH+0xE7BC	0x90DB	#CJK UNIFIED IDEOGRAPH+0xE7BD	0x9102	#CJK UNIFIED IDEOGRAPH+0xE7BE	0x9112	#CJK UNIFIED IDEOGRAPH+0xE7BF	0x9119	#CJK UNIFIED IDEOGRAPH+0xE7C0	0x9132	#CJK UNIFIED IDEOGRAPH+0xE7C1	0x9130	#CJK UNIFIED IDEOGRAPH+0xE7C2	0x914A	#CJK UNIFIED IDEOGRAPH+0xE7C3	0x9156	#CJK UNIFIED IDEOGRAPH+0xE7C4	0x9158	#CJK UNIFIED IDEOGRAPH+0xE7C5	0x9163	#CJK UNIFIED IDEOGRAPH+0xE7C6	0x9165	#CJK UNIFIED IDEOGRAPH+0xE7C7	0x9169	#CJK UNIFIED IDEOGRAPH+0xE7C8	0x9173	#CJK UNIFIED IDEOGRAPH+0xE7C9	0x9172	#CJK UNIFIED IDEOGRAPH+0xE7CA	0x918B	#CJK UNIFIED IDEOGRAPH+0xE7CB	0x9189	#CJK UNIFIED IDEOGRAPH+0xE7CC	0x9182	#CJK UNIFIED IDEOGRAPH+0xE7CD	0x91A2	#CJK UNIFIED IDEOGRAPH+0xE7CE	0x91AB	#CJK UNIFIED IDEOGRAPH+0xE7CF	0x91AF	#CJK UNIFIED IDEOGRAPH+0xE7D0	0x91AA	#CJK UNIFIED IDEOGRAPH+0xE7D1	0x91B5	#CJK UNIFIED IDEOGRAPH+0xE7D2	0x91B4	#CJK UNIFIED IDEOGRAPH+0xE7D3	0x91BA	#CJK UNIFIED IDEOGRAPH+0xE7D4	0x91C0	#CJK UNIFIED IDEOGRAPH+0xE7D5	0x91C1	#CJK UNIFIED IDEOGRAPH+0xE7D6	0x91C9	#CJK UNIFIED IDEOGRAPH+0xE7D7	0x91CB	#CJK UNIFIED IDEOGRAPH+0xE7D8	0x91D0	#CJK UNIFIED IDEOGRAPH+0xE7D9	0x91D6	#CJK UNIFIED IDEOGRAPH+0xE7DA	0x91DF	#CJK UNIFIED IDEOGRAPH+0xE7DB	0x91E1	#CJK UNIFIED IDEOGRAPH+0xE7DC	0x91DB	#CJK UNIFIED IDEOGRAPH+0xE7DD	0x91FC	#CJK UNIFIED IDEOGRAPH+0xE7DE	0x91F5	#CJK UNIFIED IDEOGRAPH+0xE7DF	0x91F6	#CJK UNIFIED IDEOGRAPH+0xE7E0	0x921E	#CJK UNIFIED IDEOGRAPH+0xE7E1	0x91FF	#CJK UNIFIED IDEOGRAPH+0xE7E2	0x9214	#CJK UNIFIED IDEOGRAPH+0xE7E3	0x922C	#CJK UNIFIED IDEOGRAPH+0xE7E4	0x9215	#CJK UNIFIED IDEOGRAPH+0xE7E5	0x9211	#CJK UNIFIED IDEOGRAPH+0xE7E6	0x925E	#CJK UNIFIED IDEOGRAPH+0xE7E7	0x9257	#CJK UNIFIED IDEOGRAPH+0xE7E8	0x9245	#CJK UNIFIED IDEOGRAPH+0xE7E9	0x9249	#CJK UNIFIED IDEOGRAPH+0xE7EA	0x9264	#CJK UNIFIED IDEOGRAPH+0xE7EB	0x9248	#CJK UNIFIED IDEOGRAPH+0xE7EC	0x9295	#CJK UNIFIED IDEOGRAPH+0xE7ED	0x923F	#CJK UNIFIED IDEOGRAPH+0xE7EE	0x924B	#CJK UNIFIED IDEOGRAPH+0xE7EF	0x9250	#CJK UNIFIED IDEOGRAPH+0xE7F0	0x929C	#CJK UNIFIED IDEOGRAPH+0xE7F1	0x9296	#CJK UNIFIED IDEOGRAPH+0xE7F2	0x9293	#CJK UNIFIED IDEOGRAPH+0xE7F3	0x929B	#CJK UNIFIED IDEOGRAPH+0xE7F4	0x925A	#CJK UNIFIED IDEOGRAPH+0xE7F5	0x92CF	#CJK UNIFIED IDEOGRAPH+0xE7F6	0x92B9	#CJK UNIFIED IDEOGRAPH+0xE7F7	0x92B7	#CJK UNIFIED IDEOGRAPH+0xE7F8	0x92E9	#CJK UNIFIED IDEOGRAPH+0xE7F9	0x930F	#CJK UNIFIED IDEOGRAPH+0xE7FA	0x92FA	#CJK UNIFIED IDEOGRAPH+0xE7FB	0x9344	#CJK UNIFIED IDEOGRAPH+0xE7FC	0x932E	#CJK UNIFIED IDEOGRAPH+0xE840	0x9319	#CJK UNIFIED IDEOGRAPH+0xE841	0x9322	#CJK UNIFIED IDEOGRAPH+0xE842	0x931A	#CJK UNIFIED IDEOGRAPH+0xE843	0x9323	#CJK UNIFIED IDEOGRAPH+0xE844	0x933A	#CJK UNIFIED IDEOGRAPH+0xE845	0x9335	#CJK UNIFIED IDEOGRAPH+0xE846	0x933B	#CJK UNIFIED IDEOGRAPH+0xE847	0x935C	#CJK UNIFIED IDEOGRAPH+0xE848	0x9360	#CJK UNIFIED IDEOGRAPH+0xE849	0x937C	#CJK UNIFIED IDEOGRAPH+0xE84A	0x936E	#CJK UNIFIED IDEOGRAPH+0xE84B	0x9356	#CJK UNIFIED IDEOGRAPH+0xE84C	0x93B0	#CJK UNIFIED IDEOGRAPH+0xE84D	0x93AC	#CJK UNIFIED IDEOGRAPH+0xE84E	0x93AD	#CJK UNIFIED IDEOGRAPH+0xE84F	0x9394	#CJK UNIFIED IDEOGRAPH+0xE850	0x93B9	#CJK UNIFIED IDEOGRAPH+0xE851	0x93D6	#CJK UNIFIED IDEOGRAPH+0xE852	0x93D7	#CJK UNIFIED IDEOGRAPH+0xE853	0x93E8	#CJK UNIFIED IDEOGRAPH+0xE854	0x93E5	#CJK UNIFIED IDEOGRAPH+0xE855	0x93D8	#CJK UNIFIED IDEOGRAPH+0xE856	0x93C3	#CJK UNIFIED IDEOGRAPH+0xE857	0x93DD	#CJK UNIFIED IDEOGRAPH+0xE858	0x93D0	#CJK UNIFIED IDEOGRAPH+0xE859	0x93C8	#CJK UNIFIED IDEOGRAPH+0xE85A	0x93E4	#CJK UNIFIED IDEOGRAPH+0xE85B	0x941A	#CJK UNIFIED IDEOGRAPH+0xE85C	0x9414	#CJK UNIFIED IDEOGRAPH+0xE85D	0x9413	#CJK UNIFIED IDEOGRAPH+0xE85E	0x9403	#CJK UNIFIED IDEOGRAPH+0xE85F	0x9407	#CJK UNIFIED IDEOGRAPH+0xE860	0x9410	#CJK UNIFIED IDEOGRAPH+0xE861	0x9436	#CJK UNIFIED IDEOGRAPH+0xE862	0x942B	#CJK UNIFIED IDEOGRAPH+0xE863	0x9435	#CJK UNIFIED IDEOGRAPH+0xE864	0x9421	#CJK UNIFIED IDEOGRAPH+0xE865	0x943A	#CJK UNIFIED IDEOGRAPH+0xE866	0x9441	#CJK UNIFIED IDEOGRAPH+0xE867	0x9452	#CJK UNIFIED IDEOGRAPH+0xE868	0x9444	#CJK UNIFIED IDEOGRAPH+0xE869	0x945B	#CJK UNIFIED IDEOGRAPH+0xE86A	0x9460	#CJK UNIFIED IDEOGRAPH+0xE86B	0x9462	#CJK UNIFIED IDEOGRAPH+0xE86C	0x945E	#CJK UNIFIED IDEOGRAPH+0xE86D	0x946A	#CJK UNIFIED IDEOGRAPH+0xE86E	0x9229	#CJK UNIFIED IDEOGRAPH+0xE86F	0x9470	#CJK UNIFIED IDEOGRAPH+0xE870	0x9475	#CJK UNIFIED IDEOGRAPH+0xE871	0x9477	#CJK UNIFIED IDEOGRAPH+0xE872	0x947D	#CJK UNIFIED IDEOGRAPH+0xE873	0x945A	#CJK UNIFIED IDEOGRAPH+0xE874	0x947C	#CJK UNIFIED IDEOGRAPH+0xE875	0x947E	#CJK UNIFIED IDEOGRAPH+0xE876	0x9481	#CJK UNIFIED IDEOGRAPH+0xE877	0x947F	#CJK UNIFIED IDEOGRAPH+0xE878	0x9582	#CJK UNIFIED IDEOGRAPH+0xE879	0x9587	#CJK UNIFIED IDEOGRAPH+0xE87A	0x958A	#CJK UNIFIED IDEOGRAPH+0xE87B	0x9594	#CJK UNIFIED IDEOGRAPH+0xE87C	0x9596	#CJK UNIFIED IDEOGRAPH+0xE87D	0x9598	#CJK UNIFIED IDEOGRAPH+0xE87E	0x9599	#CJK UNIFIED IDEOGRAPH+0xE880	0x95A0	#CJK UNIFIED IDEOGRAPH+0xE881	0x95A8	#CJK UNIFIED IDEOGRAPH+0xE882	0x95A7	#CJK UNIFIED IDEOGRAPH+0xE883	0x95AD	#CJK UNIFIED IDEOGRAPH+0xE884	0x95BC	#CJK UNIFIED IDEOGRAPH+0xE885	0x95BB	#CJK UNIFIED IDEOGRAPH+0xE886	0x95B9	#CJK UNIFIED IDEOGRAPH+0xE887	0x95BE	#CJK UNIFIED IDEOGRAPH+0xE888	0x95CA	#CJK UNIFIED IDEOGRAPH+0xE889	0x6FF6	#CJK UNIFIED IDEOGRAPH+0xE88A	0x95C3	#CJK UNIFIED IDEOGRAPH+0xE88B	0x95CD	#CJK UNIFIED IDEOGRAPH+0xE88C	0x95CC	#CJK UNIFIED IDEOGRAPH+0xE88D	0x95D5	#CJK UNIFIED IDEOGRAPH+0xE88E	0x95D4	#CJK UNIFIED IDEOGRAPH+0xE88F	0x95D6	#CJK UNIFIED IDEOGRAPH+0xE890	0x95DC	#CJK UNIFIED IDEOGRAPH+0xE891	0x95E1	#CJK UNIFIED IDEOGRAPH+0xE892	0x95E5	#CJK UNIFIED IDEOGRAPH+0xE893	0x95E2	#CJK UNIFIED IDEOGRAPH+0xE894	0x9621	#CJK UNIFIED IDEOGRAPH+0xE895	0x9628	#CJK UNIFIED IDEOGRAPH+0xE896	0x962E	#CJK UNIFIED IDEOGRAPH+0xE897	0x962F	#CJK UNIFIED IDEOGRAPH+0xE898	0x9642	#CJK UNIFIED IDEOGRAPH+0xE899	0x964C	#CJK UNIFIED IDEOGRAPH+0xE89A	0x964F	#CJK UNIFIED IDEOGRAPH+0xE89B	0x964B	#CJK UNIFIED IDEOGRAPH+0xE89C	0x9677	#CJK UNIFIED IDEOGRAPH+0xE89D	0x965C	#CJK UNIFIED IDEOGRAPH+0xE89E	0x965E	#CJK UNIFIED IDEOGRAPH+0xE89F	0x965D	#CJK UNIFIED IDEOGRAPH+0xE8A0	0x965F	#CJK UNIFIED IDEOGRAPH+0xE8A1	0x9666	#CJK UNIFIED IDEOGRAPH+0xE8A2	0x9672	#CJK UNIFIED IDEOGRAPH+0xE8A3	0x966C	#CJK UNIFIED IDEOGRAPH+0xE8A4	0x968D	#CJK UNIFIED IDEOGRAPH+0xE8A5	0x9698	#CJK UNIFIED IDEOGRAPH+0xE8A6	0x9695	#CJK UNIFIED IDEOGRAPH+0xE8A7	0x9697	#CJK UNIFIED IDEOGRAPH+0xE8A8	0x96AA	#CJK UNIFIED IDEOGRAPH+0xE8A9	0x96A7	#CJK UNIFIED IDEOGRAPH+0xE8AA	0x96B1	#CJK UNIFIED IDEOGRAPH+0xE8AB	0x96B2	#CJK UNIFIED IDEOGRAPH+0xE8AC	0x96B0	#CJK UNIFIED IDEOGRAPH+0xE8AD	0x96B4	#CJK UNIFIED IDEOGRAPH+0xE8AE	0x96B6	#CJK UNIFIED IDEOGRAPH+0xE8AF	0x96B8	#CJK UNIFIED IDEOGRAPH+0xE8B0	0x96B9	#CJK UNIFIED IDEOGRAPH+0xE8B1	0x96CE	#CJK UNIFIED IDEOGRAPH+0xE8B2	0x96CB	#CJK UNIFIED IDEOGRAPH+0xE8B3	0x96C9	#CJK UNIFIED IDEOGRAPH+0xE8B4	0x96CD	#CJK UNIFIED IDEOGRAPH+0xE8B5	0x894D	#CJK UNIFIED IDEOGRAPH+0xE8B6	0x96DC	#CJK UNIFIED IDEOGRAPH+0xE8B7	0x970D	#CJK UNIFIED IDEOGRAPH+0xE8B8	0x96D5	#CJK UNIFIED IDEOGRAPH+0xE8B9	0x96F9	#CJK UNIFIED IDEOGRAPH+0xE8BA	0x9704	#CJK UNIFIED IDEOGRAPH+0xE8BB	0x9706	#CJK UNIFIED IDEOGRAPH+0xE8BC	0x9708	#CJK UNIFIED IDEOGRAPH+0xE8BD	0x9713	#CJK UNIFIED IDEOGRAPH+0xE8BE	0x970E	#CJK UNIFIED IDEOGRAPH+0xE8BF	0x9711	#CJK UNIFIED IDEOGRAPH+0xE8C0	0x970F	#CJK UNIFIED IDEOGRAPH+0xE8C1	0x9716	#CJK UNIFIED IDEOGRAPH+0xE8C2	0x9719	#CJK UNIFIED IDEOGRAPH+0xE8C3	0x9724	#CJK UNIFIED IDEOGRAPH+0xE8C4	0x972A	#CJK UNIFIED IDEOGRAPH+0xE8C5	0x9730	#CJK UNIFIED IDEOGRAPH+0xE8C6	0x9739	#CJK UNIFIED IDEOGRAPH+0xE8C7	0x973D	#CJK UNIFIED IDEOGRAPH+0xE8C8	0x973E	#CJK UNIFIED IDEOGRAPH+0xE8C9	0x9744	#CJK UNIFIED IDEOGRAPH+0xE8CA	0x9746	#CJK UNIFIED IDEOGRAPH+0xE8CB	0x9748	#CJK UNIFIED IDEOGRAPH+0xE8CC	0x9742	#CJK UNIFIED IDEOGRAPH+0xE8CD	0x9749	#CJK UNIFIED IDEOGRAPH+0xE8CE	0x975C	#CJK UNIFIED IDEOGRAPH+0xE8CF	0x9760	#CJK UNIFIED IDEOGRAPH+0xE8D0	0x9764	#CJK UNIFIED IDEOGRAPH+0xE8D1	0x9766	#CJK UNIFIED IDEOGRAPH+0xE8D2	0x9768	#CJK UNIFIED IDEOGRAPH+0xE8D3	0x52D2	#CJK UNIFIED IDEOGRAPH+0xE8D4	0x976B	#CJK UNIFIED IDEOGRAPH+0xE8D5	0x9771	#CJK UNIFIED IDEOGRAPH+0xE8D6	0x9779	#CJK UNIFIED IDEOGRAPH+0xE8D7	0x9785	#CJK UNIFIED IDEOGRAPH+0xE8D8	0x977C	#CJK UNIFIED IDEOGRAPH+0xE8D9	0x9781	#CJK UNIFIED IDEOGRAPH+0xE8DA	0x977A	#CJK UNIFIED IDEOGRAPH+0xE8DB	0x9786	#CJK UNIFIED IDEOGRAPH+0xE8DC	0x978B	#CJK UNIFIED IDEOGRAPH+0xE8DD	0x978F	#CJK UNIFIED IDEOGRAPH+0xE8DE	0x9790	#CJK UNIFIED IDEOGRAPH+0xE8DF	0x979C	#CJK UNIFIED IDEOGRAPH+0xE8E0	0x97A8	#CJK UNIFIED IDEOGRAPH+0xE8E1	0x97A6	#CJK UNIFIED IDEOGRAPH+0xE8E2	0x97A3	#CJK UNIFIED IDEOGRAPH+0xE8E3	0x97B3	#CJK UNIFIED IDEOGRAPH+0xE8E4	0x97B4	#CJK UNIFIED IDEOGRAPH+0xE8E5	0x97C3	#CJK UNIFIED IDEOGRAPH+0xE8E6	0x97C6	#CJK UNIFIED IDEOGRAPH+0xE8E7	0x97C8	#CJK UNIFIED IDEOGRAPH+0xE8E8	0x97CB	#CJK UNIFIED IDEOGRAPH+0xE8E9	0x97DC	#CJK UNIFIED IDEOGRAPH+0xE8EA	0x97ED	#CJK UNIFIED IDEOGRAPH+0xE8EB	0x9F4F	#CJK UNIFIED IDEOGRAPH+0xE8EC	0x97F2	#CJK UNIFIED IDEOGRAPH+0xE8ED	0x7ADF	#CJK UNIFIED IDEOGRAPH+0xE8EE	0x97F6	#CJK UNIFIED IDEOGRAPH+0xE8EF	0x97F5	#CJK UNIFIED IDEOGRAPH+0xE8F0	0x980F	#CJK UNIFIED IDEOGRAPH+0xE8F1	0x980C	#CJK UNIFIED IDEOGRAPH+0xE8F2	0x9838	#CJK UNIFIED IDEOGRAPH+0xE8F3	0x9824	#CJK UNIFIED IDEOGRAPH+0xE8F4	0x9821	#CJK UNIFIED IDEOGRAPH+0xE8F5	0x9837	#CJK UNIFIED IDEOGRAPH+0xE8F6	0x983D	#CJK UNIFIED IDEOGRAPH+0xE8F7	0x9846	#CJK UNIFIED IDEOGRAPH+0xE8F8	0x984F	#CJK UNIFIED IDEOGRAPH+0xE8F9	0x984B	#CJK UNIFIED IDEOGRAPH+0xE8FA	0x986B	#CJK UNIFIED IDEOGRAPH+0xE8FB	0x986F	#CJK UNIFIED IDEOGRAPH+0xE8FC	0x9870	#CJK UNIFIED IDEOGRAPH+0xE940	0x9871	#CJK UNIFIED IDEOGRAPH+0xE941	0x9874	#CJK UNIFIED IDEOGRAPH+0xE942	0x9873	#CJK UNIFIED IDEOGRAPH+0xE943	0x98AA	#CJK UNIFIED IDEOGRAPH+0xE944	0x98AF	#CJK UNIFIED IDEOGRAPH+0xE945	0x98B1	#CJK UNIFIED IDEOGRAPH+0xE946	0x98B6	#CJK UNIFIED IDEOGRAPH+0xE947	0x98C4	#CJK UNIFIED IDEOGRAPH+0xE948	0x98C3	#CJK UNIFIED IDEOGRAPH+0xE949	0x98C6	#CJK UNIFIED IDEOGRAPH+0xE94A	0x98E9	#CJK UNIFIED IDEOGRAPH+0xE94B	0x98EB	#CJK UNIFIED IDEOGRAPH+0xE94C	0x9903	#CJK UNIFIED IDEOGRAPH+0xE94D	0x9909	#CJK UNIFIED IDEOGRAPH+0xE94E	0x9912	#CJK UNIFIED IDEOGRAPH+0xE94F	0x9914	#CJK UNIFIED IDEOGRAPH+0xE950	0x9918	#CJK UNIFIED IDEOGRAPH+0xE951	0x9921	#CJK UNIFIED IDEOGRAPH+0xE952	0x991D	#CJK UNIFIED IDEOGRAPH+0xE953	0x991E	#CJK UNIFIED IDEOGRAPH+0xE954	0x9924	#CJK UNIFIED IDEOGRAPH+0xE955	0x9920	#CJK UNIFIED IDEOGRAPH+0xE956	0x992C	#CJK UNIFIED IDEOGRAPH+0xE957	0x992E	#CJK UNIFIED IDEOGRAPH+0xE958	0x993D	#CJK UNIFIED IDEOGRAPH+0xE959	0x993E	#CJK UNIFIED IDEOGRAPH+0xE95A	0x9942	#CJK UNIFIED IDEOGRAPH+0xE95B	0x9949	#CJK UNIFIED IDEOGRAPH+0xE95C	0x9945	#CJK UNIFIED IDEOGRAPH+0xE95D	0x9950	#CJK UNIFIED IDEOGRAPH+0xE95E	0x994B	#CJK UNIFIED IDEOGRAPH+0xE95F	0x9951	#CJK UNIFIED IDEOGRAPH+0xE960	0x9952	#CJK UNIFIED IDEOGRAPH+0xE961	0x994C	#CJK UNIFIED IDEOGRAPH+0xE962	0x9955	#CJK UNIFIED IDEOGRAPH+0xE963	0x9997	#CJK UNIFIED IDEOGRAPH+0xE964	0x9998	#CJK UNIFIED IDEOGRAPH+0xE965	0x99A5	#CJK UNIFIED IDEOGRAPH+0xE966	0x99AD	#CJK UNIFIED IDEOGRAPH+0xE967	0x99AE	#CJK UNIFIED IDEOGRAPH+0xE968	0x99BC	#CJK UNIFIED IDEOGRAPH+0xE969	0x99DF	#CJK UNIFIED IDEOGRAPH+0xE96A	0x99DB	#CJK UNIFIED IDEOGRAPH+0xE96B	0x99DD	#CJK UNIFIED IDEOGRAPH+0xE96C	0x99D8	#CJK UNIFIED IDEOGRAPH+0xE96D	0x99D1	#CJK UNIFIED IDEOGRAPH+0xE96E	0x99ED	#CJK UNIFIED IDEOGRAPH+0xE96F	0x99EE	#CJK UNIFIED IDEOGRAPH+0xE970	0x99F1	#CJK UNIFIED IDEOGRAPH+0xE971	0x99F2	#CJK UNIFIED IDEOGRAPH+0xE972	0x99FB	#CJK UNIFIED IDEOGRAPH+0xE973	0x99F8	#CJK UNIFIED IDEOGRAPH+0xE974	0x9A01	#CJK UNIFIED IDEOGRAPH+0xE975	0x9A0F	#CJK UNIFIED IDEOGRAPH+0xE976	0x9A05	#CJK UNIFIED IDEOGRAPH+0xE977	0x99E2	#CJK UNIFIED IDEOGRAPH+0xE978	0x9A19	#CJK UNIFIED IDEOGRAPH+0xE979	0x9A2B	#CJK UNIFIED IDEOGRAPH+0xE97A	0x9A37	#CJK UNIFIED IDEOGRAPH+0xE97B	0x9A45	#CJK UNIFIED IDEOGRAPH+0xE97C	0x9A42	#CJK UNIFIED IDEOGRAPH+0xE97D	0x9A40	#CJK UNIFIED IDEOGRAPH+0xE97E	0x9A43	#CJK UNIFIED IDEOGRAPH+0xE980	0x9A3E	#CJK UNIFIED IDEOGRAPH+0xE981	0x9A55	#CJK UNIFIED IDEOGRAPH+0xE982	0x9A4D	#CJK UNIFIED IDEOGRAPH+0xE983	0x9A5B	#CJK UNIFIED IDEOGRAPH+0xE984	0x9A57	#CJK UNIFIED IDEOGRAPH+0xE985	0x9A5F	#CJK UNIFIED IDEOGRAPH+0xE986	0x9A62	#CJK UNIFIED IDEOGRAPH+0xE987	0x9A65	#CJK UNIFIED IDEOGRAPH+0xE988	0x9A64	#CJK UNIFIED IDEOGRAPH+0xE989	0x9A69	#CJK UNIFIED IDEOGRAPH+0xE98A	0x9A6B	#CJK UNIFIED IDEOGRAPH+0xE98B	0x9A6A	#CJK UNIFIED IDEOGRAPH+0xE98C	0x9AAD	#CJK UNIFIED IDEOGRAPH+0xE98D	0x9AB0	#CJK UNIFIED IDEOGRAPH+0xE98E	0x9ABC	#CJK UNIFIED IDEOGRAPH+0xE98F	0x9AC0	#CJK UNIFIED IDEOGRAPH+0xE990	0x9ACF	#CJK UNIFIED IDEOGRAPH+0xE991	0x9AD1	#CJK UNIFIED IDEOGRAPH+0xE992	0x9AD3	#CJK UNIFIED IDEOGRAPH+0xE993	0x9AD4	#CJK UNIFIED IDEOGRAPH+0xE994	0x9ADE	#CJK UNIFIED IDEOGRAPH+0xE995	0x9ADF	#CJK UNIFIED IDEOGRAPH+0xE996	0x9AE2	#CJK UNIFIED IDEOGRAPH+0xE997	0x9AE3	#CJK UNIFIED IDEOGRAPH+0xE998	0x9AE6	#CJK UNIFIED IDEOGRAPH+0xE999	0x9AEF	#CJK UNIFIED IDEOGRAPH+0xE99A	0x9AEB	#CJK UNIFIED IDEOGRAPH+0xE99B	0x9AEE	#CJK UNIFIED IDEOGRAPH+0xE99C	0x9AF4	#CJK UNIFIED IDEOGRAPH+0xE99D	0x9AF1	#CJK UNIFIED IDEOGRAPH+0xE99E	0x9AF7	#CJK UNIFIED IDEOGRAPH+0xE99F	0x9AFB	#CJK UNIFIED IDEOGRAPH+0xE9A0	0x9B06	#CJK UNIFIED IDEOGRAPH+0xE9A1	0x9B18	#CJK UNIFIED IDEOGRAPH+0xE9A2	0x9B1A	#CJK UNIFIED IDEOGRAPH+0xE9A3	0x9B1F	#CJK UNIFIED IDEOGRAPH+0xE9A4	0x9B22	#CJK UNIFIED IDEOGRAPH+0xE9A5	0x9B23	#CJK UNIFIED IDEOGRAPH+0xE9A6	0x9B25	#CJK UNIFIED IDEOGRAPH+0xE9A7	0x9B27	#CJK UNIFIED IDEOGRAPH+0xE9A8	0x9B28	#CJK UNIFIED IDEOGRAPH+0xE9A9	0x9B29	#CJK UNIFIED IDEOGRAPH+0xE9AA	0x9B2A	#CJK UNIFIED IDEOGRAPH+0xE9AB	0x9B2E	#CJK UNIFIED IDEOGRAPH+0xE9AC	0x9B2F	#CJK UNIFIED IDEOGRAPH+0xE9AD	0x9B32	#CJK UNIFIED IDEOGRAPH+0xE9AE	0x9B44	#CJK UNIFIED IDEOGRAPH+0xE9AF	0x9B43	#CJK UNIFIED IDEOGRAPH+0xE9B0	0x9B4F	#CJK UNIFIED IDEOGRAPH+0xE9B1	0x9B4D	#CJK UNIFIED IDEOGRAPH+0xE9B2	0x9B4E	#CJK UNIFIED IDEOGRAPH+0xE9B3	0x9B51	#CJK UNIFIED IDEOGRAPH+0xE9B4	0x9B58	#CJK UNIFIED IDEOGRAPH+0xE9B5	0x9B74	#CJK UNIFIED IDEOGRAPH+0xE9B6	0x9B93	#CJK UNIFIED IDEOGRAPH+0xE9B7	0x9B83	#CJK UNIFIED IDEOGRAPH+0xE9B8	0x9B91	#CJK UNIFIED IDEOGRAPH+0xE9B9	0x9B96	#CJK UNIFIED IDEOGRAPH+0xE9BA	0x9B97	#CJK UNIFIED IDEOGRAPH+0xE9BB	0x9B9F	#CJK UNIFIED IDEOGRAPH+0xE9BC	0x9BA0	#CJK UNIFIED IDEOGRAPH+0xE9BD	0x9BA8	#CJK UNIFIED IDEOGRAPH+0xE9BE	0x9BB4	#CJK UNIFIED IDEOGRAPH+0xE9BF	0x9BC0	#CJK UNIFIED IDEOGRAPH+0xE9C0	0x9BCA	#CJK UNIFIED IDEOGRAPH+0xE9C1	0x9BB9	#CJK UNIFIED IDEOGRAPH+0xE9C2	0x9BC6	#CJK UNIFIED IDEOGRAPH+0xE9C3	0x9BCF	#CJK UNIFIED IDEOGRAPH+0xE9C4	0x9BD1	#CJK UNIFIED IDEOGRAPH+0xE9C5	0x9BD2	#CJK UNIFIED IDEOGRAPH+0xE9C6	0x9BE3	#CJK UNIFIED IDEOGRAPH+0xE9C7	0x9BE2	#CJK UNIFIED IDEOGRAPH+0xE9C8	0x9BE4	#CJK UNIFIED IDEOGRAPH+0xE9C9	0x9BD4	#CJK UNIFIED IDEOGRAPH+0xE9CA	0x9BE1	#CJK UNIFIED IDEOGRAPH+0xE9CB	0x9C3A	#CJK UNIFIED IDEOGRAPH+0xE9CC	0x9BF2	#CJK UNIFIED IDEOGRAPH+0xE9CD	0x9BF1	#CJK UNIFIED IDEOGRAPH+0xE9CE	0x9BF0	#CJK UNIFIED IDEOGRAPH+0xE9CF	0x9C15	#CJK UNIFIED IDEOGRAPH+0xE9D0	0x9C14	#CJK UNIFIED IDEOGRAPH+0xE9D1	0x9C09	#CJK UNIFIED IDEOGRAPH+0xE9D2	0x9C13	#CJK UNIFIED IDEOGRAPH+0xE9D3	0x9C0C	#CJK UNIFIED IDEOGRAPH+0xE9D4	0x9C06	#CJK UNIFIED IDEOGRAPH+0xE9D5	0x9C08	#CJK UNIFIED IDEOGRAPH+0xE9D6	0x9C12	#CJK UNIFIED IDEOGRAPH+0xE9D7	0x9C0A	#CJK UNIFIED IDEOGRAPH+0xE9D8	0x9C04	#CJK UNIFIED IDEOGRAPH+0xE9D9	0x9C2E	#CJK UNIFIED IDEOGRAPH+0xE9DA	0x9C1B	#CJK UNIFIED IDEOGRAPH+0xE9DB	0x9C25	#CJK UNIFIED IDEOGRAPH+0xE9DC	0x9C24	#CJK UNIFIED IDEOGRAPH+0xE9DD	0x9C21	#CJK UNIFIED IDEOGRAPH+0xE9DE	0x9C30	#CJK UNIFIED IDEOGRAPH+0xE9DF	0x9C47	#CJK UNIFIED IDEOGRAPH+0xE9E0	0x9C32	#CJK UNIFIED IDEOGRAPH+0xE9E1	0x9C46	#CJK UNIFIED IDEOGRAPH+0xE9E2	0x9C3E	#CJK UNIFIED IDEOGRAPH+0xE9E3	0x9C5A	#CJK UNIFIED IDEOGRAPH+0xE9E4	0x9C60	#CJK UNIFIED IDEOGRAPH+0xE9E5	0x9C67	#CJK UNIFIED IDEOGRAPH+0xE9E6	0x9C76	#CJK UNIFIED IDEOGRAPH+0xE9E7	0x9C78	#CJK UNIFIED IDEOGRAPH+0xE9E8	0x9CE7	#CJK UNIFIED IDEOGRAPH+0xE9E9	0x9CEC	#CJK UNIFIED IDEOGRAPH+0xE9EA	0x9CF0	#CJK UNIFIED IDEOGRAPH+0xE9EB	0x9D09	#CJK UNIFIED IDEOGRAPH+0xE9EC	0x9D08	#CJK UNIFIED IDEOGRAPH+0xE9ED	0x9CEB	#CJK UNIFIED IDEOGRAPH+0xE9EE	0x9D03	#CJK UNIFIED IDEOGRAPH+0xE9EF	0x9D06	#CJK UNIFIED IDEOGRAPH+0xE9F0	0x9D2A	#CJK UNIFIED IDEOGRAPH+0xE9F1	0x9D26	#CJK UNIFIED IDEOGRAPH+0xE9F2	0x9DAF	#CJK UNIFIED IDEOGRAPH+0xE9F3	0x9D23	#CJK UNIFIED IDEOGRAPH+0xE9F4	0x9D1F	#CJK UNIFIED IDEOGRAPH+0xE9F5	0x9D44	#CJK UNIFIED IDEOGRAPH+0xE9F6	0x9D15	#CJK UNIFIED IDEOGRAPH+0xE9F7	0x9D12	#CJK UNIFIED IDEOGRAPH+0xE9F8	0x9D41	#CJK UNIFIED IDEOGRAPH+0xE9F9	0x9D3F	#CJK UNIFIED IDEOGRAPH+0xE9FA	0x9D3E	#CJK UNIFIED IDEOGRAPH+0xE9FB	0x9D46	#CJK UNIFIED IDEOGRAPH+0xE9FC	0x9D48	#CJK UNIFIED IDEOGRAPH+0xEA40	0x9D5D	#CJK UNIFIED IDEOGRAPH+0xEA41	0x9D5E	#CJK UNIFIED IDEOGRAPH+0xEA42	0x9D64	#CJK UNIFIED IDEOGRAPH+0xEA43	0x9D51	#CJK UNIFIED IDEOGRAPH+0xEA44	0x9D50	#CJK UNIFIED IDEOGRAPH+0xEA45	0x9D59	#CJK UNIFIED IDEOGRAPH+0xEA46	0x9D72	#CJK UNIFIED IDEOGRAPH+0xEA47	0x9D89	#CJK UNIFIED IDEOGRAPH+0xEA48	0x9D87	#CJK UNIFIED IDEOGRAPH+0xEA49	0x9DAB	#CJK UNIFIED IDEOGRAPH+0xEA4A	0x9D6F	#CJK UNIFIED IDEOGRAPH+0xEA4B	0x9D7A	#CJK UNIFIED IDEOGRAPH+0xEA4C	0x9D9A	#CJK UNIFIED IDEOGRAPH+0xEA4D	0x9DA4	#CJK UNIFIED IDEOGRAPH+0xEA4E	0x9DA9	#CJK UNIFIED IDEOGRAPH+0xEA4F	0x9DB2	#CJK UNIFIED IDEOGRAPH+0xEA50	0x9DC4	#CJK UNIFIED IDEOGRAPH+0xEA51	0x9DC1	#CJK UNIFIED IDEOGRAPH+0xEA52	0x9DBB	#CJK UNIFIED IDEOGRAPH+0xEA53	0x9DB8	#CJK UNIFIED IDEOGRAPH+0xEA54	0x9DBA	#CJK UNIFIED IDEOGRAPH+0xEA55	0x9DC6	#CJK UNIFIED IDEOGRAPH+0xEA56	0x9DCF	#CJK UNIFIED IDEOGRAPH+0xEA57	0x9DC2	#CJK UNIFIED IDEOGRAPH+0xEA58	0x9DD9	#CJK UNIFIED IDEOGRAPH+0xEA59	0x9DD3	#CJK UNIFIED IDEOGRAPH+0xEA5A	0x9DF8	#CJK UNIFIED IDEOGRAPH+0xEA5B	0x9DE6	#CJK UNIFIED IDEOGRAPH+0xEA5C	0x9DED	#CJK UNIFIED IDEOGRAPH+0xEA5D	0x9DEF	#CJK UNIFIED IDEOGRAPH+0xEA5E	0x9DFD	#CJK UNIFIED IDEOGRAPH+0xEA5F	0x9E1A	#CJK UNIFIED IDEOGRAPH+0xEA60	0x9E1B	#CJK UNIFIED IDEOGRAPH+0xEA61	0x9E1E	#CJK UNIFIED IDEOGRAPH+0xEA62	0x9E75	#CJK UNIFIED IDEOGRAPH+0xEA63	0x9E79	#CJK UNIFIED IDEOGRAPH+0xEA64	0x9E7D	#CJK UNIFIED IDEOGRAPH+0xEA65	0x9E81	#CJK UNIFIED IDEOGRAPH+0xEA66	0x9E88	#CJK UNIFIED IDEOGRAPH+0xEA67	0x9E8B	#CJK UNIFIED IDEOGRAPH+0xEA68	0x9E8C	#CJK UNIFIED IDEOGRAPH+0xEA69	0x9E92	#CJK UNIFIED IDEOGRAPH+0xEA6A	0x9E95	#CJK UNIFIED IDEOGRAPH+0xEA6B	0x9E91	#CJK UNIFIED IDEOGRAPH+0xEA6C	0x9E9D	#CJK UNIFIED IDEOGRAPH+0xEA6D	0x9EA5	#CJK UNIFIED IDEOGRAPH+0xEA6E	0x9EA9	#CJK UNIFIED IDEOGRAPH+0xEA6F	0x9EB8	#CJK UNIFIED IDEOGRAPH+0xEA70	0x9EAA	#CJK UNIFIED IDEOGRAPH+0xEA71	0x9EAD	#CJK UNIFIED IDEOGRAPH+0xEA72	0x9761	#CJK UNIFIED IDEOGRAPH+0xEA73	0x9ECC	#CJK UNIFIED IDEOGRAPH+0xEA74	0x9ECE	#CJK UNIFIED IDEOGRAPH+0xEA75	0x9ECF	#CJK UNIFIED IDEOGRAPH+0xEA76	0x9ED0	#CJK UNIFIED IDEOGRAPH+0xEA77	0x9ED4	#CJK UNIFIED IDEOGRAPH+0xEA78	0x9EDC	#CJK UNIFIED IDEOGRAPH+0xEA79	0x9EDE	#CJK UNIFIED IDEOGRAPH+0xEA7A	0x9EDD	#CJK UNIFIED IDEOGRAPH+0xEA7B	0x9EE0	#CJK UNIFIED IDEOGRAPH+0xEA7C	0x9EE5	#CJK UNIFIED IDEOGRAPH+0xEA7D	0x9EE8	#CJK UNIFIED IDEOGRAPH+0xEA7E	0x9EEF	#CJK UNIFIED IDEOGRAPH+0xEA80	0x9EF4	#CJK UNIFIED IDEOGRAPH+0xEA81	0x9EF6	#CJK UNIFIED IDEOGRAPH+0xEA82	0x9EF7	#CJK UNIFIED IDEOGRAPH+0xEA83	0x9EF9	#CJK UNIFIED IDEOGRAPH+0xEA84	0x9EFB	#CJK UNIFIED IDEOGRAPH+0xEA85	0x9EFC	#CJK UNIFIED IDEOGRAPH+0xEA86	0x9EFD	#CJK UNIFIED IDEOGRAPH+0xEA87	0x9F07	#CJK UNIFIED IDEOGRAPH+0xEA88	0x9F08	#CJK UNIFIED IDEOGRAPH+0xEA89	0x76B7	#CJK UNIFIED IDEOGRAPH+0xEA8A	0x9F15	#CJK UNIFIED IDEOGRAPH+0xEA8B	0x9F21	#CJK UNIFIED IDEOGRAPH+0xEA8C	0x9F2C	#CJK UNIFIED IDEOGRAPH+0xEA8D	0x9F3E	#CJK UNIFIED IDEOGRAPH+0xEA8E	0x9F4A	#CJK UNIFIED IDEOGRAPH+0xEA8F	0x9F52	#CJK UNIFIED IDEOGRAPH+0xEA90	0x9F54	#CJK UNIFIED IDEOGRAPH+0xEA91	0x9F63	#CJK UNIFIED IDEOGRAPH+0xEA92	0x9F5F	#CJK UNIFIED IDEOGRAPH+0xEA93	0x9F60	#CJK UNIFIED IDEOGRAPH+0xEA94	0x9F61	#CJK UNIFIED IDEOGRAPH+0xEA95	0x9F66	#CJK UNIFIED IDEOGRAPH+0xEA96	0x9F67	#CJK UNIFIED IDEOGRAPH+0xEA97	0x9F6C	#CJK UNIFIED IDEOGRAPH+0xEA98	0x9F6A	#CJK UNIFIED IDEOGRAPH+0xEA99	0x9F77	#CJK UNIFIED IDEOGRAPH+0xEA9A	0x9F72	#CJK UNIFIED IDEOGRAPH+0xEA9B	0x9F76	#CJK UNIFIED IDEOGRAPH+0xEA9C	0x9F95	#CJK UNIFIED IDEOGRAPH+0xEA9D	0x9F9C	#CJK UNIFIED IDEOGRAPH+0xEA9E	0x9FA0	#CJK UNIFIED IDEOGRAPH+0xEA9F	0x582F	#CJK UNIFIED IDEOGRAPH+0xEAA0	0x69C7	#CJK UNIFIED IDEOGRAPH+0xEAA1	0x9059	#CJK UNIFIED IDEOGRAPH+0xEAA2	0x7464	#CJK UNIFIED IDEOGRAPH+0xEAA3	0x51DC	#CJK UNIFIED IDEOGRAPH+0xEAA4	0x7199	#CJK UNIFIED IDEOGRAPH+0xED40	0x7E8A	#CJK UNIFIED IDEOGRAPH+0xED41	0x891C	#CJK UNIFIED IDEOGRAPH+0xED42	0x9348	#CJK UNIFIED IDEOGRAPH+0xED43	0x9288	#CJK UNIFIED IDEOGRAPH+0xED44	0x84DC	#CJK UNIFIED IDEOGRAPH+0xED45	0x4FC9	#CJK UNIFIED IDEOGRAPH+0xED46	0x70BB	#CJK UNIFIED IDEOGRAPH+0xED47	0x6631	#CJK UNIFIED IDEOGRAPH+0xED48	0x68C8	#CJK UNIFIED IDEOGRAPH+0xED49	0x92F9	#CJK UNIFIED IDEOGRAPH+0xED4A	0x66FB	#CJK UNIFIED IDEOGRAPH+0xED4B	0x5F45	#CJK UNIFIED IDEOGRAPH+0xED4C	0x4E28	#CJK UNIFIED IDEOGRAPH+0xED4D	0x4EE1	#CJK UNIFIED IDEOGRAPH+0xED4E	0x4EFC	#CJK UNIFIED IDEOGRAPH+0xED4F	0x4F00	#CJK UNIFIED IDEOGRAPH+0xED50	0x4F03	#CJK UNIFIED IDEOGRAPH+0xED51	0x4F39	#CJK UNIFIED IDEOGRAPH+0xED52	0x4F56	#CJK UNIFIED IDEOGRAPH+0xED53	0x4F92	#CJK UNIFIED IDEOGRAPH+0xED54	0x4F8A	#CJK UNIFIED IDEOGRAPH+0xED55	0x4F9A	#CJK UNIFIED IDEOGRAPH+0xED56	0x4F94	#CJK UNIFIED IDEOGRAPH+0xED57	0x4FCD	#CJK UNIFIED IDEOGRAPH+0xED58	0x5040	#CJK UNIFIED IDEOGRAPH+0xED59	0x5022	#CJK UNIFIED IDEOGRAPH+0xED5A	0x4FFF	#CJK UNIFIED IDEOGRAPH+0xED5B	0x501E	#CJK UNIFIED IDEOGRAPH+0xED5C	0x5046	#CJK UNIFIED IDEOGRAPH+0xED5D	0x5070	#CJK UNIFIED IDEOGRAPH+0xED5E	0x5042	#CJK UNIFIED IDEOGRAPH+0xED5F	0x5094	#CJK UNIFIED IDEOGRAPH+0xED60	0x50F4	#CJK UNIFIED IDEOGRAPH+0xED61	0x50D8	#CJK UNIFIED IDEOGRAPH+0xED62	0x514A	#CJK UNIFIED IDEOGRAPH+0xED63	0x5164	#CJK UNIFIED IDEOGRAPH+0xED64	0x519D	#CJK UNIFIED IDEOGRAPH+0xED65	0x51BE	#CJK UNIFIED IDEOGRAPH+0xED66	0x51EC	#CJK UNIFIED IDEOGRAPH+0xED67	0x5215	#CJK UNIFIED IDEOGRAPH+0xED68	0x529C	#CJK UNIFIED IDEOGRAPH+0xED69	0x52A6	#CJK UNIFIED IDEOGRAPH+0xED6A	0x52C0	#CJK UNIFIED IDEOGRAPH+0xED6B	0x52DB	#CJK UNIFIED IDEOGRAPH+0xED6C	0x5300	#CJK UNIFIED IDEOGRAPH+0xED6D	0x5307	#CJK UNIFIED IDEOGRAPH+0xED6E	0x5324	#CJK UNIFIED IDEOGRAPH+0xED6F	0x5372	#CJK UNIFIED IDEOGRAPH+0xED70	0x5393	#CJK UNIFIED IDEOGRAPH+0xED71	0x53B2	#CJK UNIFIED IDEOGRAPH+0xED72	0x53DD	#CJK UNIFIED IDEOGRAPH+0xED73	0xFA0E	#CJK COMPATIBILITY IDEOGRAPH+0xED74	0x549C	#CJK UNIFIED IDEOGRAPH+0xED75	0x548A	#CJK UNIFIED IDEOGRAPH+0xED76	0x54A9	#CJK UNIFIED IDEOGRAPH+0xED77	0x54FF	#CJK UNIFIED IDEOGRAPH+0xED78	0x5586	#CJK UNIFIED IDEOGRAPH+0xED79	0x5759	#CJK UNIFIED IDEOGRAPH+0xED7A	0x5765	#CJK UNIFIED IDEOGRAPH+0xED7B	0x57AC	#CJK UNIFIED IDEOGRAPH+0xED7C	0x57C8	#CJK UNIFIED IDEOGRAPH+0xED7D	0x57C7	#CJK UNIFIED IDEOGRAPH+0xED7E	0xFA0F	#CJK COMPATIBILITY IDEOGRAPH+0xED80	0xFA10	#CJK COMPATIBILITY IDEOGRAPH+0xED81	0x589E	#CJK UNIFIED IDEOGRAPH+0xED82	0x58B2	#CJK UNIFIED IDEOGRAPH+0xED83	0x590B	#CJK UNIFIED IDEOGRAPH+0xED84	0x5953	#CJK UNIFIED IDEOGRAPH+0xED85	0x595B	#CJK UNIFIED IDEOGRAPH+0xED86	0x595D	#CJK UNIFIED IDEOGRAPH+0xED87	0x5963	#CJK UNIFIED IDEOGRAPH+0xED88	0x59A4	#CJK UNIFIED IDEOGRAPH+0xED89	0x59BA	#CJK UNIFIED IDEOGRAPH+0xED8A	0x5B56	#CJK UNIFIED IDEOGRAPH+0xED8B	0x5BC0	#CJK UNIFIED IDEOGRAPH+0xED8C	0x752F	#CJK UNIFIED IDEOGRAPH+0xED8D	0x5BD8	#CJK UNIFIED IDEOGRAPH+0xED8E	0x5BEC	#CJK UNIFIED IDEOGRAPH+0xED8F	0x5C1E	#CJK UNIFIED IDEOGRAPH+0xED90	0x5CA6	#CJK UNIFIED IDEOGRAPH+0xED91	0x5CBA	#CJK UNIFIED IDEOGRAPH+0xED92	0x5CF5	#CJK UNIFIED IDEOGRAPH+0xED93	0x5D27	#CJK UNIFIED IDEOGRAPH+0xED94	0x5D53	#CJK UNIFIED IDEOGRAPH+0xED95	0xFA11	#CJK COMPATIBILITY IDEOGRAPH+0xED96	0x5D42	#CJK UNIFIED IDEOGRAPH+0xED97	0x5D6D	#CJK UNIFIED IDEOGRAPH+0xED98	0x5DB8	#CJK UNIFIED IDEOGRAPH+0xED99	0x5DB9	#CJK UNIFIED IDEOGRAPH+0xED9A	0x5DD0	#CJK UNIFIED IDEOGRAPH+0xED9B	0x5F21	#CJK UNIFIED IDEOGRAPH+0xED9C	0x5F34	#CJK UNIFIED IDEOGRAPH+0xED9D	0x5F67	#CJK UNIFIED IDEOGRAPH+0xED9E	0x5FB7	#CJK UNIFIED IDEOGRAPH+0xED9F	0x5FDE	#CJK UNIFIED IDEOGRAPH+0xEDA0	0x605D	#CJK UNIFIED IDEOGRAPH+0xEDA1	0x6085	#CJK UNIFIED IDEOGRAPH+0xEDA2	0x608A	#CJK UNIFIED IDEOGRAPH+0xEDA3	0x60DE	#CJK UNIFIED IDEOGRAPH+0xEDA4	0x60D5	#CJK UNIFIED IDEOGRAPH+0xEDA5	0x6120	#CJK UNIFIED IDEOGRAPH+0xEDA6	0x60F2	#CJK UNIFIED IDEOGRAPH+0xEDA7	0x6111	#CJK UNIFIED IDEOGRAPH+0xEDA8	0x6137	#CJK UNIFIED IDEOGRAPH+0xEDA9	0x6130	#CJK UNIFIED IDEOGRAPH+0xEDAA	0x6198	#CJK UNIFIED IDEOGRAPH+0xEDAB	0x6213	#CJK UNIFIED IDEOGRAPH+0xEDAC	0x62A6	#CJK UNIFIED IDEOGRAPH+0xEDAD	0x63F5	#CJK UNIFIED IDEOGRAPH+0xEDAE	0x6460	#CJK UNIFIED IDEOGRAPH+0xEDAF	0x649D	#CJK UNIFIED IDEOGRAPH+0xEDB0	0x64CE	#CJK UNIFIED IDEOGRAPH+0xEDB1	0x654E	#CJK UNIFIED IDEOGRAPH+0xEDB2	0x6600	#CJK UNIFIED IDEOGRAPH+0xEDB3	0x6615	#CJK UNIFIED IDEOGRAPH+0xEDB4	0x663B	#CJK UNIFIED IDEOGRAPH+0xEDB5	0x6609	#CJK UNIFIED IDEOGRAPH+0xEDB6	0x662E	#CJK UNIFIED IDEOGRAPH+0xEDB7	0x661E	#CJK UNIFIED IDEOGRAPH+0xEDB8	0x6624	#CJK UNIFIED IDEOGRAPH+0xEDB9	0x6665	#CJK UNIFIED IDEOGRAPH+0xEDBA	0x6657	#CJK UNIFIED IDEOGRAPH+0xEDBB	0x6659	#CJK UNIFIED IDEOGRAPH+0xEDBC	0xFA12	#CJK COMPATIBILITY IDEOGRAPH+0xEDBD	0x6673	#CJK UNIFIED IDEOGRAPH+0xEDBE	0x6699	#CJK UNIFIED IDEOGRAPH+0xEDBF	0x66A0	#CJK UNIFIED IDEOGRAPH+0xEDC0	0x66B2	#CJK UNIFIED IDEOGRAPH+0xEDC1	0x66BF	#CJK UNIFIED IDEOGRAPH+0xEDC2	0x66FA	#CJK UNIFIED IDEOGRAPH+0xEDC3	0x670E	#CJK UNIFIED IDEOGRAPH+0xEDC4	0xF929	#CJK COMPATIBILITY IDEOGRAPH+0xEDC5	0x6766	#CJK UNIFIED IDEOGRAPH+0xEDC6	0x67BB	#CJK UNIFIED IDEOGRAPH+0xEDC7	0x6852	#CJK UNIFIED IDEOGRAPH+0xEDC8	0x67C0	#CJK UNIFIED IDEOGRAPH+0xEDC9	0x6801	#CJK UNIFIED IDEOGRAPH+0xEDCA	0x6844	#CJK UNIFIED IDEOGRAPH+0xEDCB	0x68CF	#CJK UNIFIED IDEOGRAPH+0xEDCC	0xFA13	#CJK COMPATIBILITY IDEOGRAPH+0xEDCD	0x6968	#CJK UNIFIED IDEOGRAPH+0xEDCE	0xFA14	#CJK COMPATIBILITY IDEOGRAPH+0xEDCF	0x6998	#CJK UNIFIED IDEOGRAPH+0xEDD0	0x69E2	#CJK UNIFIED IDEOGRAPH+0xEDD1	0x6A30	#CJK UNIFIED IDEOGRAPH+0xEDD2	0x6A6B	#CJK UNIFIED IDEOGRAPH+0xEDD3	0x6A46	#CJK UNIFIED IDEOGRAPH+0xEDD4	0x6A73	#CJK UNIFIED IDEOGRAPH+0xEDD5	0x6A7E	#CJK UNIFIED IDEOGRAPH+0xEDD6	0x6AE2	#CJK UNIFIED IDEOGRAPH+0xEDD7	0x6AE4	#CJK UNIFIED IDEOGRAPH+0xEDD8	0x6BD6	#CJK UNIFIED IDEOGRAPH+0xEDD9	0x6C3F	#CJK UNIFIED IDEOGRAPH+0xEDDA	0x6C5C	#CJK UNIFIED IDEOGRAPH+0xEDDB	0x6C86	#CJK UNIFIED IDEOGRAPH+0xEDDC	0x6C6F	#CJK UNIFIED IDEOGRAPH+0xEDDD	0x6CDA	#CJK UNIFIED IDEOGRAPH+0xEDDE	0x6D04	#CJK UNIFIED IDEOGRAPH+0xEDDF	0x6D87	#CJK UNIFIED IDEOGRAPH+0xEDE0	0x6D6F	#CJK UNIFIED IDEOGRAPH+0xEDE1	0x6D96	#CJK UNIFIED IDEOGRAPH+0xEDE2	0x6DAC	#CJK UNIFIED IDEOGRAPH+0xEDE3	0x6DCF	#CJK UNIFIED IDEOGRAPH+0xEDE4	0x6DF8	#CJK UNIFIED IDEOGRAPH+0xEDE5	0x6DF2	#CJK UNIFIED IDEOGRAPH+0xEDE6	0x6DFC	#CJK UNIFIED IDEOGRAPH+0xEDE7	0x6E39	#CJK UNIFIED IDEOGRAPH+0xEDE8	0x6E5C	#CJK UNIFIED IDEOGRAPH+0xEDE9	0x6E27	#CJK UNIFIED IDEOGRAPH+0xEDEA	0x6E3C	#CJK UNIFIED IDEOGRAPH+0xEDEB	0x6EBF	#CJK UNIFIED IDEOGRAPH+0xEDEC	0x6F88	#CJK UNIFIED IDEOGRAPH+0xEDED	0x6FB5	#CJK UNIFIED IDEOGRAPH+0xEDEE	0x6FF5	#CJK UNIFIED IDEOGRAPH+0xEDEF	0x7005	#CJK UNIFIED IDEOGRAPH+0xEDF0	0x7007	#CJK UNIFIED IDEOGRAPH+0xEDF1	0x7028	#CJK UNIFIED IDEOGRAPH+0xEDF2	0x7085	#CJK UNIFIED IDEOGRAPH+0xEDF3	0x70AB	#CJK UNIFIED IDEOGRAPH+0xEDF4	0x710F	#CJK UNIFIED IDEOGRAPH+0xEDF5	0x7104	#CJK UNIFIED IDEOGRAPH+0xEDF6	0x715C	#CJK UNIFIED IDEOGRAPH+0xEDF7	0x7146	#CJK UNIFIED IDEOGRAPH+0xEDF8	0x7147	#CJK UNIFIED IDEOGRAPH+0xEDF9	0xFA15	#CJK COMPATIBILITY IDEOGRAPH+0xEDFA	0x71C1	#CJK UNIFIED IDEOGRAPH+0xEDFB	0x71FE	#CJK UNIFIED IDEOGRAPH+0xEDFC	0x72B1	#CJK UNIFIED IDEOGRAPH+0xEE40	0x72BE	#CJK UNIFIED IDEOGRAPH+0xEE41	0x7324	#CJK UNIFIED IDEOGRAPH+0xEE42	0xFA16	#CJK COMPATIBILITY IDEOGRAPH+0xEE43	0x7377	#CJK UNIFIED IDEOGRAPH+0xEE44	0x73BD	#CJK UNIFIED IDEOGRAPH+0xEE45	0x73C9	#CJK UNIFIED IDEOGRAPH+0xEE46	0x73D6	#CJK UNIFIED IDEOGRAPH+0xEE47	0x73E3	#CJK UNIFIED IDEOGRAPH+0xEE48	0x73D2	#CJK UNIFIED IDEOGRAPH+0xEE49	0x7407	#CJK UNIFIED IDEOGRAPH+0xEE4A	0x73F5	#CJK UNIFIED IDEOGRAPH+0xEE4B	0x7426	#CJK UNIFIED IDEOGRAPH+0xEE4C	0x742A	#CJK UNIFIED IDEOGRAPH+0xEE4D	0x7429	#CJK UNIFIED IDEOGRAPH+0xEE4E	0x742E	#CJK UNIFIED IDEOGRAPH+0xEE4F	0x7462	#CJK UNIFIED IDEOGRAPH+0xEE50	0x7489	#CJK UNIFIED IDEOGRAPH+0xEE51	0x749F	#CJK UNIFIED IDEOGRAPH+0xEE52	0x7501	#CJK UNIFIED IDEOGRAPH+0xEE53	0x756F	#CJK UNIFIED IDEOGRAPH+0xEE54	0x7682	#CJK UNIFIED IDEOGRAPH+0xEE55	0x769C	#CJK UNIFIED IDEOGRAPH+0xEE56	0x769E	#CJK UNIFIED IDEOGRAPH+0xEE57	0x769B	#CJK UNIFIED IDEOGRAPH+0xEE58	0x76A6	#CJK UNIFIED IDEOGRAPH+0xEE59	0xFA17	#CJK COMPATIBILITY IDEOGRAPH+0xEE5A	0x7746	#CJK UNIFIED IDEOGRAPH+0xEE5B	0x52AF	#CJK UNIFIED IDEOGRAPH+0xEE5C	0x7821	#CJK UNIFIED IDEOGRAPH+0xEE5D	0x784E	#CJK UNIFIED IDEOGRAPH+0xEE5E	0x7864	#CJK UNIFIED IDEOGRAPH+0xEE5F	0x787A	#CJK UNIFIED IDEOGRAPH+0xEE60	0x7930	#CJK UNIFIED IDEOGRAPH+0xEE61	0xFA18	#CJK COMPATIBILITY IDEOGRAPH+0xEE62	0xFA19	#CJK COMPATIBILITY IDEOGRAPH+0xEE63	0xFA1A	#CJK COMPATIBILITY IDEOGRAPH+0xEE64	0x7994	#CJK UNIFIED IDEOGRAPH+0xEE65	0xFA1B	#CJK COMPATIBILITY IDEOGRAPH+0xEE66	0x799B	#CJK UNIFIED IDEOGRAPH+0xEE67	0x7AD1	#CJK UNIFIED IDEOGRAPH+0xEE68	0x7AE7	#CJK UNIFIED IDEOGRAPH+0xEE69	0xFA1C	#CJK COMPATIBILITY IDEOGRAPH+0xEE6A	0x7AEB	#CJK UNIFIED IDEOGRAPH+0xEE6B	0x7B9E	#CJK UNIFIED IDEOGRAPH+0xEE6C	0xFA1D	#CJK COMPATIBILITY IDEOGRAPH+0xEE6D	0x7D48	#CJK UNIFIED IDEOGRAPH+0xEE6E	0x7D5C	#CJK UNIFIED IDEOGRAPH+0xEE6F	0x7DB7	#CJK UNIFIED IDEOGRAPH+0xEE70	0x7DA0	#CJK UNIFIED IDEOGRAPH+0xEE71	0x7DD6	#CJK UNIFIED IDEOGRAPH+0xEE72	0x7E52	#CJK UNIFIED IDEOGRAPH+0xEE73	0x7F47	#CJK UNIFIED IDEOGRAPH+0xEE74	0x7FA1	#CJK UNIFIED IDEOGRAPH+0xEE75	0xFA1E	#CJK COMPATIBILITY IDEOGRAPH+0xEE76	0x8301	#CJK UNIFIED IDEOGRAPH+0xEE77	0x8362	#CJK UNIFIED IDEOGRAPH+0xEE78	0x837F	#CJK UNIFIED IDEOGRAPH+0xEE79	0x83C7	#CJK UNIFIED IDEOGRAPH+0xEE7A	0x83F6	#CJK UNIFIED IDEOGRAPH+0xEE7B	0x8448	#CJK UNIFIED IDEOGRAPH+0xEE7C	0x84B4	#CJK UNIFIED IDEOGRAPH+0xEE7D	0x8553	#CJK UNIFIED IDEOGRAPH+0xEE7E	0x8559	#CJK UNIFIED IDEOGRAPH+0xEE80	0x856B	#CJK UNIFIED IDEOGRAPH+0xEE81	0xFA1F	#CJK COMPATIBILITY IDEOGRAPH+0xEE82	0x85B0	#CJK UNIFIED IDEOGRAPH+0xEE83	0xFA20	#CJK COMPATIBILITY IDEOGRAPH+0xEE84	0xFA21	#CJK COMPATIBILITY IDEOGRAPH+0xEE85	0x8807	#CJK UNIFIED IDEOGRAPH+0xEE86	0x88F5	#CJK UNIFIED IDEOGRAPH+0xEE87	0x8A12	#CJK UNIFIED IDEOGRAPH+0xEE88	0x8A37	#CJK UNIFIED IDEOGRAPH+0xEE89	0x8A79	#CJK UNIFIED IDEOGRAPH+0xEE8A	0x8AA7	#CJK UNIFIED IDEOGRAPH+0xEE8B	0x8ABE	#CJK UNIFIED IDEOGRAPH+0xEE8C	0x8ADF	#CJK UNIFIED IDEOGRAPH+0xEE8D	0xFA22	#CJK COMPATIBILITY IDEOGRAPH+0xEE8E	0x8AF6	#CJK UNIFIED IDEOGRAPH+0xEE8F	0x8B53	#CJK UNIFIED IDEOGRAPH+0xEE90	0x8B7F	#CJK UNIFIED IDEOGRAPH+0xEE91	0x8CF0	#CJK UNIFIED IDEOGRAPH+0xEE92	0x8CF4	#CJK UNIFIED IDEOGRAPH+0xEE93	0x8D12	#CJK UNIFIED IDEOGRAPH+0xEE94	0x8D76	#CJK UNIFIED IDEOGRAPH+0xEE95	0xFA23	#CJK COMPATIBILITY IDEOGRAPH+0xEE96	0x8ECF	#CJK UNIFIED IDEOGRAPH+0xEE97	0xFA24	#CJK COMPATIBILITY IDEOGRAPH+0xEE98	0xFA25	#CJK COMPATIBILITY IDEOGRAPH+0xEE99	0x9067	#CJK UNIFIED IDEOGRAPH+0xEE9A	0x90DE	#CJK UNIFIED IDEOGRAPH+0xEE9B	0xFA26	#CJK COMPATIBILITY IDEOGRAPH+0xEE9C	0x9115	#CJK UNIFIED IDEOGRAPH+0xEE9D	0x9127	#CJK UNIFIED IDEOGRAPH+0xEE9E	0x91DA	#CJK UNIFIED IDEOGRAPH+0xEE9F	0x91D7	#CJK UNIFIED IDEOGRAPH+0xEEA0	0x91DE	#CJK UNIFIED IDEOGRAPH+0xEEA1	0x91ED	#CJK UNIFIED IDEOGRAPH+0xEEA2	0x91EE	#CJK UNIFIED IDEOGRAPH+0xEEA3	0x91E4	#CJK UNIFIED IDEOGRAPH+0xEEA4	0x91E5	#CJK UNIFIED IDEOGRAPH+0xEEA5	0x9206	#CJK UNIFIED IDEOGRAPH+0xEEA6	0x9210	#CJK UNIFIED IDEOGRAPH+0xEEA7	0x920A	#CJK UNIFIED IDEOGRAPH+0xEEA8	0x923A	#CJK UNIFIED IDEOGRAPH+0xEEA9	0x9240	#CJK UNIFIED IDEOGRAPH+0xEEAA	0x923C	#CJK UNIFIED IDEOGRAPH+0xEEAB	0x924E	#CJK UNIFIED IDEOGRAPH+0xEEAC	0x9259	#CJK UNIFIED IDEOGRAPH+0xEEAD	0x9251	#CJK UNIFIED IDEOGRAPH+0xEEAE	0x9239	#CJK UNIFIED IDEOGRAPH+0xEEAF	0x9267	#CJK UNIFIED IDEOGRAPH+0xEEB0	0x92A7	#CJK UNIFIED IDEOGRAPH+0xEEB1	0x9277	#CJK UNIFIED IDEOGRAPH+0xEEB2	0x9278	#CJK UNIFIED IDEOGRAPH+0xEEB3	0x92E7	#CJK UNIFIED IDEOGRAPH+0xEEB4	0x92D7	#CJK UNIFIED IDEOGRAPH+0xEEB5	0x92D9	#CJK UNIFIED IDEOGRAPH+0xEEB6	0x92D0	#CJK UNIFIED IDEOGRAPH+0xEEB7	0xFA27	#CJK COMPATIBILITY IDEOGRAPH+0xEEB8	0x92D5	#CJK UNIFIED IDEOGRAPH+0xEEB9	0x92E0	#CJK UNIFIED IDEOGRAPH+0xEEBA	0x92D3	#CJK UNIFIED IDEOGRAPH+0xEEBB	0x9325	#CJK UNIFIED IDEOGRAPH+0xEEBC	0x9321	#CJK UNIFIED IDEOGRAPH+0xEEBD	0x92FB	#CJK UNIFIED IDEOGRAPH+0xEEBE	0xFA28	#CJK COMPATIBILITY IDEOGRAPH+0xEEBF	0x931E	#CJK UNIFIED IDEOGRAPH+0xEEC0	0x92FF	#CJK UNIFIED IDEOGRAPH+0xEEC1	0x931D	#CJK UNIFIED IDEOGRAPH+0xEEC2	0x9302	#CJK UNIFIED IDEOGRAPH+0xEEC3	0x9370	#CJK UNIFIED IDEOGRAPH+0xEEC4	0x9357	#CJK UNIFIED IDEOGRAPH+0xEEC5	0x93A4	#CJK UNIFIED IDEOGRAPH+0xEEC6	0x93C6	#CJK UNIFIED IDEOGRAPH+0xEEC7	0x93DE	#CJK UNIFIED IDEOGRAPH+0xEEC8	0x93F8	#CJK UNIFIED IDEOGRAPH+0xEEC9	0x9431	#CJK UNIFIED IDEOGRAPH+0xEECA	0x9445	#CJK UNIFIED IDEOGRAPH+0xEECB	0x9448	#CJK UNIFIED IDEOGRAPH+0xEECC	0x9592	#CJK UNIFIED IDEOGRAPH+0xEECD	0xF9DC	#CJK COMPATIBILITY IDEOGRAPH+0xEECE	0xFA29	#CJK COMPATIBILITY IDEOGRAPH+0xEECF	0x969D	#CJK UNIFIED IDEOGRAPH+0xEED0	0x96AF	#CJK UNIFIED IDEOGRAPH+0xEED1	0x9733	#CJK UNIFIED IDEOGRAPH+0xEED2	0x973B	#CJK UNIFIED IDEOGRAPH+0xEED3	0x9743	#CJK UNIFIED IDEOGRAPH+0xEED4	0x974D	#CJK UNIFIED IDEOGRAPH+0xEED5	0x974F	#CJK UNIFIED IDEOGRAPH+0xEED6	0x9751	#CJK UNIFIED IDEOGRAPH+0xEED7	0x9755	#CJK UNIFIED IDEOGRAPH+0xEED8	0x9857	#CJK UNIFIED IDEOGRAPH+0xEED9	0x9865	#CJK UNIFIED IDEOGRAPH+0xEEDA	0xFA2A	#CJK COMPATIBILITY IDEOGRAPH+0xEEDB	0xFA2B	#CJK COMPATIBILITY IDEOGRAPH+0xEEDC	0x9927	#CJK UNIFIED IDEOGRAPH+0xEEDD	0xFA2C	#CJK COMPATIBILITY IDEOGRAPH+0xEEDE	0x999E	#CJK UNIFIED IDEOGRAPH+0xEEDF	0x9A4E	#CJK UNIFIED IDEOGRAPH+0xEEE0	0x9AD9	#CJK UNIFIED IDEOGRAPH+0xEEE1	0x9ADC	#CJK UNIFIED IDEOGRAPH+0xEEE2	0x9B75	#CJK UNIFIED IDEOGRAPH+0xEEE3	0x9B72	#CJK UNIFIED IDEOGRAPH+0xEEE4	0x9B8F	#CJK UNIFIED IDEOGRAPH+0xEEE5	0x9BB1	#CJK UNIFIED IDEOGRAPH+0xEEE6	0x9BBB	#CJK UNIFIED IDEOGRAPH+0xEEE7	0x9C00	#CJK UNIFIED IDEOGRAPH+0xEEE8	0x9D70	#CJK UNIFIED IDEOGRAPH+0xEEE9	0x9D6B	#CJK UNIFIED IDEOGRAPH+0xEEEA	0xFA2D	#CJK COMPATIBILITY IDEOGRAPH+0xEEEB	0x9E19	#CJK UNIFIED IDEOGRAPH+0xEEEC	0x9ED1	#CJK UNIFIED IDEOGRAPH+0xEEEF	0x2170	#SMALL ROMAN NUMERAL ONE+0xEEF0	0x2171	#SMALL ROMAN NUMERAL TWO+0xEEF1	0x2172	#SMALL ROMAN NUMERAL THREE+0xEEF2	0x2173	#SMALL ROMAN NUMERAL FOUR+0xEEF3	0x2174	#SMALL ROMAN NUMERAL FIVE+0xEEF4	0x2175	#SMALL ROMAN NUMERAL SIX+0xEEF5	0x2176	#SMALL ROMAN NUMERAL SEVEN+0xEEF6	0x2177	#SMALL ROMAN NUMERAL EIGHT+0xEEF7	0x2178	#SMALL ROMAN NUMERAL NINE+0xEEF8	0x2179	#SMALL ROMAN NUMERAL TEN+0xEEF9	0xFFE2	#FULLWIDTH NOT SIGN+0xEEFA	0xFFE4	#FULLWIDTH BROKEN BAR+0xEEFB	0xFF07	#FULLWIDTH APOSTROPHE+0xEEFC	0xFF02	#FULLWIDTH QUOTATION MARK+0xFA40	0x2170	#SMALL ROMAN NUMERAL ONE+0xFA41	0x2171	#SMALL ROMAN NUMERAL TWO+0xFA42	0x2172	#SMALL ROMAN NUMERAL THREE+0xFA43	0x2173	#SMALL ROMAN NUMERAL FOUR+0xFA44	0x2174	#SMALL ROMAN NUMERAL FIVE+0xFA45	0x2175	#SMALL ROMAN NUMERAL SIX+0xFA46	0x2176	#SMALL ROMAN NUMERAL SEVEN+0xFA47	0x2177	#SMALL ROMAN NUMERAL EIGHT+0xFA48	0x2178	#SMALL ROMAN NUMERAL NINE+0xFA49	0x2179	#SMALL ROMAN NUMERAL TEN+0xFA4A	0x2160	#ROMAN NUMERAL ONE+0xFA4B	0x2161	#ROMAN NUMERAL TWO+0xFA4C	0x2162	#ROMAN NUMERAL THREE+0xFA4D	0x2163	#ROMAN NUMERAL FOUR+0xFA4E	0x2164	#ROMAN NUMERAL FIVE+0xFA4F	0x2165	#ROMAN NUMERAL SIX+0xFA50	0x2166	#ROMAN NUMERAL SEVEN+0xFA51	0x2167	#ROMAN NUMERAL EIGHT+0xFA52	0x2168	#ROMAN NUMERAL NINE+0xFA53	0x2169	#ROMAN NUMERAL TEN+0xFA54	0xFFE2	#FULLWIDTH NOT SIGN+0xFA55	0xFFE4	#FULLWIDTH BROKEN BAR+0xFA56	0xFF07	#FULLWIDTH APOSTROPHE+0xFA57	0xFF02	#FULLWIDTH QUOTATION MARK+0xFA58	0x3231	#PARENTHESIZED IDEOGRAPH STOCK+0xFA59	0x2116	#NUMERO SIGN+0xFA5A	0x2121	#TELEPHONE SIGN+0xFA5B	0x2235	#BECAUSE+0xFA5C	0x7E8A	#CJK UNIFIED IDEOGRAPH+0xFA5D	0x891C	#CJK UNIFIED IDEOGRAPH+0xFA5E	0x9348	#CJK UNIFIED IDEOGRAPH+0xFA5F	0x9288	#CJK UNIFIED IDEOGRAPH+0xFA60	0x84DC	#CJK UNIFIED IDEOGRAPH+0xFA61	0x4FC9	#CJK UNIFIED IDEOGRAPH+0xFA62	0x70BB	#CJK UNIFIED IDEOGRAPH+0xFA63	0x6631	#CJK UNIFIED IDEOGRAPH+0xFA64	0x68C8	#CJK UNIFIED IDEOGRAPH+0xFA65	0x92F9	#CJK UNIFIED IDEOGRAPH+0xFA66	0x66FB	#CJK UNIFIED IDEOGRAPH+0xFA67	0x5F45	#CJK UNIFIED IDEOGRAPH+0xFA68	0x4E28	#CJK UNIFIED IDEOGRAPH+0xFA69	0x4EE1	#CJK UNIFIED IDEOGRAPH+0xFA6A	0x4EFC	#CJK UNIFIED IDEOGRAPH+0xFA6B	0x4F00	#CJK UNIFIED IDEOGRAPH+0xFA6C	0x4F03	#CJK UNIFIED IDEOGRAPH+0xFA6D	0x4F39	#CJK UNIFIED IDEOGRAPH+0xFA6E	0x4F56	#CJK UNIFIED IDEOGRAPH+0xFA6F	0x4F92	#CJK UNIFIED IDEOGRAPH+0xFA70	0x4F8A	#CJK UNIFIED IDEOGRAPH+0xFA71	0x4F9A	#CJK UNIFIED IDEOGRAPH+0xFA72	0x4F94	#CJK UNIFIED IDEOGRAPH+0xFA73	0x4FCD	#CJK UNIFIED IDEOGRAPH+0xFA74	0x5040	#CJK UNIFIED IDEOGRAPH+0xFA75	0x5022	#CJK UNIFIED IDEOGRAPH+0xFA76	0x4FFF	#CJK UNIFIED IDEOGRAPH+0xFA77	0x501E	#CJK UNIFIED IDEOGRAPH+0xFA78	0x5046	#CJK UNIFIED IDEOGRAPH+0xFA79	0x5070	#CJK UNIFIED IDEOGRAPH+0xFA7A	0x5042	#CJK UNIFIED IDEOGRAPH+0xFA7B	0x5094	#CJK UNIFIED IDEOGRAPH+0xFA7C	0x50F4	#CJK UNIFIED IDEOGRAPH+0xFA7D	0x50D8	#CJK UNIFIED IDEOGRAPH+0xFA7E	0x514A	#CJK UNIFIED IDEOGRAPH+0xFA80	0x5164	#CJK UNIFIED IDEOGRAPH+0xFA81	0x519D	#CJK UNIFIED IDEOGRAPH+0xFA82	0x51BE	#CJK UNIFIED IDEOGRAPH+0xFA83	0x51EC	#CJK UNIFIED IDEOGRAPH+0xFA84	0x5215	#CJK UNIFIED IDEOGRAPH+0xFA85	0x529C	#CJK UNIFIED IDEOGRAPH+0xFA86	0x52A6	#CJK UNIFIED IDEOGRAPH+0xFA87	0x52C0	#CJK UNIFIED IDEOGRAPH+0xFA88	0x52DB	#CJK UNIFIED IDEOGRAPH+0xFA89	0x5300	#CJK UNIFIED IDEOGRAPH+0xFA8A	0x5307	#CJK UNIFIED IDEOGRAPH+0xFA8B	0x5324	#CJK UNIFIED IDEOGRAPH+0xFA8C	0x5372	#CJK UNIFIED IDEOGRAPH+0xFA8D	0x5393	#CJK UNIFIED IDEOGRAPH+0xFA8E	0x53B2	#CJK UNIFIED IDEOGRAPH+0xFA8F	0x53DD	#CJK UNIFIED IDEOGRAPH+0xFA90	0xFA0E	#CJK COMPATIBILITY IDEOGRAPH+0xFA91	0x549C	#CJK UNIFIED IDEOGRAPH+0xFA92	0x548A	#CJK UNIFIED IDEOGRAPH+0xFA93	0x54A9	#CJK UNIFIED IDEOGRAPH+0xFA94	0x54FF	#CJK UNIFIED IDEOGRAPH+0xFA95	0x5586	#CJK UNIFIED IDEOGRAPH+0xFA96	0x5759	#CJK UNIFIED IDEOGRAPH+0xFA97	0x5765	#CJK UNIFIED IDEOGRAPH+0xFA98	0x57AC	#CJK UNIFIED IDEOGRAPH+0xFA99	0x57C8	#CJK UNIFIED IDEOGRAPH+0xFA9A	0x57C7	#CJK UNIFIED IDEOGRAPH+0xFA9B	0xFA0F	#CJK COMPATIBILITY IDEOGRAPH+0xFA9C	0xFA10	#CJK COMPATIBILITY IDEOGRAPH+0xFA9D	0x589E	#CJK UNIFIED IDEOGRAPH+0xFA9E	0x58B2	#CJK UNIFIED IDEOGRAPH+0xFA9F	0x590B	#CJK UNIFIED IDEOGRAPH+0xFAA0	0x5953	#CJK UNIFIED IDEOGRAPH+0xFAA1	0x595B	#CJK UNIFIED IDEOGRAPH+0xFAA2	0x595D	#CJK UNIFIED IDEOGRAPH+0xFAA3	0x5963	#CJK UNIFIED IDEOGRAPH+0xFAA4	0x59A4	#CJK UNIFIED IDEOGRAPH+0xFAA5	0x59BA	#CJK UNIFIED IDEOGRAPH+0xFAA6	0x5B56	#CJK UNIFIED IDEOGRAPH+0xFAA7	0x5BC0	#CJK UNIFIED IDEOGRAPH+0xFAA8	0x752F	#CJK UNIFIED IDEOGRAPH+0xFAA9	0x5BD8	#CJK UNIFIED IDEOGRAPH+0xFAAA	0x5BEC	#CJK UNIFIED IDEOGRAPH+0xFAAB	0x5C1E	#CJK UNIFIED IDEOGRAPH+0xFAAC	0x5CA6	#CJK UNIFIED IDEOGRAPH+0xFAAD	0x5CBA	#CJK UNIFIED IDEOGRAPH+0xFAAE	0x5CF5	#CJK UNIFIED IDEOGRAPH+0xFAAF	0x5D27	#CJK UNIFIED IDEOGRAPH+0xFAB0	0x5D53	#CJK UNIFIED IDEOGRAPH+0xFAB1	0xFA11	#CJK COMPATIBILITY IDEOGRAPH+0xFAB2	0x5D42	#CJK UNIFIED IDEOGRAPH+0xFAB3	0x5D6D	#CJK UNIFIED IDEOGRAPH+0xFAB4	0x5DB8	#CJK UNIFIED IDEOGRAPH+0xFAB5	0x5DB9	#CJK UNIFIED IDEOGRAPH+0xFAB6	0x5DD0	#CJK UNIFIED IDEOGRAPH+0xFAB7	0x5F21	#CJK UNIFIED IDEOGRAPH+0xFAB8	0x5F34	#CJK UNIFIED IDEOGRAPH+0xFAB9	0x5F67	#CJK UNIFIED IDEOGRAPH+0xFABA	0x5FB7	#CJK UNIFIED IDEOGRAPH+0xFABB	0x5FDE	#CJK UNIFIED IDEOGRAPH+0xFABC	0x605D	#CJK UNIFIED IDEOGRAPH+0xFABD	0x6085	#CJK UNIFIED IDEOGRAPH+0xFABE	0x608A	#CJK UNIFIED IDEOGRAPH+0xFABF	0x60DE	#CJK UNIFIED IDEOGRAPH+0xFAC0	0x60D5	#CJK UNIFIED IDEOGRAPH+0xFAC1	0x6120	#CJK UNIFIED IDEOGRAPH+0xFAC2	0x60F2	#CJK UNIFIED IDEOGRAPH+0xFAC3	0x6111	#CJK UNIFIED IDEOGRAPH+0xFAC4	0x6137	#CJK UNIFIED IDEOGRAPH+0xFAC5	0x6130	#CJK UNIFIED IDEOGRAPH+0xFAC6	0x6198	#CJK UNIFIED IDEOGRAPH+0xFAC7	0x6213	#CJK UNIFIED IDEOGRAPH+0xFAC8	0x62A6	#CJK UNIFIED IDEOGRAPH+0xFAC9	0x63F5	#CJK UNIFIED IDEOGRAPH+0xFACA	0x6460	#CJK UNIFIED IDEOGRAPH+0xFACB	0x649D	#CJK UNIFIED IDEOGRAPH+0xFACC	0x64CE	#CJK UNIFIED IDEOGRAPH+0xFACD	0x654E	#CJK UNIFIED IDEOGRAPH+0xFACE	0x6600	#CJK UNIFIED IDEOGRAPH+0xFACF	0x6615	#CJK UNIFIED IDEOGRAPH+0xFAD0	0x663B	#CJK UNIFIED IDEOGRAPH+0xFAD1	0x6609	#CJK UNIFIED IDEOGRAPH+0xFAD2	0x662E	#CJK UNIFIED IDEOGRAPH+0xFAD3	0x661E	#CJK UNIFIED IDEOGRAPH+0xFAD4	0x6624	#CJK UNIFIED IDEOGRAPH+0xFAD5	0x6665	#CJK UNIFIED IDEOGRAPH+0xFAD6	0x6657	#CJK UNIFIED IDEOGRAPH+0xFAD7	0x6659	#CJK UNIFIED IDEOGRAPH+0xFAD8	0xFA12	#CJK COMPATIBILITY IDEOGRAPH+0xFAD9	0x6673	#CJK UNIFIED IDEOGRAPH+0xFADA	0x6699	#CJK UNIFIED IDEOGRAPH+0xFADB	0x66A0	#CJK UNIFIED IDEOGRAPH+0xFADC	0x66B2	#CJK UNIFIED IDEOGRAPH+0xFADD	0x66BF	#CJK UNIFIED IDEOGRAPH+0xFADE	0x66FA	#CJK UNIFIED IDEOGRAPH+0xFADF	0x670E	#CJK UNIFIED IDEOGRAPH+0xFAE0	0xF929	#CJK COMPATIBILITY IDEOGRAPH+0xFAE1	0x6766	#CJK UNIFIED IDEOGRAPH+0xFAE2	0x67BB	#CJK UNIFIED IDEOGRAPH+0xFAE3	0x6852	#CJK UNIFIED IDEOGRAPH+0xFAE4	0x67C0	#CJK UNIFIED IDEOGRAPH+0xFAE5	0x6801	#CJK UNIFIED IDEOGRAPH+0xFAE6	0x6844	#CJK UNIFIED IDEOGRAPH+0xFAE7	0x68CF	#CJK UNIFIED IDEOGRAPH+0xFAE8	0xFA13	#CJK COMPATIBILITY IDEOGRAPH+0xFAE9	0x6968	#CJK UNIFIED IDEOGRAPH+0xFAEA	0xFA14	#CJK COMPATIBILITY IDEOGRAPH+0xFAEB	0x6998	#CJK UNIFIED IDEOGRAPH+0xFAEC	0x69E2	#CJK UNIFIED IDEOGRAPH+0xFAED	0x6A30	#CJK UNIFIED IDEOGRAPH+0xFAEE	0x6A6B	#CJK UNIFIED IDEOGRAPH+0xFAEF	0x6A46	#CJK UNIFIED IDEOGRAPH+0xFAF0	0x6A73	#CJK UNIFIED IDEOGRAPH+0xFAF1	0x6A7E	#CJK UNIFIED IDEOGRAPH+0xFAF2	0x6AE2	#CJK UNIFIED IDEOGRAPH+0xFAF3	0x6AE4	#CJK UNIFIED IDEOGRAPH+0xFAF4	0x6BD6	#CJK UNIFIED IDEOGRAPH+0xFAF5	0x6C3F	#CJK UNIFIED IDEOGRAPH+0xFAF6	0x6C5C	#CJK UNIFIED IDEOGRAPH+0xFAF7	0x6C86	#CJK UNIFIED IDEOGRAPH+0xFAF8	0x6C6F	#CJK UNIFIED IDEOGRAPH+0xFAF9	0x6CDA	#CJK UNIFIED IDEOGRAPH+0xFAFA	0x6D04	#CJK UNIFIED IDEOGRAPH+0xFAFB	0x6D87	#CJK UNIFIED IDEOGRAPH+0xFAFC	0x6D6F	#CJK UNIFIED IDEOGRAPH+0xFB40	0x6D96	#CJK UNIFIED IDEOGRAPH+0xFB41	0x6DAC	#CJK UNIFIED IDEOGRAPH+0xFB42	0x6DCF	#CJK UNIFIED IDEOGRAPH+0xFB43	0x6DF8	#CJK UNIFIED IDEOGRAPH+0xFB44	0x6DF2	#CJK UNIFIED IDEOGRAPH+0xFB45	0x6DFC	#CJK UNIFIED IDEOGRAPH+0xFB46	0x6E39	#CJK UNIFIED IDEOGRAPH+0xFB47	0x6E5C	#CJK UNIFIED IDEOGRAPH+0xFB48	0x6E27	#CJK UNIFIED IDEOGRAPH+0xFB49	0x6E3C	#CJK UNIFIED IDEOGRAPH+0xFB4A	0x6EBF	#CJK UNIFIED IDEOGRAPH+0xFB4B	0x6F88	#CJK UNIFIED IDEOGRAPH+0xFB4C	0x6FB5	#CJK UNIFIED IDEOGRAPH+0xFB4D	0x6FF5	#CJK UNIFIED IDEOGRAPH+0xFB4E	0x7005	#CJK UNIFIED IDEOGRAPH+0xFB4F	0x7007	#CJK UNIFIED IDEOGRAPH+0xFB50	0x7028	#CJK UNIFIED IDEOGRAPH+0xFB51	0x7085	#CJK UNIFIED IDEOGRAPH+0xFB52	0x70AB	#CJK UNIFIED IDEOGRAPH+0xFB53	0x710F	#CJK UNIFIED IDEOGRAPH+0xFB54	0x7104	#CJK UNIFIED IDEOGRAPH+0xFB55	0x715C	#CJK UNIFIED IDEOGRAPH+0xFB56	0x7146	#CJK UNIFIED IDEOGRAPH+0xFB57	0x7147	#CJK UNIFIED IDEOGRAPH+0xFB58	0xFA15	#CJK COMPATIBILITY IDEOGRAPH+0xFB59	0x71C1	#CJK UNIFIED IDEOGRAPH+0xFB5A	0x71FE	#CJK UNIFIED IDEOGRAPH+0xFB5B	0x72B1	#CJK UNIFIED IDEOGRAPH+0xFB5C	0x72BE	#CJK UNIFIED IDEOGRAPH+0xFB5D	0x7324	#CJK UNIFIED IDEOGRAPH+0xFB5E	0xFA16	#CJK COMPATIBILITY IDEOGRAPH+0xFB5F	0x7377	#CJK UNIFIED IDEOGRAPH+0xFB60	0x73BD	#CJK UNIFIED IDEOGRAPH+0xFB61	0x73C9	#CJK UNIFIED IDEOGRAPH+0xFB62	0x73D6	#CJK UNIFIED IDEOGRAPH+0xFB63	0x73E3	#CJK UNIFIED IDEOGRAPH+0xFB64	0x73D2	#CJK UNIFIED IDEOGRAPH+0xFB65	0x7407	#CJK UNIFIED IDEOGRAPH+0xFB66	0x73F5	#CJK UNIFIED IDEOGRAPH+0xFB67	0x7426	#CJK UNIFIED IDEOGRAPH+0xFB68	0x742A	#CJK UNIFIED IDEOGRAPH+0xFB69	0x7429	#CJK UNIFIED IDEOGRAPH+0xFB6A	0x742E	#CJK UNIFIED IDEOGRAPH+0xFB6B	0x7462	#CJK UNIFIED IDEOGRAPH+0xFB6C	0x7489	#CJK UNIFIED IDEOGRAPH+0xFB6D	0x749F	#CJK UNIFIED IDEOGRAPH+0xFB6E	0x7501	#CJK UNIFIED IDEOGRAPH+0xFB6F	0x756F	#CJK UNIFIED IDEOGRAPH+0xFB70	0x7682	#CJK UNIFIED IDEOGRAPH+0xFB71	0x769C	#CJK UNIFIED IDEOGRAPH+0xFB72	0x769E	#CJK UNIFIED IDEOGRAPH+0xFB73	0x769B	#CJK UNIFIED IDEOGRAPH+0xFB74	0x76A6	#CJK UNIFIED IDEOGRAPH+0xFB75	0xFA17	#CJK COMPATIBILITY IDEOGRAPH+0xFB76	0x7746	#CJK UNIFIED IDEOGRAPH+0xFB77	0x52AF	#CJK UNIFIED IDEOGRAPH+0xFB78	0x7821	#CJK UNIFIED IDEOGRAPH+0xFB79	0x784E	#CJK UNIFIED IDEOGRAPH+0xFB7A	0x7864	#CJK UNIFIED IDEOGRAPH+0xFB7B	0x787A	#CJK UNIFIED IDEOGRAPH+0xFB7C	0x7930	#CJK UNIFIED IDEOGRAPH+0xFB7D	0xFA18	#CJK COMPATIBILITY IDEOGRAPH+0xFB7E	0xFA19	#CJK COMPATIBILITY IDEOGRAPH+0xFB80	0xFA1A	#CJK COMPATIBILITY IDEOGRAPH+0xFB81	0x7994	#CJK UNIFIED IDEOGRAPH+0xFB82	0xFA1B	#CJK COMPATIBILITY IDEOGRAPH+0xFB83	0x799B	#CJK UNIFIED IDEOGRAPH+0xFB84	0x7AD1	#CJK UNIFIED IDEOGRAPH+0xFB85	0x7AE7	#CJK UNIFIED IDEOGRAPH+0xFB86	0xFA1C	#CJK COMPATIBILITY IDEOGRAPH+0xFB87	0x7AEB	#CJK UNIFIED IDEOGRAPH+0xFB88	0x7B9E	#CJK UNIFIED IDEOGRAPH+0xFB89	0xFA1D	#CJK COMPATIBILITY IDEOGRAPH+0xFB8A	0x7D48	#CJK UNIFIED IDEOGRAPH+0xFB8B	0x7D5C	#CJK UNIFIED IDEOGRAPH+0xFB8C	0x7DB7	#CJK UNIFIED IDEOGRAPH+0xFB8D	0x7DA0	#CJK UNIFIED IDEOGRAPH+0xFB8E	0x7DD6	#CJK UNIFIED IDEOGRAPH+0xFB8F	0x7E52	#CJK UNIFIED IDEOGRAPH+0xFB90	0x7F47	#CJK UNIFIED IDEOGRAPH+0xFB91	0x7FA1	#CJK UNIFIED IDEOGRAPH+0xFB92	0xFA1E	#CJK COMPATIBILITY IDEOGRAPH+0xFB93	0x8301	#CJK UNIFIED IDEOGRAPH+0xFB94	0x8362	#CJK UNIFIED IDEOGRAPH+0xFB95	0x837F	#CJK UNIFIED IDEOGRAPH+0xFB96	0x83C7	#CJK UNIFIED IDEOGRAPH+0xFB97	0x83F6	#CJK UNIFIED IDEOGRAPH+0xFB98	0x8448	#CJK UNIFIED IDEOGRAPH+0xFB99	0x84B4	#CJK UNIFIED IDEOGRAPH+0xFB9A	0x8553	#CJK UNIFIED IDEOGRAPH+0xFB9B	0x8559	#CJK UNIFIED IDEOGRAPH+0xFB9C	0x856B	#CJK UNIFIED IDEOGRAPH+0xFB9D	0xFA1F	#CJK COMPATIBILITY IDEOGRAPH+0xFB9E	0x85B0	#CJK UNIFIED IDEOGRAPH+0xFB9F	0xFA20	#CJK COMPATIBILITY IDEOGRAPH+0xFBA0	0xFA21	#CJK COMPATIBILITY IDEOGRAPH+0xFBA1	0x8807	#CJK UNIFIED IDEOGRAPH+0xFBA2	0x88F5	#CJK UNIFIED IDEOGRAPH+0xFBA3	0x8A12	#CJK UNIFIED IDEOGRAPH+0xFBA4	0x8A37	#CJK UNIFIED IDEOGRAPH+0xFBA5	0x8A79	#CJK UNIFIED IDEOGRAPH+0xFBA6	0x8AA7	#CJK UNIFIED IDEOGRAPH+0xFBA7	0x8ABE	#CJK UNIFIED IDEOGRAPH+0xFBA8	0x8ADF	#CJK UNIFIED IDEOGRAPH+0xFBA9	0xFA22	#CJK COMPATIBILITY IDEOGRAPH+0xFBAA	0x8AF6	#CJK UNIFIED IDEOGRAPH+0xFBAB	0x8B53	#CJK UNIFIED IDEOGRAPH+0xFBAC	0x8B7F	#CJK UNIFIED IDEOGRAPH+0xFBAD	0x8CF0	#CJK UNIFIED IDEOGRAPH+0xFBAE	0x8CF4	#CJK UNIFIED IDEOGRAPH+0xFBAF	0x8D12	#CJK UNIFIED IDEOGRAPH+0xFBB0	0x8D76	#CJK UNIFIED IDEOGRAPH+0xFBB1	0xFA23	#CJK COMPATIBILITY IDEOGRAPH+0xFBB2	0x8ECF	#CJK UNIFIED IDEOGRAPH+0xFBB3	0xFA24	#CJK COMPATIBILITY IDEOGRAPH+0xFBB4	0xFA25	#CJK COMPATIBILITY IDEOGRAPH+0xFBB5	0x9067	#CJK UNIFIED IDEOGRAPH+0xFBB6	0x90DE	#CJK UNIFIED IDEOGRAPH+0xFBB7	0xFA26	#CJK COMPATIBILITY IDEOGRAPH+0xFBB8	0x9115	#CJK UNIFIED IDEOGRAPH+0xFBB9	0x9127	#CJK UNIFIED IDEOGRAPH+0xFBBA	0x91DA	#CJK UNIFIED IDEOGRAPH+0xFBBB	0x91D7	#CJK UNIFIED IDEOGRAPH+0xFBBC	0x91DE	#CJK UNIFIED IDEOGRAPH+0xFBBD	0x91ED	#CJK UNIFIED IDEOGRAPH+0xFBBE	0x91EE	#CJK UNIFIED IDEOGRAPH+0xFBBF	0x91E4	#CJK UNIFIED IDEOGRAPH+0xFBC0	0x91E5	#CJK UNIFIED IDEOGRAPH+0xFBC1	0x9206	#CJK UNIFIED IDEOGRAPH+0xFBC2	0x9210	#CJK UNIFIED IDEOGRAPH+0xFBC3	0x920A	#CJK UNIFIED IDEOGRAPH+0xFBC4	0x923A	#CJK UNIFIED IDEOGRAPH+0xFBC5	0x9240	#CJK UNIFIED IDEOGRAPH+0xFBC6	0x923C	#CJK UNIFIED IDEOGRAPH+0xFBC7	0x924E	#CJK UNIFIED IDEOGRAPH+0xFBC8	0x9259	#CJK UNIFIED IDEOGRAPH+0xFBC9	0x9251	#CJK UNIFIED IDEOGRAPH+0xFBCA	0x9239	#CJK UNIFIED IDEOGRAPH+0xFBCB	0x9267	#CJK UNIFIED IDEOGRAPH+0xFBCC	0x92A7	#CJK UNIFIED IDEOGRAPH+0xFBCD	0x9277	#CJK UNIFIED IDEOGRAPH+0xFBCE	0x9278	#CJK UNIFIED IDEOGRAPH+0xFBCF	0x92E7	#CJK UNIFIED IDEOGRAPH+0xFBD0	0x92D7	#CJK UNIFIED IDEOGRAPH+0xFBD1	0x92D9	#CJK UNIFIED IDEOGRAPH+0xFBD2	0x92D0	#CJK UNIFIED IDEOGRAPH+0xFBD3	0xFA27	#CJK COMPATIBILITY IDEOGRAPH+0xFBD4	0x92D5	#CJK UNIFIED IDEOGRAPH+0xFBD5	0x92E0	#CJK UNIFIED IDEOGRAPH+0xFBD6	0x92D3	#CJK UNIFIED IDEOGRAPH+0xFBD7	0x9325	#CJK UNIFIED IDEOGRAPH+0xFBD8	0x9321	#CJK UNIFIED IDEOGRAPH+0xFBD9	0x92FB	#CJK UNIFIED IDEOGRAPH+0xFBDA	0xFA28	#CJK COMPATIBILITY IDEOGRAPH+0xFBDB	0x931E	#CJK UNIFIED IDEOGRAPH+0xFBDC	0x92FF	#CJK UNIFIED IDEOGRAPH+0xFBDD	0x931D	#CJK UNIFIED IDEOGRAPH+0xFBDE	0x9302	#CJK UNIFIED IDEOGRAPH+0xFBDF	0x9370	#CJK UNIFIED IDEOGRAPH+0xFBE0	0x9357	#CJK UNIFIED IDEOGRAPH+0xFBE1	0x93A4	#CJK UNIFIED IDEOGRAPH+0xFBE2	0x93C6	#CJK UNIFIED IDEOGRAPH+0xFBE3	0x93DE	#CJK UNIFIED IDEOGRAPH+0xFBE4	0x93F8	#CJK UNIFIED IDEOGRAPH+0xFBE5	0x9431	#CJK UNIFIED IDEOGRAPH+0xFBE6	0x9445	#CJK UNIFIED IDEOGRAPH+0xFBE7	0x9448	#CJK UNIFIED IDEOGRAPH+0xFBE8	0x9592	#CJK UNIFIED IDEOGRAPH+0xFBE9	0xF9DC	#CJK COMPATIBILITY IDEOGRAPH+0xFBEA	0xFA29	#CJK COMPATIBILITY IDEOGRAPH+0xFBEB	0x969D	#CJK UNIFIED IDEOGRAPH+0xFBEC	0x96AF	#CJK UNIFIED IDEOGRAPH+0xFBED	0x9733	#CJK UNIFIED IDEOGRAPH+0xFBEE	0x973B	#CJK UNIFIED IDEOGRAPH+0xFBEF	0x9743	#CJK UNIFIED IDEOGRAPH+0xFBF0	0x974D	#CJK UNIFIED IDEOGRAPH+0xFBF1	0x974F	#CJK UNIFIED IDEOGRAPH+0xFBF2	0x9751	#CJK UNIFIED IDEOGRAPH+0xFBF3	0x9755	#CJK UNIFIED IDEOGRAPH+0xFBF4	0x9857	#CJK UNIFIED IDEOGRAPH+0xFBF5	0x9865	#CJK UNIFIED IDEOGRAPH+0xFBF6	0xFA2A	#CJK COMPATIBILITY IDEOGRAPH+0xFBF7	0xFA2B	#CJK COMPATIBILITY IDEOGRAPH+0xFBF8	0x9927	#CJK UNIFIED IDEOGRAPH+0xFBF9	0xFA2C	#CJK COMPATIBILITY IDEOGRAPH+0xFBFA	0x999E	#CJK UNIFIED IDEOGRAPH+0xFBFB	0x9A4E	#CJK UNIFIED IDEOGRAPH+0xFBFC	0x9AD9	#CJK UNIFIED IDEOGRAPH+0xFC40	0x9ADC	#CJK UNIFIED IDEOGRAPH+0xFC41	0x9B75	#CJK UNIFIED IDEOGRAPH+0xFC42	0x9B72	#CJK UNIFIED IDEOGRAPH+0xFC43	0x9B8F	#CJK UNIFIED IDEOGRAPH+0xFC44	0x9BB1	#CJK UNIFIED IDEOGRAPH+0xFC45	0x9BBB	#CJK UNIFIED IDEOGRAPH+0xFC46	0x9C00	#CJK UNIFIED IDEOGRAPH+0xFC47	0x9D70	#CJK UNIFIED IDEOGRAPH+0xFC48	0x9D6B	#CJK UNIFIED IDEOGRAPH+0xFC49	0xFA2D	#CJK COMPATIBILITY IDEOGRAPH+0xFC4A	0x9E19	#CJK UNIFIED IDEOGRAPH+0xFC4B	0x9ED1	#CJK UNIFIED IDEOGRAPH
+ test/datafiles/unit/carolus-rex.cdtext view

binary file changed (absent → 720 bytes)

+ test/datafiles/unit/deeper-dance.cdtext view

binary file changed (absent → 684 bytes)

+ test/datafiles/unit/pearl-jam.cdtext view

binary file changed (absent → 829 bytes)

+ test/datafiles/unit/revolution-days.cdtext view

binary file changed (absent → 468 bytes)

+ test/datafiles/upstream/bad-cat1.cue view
@@ -0,0 +1,9 @@+REM $Id: bad-cat1.cue,v 1.1 2004/07/12 03:59:59 rocky Exp $+REM test catalog number - no catalog after word CATALOG++CATALOG++FILE "cdda.bin" BINARY++TRACK 01 AUDIO+    INDEX 01 00:00:00
+ test/datafiles/upstream/bad-cat1.toc view
@@ -0,0 +1,8 @@+// $Id: bad-cat1.toc,v 1.1 2004/05/08 20:36:02 rocky Exp $+// test catalog number - no catalog after word CATALOG++CATALOG++TRACK AUDIO+NO COPY+FILE "cdda.bin" 1:0:0
+ test/datafiles/upstream/bad-cat2.cue view
@@ -0,0 +1,9 @@+REM $Id: bad-cat2.cue,v 1.1 2004/07/09 20:47:08 rocky Exp $+REM test catalog number. -- not enough digits++CATALOG "167890123"++FILE "cdda.bin" BINARY++TRACK 01 AUDIO+    INDEX 01 00:00:00
+ test/datafiles/upstream/bad-cat2.toc view
@@ -0,0 +1,8 @@+// $Id: bad-cat2.toc,v 1.2 2004/07/09 20:47:08 rocky Exp $+// test catalog number. -- not enough digits++CATALOG 167890123  // Should be 13 digits++TRACK AUDIO+NO COPY+FILE "cdda.bin" 1:0:0
+ test/datafiles/upstream/bad-cat3.cue view
@@ -0,0 +1,9 @@+REM $Id: bad-cat3.cue,v 1.2 2004/07/10 01:18:02 rocky Exp $+REM test catalog number. -- invalid decimal digit++CATALOG 123456789b123++FILE "cdda.bin" BINARY++TRACK 01 AUDIO+    INDEX 01 00:00:00
+ test/datafiles/upstream/bad-cat3.toc view
@@ -0,0 +1,8 @@+// $Id: bad-cat3.toc,v 1.1 2004/05/08 20:36:02 rocky Exp $+// test catalog number - non-digit catalog name++CATALOG "123456789A123"++TRACK AUDIO+NO COPY+FILE "cdda.bin" 1:0:0
+ test/datafiles/upstream/bad-file.toc view
@@ -0,0 +1,13 @@+// $Id: bad-file.toc,v 1.1 2005/01/23 00:45:57 rocky Exp $+// XA disk +// ++CD_ROM_XA++TRACK MODE2_FORM2+FILE "foo.bin" 00:00:00 00:13:57++TRACK MODE2_FORM1+PREGAP 0:2:0+FILE "foo.bin" 00:20:71 00:00:00+
+ test/datafiles/upstream/bad-mode1.cue view
@@ -0,0 +1,7 @@+REM $Id: bad-mode1.cue,v 1.1 2004/07/10 01:18:02 rocky Exp $+REM "MODE1_FORM45" is not a valid mode.++FILE "cdda.bin" BINARY++TRACK 01 MODE3_FORM1+    INDEX 01 00:00:00
+ test/datafiles/upstream/bad-mode1.toc view
@@ -0,0 +1,5 @@+// $Id: bad-mode1.toc,v 1.1 2004/05/07 10:57:50 rocky Exp $+CD_DA++TRACK MODE1_FORM45  // "MODE1_FORM45" is not a valid mode.+SILENCE 10:0:0
+ test/datafiles/upstream/bad-msf-1.cue view
@@ -0,0 +1,7 @@+REM $Id: bad-msf-1.cue,v 1.1 2004/07/12 03:57:28 rocky Exp $+REM bad MSF in second field - frame should be less than 75++FILE "cdda.bin" BINARY++TRACK 01 AUDIO+    INDEX 01 00:00:100
+ test/datafiles/upstream/bad-msf-1.toc view
@@ -0,0 +1,6 @@+// $Id: bad-msf-1.toc,v 1.1 2004/05/07 10:57:50 rocky Exp $+// bad MSF in second field++TRACK AUDIO+NO COPY       // so that all CTL flags are 0+FILE "cdda.bin" 0:0:75  // frame should be less than 75
+ test/datafiles/upstream/bad-msf-2.cue view
@@ -0,0 +1,7 @@+REM $Id: bad-msf-2.cue,v 1.1 2004/07/10 01:18:02 rocky Exp $+REM bad MSF in second field - seconds should be less than 60++FILE "cdda.bin" BINARY++TRACK 01 AUDIO+    INDEX 01 00:90:00
+ test/datafiles/upstream/bad-msf-2.toc view
@@ -0,0 +1,6 @@+// $Id: bad-msf-2.toc,v 1.1 2004/05/07 10:57:50 rocky Exp $+// bad MSF in second field++TRACK AUDIO+NO COPY       // so that all CTL flags are 0+FILE "cdda.bin" 0:60:0  // seconds should be less than 60
+ test/datafiles/upstream/bad-msf-3.cue view
@@ -0,0 +1,7 @@+REM $Id: bad-msf-3.cue,v 1.1 2004/07/12 03:58:55 rocky Exp $+REM bad MSF in second field ++FILE "cdda.bin" BINARY++TRACK 01 AUDIO+    INDEX 01 xx:yy:0
+ test/datafiles/upstream/bad-msf-3.toc view
@@ -0,0 +1,6 @@+// $Id: bad-msf-3.toc,v 1.1 2004/07/10 01:18:02 rocky Exp $+// bad MSF in second field++TRACK AUDIO+NO COPY       // so that all CTL flags are 0+FILE "cdda.bin" xx:yy:zz  // Should be digits
+ test/datafiles/upstream/cdda.bin view

binary file changed (absent → 710304 bytes)

+ test/datafiles/upstream/cdda.cue view
@@ -0,0 +1,9 @@+TITLE "Join us now we have the software"
+CATALOG 0000010271955
+PERFORMER "Richard Stallman"
+FILE "CDDA.BIN" BINARY
+  TRACK 01 AUDIO
+    TITLE "Soft"
+    PERFORMER "Richard S"
+    FLAGS DCP
+    INDEX 01 00:00:00
+ test/datafiles/upstream/cdtext.toc view
@@ -0,0 +1,48 @@+CD_DA++// global CD-TEXT data++CD_TEXT {++  // Mapping from language number (0..7) used in 'LANGUAGE' statements +  // to language code.+///  LANGUAGE_MAP {+///    0 : EN  // 9 is the code for ENGLISH,+///            // I don't know any other language code, yet+///  }++  // Language number should always start with 0+  LANGUAGE 0 {+    // Required fields - at least all CD-TEXT CDs I've seen so far have them.+    TITLE "Join us now we have the software"+    PERFORMER "Richard Stallman"+    DISC_ID "0000010271955"+    UPC_EAN "" // usually empty++    // Further possible items, all of them are optional+    ARRANGER ""+    SONGWRITER ""+    MESSAGE "" +    GENRE "" // I'm not sure if this should be really ascii data+  }+}+++TRACK AUDIO+// track specific CD-TEXT data+CD_TEXT {+  LANGUAGE 0 {+    // if an item is defined for one track it should be defined for all tracks+    TITLE "Soft"++    PERFORMER "Richard S"+    ISRC "US-XX1-98-01234"++    ARRANGER ""+    SONGWRITER ""+    MESSAGE "" +  }+}++SILENCE 1:0:0+
+ test/datafiles/upstream/data1.toc view
@@ -0,0 +1,8 @@+// $Id: data1.toc,v 1.1 2004/05/08 20:36:02 rocky Exp $+// Just a single MODE1 track.++CD_ROM++TRACK MODE1+SILENCE 0:59:74+
+ test/datafiles/upstream/data2.toc view
@@ -0,0 +1,13 @@+// $Id+// MODE1 track followed by an AUDIO track++CD_ROM++TRACK MODE1+FILE "isofs-m1.bin" 00:00:00 +ZERO 1:0:0++TRACK AUDIO+PREGAP 0:2:0+FILE "cdda.bin" 00:00:00 +
+ test/datafiles/upstream/data5.toc view
@@ -0,0 +1,13 @@+// $Id: data5.toc,v 1.2 2005/01/23 00:45:57 rocky Exp $+// XA disk +// ++CD_ROM_XA++TRACK MODE2_FORM2+FILE "isofs-m1.bin" 00:00:00 00:01:57++TRACK MODE2_FORM1+PREGAP 0:2:0+FILE "isofs-m1.bin" 00:20:71 00:00:10+
+ test/datafiles/upstream/data6.toc view
@@ -0,0 +1,8 @@+// $Id: data6.toc,v 1.2 2005/01/23 00:45:57 rocky Exp $+// MODE2 track+// ++CD_ROM++TRACK MODE2+FILE "isofs-m1.bin" 00:00:00 00:01:57
+ test/datafiles/upstream/data7.toc view
@@ -0,0 +1,13 @@+// $Id: data7.toc,v 1.2 2005/01/23 00:45:57 rocky Exp $+// Video CD+// ++CD_ROM_XA++TRACK MODE1 // ISO filesystem+FILE "isofs-m1.bin" 00:00:00 00:03:57++TRACK MODE2_FORM_MIX // XA track with form 1 and form 2 sectors+PREGAP 0:2:0+FILE "isofs-m1.bin" 00:20:71 00:00:00+
+ test/datafiles/upstream/isofs-m1.bin view

binary file changed (absent → 710304 bytes)

+ test/datafiles/upstream/isofs-m1.cue view
@@ -0,0 +1,4 @@+CATALOG 0000012101954
+FILE "ISOFS-M1.BIN" BINARY
+  TRACK 01 MODE1/2352
+    INDEX 01 00:00:00
+ test/datafiles/upstream/p1.bin view

binary file changed (absent → 710304 bytes)

+ test/datafiles/upstream/p1.cue view
@@ -0,0 +1,12 @@+TITLE "Join us now we have the software"
+CATALOG 0000010271955
+PERFORMER "Richard Stallman"
+FILE "BOING.BIN" BINARY
+  TRACK 01 AUDIO
+    FLAGS DCP
+    INDEX 00 00:00:00
+    INDEX 01 00:01:00
+  TRACK 02 AUDIO
+    FLAGS DCP
+    INDEX 00 00:02:00
+    INDEX 01 00:03:00
+ test/datafiles/upstream/p1.nrg view

binary file changed (absent → 1063470 bytes)

+ test/datafiles/upstream/t1.toc view
@@ -0,0 +1,5 @@+// simplest cue sheet++TRACK AUDIO+NO COPY // so that all CTL flags are 0+SILENCE 0:0:74  // frames are just under 75
+ test/datafiles/upstream/t10.toc view
@@ -0,0 +1,8 @@+// non default CTL flag of track 1 ++TRACK AUDIO+COPY+NO PRE_EMPHASIS+FOUR_CHANNEL_AUDIO+FILE "cdda.bin" 1:0:0+
+ test/datafiles/upstream/t2.toc view
@@ -0,0 +1,6 @@+// additional pre-gap for track 1++TRACK AUDIO+NO COPY       // so that all CTL flags are 0+FILE "cdda.bin" 0:59:0  // Seconds are just under 60+START 0:10:0  // 10 second pre-gap
+ test/datafiles/upstream/t3.toc view
@@ -0,0 +1,11 @@+// simplest cue sheet for two tracks++TRACK AUDIO+NO COPY       // so that all CTL flags are 0+FILE "cdda.bin" 180:0:0  // 180 for number of minutes is okay, although+                         // it is not for a second or a frame value.++TRACK AUDIO+NO COPY       // so that all CTL flags are 0+FILE "cdda.bin" 1:0:0+
+ test/datafiles/upstream/t4.toc view
@@ -0,0 +1,8 @@+// non default CTL flag of track 1 ++TRACK AUDIO+COPY+PRE_EMPHASIS+FOUR_CHANNEL_AUDIO+FILE "cdda.bin" 1:0:0+
+ test/datafiles/upstream/t5.toc view
@@ -0,0 +1,8 @@+// test catalog number++CATALOG "1234567890123"++TRACK AUDIO+NO COPY+FILE "cdda.bin" 1:0:0+
+ test/datafiles/upstream/t6.toc view
@@ -0,0 +1,7 @@+// test ISRC code+++TRACK AUDIO+NO COPY+ISRC "DEMUA9800001"+FILE "cdda.bin" 1:0:0
+ test/datafiles/upstream/t7.toc view
@@ -0,0 +1,12 @@+// check two tracks with pre-gap and ISRC+++TRACK AUDIO+NO COPY+FILE "cdda.bin" 1:0:0++TRACK AUDIO+NO COPY+ISRC "DEMUA9800001"+FILE "cdda.bin" 1:0:0+START 0:5:0   // pre-gap
+ test/datafiles/upstream/t8.toc view
@@ -0,0 +1,14 @@+// check index increments+++TRACK AUDIO+NO COPY+FILE "cdda.bin" 0:10:0+INDEX 1:0:0+INDEX 2:0:0+++TRACK AUDIO+NO COPY+FILE "cdda.bin" 0:10:0+START 0:5:0   // pre-gap
+ test/datafiles/upstream/t9.toc view
@@ -0,0 +1,31 @@+CD_DA+// check mulitple tracks+CATALOG "0724385356926"++TRACK AUDIO+ISRC "USEM39600078"+COPY+FILE "cdda.bin" 0:10:0+START 0:5:0++TRACK AUDIO+NO COPY+ISRC "USEM39600079"+FILE "cdda.bin" 0:10:0+START 0:2:0++TRACK AUDIO+COPY+FILE "cdda.bin" 0:10:0+START 0:1:30++TRACK AUDIO+NO COPY+START 0:0:0+FILE "cdda.bin" 0:10:0++TRACK AUDIO+ISRC "EDUMA9892346"+NO COPY+FILE "cdda.bin" 0:10:0+START 0:2:1
+ test/datafiles/upstream/vcd2.toc view
@@ -0,0 +1,22 @@+// Taken from one of Steve Schultz's VCD collection. +// The .bin and offsets have been changed and are wrong. +CD_ROM_XA+++// Track 1+TRACK MODE2_FORM_MIX+COPY+DATAFILE "cdda.bin" 00:00:00 // comment+++// Track 2+TRACK MODE2_FORM_MIX+COPY+DATAFILE "cdda.bin" #100 00:00:03 +++// Track 3+TRACK MODE2_FORM_MIX+COPY+DATAFILE "cdda.bin" #200 00:00:25 +