diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..e0b0428 --- /dev/null +++ b/.clang-format @@ -0,0 +1,22 @@ +BasedOnStyle: WebKit +ColumnLimit: 90 +AlwaysBreakTemplateDeclarations: Yes +AlignAfterOpenBracket: Align +AllowShortFunctionsOnASingleLine: Empty +BreakConstructorInitializers: BeforeColon +PackConstructorInitializers: Never +Cpp11BracedListStyle: True +SpaceBeforeCpp11BracedList: False +BreakBeforeBraces: Custom +BraceWrapping: + AfterFunction: False +AllowShortEnumsOnASingleLine: False +BreakStringLiterals: False +AlwaysBreakAfterReturnType: None +PenaltyReturnTypeOnItsOwnLine: 200 +ContinuationIndentWidth: 4 +IndentWidth: 2 +BreakBeforeBinaryOperators: None +IndentAccessModifiers: False +AccessModifierOffset: -2 +ReflowComments: false diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..301fc68 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,58 @@ +name: CI + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + gcc-linux: + runs-on: ubuntu-latest + container: + image: ghcr.io/ednolan/ubuntu24.10_gcc14.2.0 + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + - name: Run + run: | + ./ci.sh -DCMAKE_CXX_FLAGS='-fsanitize=address -fsanitize=undefined -fsanitize-undefined-trap-on-error -coverage' + - name: Paper + run: | + cmake --build ./build -t p2728 + - name: Coverage + run: | + lcov --directory ./build --capture --output-file ./build/coverage_all.info + lcov --remove ./build/coverage_all.info -o ./build/coverage.info '/usr/include/*' "$PWD/src/UtfView/tests/*" "$PWD/deps/*" + - name: Coveralls + uses: coverallsapp/github-action@master + with: + path-to-lcov: ${{runner.workspace}}/UtfView/build/coverage.info + github-token: ${{ secrets.GITHUB_TOKEN }} + clang-linux: + runs-on: ubuntu-latest + container: + image: ghcr.io/ednolan/ubuntu24.10_clang19.1.0rc3 + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + - name: Run + run: | + ./ci.sh -DCMAKE_CXX_FLAGS='-fsanitize=address -fsanitize=undefined -fsanitize-undefined-trap-on-error -stdlib=libc++' + msvc-windows: + runs-on: windows-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + - name: Run + shell: bash + run: | + ./ci.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..0da792a --- /dev/null +++ b/.gitmodules @@ -0,0 +1,12 @@ +[submodule "deps/stl_interfaces"] + path = deps/stl_interfaces + url = https://github.com/ednolan/stl_interfaces.git +[submodule "deps/assert"] + path = deps/assert + url = https://github.com/boostorg/assert.git +[submodule "deps/config"] + path = deps/config + url = https://github.com/boostorg/config.git +[submodule "deps/wg21"] + path = deps/wg21 + url = https://github.com/mpark/wg21.git diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..42fa7cb --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-3.0-only + +cmake_minimum_required(VERSION 3.27) +project(utfview CXX) + +if (BUILD_TESTING) + include(CTest) +endif() + +if (NOT TARGET boost_config) + add_subdirectory(deps/config) +endif() + +if (NOT TARGET boost_assert) + add_subdirectory(deps/assert) +endif() + +if (NOT TARGET boost_stl_interfaces) + add_definitions(-DBOOST_STL_INTERFACES_ENABLE_DEDUCED_THIS) + add_subdirectory(deps/stl_interfaces) +else() + message(FATAL_ERROR "Conflicting dependency: boost_stl_interfaces already exists, but we need our own fork") +endif() + +add_subdirectory(src/UtfView) + +add_subdirectory(paper) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + 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. + + + Copyright (C) + + 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 . + +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: + + Copyright (C) + 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 +. + + 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 +. diff --git a/P2728_unicode_1_transcoding.md b/P2728_unicode_1_transcoding.md deleted file mode 100644 index 2d53194..0000000 --- a/P2728_unicode_1_transcoding.md +++ /dev/null @@ -1,1873 +0,0 @@ ---- -title: "Unicode in the Library, Part 1: UTF Transcoding" -document: P2728R6 -date: 2023-07-11 -audience: - - SG-16 Unicode - - LEWG -author: - - name: Zach Laine - email: -toc: true -monofont: "DejaVu Sans Mono" - ---- - -# Changelog - -## Changes since R0 - -- When naming code points in interfaces, use `char32_t`. -- When naming code units in interfaces, use `charN_t`. -- Remove each eager algorithm, leaving in its corresponding view. -- Remove all the output iterators. -- Change template parameters to `utfN_view` to the types of the from-range, - instead of the types of the transcoding iterators used to implement the view. -- Remove all make-functions. -- Replace the misbegotten `as_utfN()` functions with the `as_utfN` view - adaptors that should have been there all along. -- Add missing `transcoding_error_handler` concept. -- Turn `unpack_iterator_and_sentinel` into a CPO. -- Lower the UTF iterator concepts from bidirectional to input. - -## Changes since R1 - -- Reintroduce the transcoding-from-a-buffer example. -- Generalize `null_sentinel_t` to a non-Unicode-specific facility. -- In utility functions that search for ill-formed encoding, take a range - argument instead of a pair of iterator arguments. -- Replace `utf{8,16,32}_view` with a single `utf_view`. - -## Changes since R2 - -- Add `noexcept` where appropriate. -- Remove non-essential constants and utility functions, and elaborate on the - usage of the ones that remain. -- Note differences from similar elements proposed in [@P1629R1]. -- Extend the examples slightly. -- Correct an error in the description of the view adaptors' semantics, and - provide several examples of their use. - -## Changes since R3 - -- Changed the definition of the `code_unit` concept, and added `as_charN_t` - adaptors. -- Removed the utility functions and Unicode-related constants, except - `replacement_character`. -- Changed the constraint on `utf_iterator` slightly. -- Change `null_sentinel_t` back to being Unicode-specific. - -## Changes since R4 - -- Replace `unpacking_owning_view` with `unpacking_view`, and use it to do - unpacking, rather than sometimes doing the unpacking in the adaptor. -- Ensure `const` and non-`const` overloads for `begin` and `end` in all views. -- Move `null_sentinel_t` to `std`, remove its `base` member function, and make - it useful for more than just pointers, based on SG-9 guidance. - -## Changes since R5 - -- Simplify the complicated constraint on the compariason operator for - `null_sentinel_t`. -- Introduce `ranges::project_view`, and inplement `charN_view`s in terms of - that. -- Convert the `utfN_view`s to aliases, rather than individual classes. - -# Motivation - -Unicode is important to many, many users in everyday software. It is not -exotic or weird. Well, it's weird, but it's not weird to see it used. C and -C++ are the only major production languages with essentially no support for -Unicode. - -Let's fix. - -To fix, first we start with the most basic representations of strings in -Unicode: UTF. You might get a UTF string from anywhere; on Windows you often -get them from the OS, in UTF-16. In web-adjacent applications, strings are -most commonly in UTF-8. In ASCII-only applications, everything is in UTF-8, -by its definition as a superset of ASCII. - -Often, an application needs to switch between UTFs: 8 -> 16, 32 -> 16, etc. -In SG-16 we've taken to calling such UTF-N -> UTF-M operations "transcoding". - -I'm proposing interfaces to do transcoding that meet certain design -requirements that I think are important; I hope you'll agree: - -- Ranges are the future. We should have range-friendly ways of doing - transcoding. This includes support for sentinels and lazy views. -- Iterators are the present. We should support generic programming, whether - it is done in terms of pointers, a particular iterator, or an iterator type - specified as a template parameter. -- A null-terminated string should not be treated as a special case. The - ubiquity of such strings means that they should be treated as first-class - strings. -- It is common to want to view the same text as code points and code units at - different times. It is therefore important that transcoding iterators have - a convenient way to access the underlying sequence of code units being - transcoded. -- Memory safety is important. Ensuring that the Unicode part of the standard - library is as memory safe as possible should be a priority. - -## A note about P1629 - -[@P1629R1] from JeanHeyd Meneide is a much more ambitious proposal that aims -to standardize a general-purpose text encoding conversion mechanism. This -proposal is not at odds with P1629; the two proposals have largely orthogonal -aims. This proposal only concerns itself with UTF interconversions, which is -all that is required for Unicode support. P1629 is concerned with those -conversions, plus a lot more. Accepting both proposals would not cause -problems; in fact, the APIs proposed here could be used to implement parts of -the P1629 design. - -There are some differences between the way that the transcode views and -iterators from [@P1629R1] work and the transcoding view and iterators from -this paper work. First, `std::text::transcode_view` has no direct support for -null-terminated strings. Second, it does not do the unpacking described in -this paper. Third, it is not printable and streamable. - -# The shortest Unicode primer imaginable - -There are multiple encoding types defined in Unicode: UTF-8, UTF-16, and -UTF-32. - -A *code unit* is the lowest-level datum-type in your Unicode data. Examples -are a `char8_t` in UTF-8 and a `char32_t` in UTF-32. - -A *code point* is a 32-bit integral value that represents a single Unicode -value. Examples are U+0041 "A" "LATIN CAPITAL LETTER A" and U+0308 "ยจ" -"COMBINING DIAERESIS". - -A code point may be consist of multiple code units. For instance, 3 UTF-8 -code units in sequence may encode a particular code point. - -# A few examples - -## Case 1: Adapt to an existing range interface taking a different UTF - -In this case, we have a generic range interface to transcode into, so we use a -transcoding view. - -```cpp -// A generic function that accepts sequences of UTF-16. -template -void process_input(R r); -void process_input_again(std::uc::utf_view> r); - -std::u8string input = get_utf8_input(); -auto input_utf16 = input | std::uc::as_utf16; - -process_input(input_utf16); -process_input_again(input_utf16); -``` - -## Case 2: Adapt to an existing iterator interface taking a different UTF - -This time, we have a generic iterator interface we want to transcode into, so -we want to use the transcoding iterators. - -```cpp -// A generic function that accepts sequences of UTF-16. -template -void process_input(I first, I last); - -std::u8string input = get_utf8_input(); - -process_input( - std::uc::utf_iterator( - input.begin(), input.begin(), input.end()), - std::uc::utf_iterator( - input.begin(), input.end(), input.end())); - -// Even more conveniently: -auto const utf16_view = input | std::uc::as_utf16; -process_input(utf16_view.begin(), utf16.end()); -``` - -## Case 3: Adapt a range of non-character-type values - -Let's say that we want to take code points that we got from ICU, and transcode -them to UTF-8. The problem is that ICU's code point type is `int`. Since -`int` is not a character type, it's not deduced by `as_utf8` to be UTF-32 -data. - -```cpp -// A generic function that accepts sequences of UTF-16. -template -void process_input(R r); - -std::vector input = get_icu_code_points(); -// This is ill-formed without the as_char32_t adaptation. -auto input_utf8 = input | std::uc::as_char32_t | std::uc::as_utf8; - -process_input(input_utf8); -``` - -## Case 4: Print the results of transcoding - -Text processing is pretty useless without I/O. All of the Unicode algorithms -operate on code points, and so the output of any of those algorithms will be -in code points/UTF-32. It should be easy to print the results to a -`std::ostream`, to a `std::wostream` on Windows, or using `std::format` and -`std::print`. `utf_view` is therefore printable and streamable. - -```c++ -void double_print(char32_t const * str) -{ - auto utf8 = str | std::uc::as_utf8; - std::print("{}", utf8); - std::cerr << utf8; -} -``` - -# Proposed design - -## Dependencies - -This proposal depends on the existence of -[P2727](https://isocpp.org/files/papers/P2727R0.html) -"std::iterator_interface". - -## Add concepts that describe parameters to transcoding APIs - -The macro `CODE_UNIT_CONCEPT_OPTION_2` is used below to indicate the two -options for how to define `code_unit`. See below for a description of the two -options. - -```cpp -namespace std::uc { - - enum class format { utf8 = 1, utf16 = 2, utf32 = 4 }; - - inline constexpr format @*wchar-t-format*@ = @*see below*@; // @*exposition only*@ - - template - concept code_unit = (same_as && F == format::utf8) || - (same_as && F == format::utf16) || - (same_as && F == format::utf32) -#if CODE_UNIT_CONCEPT_OPTION_2 - || (same_as && F == format::utf8) - || (same_as && F == @*wchar-t-format*@) -#endif - ; - - template - concept utf8_code_unit = code_unit; - - template - concept utf16_code_unit = code_unit; - - template - concept utf32_code_unit = code_unit; - - template - concept utf_code_unit = utf8_code_unit || utf16_code_unit || utf32_code_unit; - - template - concept code_unit_iter = - input_iterator && code_unit, F>; - template - concept code_unit_pointer = - is_pointer_v && code_unit, F>; - template - concept code_unit_range = ranges::input_range && - code_unit, F>; - - template - concept utf8_iter = code_unit_iter; - template - concept utf8_pointer = code_unit_pointer; - template - concept utf8_range = code_unit_range; - - template - concept utf16_iter = code_unit_iter; - template - concept utf16_pointer = code_unit_pointer; - template - concept utf16_range = code_unit_range; - - template - concept utf32_iter = code_unit_iter; - template - concept utf32_pointer = code_unit_pointer; - template - concept utf32_range = code_unit_range; - - template - concept utf_iter = utf8_iter || utf16_iter || utf32_iter; - template - concept utf_pointer = utf8_pointer || utf16_pointer || utf32_pointer; - template - concept utf_range = utf8_range || utf16_range || utf32_range; - - template - concept utf_range_like = - utf_range> || utf_pointer>; - - template - concept utf8_input_range_like = - (ranges::input_range> && utf8_code_unit>) || - utf8_pointer>; - template - concept utf16_input_range_like = - (ranges::input_range> && utf16_code_unit>) || - utf16_pointer>; - template - concept utf32_input_range_like = - (ranges::input_range> && utf32_code_unit>) || - utf32_pointer>; - - template - concept utf_input_range_like = - utf8_input_range_like || utf16_input_range_like || utf32_input_range_like; - - template - concept transcoding_error_handler = - requires (T t, string_view msg) { { t(msg) } -> same_as; }; - -} -``` - -There are two options for how the `code_unit` concept is defined. - -### Code unit option 1 - -This is represented by `CODE_UNIT_CONCEPT_OPTION_2 == 0` in the code above. -In this option, a code unit must be one of `char8_t`, `char16_t`, and -`char32_t`. - -### Code unit option 2 - -This is represented by `CODE_UNIT_CONCEPT_OPTION_2 == 1` in the code above. -In this option, a code unit must be a character type. This includes the -`charN_t` character types from Option 1, plus `char` and `wchar_t`. The value -of `@*wchar-t-format*@` is implementation defined, but must be -`uc::format::utf16` or `uc::format::utf32`. - -### The impact of options 1 and 2 - -Here are some examples of the differences between Options 1 and 2. The -`as_utfN` and `as_charN` adaptors are discussed later in this paper. - -The `as_utfN` adaptors produce `utfN_view`s, which do transcoding. - -The `as_utfN` adaptors produce `charN_view`s that are each very similar to a -`transform_view` that casts each element of the adapted range to a `charN_t` -value. A `charN_view` differs from the equivalent transform in that it may be -a borrowed range, and that the `utfN_view` views know about the `charN_view`s, -and can optimize away the work that would be done by the `charN_view`. This -turns `charN_view` into a no-op when nested within a `utfN_view`. - -Note the use of `charN_t` below with `std::wstring`. That's there because -whether you write `as_char16_t` or `as_char32_t` is implementation-dependent. - -::: tonytable - -### Option 1 -```c++ -using namespace std::uc; - -auto v1 = u8"text" | as_utf32; // Ok. -auto v2 = u"text" | as_utf8; // Ok. -auto v3 = U"text" | as_utf16; // Ok. - -auto v4 = std::u8string(u8"text") | as_utf32; // Ok. -auto v5 = std::u16string(u"text") | as_utf8; // Ok. -auto v6 = std::u32string(U"text") | as_utf16; // Ok. - -auto v7 = std::string | as_utf32; // Error; ill-formed. -auto v8 = std::wstring | as_utf8; // Error; ill-formed. - -auto v9 = std::string | as_char8_t | as_utf32; // Ok. -auto v10 = std::wstring | as_charN_t | as_utf8; // Ok. -``` - -### Option 2 -```c++ -using namespace std::uc; - -auto v1 = u8"text" | as_utf32; // Ok. -auto v2 = u"text" | as_utf8; // Ok. -auto v3 = U"text" | as_utf16; // Ok. - -auto v4 = std::u8string(u8"text") | as_utf32; // Ok. -auto v5 = std::u16string(u"text") | as_utf8; // Ok. -auto v6 = std::u32string(U"text") | as_utf16; // Ok. - -auto v7 = std::string | as_utf32; // Ok. -auto v8 = std::wstring | as_utf8; // Ok. - -auto v9 = std::string | as_char8_t | as_utf32; // Ok. -auto v10 = std::wstring | as_charN_t | as_utf8; // Ok. -``` - -::: - -In short, Option 1 forces you to write "`| as_char8_t`" everywhere you want to -use a `std::string` with the interfaces proposed in this paper. - -Option 1 is supported by most of SG-16. Here is the relevant SG-16 poll: - -*UTF transcoding interfaces provided by the C++ standard library should operate -on charN_t types, with support for other types provided by adapters, possibly -with a special case for char and wchar_t when their associated literal -encodings are UTF.* - -+----+---+---+---+----+ -| SF | F | N | A | SA | -+====+===+===+===+====+ -| 6 |1 |0 |0 | 1 | -+----+---+---+---+----+ - -(I have chosen to ignore the "possibly with a special case for char and -wchar_t when their associated literal encodings are UTF" part. Making the -evaluation of a concept change based on the literal encoding seems like a -flaky move to me; the literal encoding can change TU to TU.) - -The feeling in SG-16 is that the `charN_t` types are designed to represent UTF -encodings, and `char` is not. A `char const *` string could be in any one of -dozens (hundreds?) of encodings. The addition of "`| as_char8_t`" to adapt -ranges of `char` is meant to act as a lexical indicator of user intent. - -I believe this decision is a mistake. I would very, very much *not* like to -standardize Unicode interfaces that do not easily interoperate with -`std::string`. This is my reasoning: - -First, `char` and `char8_t` maintain exactly the same set of invariants -- the -empty set. Note that this is true even for string literals. The encoding of -`u8"text"` is not necessarily UTF-8! It depends on the flags you pass to your -compiler. Those flags are allowed to vary TU by TU. I have been bitten by -the "`u8` does not necessarily mean UTF-8" oddity of MSVC before. - -Second, "`| as_char8_t`" is a no-op when used with `utfN_view`/`utf_view`. It -does not actually do anything to help you get your program's text into UTF-8 -encoding, nor to detect that you have non-UTF-8 encoded text in your program. - -Third, people use `std::string` a lot. They use `char` string literals a lot. -They use `std::u8string` and `char8_t` string literals almost not at all. -Using Github Code Search, I found 15.3M references to `std::string` and 6.7k -references to `std::u8string`. Even were everyone to switch from -`std::string` to `std::u8string` today, we should still have to deal with lots -and lots of `char const *` strings for C API compatibility. - -Finally, whether a given range of code units is properly UTF encoded may be a -precondition of a given API that the user writes, but it is not a precondition -of *any* API proposed in this paper, nor is it a precondition of any API I'm -proposing in the papers that will follow this one. - -In short, I think `"text" | std::uc::as_utf32` should "just work". Making -users write `"text" | std::uc::as_char8_t | std::uc::as_utf32`, when that does -not increase correctness or efficiency -- and produces no different object -code -- seems wrongheaded to me. Users that want the extra explicitness can -still write the longer version under both options. Users that do not want -this explicitness should not be forced to write it. - -## Add a null-terminated sequence sentinel - -```cpp -namespace std { - struct null_sentinel_t { - template - requires default_initializable> && - equality_comparable, iter_value_t> - friend constexpr auto operator==(I it, null_sentinel_t) { return *it == iter_value_t{}; } - }; - - inline constexpr null_sentinel_t null_sentinel; -} -``` - -This sentinel type matches any iterator position `it` at which `*it` is equal -to a default-constructed object of type `iter_value_t`. This works for -null-terminated strings, but can also serve as the sentinel for any forward -range terminated by a default-constructed value. - -Because this type is potentially useful for lots of ranges unrelated to -Unicode or text, it is in the `std` namespace, not `std::uc`. - -If you're wondering why `@*ITER_CONCEPT*@` is used instead of directly -requiring `forward_iterator`, it's because the latter causes recursion in a -check of `equality_comparable` within `forward_iterator`. - - -## Add the transcoding iterator template - -I'm using [P2727](https://isocpp.org/files/papers/P2727R0.html)'s -`iterator_interface` here for simplicity. - -First, the synopsis: - -```c++ -namespace std::uc { - inline constexpr char32_t replacement_character = 0xfffd; - - struct use_replacement_character { - constexpr char32_t operator()(string_view error_msg) const noexcept; - }; - - template - constexpr auto @*format-to-type*@() { // @*exposition only*@ - if constexpr (Format == format::utf8) { - return char8_t{}; - } else if constexpr (Format == format::utf16) { - return char16_t{}; - } else { - return char32_t{}; - } - } - - template - using @*format-to-type-t*@ = decltype(@*format-to-type*@()); // @*exposition only*@ - - template< - format FromFormat, - format ToFormat, - input_iterator I, - sentinel_for S = I, - transcoding_error_handler ErrorHandler = use_replacement_character> - requires convertible_to, @*format-to-type-t*@> - class utf_iterator; -} -``` - -Then the definitions: - -```c++ -namespace std::uc { - template - constexpr auto @*bidirectional-at-most*@() { // @*exposition only*@ - if constexpr (bidirectional_iterator) { - return bidirectional_iterator_tag{}; - } else if constexpr (forward_iterator) { - return forward_iterator_tag{}; - } else if constexpr (input_iterator) { - return input_iterator_tag{}; - } - } - - template - using @*bidirectional-at-most-t*@ = decltype(@*bidirectional-at-most*@()); // @*exposition only*@ - - template> - struct @*first-and-curr*@ { // @*exposition only*@ - @*first-and-curr*@() = default; - @*first-and-curr*@(I curr) : curr{curr} {} - template - requires convertible_to - @*first-and-curr*@(const @*first-and-curr*@& other) : curr{other.curr} {} - - I curr; - }; - template - struct @*first-and-curr*@ { // @*exposition only*@ - @*first-and-curr*@() = default; - @*first-and-curr*@(I first, I curr) : first{first}, curr{curr} {} - template - requires convertible_to - @*first-and-curr*@(const @*first-and-curr*@& other) : first{other.first}, curr{other.curr} {} - - I first; - I curr; - }; - - struct use_replacement_character { - constexpr char32_t operator()(string_view) const noexcept { return replacement_character; } - }; - - template< - format FromFormat, - format ToFormat, - input_iterator I, - sentinel_for S, - transcoding_error_handler ErrorHandler> - requires convertible_to, @*format-to-type-t*@> - class utf_iterator : public iterator_interface< - @*bidirectional-at-most*@, - @*format-to-type-t*@, - @*format-to-type-t*@> { - public: - using value_type = @*format-to-type-t*@; - - constexpr utf_iterator() = default; - - constexpr utf_iterator(I first, I it, S last) requires bidirectional_iterator - : first_and_curr_{first, it}, last_(last) { - if (curr() != last_) - read(); - } - constexpr utf_iterator(I it, S last) requires (!bidirectional_iterator) - : first_and_curr_{it}, last_(last) { - if (curr() != last_) - read(); - } - - template - requires convertible_to && convertible_to - constexpr utf_iterator(const utf_iterator& other) : - buf_(other.buf_), - first_and_curr_(other.first_and_curr_), - buf_index_(other.buf_index_), - buf_last_(other.buf_last_), - last_(other.last_) - {} - - constexpr I begin() const requires bidirectional_iterator { return first(); } - constexpr S end() const { return last_; } - - constexpr I base() const requires forward_iterator { return curr(); } - - constexpr value_type operator*() const { return buf_[buf_index_]; } - - constexpr utf_iterator& operator++() { - if (buf_index_ + 1 == buf_last_ && curr() != last_) { - if constexpr (forward_iterator) { - advance(curr(), to_increment_); - } - if (curr() == last_) - buf_index_ = 0; - else - read(); - } else if (buf_index_ + 1 <= buf_last_) { - ++buf_index_; - } - return *this; - } - - constexpr utf_iterator& operator--() requires bidirectional_iterator { - if (!buf_index_ && curr() != first()) - read_reverse(); - else if (buf_index_) - --buf_index_; - return *this; - } - - friend constexpr bool operator==(utf_iterator lhs, utf_iterator rhs) - requires forward_iterator || requires (I i) { i != i; } { - if constexpr (forward_iterator) { - return lhs.curr() == rhs.curr() && lhs.buf_index_ == rhs.buf_index_; - } else { - if (lhs.curr() != rhs.curr()) - return false; - - if (lhs.buf_index_ == rhs.buf_index_ && - lhs.buf_last_ == rhs.buf_last_) { - return true; - } - - return lhs.buf_index_ == lhs.buf_last_ && - rhs.buf_index_ == rhs.buf_last_; - } - } - - friend constexpr bool operator==(utf_iterator lhs, S rhs) - if constexpr (forward_iterator) { - return lhs.curr() == rhs; - } else { - return lhs.curr() == rhs && lhs.buf_index_ == lhs.buf_last_; - } - } - - using base_type = // @*exposition only*@ - iterator_interface<@*bidirectional-at-most-t*@, value_type, value_type>; - using base_type::operator++; - using base_type::operator--; - - private: - constexpr void read(); // @*exposition only*@ - constexpr void read_reverse(); // @*exposition only*@ - - constexpr I first() const requires bidirectional_iterator // @*exposition only*@ - { return first_and_curr_.first; } - constexpr I& curr() { return first_and_curr_.curr; } // @*exposition only*@ - constexpr I curr() const { return first_and_curr_.curr; } // @*exposition only*@ - - array(ToFormat)> buf_; // @*exposition only*@ - - @*first-and-curr*@ first_and_curr_; // @*exposition only*@ - - uint8_t buf_index_ = 0; // @*exposition only*@ - uint8_t buf_last_ = 0; // @*exposition only*@ - uint8_t to_increment_ = 0; // @*exposition only*@ - - [[no_unique_address]] S last_; // @*exposition only*@ - - template< - format FromFormat2, - format ToFormat2, - code_unit_iter I2, - sentinel_for S2, - transcoding_error_handler ErrorHandler2> - friend class utf_iterator; - }; -} -``` - -`use_replacement_character` is an error handler type that can be used with -`utf_iterator`. It accepts a `string_view` error message, and returns the -replacement character. The user can substitute their own type here, which may -throw, abort, log, etc. - -`utf_iterator` is an iterator that transcodes from UTF-N to UTF-M, where N and -M are each one of 8, 16, or 32. N may equal M. UTF-N to UTF-N operation -invokes the error handler as appropriate, but does not change format. -`utf_iterator` does its work by adapting an underlying range of code units. -Each code point `c` to be transcoded is decoded from `FromFormat` in the -underlying range. `c` is then encoded to `ToFormat` into an internal buffer. -If ill-formed UTF is encountered during the decoding step, `c` is whatever -invoking the error handler returns; using the default error handler, this is -`replacement_character`. - -`utf_iterator` maintains certain invariants; the invariants differ based on -whether `utf_iterator` is an input iterator. - -For input iterators the invariant is: if `*this` is at the end of the range -being adapted, then `curr()` == `last_`; otherwise, the position of `curr()` -is always at the end of the current code point `c` within the range being -adapted, and `buf_` contains the code units in `ToFormat` that comprise `c`. - -For forward and bidirectional iterators, the invariant is: if `*this` is at -the end of the range being adapted, then `curr()` == `last_`; otherwise, the -position of `curr()` is always at the beginning of the current code point `c` -within the range being adapted, and `buf_` contains the code units in -`ToFormat` that comprise `c`. - -When ill-formed UTF is encountered in the range being adapted, `utf_iterator` -calls `ErrorHandler{}.operator()` to produce a character to represent the -ill-formed sequence. The number and position of error handler invocations -within the transcoded output is the same, whether the range being adapted is -traversed forward or backward. The number and position of the error handler -invocations should use the "substitution of maximal subparts" approach -described in Chapter 3 of the Unicode standard. - -Besides the constructors, no member function of `utf_iterator` has -preconditions. As long as a `utf_iterator` `i` is constructed with proper -arguments, all subsequent operations on `i` are memory safe. This includes -decrementing a `utf_iterator` at the beginning of the range being adapted, and -incrementing or dereferencing a `utf_iterator` at the end of the range being -adapted. - -If `FromFormat` and `ToFormat` are not each one of `format::utf8`, -`format::utf16`, or `format::utf32`, the program is ill-formed. - -If `input_iterator` is `true`, `noexcept(ErrorHandler{}("")))` must be -`true` as well; otherwise, the program is ill-formed. - -The exposition-only member function `read` decodes the code point `c` as -`FromFormat` starting from position `curr()` in the range being adapted (`c` -may be `replacement_character`); sets `to_increment_` to the number of code -units read while decoding `c`; encodes `c` as `ToFormat` into `buf_`; sets -`buf_index_` to `0`; and sets `buf_last_` to the number of code units encoded -into `buf_`. If `forward_iterator` is `true`, `curr()` is set to the -position it had before `read` was called. If an exception is thrown during a -call to `read`, the call to `read` has no effect. - -The exposition-only member function `read_reverse` decodes the code point `c` -as `FromFormat` ending at position `curr()` in the range being adapted (`c` -may be `replacement_character`); sets `to_increment_` to the number of code -units read while decoding `c`; encodes `c` as `ToFormat` into `buf_`; sets -`buf_last_` to the number of code units encoded into `buf_`; and sets -`buf_index_` to `buf_last_ - 1`. If an exception is thrown during a call to -`read_reverse`, the call to `read_reverse` has no effect. - -### Why `utf_iterator` is constrained the way it is - -The template parameter `I` to `utf_iterator` is not constrained with -`code_unit_iter` as it was in earlier revisions of this paper. -Instead, `I` must be an `input_iterator` whose value type is convertible to -`@*format-to-type-t*@`. This allows two uses of `utf_iterator` -that the previous constraint would not. - -First, `utf_iterator` can be used to adapt an iterator whose value type is -some non-character type. This is useful in general, since lots of existing -Unicode-aware user code uses `uint32_t` for UTF-32, or `short` for UTF-16 or -whatever. It is useful in particular because ICU uses `int` for its -UTF-32/code point type. - -Second, because of the first point, adaptations of ranges of non-character -types can be made more efficient. Consider: - -```c++ -std::vector code_points_from_icu = /* ... */; -auto v = code_points_from_icu | std::uc::as_char32_t | std::uc::as_utf8; -auto first = v.begin(); -``` - -The type of `first` is: - -```c++ -std::uc::utf_iterator::iterator> -``` - -That is, the adapting iterator that `as_char32_t` uses is gone. This makes -using `as_char32_t` more efficient, when used in conjunction with `as_utfN`. -If `utf_iterator`'s `I` were required to be a `utf_iter`, this optimization -would not work. - -### Why `utf_iterator` is not a nested type within `utf_view` - -Most users will use views most of the time. However, it can be useful to use -iterators some of the time. For example, say I wanted to track some -user-visible cursor within some bit of text. If I wanted to represent that -cursor independently from the view within which it is found, it can be awkward -to do so without an independent iterator template. - -```c++ -// This is the easy case. We have the View right there, and can use -// ranges::iterator_t to get its iterator type. - -template -struct my_state_type -{ - View all_text_; - std::ranges::iterator_t> current_position_; - // other state ... -}; - -// This one, not so much. Since we don't have the View type, we have to make -// the type of current_position_ a template parameter, even if there's only one -// type ever in use for a given view. - -template -struct my_other_state_type -{ - Iterator current_position_; - // other state ... -}; -``` - -Using `utf_iterator` allows us to write more specific code. Sometimes, -generic code is more desirable; sometimes nongeneric code is more desirable. - -```c++ -struct my_other_state_type -{ - std::uc::utf_iterator current_position_; - // other state ... -}; -``` - -Further, `utf_iterator` has configurability options that do not work for -`utfN_view`, like the `ErrorHandler` template parameter. This will not be -used often, but some users will want it sometimes. I don't think such -alternate uses are going to be common enough to justify complicating -`utfN_view`; those uses belong in a lower-level interface like `utf_iterator`. - -### Optional: Add aliases for common `utf_iterator` specializations - -```c++ -namespace std::uc { - template< - utf8_iter I, - std::sentinel_for S = I, - transcoding_error_handler ErrorHandler = use_replacement_character> - using utf_8_to_16_iterator = - utf_iterator; - template< - utf16_iter I, - std::sentinel_for S = I, - transcoding_error_handler ErrorHandler = use_replacement_character> - using utf_16_to_8_iterator = - utf_iterator; - - template< - utf8_iter I, - std::sentinel_for S = I, - transcoding_error_handler ErrorHandler = use_replacement_character> - using utf_8_to_32_iterator = - utf_iterator; - template< - utf32_iter I, - std::sentinel_for S = I, - transcoding_error_handler ErrorHandler = use_replacement_character> - using utf_32_to_8_iterator = - utf_iterator; - - template< - utf16_iter I, - std::sentinel_for S = I, - transcoding_error_handler ErrorHandler = use_replacement_character> - using utf_16_to_32_iterator = - utf_iterator; - template< - utf32_iter I, - std::sentinel_for S = I, - transcoding_error_handler ErrorHandler = use_replacement_character> - using utf_32_to_16_iterator = - utf_iterator; -} -``` - -These aliases make it easier to spell `utf_iterator`s. Consider -`utf_8_to_32_iterator` versus `utf_iterator`. More importantly, they allow CTAD to work, as -in `utf_8_to_32_iterator(first, it, last)`. These aliases are completely -optional, of course. Let us poll. - -### Add `unpack_iterator_and_sentinel` CPO for iterator "unpacking" - -```cpp -struct no_op_repacker { - template T operator()(T x) const { return x; } -}; - -template S, class Repack> -struct unpack_result { - static constexpr format format_tag = FormatTag; - - I first; - [[no_unique_address]] S last; - [[no_unique_address]] Repack repack; -}; - -// CPO equivalent to: -template S, class Repack = no_op_repacker> - constexpr auto unpack_iterator_and_sentinel(I first, S last, Repack repack = Repack()); -``` - -Any `utf_iterator` `ti` contains two iterators and a sentinel. If one were to -adapt `ti` in another transcoding iterator `ti2`, one quickly encounters a -problem -- since for example `utf_iterator>` would be the size of -9 pointers! Further, such an iterator would do a UTF-8 to UTF-16 to UTF-32 -conversion, when it could have done a direct UTF-8 to UTF-32 conversion -instead. - -One would obviously never write a type like the monstrosity above. However, -it is quite possible to accidentally construct one in generic code. Consider: - -```c++ -using namespace std::uc; - -template -void f(Iter it, null_sentinel_t) { -#if _MSC_VER - // On Windows, do something with 'it' that requires UTF-16. - utf_iterator it16; - windows_function(it16, null_sentinel); -#endif - - // ... etc. -} - -int main(int argc, char const * argv[]) { - utf_iterator it(argv[1], null_sentinel); - - f(it, null_sentinel); - - // ... etc. -} -``` - -This example is a bit contrived, since users will not create iterators -directly like this very often. Users are much more likely to use the -`utfN_view` views and `as_utfN` view adaptors being proposed below. The view -adaptors are defined in such a way that they avoid this problem altogether. -They do this by unpacking the view they are adapting before adapting it. For -instance: - -```cpp -std::u8string str = u8"some text"; - -auto utf16_str = str | std::uc::as_utf16; - -static_assert(std::same_as< - decltype(utf16_str.begin()), - std::uc::utf_iterator ->); - -auto utf32_str = utf16_str | std::uc::as_utf32; - -// Poof! The utf_iterator ->); -``` - -The unpacking logic is used in the view adaptors, as shown above. This allows -you to write `r | std::uc::as_utf32` in a generic context, without caring -whether `r` is a range of UTF-8, UTF-16, or UTF-32. You also do not need to -care about whether `r` is a common range or not. You also can ignore whether -`r` is comprised of raw pointers, some other kind of iterator, or transcoding -iterators. - -This becomes especially useful in the APIs proposed in later papers that -depend on this paper. In particular, APIs in subsequent papers accept any -UTF-N iterator, and then transcode internally to UTF-32. However, this -creates a minor problem for some algorithms. Consider this algorithm (not -proposed) as an example. - -```c++ -template S, output_iterator O> - requires (utf8_code_unit> || utf16_code_unit>) -transcode_result transcode_to_utf32(I first, S last, O out); -``` - -Such a transcoding algorithm is pretty similar to `std::ranges::copy`, in that -you should return both the output iterator *and* the final position of the -input iterator (`transcode_result` is an alias for `in_out_result`). For such -interfaces, it can be difficult in the general case to form an iterator of -type `I` to return to the user: - -```c++ -template S, output_iterator O> - requires (utf8_code_unit> || utf16_code_unit>) -transcode_result transcode_to_utf32(I first, S last, O out) { - // Get the input as UTF-32. This may involve unpacking, so possibly decltype(r.begin()) != I. - auto r = ranges::subrange(first, last) | uc::as_utf32; - - // Do transcoding. - auto copy_result = ranges::copy(r, out); - - // Return an in_out_result. - return result{/* ??? */, copy_result.out}; -} -``` - -What should we write for `/* ??? */`? That is, how do we get back from the -UTF-32 iterator `r.begin()` to an `I` iterator? It's harder than it first -seems; consider the case where `I` is -`std::uc::utf_16_to_32_iterator>`. -The solution is for the unpacking algorithm to remember the structure of -whatever iterator it unpacks, and then rebuild the structure when returning -the result. To demonstrate, here is the implementation of -`transcode_to_utf32` from Boost.Text: - -```c++ -template S, std::output_iterator O> - requires (utf8_code_unit> || utf16_code_unit>) -transcode_result transcode_to_utf32(I first, S last, O out) -{ - auto const r = boost::text::unpack_iterator_and_sentinel(first, last); - auto unpacked = detail::transcode_to_32( - detail::tag_t, r.first, r.last, -1, out); - return {r.repack(unpacked.in), unpacked.out}; -} -``` - -Note the call to `r.repack`. This is an invocable created by the unpacking -process itself. - -If this all sounds way too complicated, it's not bad at all. Here's the -unpacking/repacking implementation from Boost.Text: -[unpack.hpp](https://github.com/tzlaine/text/blob/develop/include/boost/text/unpack.hpp). - -`unpack_iterator_and_sentinel` is a CPO. It is intended to work with UDTs -that provide their own unpacking implementation. It returns an -`unpack_result`. - -In telecon review, some concerns were voiced about the name -`uc::unpack_iterator_and_sentinel`. Some people felt that the name should -include some mention of "UTF" or "transcoding" or "Unicode". I think that -it's fine as-is, since it's in namesapce `std::uc`, but a poll on renaming -might be in order. I suggest `uc::unpack_utf_iterator_and_sentinel` as a -possible alternative. - -### Why input iterators are not unpackable - -Input iterators are messed up. They barely resemble the other iterators. For -one thing, they are single-pass. This means that when a `utf_iterator` -adapting an input iterator reads the next code point from the range it is -adapting, it must leave the iterator at a location that is just after the -current code point. It has no choice, since it cannot backtrack. - -It is possible to unpack an input iterator in an entirely different way than -other iterators. The unpack operation for input iterators could be to produce -the underlying code unit iterator (the adapted input iterator itself), *plus* -the current code point that the input iterator was just used to read. - -However, this is not very much help. Consider a case in which we need to -unpack a UTF-8 to UTF-32 transcoding iterator so we can form a UTF-8 to UTF-16 -iterator instead. The unpack operation will produce an unpacked input -transcoding iterator -- the moral equivalent of `std::pair`. - -What can you do with this? Well, you can try to construct a -`utf_iterator` from it. That would mean -adding a constructor that takes an input iterator and a `char32_t`. This -would also mean that any user transcoding iterator types that are usable with -the `unpack_iterator_and_sentinel` CPO would also need to unpack their input -iterator into an iterator/code point pair, and that those user types would -also need to add this odd constructor. - -This is all weird. It's also a pretty small use case. People don't use input -iterators that often. Since this can always be added later, it is not being -proposed right now. - -## Add `project_view` - -This template is a `std::ranges` view and adaptor that makes the -implementation of the code unit views and adaptors nearly trivial. It is -being added based on input from SG-9. No one in the SG-9 telecon could think -of a name everyone liked; suggestions are welcome. - -```c++ -namespace std::ranges { - template - requires view && - regular_invocable> && - @*can-reference*@>> - class project_view : public view_interface> - { - V @*base_*@ = V(); // @*exposition only*@ - - template - class @*iterator*@; // @*exposition only*@ - template - class @*sentinel*@; // @*exposition only*@ - - public: - constexpr project_view() requires default_initializable = default; - constexpr explicit project_view(V base) : @*base_*@(std::move(base)) {} - - constexpr V& base() & { return @*base_*@; } - constexpr const V& base() const& { return @*base_*@; } - constexpr V base() && { return std::move(@*base_*@); } - - constexpr @*iterator*@ begin() { return @*iterator*@{ranges::begin(@*base_*@)}; } - constexpr @*iterator*@ begin() const requires range - { return @*iterator*@{ranges::begin(@*base_*@)}; } - - constexpr @*sentinel*@ end() { return @*sentinel*@{ranges::end(@*base_*@)}; } - constexpr @*iterator*@ end() requires common_range { return @*iterator*@{ranges::end(@*base_*@)}; } - constexpr @*sentinel*@ end() const requires range { return @*sentinel*@{ranges::end(@*base_*@)}; } - constexpr @*iterator*@ end() const requires common_range - { return @*iterator*@{ranges::end(@*base_*@)}; } - - constexpr auto size() requires sized_range { return ranges::size(@*base_*@); } - constexpr auto size() const requires sized_range { return ranges::size(@*base_*@); } - }; - - template - requires view && - regular_invocable> && - @*can-reference*@>> - template - class project_view::@*iterator*@ - : public std::proxy_iterator_interface< - iterator_to_tag_t>>, - invoke_result_t>> - { - public: - using reference_type = invoke_result_t>; - - private: - using @*iterator_type*@ = iterator_t<@*maybe-const*@>; // @*exposition only*@ - - friend std::iterator_interface_access; - @*iterator_type*@ & base_reference() noexcept { return @*it_*@; } // @*exposition only*@ - @*iterator_type*@ base_reference() const { return @*it_*@; } // @*exposition only*@ - - @*iterator_type*@ @*it_*@ = @*iterator_type*@(); // @*exposition only*@ - - friend project_view::@*sentinel*@; - - public: - constexpr @*iterator*@() = default; - constexpr @*iterator*@(@*iterator_type*@ it) : @*it_*@(std::move(it)) {} - - constexpr reference_type operator*() const { return F(*@*it_*@); } - }; - - template - requires view && - regular_invocable> && - @*can-reference*@>> - template - class project_view::@*sentinel*@ - { - using @*Base*@ = @*maybe-const*@; // @*exposition only*@ - using @*sentinel_type*@ = sentinel_t<@*Base*@>; // @*exposition only*@ - - @*sentinel_type*@ @*end_*@ = @*sentinel_type*@(); // @*exposition only*@ - - public: - constexpr @*sentinel*@() = default; - constexpr explicit @*sentinel*@(@*sentinel_type*@ end) : @*end_*@(std::move(end)) {} - constexpr @*sentinel*@(@*sentinel*@ i) requires Const - && convertible_to, sentinel_t<@*Base*@>>; - - constexpr @*sentinel_type*@ base() const { return @*end_*@; } - - template - requires sentinel_for<@*sentinel_type*@, iterator_t<@*maybe-const*@>> - friend constexpr bool operator==(const @*iterator*@ & x, const @*sentinel*@ & y) - { return x.@*it_*@ == y.@*end_*@; } - - template - requires sized_sentinel_for<@*sentinel_type*@, iterator_t<@*maybe-const*@>> - friend constexpr range_difference_t<@*maybe-const*@> - operator-(const @*iterator*@ & x, const @*sentinel*@ & y) - { return x.@*it_*@ - y.@*end_*@; } - - template - requires sized_sentinel_for<@*sentinel_type*@, iterator_t<@*maybe-const*@>> - friend constexpr range_difference_t<@*maybe-const*@> - operator-(const @*sentinel*@ & y, const @*iterator*@ & x) - { return y.@*end_*@ - x.@*it_*@; } - }; - - template - project_view(R &&) -> project_view, F>; -} -``` - -`project_view` presents a view of an underlying sequence after applying a -transformation function to each element. - -The name `views::project` denotes a range adaptor object -([range.adaptor.object]). Given subexpression `E` and the non-type template -parameter `F`, let `A` be: - -```c++ -template -using A = project_view; -``` - -`viewsโ€‹::โ€‹project(E)` is expression-equivalent to `A(E)`. - -\[Example 1: -```c++ -vector is{ 0, 1, 2, 3, 4 }; -struct f { - static int operator()(int i) const { return i * i; } -}; -auto squares = views::project(is); -for (int i : squares) - cout << i << ' '; // prints 0 1 4 9 16 -``` -โ€” end example\] - - -## Add code unit views and adaptors - -```c++ -namespace std::uc { - template - constexpr auto @*iterator-to-tag*@() { // @*exposition only*@ - if constexpr (random_access_iterator) { - return random_access_iterator_tag{}; - } else if constexpr (bidirectional_iterator) { - return bidirectional_iterator_tag{}; - } else if constexpr (forward_iterator) { - return forward_iterator_tag{}; - } else { - return input_iterator_tag{}; - } - } - - template - using @*iterator-to-tag_t*@ = decltype(@*iterator-to-tag*@()); // @*exposition only*@ - - template - struct @*cast-to-charn*@ { // @*exposition only*@ - static constexpr Char operator()(Char c) const { return c; } - }; - - template - using char8_view = project_view{}>; - template - using char16_view = project_view{}>; - template - using char32_view = project_view{}>; - - inline constexpr @*unspecified*@ as_char8_t; - inline constexpr @*unspecified*@ as_char16_t; - inline constexpr @*unspecified*@ as_char32_t; -} -``` - -`char8_view` produces a view of `char8_t` elements from another view. -`char16_view` produces a view of `char16_t` elements from another view. -`char32_view` produces a view of `char32_t` elements from another view. Let -`charN_view` denote any one of the views `char8_view`, `char16_view`, and -`char32_view`. - -The names `as_char8_t`, `as_char16_t`, and `as_char32_t` denote range adaptor -objects ([range.adaptor.object]). `as_char8_t` produces `char8_view`s, -`as_char16_t` produces `char16_view`s, and `as_char32_t` produces -`char32_view`s. Let `as_charN_t` denote any one of `as_char8_t`, -`as_char16_t`, and `as_char32_t`, and let `V` denote the `charN_view` -associated with that object. Let `E` be an expression and let `T` be -`remove_cvref_t`. Let `F` be the `format` enumerator -associated with `as_charN_t`. If `decltype((E))` does not model -`utf_pointer` and if `charN_view(E)` is ill-formed, `as_charN_t(E)` is -ill-formed. The expression `as_charN_t(E)` is expression-equivalent to: - -- If `T` is a specialization of `empty_view` ([range.empty.view]), then - `empty_view<@*format-to-type-t*@>{}`. - -- Otherwise, if `is_pointer_v` is `true`, then - `V(ranges::subrange(E, null_sentinel))`. - -- Otherwise, `V(E)`. - -\[Example 1: -```c++ -vector v = {'U', 'n', 'i', 'c', 'o', 'd', 'e'}; -for (auto c : v | uc::as_char8_t) { - static_assert(same_as); - cout << (char)c << ' '; // prints U n i c o d e -} -``` -โ€” end example\] - -### Why `as_charN_t` requires `utf_pointer` - -It may seem odd that `foo | as_charN_t` is well formed if `decltype(foo)` is -`std::vector`, but ill-formed if `decltype(foo)` is `int *`. However, -this is intentional. - -If you write `std::vector{/* ... */} | as_char32_t`, the result is always a -view whose value type is `char32_t`. If you write: - -```c++ -int * ptr = /* ... */; -auto v = ptr | as_char32_t; -``` - -`v` may be a view of `char32_t` values that ends in a null terminator, or it -may be an error that results in UB. Null-terminated strings are very common, -but null-terminated strings of a non-character type are rare. It seems far -more safe and idiomatic to restrict the pointer-adaptation case only to -`utf_pointer`s. - -## Add transcoding views and adaptors - -The macro `CODE_UNIT_CONCEPT_OPTION_2` is used below to indicate the two -options for how to define `@*format-of*@`, based on the definition of -`code_unit`. - -```cpp -namespace std::uc { - template - constexpr format @*format-of*@() { // @*exposition only*@ - if constexpr (same_as) { - return format::utf8{}; - } else if constexpr (same_as) { - return format::utf16{}; - } else if constexpr (same_as) { - return format::utf32{}; -#if CODE_UNIT_CONCEPT_OPTION_2 - } else if constexpr (same_as) { - return format::utf8{}; - } else if constexpr (same_as) { - return @*wchar-t-format*@; -#endif - } - } - - template - requires ranges::view && ranges::forward_range - class unpacking_view : public ranges::view_interface> { - V @*base_*@ = V(); // @*exposition only*@ - - public: - constexpr unpacking_view() requires default_initializable = default; - constexpr unpacking_view(V base) : @*base_*@(std::move(base)) {} - - constexpr V base() const & requires copy_constructible { return @*base_*@; } - constexpr V base() && { return std::move(@*base_*@); } - - constexpr auto code_units() const noexcept { - auto unpacked = uc::unpack_iterator_and_sentinel(ranges::begin(@*base_*@), ranges::end(@*base_*@)); - return ranges::subrange(unpacked.first, unpacked.last); - } - - constexpr auto begin() { return ranges::begin(code_units()); } - constexpr auto begin() const { return ranges::begin(code_units()); } - - constexpr auto end() { return ranges::end(code_units()); } - constexpr auto end() const { return ranges::end(code_units()); } - }; - - template - unpacking_view(R &&) -> unpacking_view>; - - template - constexpr bool @*is-charn-view*@ = false; // @*exposition only*@ - template - constexpr bool @*is-charn-view*@> = true; // @*exposition only*@ - template - constexpr bool @*is-charn-view*@> = true; // @*exposition only*@ - template - constexpr bool @*is-charn-view*@> = true; // @*exposition only*@ - - template - requires ranges::view - class utf_view : public ranges::view_interface> { - V @*base_*@ = V(); // @*exposition only*@ - - template - static constexpr auto make_begin(I first, S last) { // @*exposition only*@ - if constexpr (bidirectional_iterator) { - return utf_iterator{ - first, first, last}; - } else { - return utf_iterator{first, last}; - } - } - template - static constexpr auto make_end(I first, S last) { // @*exposition only*@ - if constexpr (!same_as) { - return last; - } else if constexpr (bidirectional_iterator) { - return utf_iterator{ - first, last, last}; - } else { - return utf_iterator{last, last}; - } - } - - public: - constexpr utf_view() requires default_initializable = default; - constexpr utf_view(V base) : @*base_*@{std::move(base)} {} - - constexpr V base() const & requires copy_constructible { return @*base_*@; } - constexpr V base() && { return std::move(@*base_*@); } - - constexpr auto begin() { - constexpr format from_format = @*format-of*@>(); - if constexpr(@*is-charn-view*@) { - return make_begin(@*base_*@.impl_.begin().base(), @*base_*@.impl_.end().base()); - } else { - return make_begin(ranges::begin(@*base_*@), ranges::end(@*base_*@)); - } - } - constexpr auto begin() const { - constexpr format from_format = @*format-of*@>(); - if constexpr(@*is-charn-view*@) { - return make_begin(ranges::begin(@*base_*@.base()), ranges::end(@*base_*@.base())); - } else { - return make_begin(ranges::begin(@*base_*@), ranges::end(@*base_*@)); - } - } - - constexpr auto end() { - constexpr format from_format = @*format-of*@>(); - if constexpr(@*is-charn-view*@) { - return make_end(@*base_*@.impl_.begin().base(), @*base_*@.impl_.end().base()); - } else { - return make_end(ranges::begin(@*base_*@), ranges::end(@*base_*@)); - } - } - constexpr auto end() const { - constexpr format from_format = @*format-of*@>(); - if constexpr(@*is-charn-view*@) { - return make_end(ranges::begin(@*base_*@.base()), ranges::end(@*base_*@.base())); - } else { - return make_end(ranges::begin(@*base_*@), ranges::end(@*base_*@)); - } - } - - friend ostream & operator<<(ostream & os, utf_view v); - friend wostream & operator<<(wostream & os, utf_view v); - }; - - template - utf_view(R &&) -> utf_view>; - - template - using utf8_view = utf_view; - template - using utf16_view = utf_view; - template - using utf32_view = utf_view; -} - -namespace std::ranges { - template - inline constexpr bool enable_borrowed_range> = enable_borrowed_range; - template - inline constexpr bool enable_borrowed_range> = enable_borrowed_range; -} - -namespace std::uc { - template - constexpr decltype(auto) @*unpack-range*@(R && r) { - using T = remove_cvref_t; - if constexpr (ranges::forward_range) { - auto unpacked = uc::unpack_iterator_and_sentinel(ranges::begin(r), ranges::end(r)); - if constexpr (is_bounded_array_v) { - constexpr auto n = extent_v; - if (n && !r[n - 1]) - --unpacked.last; - return ranges::subrange(unpacked.first, unpacked.last); - } else if constexpr (!same_as> || - !same_as>) { - return unpacking_view(forward(r)); - } else { - return forward(r); - } - } else { - return forward(r); - } - } - - inline constexpr @*unspecified*@ as_utf8; - inline constexpr @*unspecified*@ as_utf16; - inline constexpr @*unspecified*@ as_utf32; -} -``` - -`unpacking_view` knows how to unpack a range into code unit iterators using -`unpack_iterator_and_sentinel`. - -`utf_view` produces a view in UTF format `Format` of the elements from another -UTF view. `utf8_view` produces a UTF-8 view of the elements from another UTF -view. `utf16_view` produces a UTF-16 view of the elements from another UTF -view. `utf32_view` produces a UTF-32 view of the elements from another UTF -view. Let `utfN_view` denote any one of the views `utf8_view`, `utf16_view`, -and `utf32_view`. - -The names `as_utf8`, `as_utf16`, and `as_utf32` denote range adaptor objects -([range.adaptor.object]). `as_utf8` produces `utf8_view`s, `as_utf16` -produces `utf16_view`s, and `as_utf32` produces `utf32_view`s. Let `as_utfN` -denote any one of `as_utf8`, `as_utf16`, and `as_utf32`, and let `V` denote -the `utfN_view` associated with that object. Let `charN_view` denote any one -of `char8_view`, `char16_view`, and `char32_view`. Let `E` be an expression -and let `T` be `remove_cvref_t`. Let `F` be the `format` -enumerator associated with `as_utfN`. If `decltype((E))` does not model -`utf_range_like`, `as_utfN(E)` is ill-formed. The expression `as_utfN(E)` is -expression-equivalent to: - -- If `T` is a specialization of `empty_view` ([range.empty.view]), then - `empty_view<@*format-to-type-t*@>{}`. - -- Otherwise, if `T` is a specialization of `utfN_view`, then `V(E.base())`. - -- Otherwise, if `T` is a specialization of `charN_view`, then `V(E)`. - -- Otherwise, if `is_pointer_v` is `true`, then - `V(ranges::subrange(E, null_sentinel))`. - -- Otherwise, `V(@*unpack-range*@(E))`. - -\[Example 1: -```c++ -std::u32string s = U"Unicode"; -for (char8_t c : s | std::uc::as_utf8) - cout << (char)c << ' '; // prints U n i c o d e -``` -โ€” end example\] - -\[Example 2: -```c++ -auto * s = L"is weird."; -for (char8_t c : s | std::uc::as_utf8) - cout << (char)c << ' '; // prints i s w e i r d . -``` -โ€” end example\] - -The `ostream` and `wostream` stream operators transcode the `utf_view` to -UTF-8 and UTF-16, respectively (if transcoding is needed). The `wostream` -overload is only defined on Windows. - -### Why there are three `utfN_view`s views plus `utf_view` - -The views in `std::ranges` are constrained to accept only `std::ranges::view` -template parameters. However, they accept `std::ranges::viewable_range`s in -practice, because they each have a deduction guide that likes like this: - -```c++ -template -utf8_view(R &&) -> utf8_view>; -``` - -It's not possible to make this work for `utf_view`, since to use it you must -supply a `format` NTTP. So, we need the `utfN_view`s. It might be possible -to make `utf_view` an exposition-only implementation detail, but I think some -users might find use for it, especially in generic contexts. For instance: - -```c++ -template -auto f(std::uc::utf_view const & view) { - // Use F, V, and view here.... -} -``` - -### `unpacking_view` - -For a particular `V` being adapted by `as_utfN`, there are two cases: 1) `V` -is unpackable (taht is, unpacking produces different iterator/sentinel types -than what you had before unpacking), and 2) `V` is not unpackable. The second -case is easy; since `V` is already unpacked, you just construct a `utfN_view` -from `V`, and you're done. The first case is a little harder. For that case, -we either need to let `utfN_view` know statically that it must do some -unpacking, or we must introduce yet another view that does it for us. -Introducing a view is the right answer, because introducing an NTTP to -`utfN_view` would be unergonomic. For instance: - -```c++ -template -void f(std::uc::utf32_view const & utf32) { - // ... -} -``` - -What do we write for the `/* ??? */` -- the NTTP that indicates whether `V` is -already unpacked or not? We have to do a nontrivial amount of work involving -`V` to know what to write there. - -So, we have `unpacking_view` instead. When `V` is unpackable, `as_utfN` -returns a `utfN_view>`. - -In the previous revision of this paper, the `as_utfN` adaptor unpacked the -adapted range most of the time, except for the one case where it could not. -That case was when `r` in `r | as_utfN` is an rvalue whose `begin()` and -`end()` are unpackable. In that case, we needed a special-case type called -`unpacking_owning_view` that would store `r` and unpack `r.begin()` and -`r.end()`. This is not ideal, because doing the unpacking in the adaptor -loses information. It loses information because the unpacked view used to -construct `utfN_view` is a `ranges::subrange`, not the original range. For -example, if you start with an lvalue `vector`, then keeping -`unpacking_view>>` means that you can get access to the -`vector` itself with a chain of `base()` calls. You lose that if it's a -`subrange::iterator, typename vector::iterator>`. - -### Adaptor examples - -```c++ -struct my_text_type -{ - my_text_type() = default; - my_text_type(std::u8string utf8) : utf8_(std::move(utf8)) {} - - auto begin() const { - return std::uc::utf_8_to_32_iterator( - utf8_.begin(), utf8_.begin(), utf8_.end()); - } - auto end() const { - return std::uc::utf_8_to_32_iterator( - utf8_.begin(), utf8_.end(), utf8_.end()); - } - -private: - std::u8string utf8_; -}; - -static_assert(std::is_same_v< - decltype(my_text_type(u8"text") | std::uc::as_utf16), - std::uc::utf16_view>>>); - -static_assert(std::is_same_v< - decltype(u8"text" | std::uc::as_utf16), - std::uc::utf16_view>>); - -static_assert(std::is_same_v< - decltype(std::u8string(u8"text") | std::uc::as_utf16), - std::uc::utf16_view>>); - -std::u8string const str = u8"text"; - -static_assert(std::is_same_v< - decltype(str | std::uc::as_utf16), - std::uc::utf16_view>>); - -static_assert(std::is_same_v< - decltype(str.c_str() | std::uc::as_utf16), - std::uc::utf16_view>>); - -static_assert(std::is_same_v< - decltype(std::ranges::empty_view{} | std::uc::as_char16_t), - std::ranges::empty_view>); - -std::u16string str2 = u"text"; - -static_assert(std::is_same_v< - decltype(str2 | std::uc::as_utf16), - std::uc::utf16_view>>); - -static_assert(std::is_same_v< - decltype(str2.c_str() | std::uc::as_utf16), - std::uc::utf16_view>>); -``` - -### Why `utf_view` always uses `utf_iterator`, even in UTF-N to UTF-N cases - -You might expect that if `r` in `r | as_utfN` is already in UTF-N, `r | -as_utfN` might just be `r`. This is not what the `as_utfN` adaptors do, -though. - -The adaptors each produce a view `utfv` that stores a view of type `V`, where -`V` is made from the result of unpacking `r`. Further, `utfv.begin()` is -always a specialization of `utf_iterator`. `utfv.end()` is also a -specialization of `utf_iterator` (if `common_range`), or otherwise the -sentinel value for `V`. - -This gives `r | as_utfN` some nice, consistent properties. With the -exception of `empty_view{} | as_utfN`, the following are always true: - -- `r | as_utfN` produces well-formed UTF. Since the default `ErrorHandler` - template parameter to `utf_iterator` `use_replacement_character` is always - used, any ill-formed UTF is replaced with `replacement_character`. This is - true even when the input was already UTF-N. Remember, the input could have - been UTF-N but had ill-formed UTF in it. - -- `r | as_utfN` has a consistent API. If `r | as_utfN` were sometimes `r`, - and since `r` may be a reference to an array, you'd have to use - `std::ranges::begin(r)` and `::end(r)` all the time. However, you'd - probably write `r.begin()` and `r.end()`, only to one day get bitten by an - array-reference `r`. - -- `r | as_utfN` is formattable/printable. This means you can adapt anything - that can be UTF-transcoded to do I/O in a consistent way. For example: - -```c++ - auto str0 = std::format("{}", std::u8string{}); // Error: ill-formed! - auto str1 = std::format("{}", std::u8string{} | std::uc::as_utf8); // Ok. -``` - -### Add `utf_view` specialization of `formatter` - -These should be added to the list of "the debug-enabled string type -specializations" in [format.formatter.spec]. This allows `utf_view` and -`utfN_view` to be used in `std::format()` and `std::print()`. The intention -is that the formatter will transcode to UTF-8 if the formatter's `CharT` is -`char`, or to UTF-16 or UTF-32 (which one is implementation defined) if the -formatter's `CharT` is `wchar_t` -- if transcoding is necessary at all. - -```cpp -namespace std { - template - struct formatter, CharT> { - private: - formatter, CharT> @*underlying_*@; // @*exposition only*@ - - public: - template - constexpr typename ParseContext::iterator - parse(ParseContext& ctx); - - template - typename FormatContext::iterator - format(const uc::utf_view& view, FormatContext& ctx) const; - - constexpr void set_debug_format() noexcept; - }; -} -``` - -```c++ -template - constexpr typename ParseContext::iterator - parse(ParseContext& ctx); -``` - -Effects: Equivalent to: -```c++ -return @*underlying_*@.parse(ctx); -``` - -```c++ -template - typename FormatContext::iterator - format(const uc::utf_view& view, FormatContext& ctx) const; -``` - -Effects: Equivalent to: -```c++ -auto adaptor = @*see below*@; -return @*underlying_*@.format(basic_string(from_range, view | adaptor), ctx); -``` - -`adaptor` is `uc::as_utf8` if `CharT` is `char`. Otherwise, it is -implementation defined whether `adaptor` is `uc::as_utf16` or `uc::as_utf32`. - -```c++ -constexpr void set_debug_format() noexcept; -``` - -Effects: Equivalent to: -```c++ -@*underlying_*@.set_debug_format(); -``` - -## Add a feature test macro - -Add the feature test macro `__cpp_lib_unicode_transcoding`. - -## Design notes - -None of the proposed interfaces is subject to change in future versions of -Unicode; each relates to the guaranteed-stable subset. Just sayin'. - -None of the proposed interfaces allocates or throws, unless the user supplies -a throwing `ErrorHandler` template parameter to `utf_iterator`. - -The proposed interfaces allow users to choose amongst multiple -convenience-vs-compatibility tradeoffs. Explicitly, they are: - -- If you need compatibility with existing iterator-based algorithms (such as - the standard algorithms), use the transcoding iterators. -- If you want streamability or the convenience of constructing ranges with a - single `| as_utfN` adaptor use, use the transcoding views. - -All the transcoding iterators allow you access to the underlying iterator via -`.base()` (except when adapting an input iterator), following the convention -of the iterator adaptors already in the standard. - -The transcoding views are lazy, as you'd expect. They also compose with the -standard view adaptors, so just transcoding at most 10 UTF-16 code units out -of some UTF can be done with `foo | std::uc::as_utf16 | -std::ranges::views::take(10)`. - -Error handling is explicitly configurable in the transcoding iterators. This -gives control to those who want to do something other than the default. The -default, according to Unicode, is to produce a replacement character -(`0xfffd`) in the output when broken UTF encoding is seen in the input. This -is what all these interfaces do, unless you configure one of the iterators as -mentioned above. - -The production of replacement characters as error-handling strategy is good -for memory compactness and safety. It allows us to store all our text as -UTF-8 (or, less compactly, as UTF-16), and then process code points as -transcoding views. If an error occurs, the transcoding views will simply -produce a replacement character; there is no danger of UB. - -A null-terminated pointer `p` to an 8-, 16-, or 32-bit string of code units is -considered the implicit range `[p, null_sentinel)`. This makes user code much -more natural; `"foo" | as_utf16`, `"foo"sv | as_utf16`, and `"foo"s | -as_utf16` are roughly equivalent (though the iterator type of the resulting -view may differ). - -Iterators are constructed from more than one underlying iterator. To do -iteration in many text-handling contexts, you need to know the beginning and -the end of the range you are iterating over, just to be able to do iteration -correctly. Note that this is not a safety issue, but a correctness one. For -example, say we have a string `s` of UTF-8 code units that we would like to -iterate over to produce UTF-32 code points. If the last code unit in `s` is -`0xe0`, we should expect two more code units to follow. They are not present, -though, because `0xe0` is the last code unit. Now consider how you would -implement `operator++()` for an iterator `iter` that transcodes from UTF-8 to -UTF-32. If you advance far enough to get the next UTF-32 code point in each -call to `operator++()`, you may run off the end of `s` when you find `0xe0` -and try to read two more code units. Note that it does not matter that `iter` -probably comes from a range with an end-iterator or sentinel as its mate; -inside `iter`'s `operator++()` this is no help. `iter` must therefore have the -end-iterator or sentinel as a data member. The same logic applies to the other -end of the range if `iter` is bidirectional โ€” it must also have the iterator -to the start of the underlying range as a data member. This unfortunate -reality comes up over and over in the proposed iterators, not just the ones -that are UTF transcoding iterators. This is why iterators in this proposal -(and the ones to come) usually consist of three underlying iterators. - -# Implementation experience - -All the interfaces proposed here have been implemented, and re-implemented, -several times over the last 5 years or so. They are part of a proposed (but -not yet accepted!) Boost library, -[Boost.Text](https://github.com/tzlaine/text). - -The library has hundreds of stars, though I'm not sure how many users that -equates to. All of the interfaces proposed here are among the best-exercised -in the library. There are comprehensive tests for all the proposed entities, -and those entities are used as the foundation upon which all the other library -entities are composed. - -Though there are a lot of individual entities proposed here, at one time or -another I have need each one of them, though maybe not in every UTF-N -> UTF-M -permutation. Those transcoding permutations are there mostly for -completeness. I have only ever needed UTF-8 <-> UTF->32 in any of my work -that uses Unicode. Frequent Windows users will also need to convert to and -from UTF-16 sometimes, because that is the UTF that the OS APIs use. diff --git a/README.md b/README.md new file mode 100644 index 0000000..070a450 --- /dev/null +++ b/README.md @@ -0,0 +1,109 @@ +# UtfView: C++26 UTF Transcoding Views + + + +[![CI](https://github.com/ednolan/UtfView/actions/workflows/ci.yml/badge.svg)](https://github.com/ednolan/utfview/actions) [![Coverage](https://coveralls.io/repos/github/ednolan/UtfView/badge.svg?branch=main)](https://coveralls.io/github/ednolan/UtfView?branch=main) + +This repository implements the functionality proposed by P2728 for C++26, including: + +- Transcoding UTF views `to_utf8`, `to_utf16`, and `to_utf32` +- `null_sentinel` sentinel and `null_term` CPO for creating views of null-terminated strings +- Casting views for creating views of `charN_t`, which are `as_char8`, `as_char16`, `as_char32` + +## Examples + +Transcoding a UTF-8 string literal to a `std::u32string`: + +``` +std::u32string hello_world = + u8"ใ“ใ‚“ใซใกใฏไธ–็•Œ" | utfview::to_utf32 | std::ranges::to(); +``` + +Sanitizing potentially invalid Unicode C strings by replacing invalid code units with replacement characters: + +``` +template +std::basic_string sanitize(CharT const* str) { + return utfview::null_term(str) | utfview::to_utf | std::ranges::to>(); +} +``` + +Returning the final non-ASCII code point in a string, transcoding backwards lazily: + +``` +std::optional last_nonascii(std::ranges::view auto str) { + for (auto c : str | utfview::to_utf32 | std::views::reverse + | std::views::filter([](char32_t c) { return c > 0x7f; }) + | std::views::take(1)) { + return c; + } + return std::nullopt; +} +``` + +Transcoding strings and throwing a descriptive exception on invalid UTF: + +(This example assumes the existence of the `enum_to_string` function from +[P2996](https://isocpp.org/files/papers/P2996R6.html#enum-to-string)) + +``` +template +std::basic_string transcode_or_throw(std::basic_string_view input) { + std::basic_string result; + auto view = input | to_utf; + for (auto it = view.begin(), end = view.end(); it != end; ++it) { + if (it.success()) { + result.push_back(*it); + } else { + throw std::runtime_error("error at position " + + std::to_string(it.base() - input.begin()) + ": " + + enum_to_string(it.success().error())); + } + } + return result; +} +``` + +## How to Build + +### Minimum Requirements + +UtfView requires being built in C++23 mode. + +UtfView has the following minimum compiler requirements: + +- GCC 14 +- Clang 19 +- MSVC 17.11.2 (earlier MSVC versions may also work but are not tested in CI) + +### Dependencies + +UtfView depends on [Boost.STLInterfaces](https://github.com/boostorg/stl_interfaces). It brings in this library and its dependencies via git submodules. If you add UtfView to your project your project already uses Boost, it will target your project's stl_interfaces instead of using its own submodule. + +### Instructions + +This excerpt from the project's CI script provides an example of building the project and running the tests: + + mkdir "$checkout/build" + cd "$checkout/build" + cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_STANDARD=23 -DBUILD_TESTING=On "$@" + cmake --build . --parallel + ctest -C Debug + +### Paper + +UtfView is based on P2728. + +- The latest official revision of P2728 can be found at https://wg21.link/p2728 +- The unofficial latest draft Markdown source for the paper can be found in this repository at [paper/P2828.md](https://github.com/ednolan/UtfView/blob/main/paper/P2728.md) +- The paper's committee status page can be found at https://github.com/cplusplus/papers/issues/1422 + +## Authors + +This implementation of P2728 is a fork by Eddie Nolan of the implementation of P2728R6 in libstdc++ by Jonathan Wakely at [`gcc/libstdc++-v3/include/bits/unicode.h`](https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=libstdc%2B%2B-v3/include/bits/unicode.h;h=66f8399fdfb05d85fcdb37fa9ec7c4089feb7a7d;hb=37a4c5c23a27). + +## License + +UtfView is licensed under GPLv3. diff --git a/ci.sh b/ci.sh new file mode 100755 index 0000000..64414f3 --- /dev/null +++ b/ci.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +set -euo pipefail + +function main() { + local -a cxx_flags=("$@") + local checkout="$PWD" + mkdir "$checkout/build" + cd "$checkout/build" + cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_STANDARD=23 -DBUILD_TESTING=On "$@" + cmake --build . --parallel + export ASAN_OPTIONS=alloc_dealloc_mismatch=0 # https://github.com/llvm/llvm-project/issues/59432 + ctest -C Debug +} + +main "$@" diff --git a/deps/assert b/deps/assert new file mode 160000 index 0000000..242fdfb --- /dev/null +++ b/deps/assert @@ -0,0 +1 @@ +Subproject commit 242fdfb1373127331cb229379b50b1dba0f53e49 diff --git a/deps/config b/deps/config new file mode 160000 index 0000000..5734e16 --- /dev/null +++ b/deps/config @@ -0,0 +1 @@ +Subproject commit 5734e160e08b8df898c7f747000f27a3aafb7b2b diff --git a/deps/stl_interfaces b/deps/stl_interfaces new file mode 160000 index 0000000..a4b7b5f --- /dev/null +++ b/deps/stl_interfaces @@ -0,0 +1 @@ +Subproject commit a4b7b5fd5aa137393580bcf5567ed9a39cd18ce7 diff --git a/deps/wg21 b/deps/wg21 new file mode 160000 index 0000000..0c965d0 --- /dev/null +++ b/deps/wg21 @@ -0,0 +1 @@ +Subproject commit 0c965d0d7bb71b66401b324f655ad881063e16d3 diff --git a/include/UtfView/code_unit_view.hpp b/include/UtfView/code_unit_view.hpp new file mode 100644 index 0000000..6fe0ff3 --- /dev/null +++ b/include/UtfView/code_unit_view.hpp @@ -0,0 +1,608 @@ +// SPDX-License-Identifier: GPL-3.0-only + +#ifndef UTFVIEW_CODE_UNIT_VIEW_HPP +#define UTFVIEW_CODE_UNIT_VIEW_HPP + +#include +#include +#include +#include +#include +#include + +namespace utfview { + +/* PAPER: namespace std::uc { */ + +/* PAPER */ + +template +consteval auto exposition_only_iterator_to_tag() { // @*exposition only*@ + if constexpr (std::random_access_iterator) { + return std::random_access_iterator_tag{}; + } else if constexpr (std::bidirectional_iterator) { + return std::bidirectional_iterator_tag{}; + } else if constexpr (std::forward_iterator) { + return std::forward_iterator_tag{}; + } else if constexpr (std::input_iterator) { + return std::input_iterator_tag{}; + } +} + +template +using exposition_only_iterator_to_tag_t = + decltype(exposition_only_iterator_to_tag()); // @*exposition only*@ + +template +concept exposition_only_convertible_to_charN_t_view = + exposition_only_code_unit_to && std::ranges::view && + std::convertible_to, ToType>; + +template V> +class as_char8_t_view : public std::ranges::view_interface> { + V base_ = V(); // @*exposition only*@ + + template + class exposition_only_iterator; // @*exposition only*@ + template + class exposition_only_sentinel; // @*exposition only*@ + +public: + constexpr as_char8_t_view() + requires std::default_initializable + = default; + constexpr as_char8_t_view(V base) + : base_(std::move(base)) { } + + constexpr V& base() & { + return base_; + } + constexpr const V& base() const& + requires std::copy_constructible + { + return base_; + } + constexpr V base() && { + return std::move(base_); + } + + constexpr exposition_only_iterator begin() { + return exposition_only_iterator{std::ranges::begin(base_)}; + } + constexpr exposition_only_iterator begin() const + requires std::ranges::range + { + return exposition_only_iterator{std::ranges::begin(base_)}; + } + + constexpr exposition_only_sentinel end() { + return exposition_only_sentinel{std::ranges::end(base_)}; + } + constexpr exposition_only_iterator end() + requires std::ranges::common_range + { + return exposition_only_iterator{std::ranges::end(base_)}; + } + constexpr exposition_only_sentinel end() const + requires std::ranges::range + { + return exposition_only_sentinel{std::ranges::end(base_)}; + } + constexpr exposition_only_iterator end() const + requires std::ranges::common_range + { + return exposition_only_iterator{std::ranges::end(base_)}; + } + + constexpr auto size() + requires std::ranges::sized_range + { + return std::ranges::size(base_); + } + constexpr auto size() const + requires std::ranges::sized_range + { + return std::ranges::size(base_); + } +}; + +template V> +template +class as_char8_t_view::exposition_only_iterator + : public boost::stl_interfaces::proxy_iterator_interface< + exposition_only_iterator_to_tag_t< + std::ranges::iterator_t>>, + char8_t> { +public: + using reference_type = char8_t; + +private: + using exposition_only_iterator_type = std::ranges::iterator_t< + exposition_only_maybe_const>; // @*exposition only*@ + + friend boost::stl_interfaces::access; + + constexpr exposition_only_iterator_type& base_reference() noexcept { + return it_; + } // @*exposition only*@ + constexpr exposition_only_iterator_type base_reference() const { + return it_; + } // @*exposition only*@ + + exposition_only_iterator_type it_ = + exposition_only_iterator_type(); // @*exposition only*@ + +public: + constexpr exposition_only_iterator() = default; + constexpr exposition_only_iterator(exposition_only_iterator_type it) + : it_(std::move(it)) { } + + constexpr reference_type operator*() const { + return *it_; + } +}; + +template V> +template +class as_char8_t_view::exposition_only_sentinel { + using exposition_only_base = + exposition_only_maybe_const; // @*exposition only*@ + using exposition_only_sentinel_type = + std::ranges::sentinel_t; // @*exposition only*@ + + exposition_only_sentinel_type end_ = + exposition_only_sentinel_type(); // @*exposition only*@ + +public: + constexpr exposition_only_sentinel() = default; + constexpr explicit exposition_only_sentinel(exposition_only_sentinel_type end) + : end_(std::move(end)) { } + constexpr exposition_only_sentinel(exposition_only_sentinel i) + requires Const && + std::convertible_to, + std::ranges::sentinel_t>; + + constexpr exposition_only_sentinel_type base() const { + return end_; + } + + template + requires std::sentinel_for< + exposition_only_sentinel_type, + std::ranges::iterator_t>> + friend constexpr bool operator==(const exposition_only_iterator& x, + const exposition_only_sentinel& y) { + return x.it_ == y.end_; + } + + template + requires std::sized_sentinel_for< + exposition_only_sentinel_type, + std::ranges::iterator_t>> + friend constexpr std::ranges::range_difference_t< + exposition_only_maybe_const> + operator-(const exposition_only_iterator& x, + const exposition_only_sentinel& y) { + return x.it_ - y.end_; + } + + template + requires std::sized_sentinel_for< + exposition_only_sentinel_type, + std::ranges::iterator_t>> + friend constexpr std::ranges::range_difference_t< + exposition_only_maybe_const> + operator-(const exposition_only_sentinel& y, + const exposition_only_iterator& x) { + return y.end_ - x.it_; + } +}; + +template +as_char8_t_view(R&&) -> as_char8_t_view>; + +template V> +class as_char16_t_view : public std::ranges::view_interface> { + V base_ = V(); // @*exposition only*@ + + template + class exposition_only_iterator; // @*exposition only*@ + template + class exposition_only_sentinel; // @*exposition only*@ + +public: + constexpr as_char16_t_view() + requires std::default_initializable + = default; + constexpr as_char16_t_view(V base) + : base_(std::move(base)) { } + + constexpr V& base() & { + return base_; + } + constexpr const V& base() const& + requires std::copy_constructible + { + return base_; + } + constexpr V base() && { + return std::move(base_); + } + + constexpr exposition_only_iterator begin() { + return exposition_only_iterator{std::ranges::begin(base_)}; + } + constexpr exposition_only_iterator begin() const + requires std::ranges::range + { + return exposition_only_iterator{std::ranges::begin(base_)}; + } + + constexpr exposition_only_sentinel end() { + return exposition_only_sentinel{std::ranges::end(base_)}; + } + constexpr exposition_only_iterator end() + requires std::ranges::common_range + { + return exposition_only_iterator{std::ranges::end(base_)}; + } + constexpr exposition_only_sentinel end() const + requires std::ranges::range + { + return exposition_only_sentinel{std::ranges::end(base_)}; + } + constexpr exposition_only_iterator end() const + requires std::ranges::common_range + { + return exposition_only_iterator{std::ranges::end(base_)}; + } + + constexpr auto size() + requires std::ranges::sized_range + { + return std::ranges::size(base_); + } + constexpr auto size() const + requires std::ranges::sized_range + { + return std::ranges::size(base_); + } +}; + +template V> +template +class as_char16_t_view::exposition_only_iterator + : public boost::stl_interfaces::proxy_iterator_interface< + exposition_only_iterator_to_tag_t< + std::ranges::iterator_t>>, + char16_t> { +public: + using reference_type = char16_t; + +private: + using exposition_only_iterator_type = std::ranges::iterator_t< + exposition_only_maybe_const>; // @*exposition only*@ + + friend boost::stl_interfaces::access; + + constexpr exposition_only_iterator_type& base_reference() noexcept { + return it_; + } // @*exposition only*@ + constexpr exposition_only_iterator_type base_reference() const { + return it_; + } // @*exposition only*@ + + exposition_only_iterator_type it_ = + exposition_only_iterator_type(); // @*exposition only*@ + +public: + constexpr exposition_only_iterator() = default; + constexpr exposition_only_iterator(exposition_only_iterator_type it) + : it_(std::move(it)) { } + + constexpr reference_type operator*() const { + return *it_; + } +}; + +template V> +template +class as_char16_t_view::exposition_only_sentinel { + using exposition_only_base = + exposition_only_maybe_const; // @*exposition only*@ + using exposition_only_sentinel_type = + std::ranges::sentinel_t; // @*exposition only*@ + + exposition_only_sentinel_type end_ = + exposition_only_sentinel_type(); // @*exposition only*@ + +public: + constexpr exposition_only_sentinel() = default; + constexpr explicit exposition_only_sentinel(exposition_only_sentinel_type end) + : end_(std::move(end)) { } + constexpr exposition_only_sentinel(exposition_only_sentinel i) + requires Const && + std::convertible_to, + std::ranges::sentinel_t>; + + constexpr exposition_only_sentinel_type base() const { + return end_; + } + + template + requires std::sentinel_for< + exposition_only_sentinel_type, + std::ranges::iterator_t>> + friend constexpr bool operator==(const exposition_only_iterator& x, + const exposition_only_sentinel& y) { + return x.it_ == y.end_; + } + + template + requires std::sized_sentinel_for< + exposition_only_sentinel_type, + std::ranges::iterator_t>> + friend constexpr std::ranges::range_difference_t< + exposition_only_maybe_const> + operator-(const exposition_only_iterator& x, + const exposition_only_sentinel& y) { + return x.it_ - y.end_; + } + + template + requires std::sized_sentinel_for< + exposition_only_sentinel_type, + std::ranges::iterator_t>> + friend constexpr std::ranges::range_difference_t< + exposition_only_maybe_const> + operator-(const exposition_only_sentinel& y, + const exposition_only_iterator& x) { + return y.end_ - x.it_; + } +}; + +template +as_char16_t_view(R&&) -> as_char16_t_view>; + +template V> +class as_char32_t_view : public std::ranges::view_interface> { + V base_ = V(); // @*exposition only*@ + + template + class exposition_only_iterator; // @*exposition only*@ + template + class exposition_only_sentinel; // @*exposition only*@ + +public: + constexpr as_char32_t_view() + requires std::default_initializable + = default; + constexpr as_char32_t_view(V base) + : base_(std::move(base)) { } + + constexpr V& base() & { + return base_; + } + constexpr const V& base() const& + requires std::copy_constructible + { + return base_; + } + constexpr V base() && { + return std::move(base_); + } + + constexpr exposition_only_iterator begin() { + return exposition_only_iterator{std::ranges::begin(base_)}; + } + constexpr exposition_only_iterator begin() const + requires std::ranges::range + { + return exposition_only_iterator{std::ranges::begin(base_)}; + } + + constexpr exposition_only_sentinel end() { + return exposition_only_sentinel{std::ranges::end(base_)}; + } + constexpr exposition_only_iterator end() + requires std::ranges::common_range + { + return exposition_only_iterator{std::ranges::end(base_)}; + } + constexpr exposition_only_sentinel end() const + requires std::ranges::range + { + return exposition_only_sentinel{std::ranges::end(base_)}; + } + constexpr exposition_only_iterator end() const + requires std::ranges::common_range + { + return exposition_only_iterator{std::ranges::end(base_)}; + } + + constexpr auto size() + requires std::ranges::sized_range + { + return std::ranges::size(base_); + } + constexpr auto size() const + requires std::ranges::sized_range + { + return std::ranges::size(base_); + } +}; + +template V> +template +class as_char32_t_view::exposition_only_iterator + : public boost::stl_interfaces::proxy_iterator_interface< + exposition_only_iterator_to_tag_t< + std::ranges::iterator_t>>, + char32_t> { +public: + using reference_type = char32_t; + +private: + using exposition_only_iterator_type = std::ranges::iterator_t< + exposition_only_maybe_const>; // @*exposition only*@ + + friend boost::stl_interfaces::access; + + constexpr exposition_only_iterator_type& base_reference() noexcept { + return it_; + } // @*exposition only*@ + constexpr exposition_only_iterator_type base_reference() const { + return it_; + } // @*exposition only*@ + + exposition_only_iterator_type it_ = + exposition_only_iterator_type(); // @*exposition only*@ + +public: + constexpr exposition_only_iterator() = default; + constexpr exposition_only_iterator(exposition_only_iterator_type it) + : it_(std::move(it)) { } + + constexpr reference_type operator*() const { + return *it_; + } +}; + +template V> +template +class as_char32_t_view::exposition_only_sentinel { + using exposition_only_base = + exposition_only_maybe_const; // @*exposition only*@ + using exposition_only_sentinel_type = + std::ranges::sentinel_t; // @*exposition only*@ + + exposition_only_sentinel_type end_ = + exposition_only_sentinel_type(); // @*exposition only*@ + +public: + constexpr exposition_only_sentinel() = default; + constexpr explicit exposition_only_sentinel(exposition_only_sentinel_type end) + : end_(std::move(end)) { } + constexpr exposition_only_sentinel(exposition_only_sentinel i) + requires Const && + std::convertible_to, + std::ranges::sentinel_t>; + + constexpr exposition_only_sentinel_type base() const { + return end_; + } + + template + requires std::sentinel_for< + exposition_only_sentinel_type, + std::ranges::iterator_t>> + friend constexpr bool operator==(const exposition_only_iterator& x, + const exposition_only_sentinel& y) { + return x.it_ == y.end_; + } + + template + requires std::sized_sentinel_for< + exposition_only_sentinel_type, + std::ranges::iterator_t>> + friend constexpr std::ranges::range_difference_t< + exposition_only_maybe_const> + operator-(const exposition_only_iterator& x, + const exposition_only_sentinel& y) { + return x.it_ - y.end_; + } + + template + requires std::sized_sentinel_for< + exposition_only_sentinel_type, + std::ranges::iterator_t>> + friend constexpr std::ranges::range_difference_t< + exposition_only_maybe_const> + operator-(const exposition_only_sentinel& y, + const exposition_only_iterator& x) { + return y.end_ - x.it_; + } +}; + +template +as_char32_t_view(R&&) -> as_char32_t_view>; + +/* !PAPER */ + +namespace detail { + + template + using as_charN_t_view = + std::conditional_t, as_char8_t_view, + std::conditional_t, + as_char16_t_view, as_char32_t_view>>; + + template + struct as_code_unit_impl + : std::ranges::range_adaptor_closure> { + template + requires std::convertible_to, ToType> + constexpr auto operator()(R&& r) const { + using T = std::remove_cvref_t; + if constexpr (exposition_only_is_empty_view) { + return std::ranges::empty_view{}; + } else if constexpr (std::is_bounded_array_v) { + constexpr auto n = std::extent_v; + auto first{std::ranges::begin(r)}; + auto last{std::ranges::end(r)}; + if (n && !r[n - 1]) { + --last; + } + std::ranges::subrange subrange(first, last); + return as_charN_t_view(std::move(subrange)); + } else { + auto view = std::views::all(std::forward(r)); + return as_charN_t_view(std::move(view)); + } + } + }; + +} // namespace detail + +inline constexpr detail::as_code_unit_impl as_char8_t; + +inline constexpr detail::as_code_unit_impl as_char16_t; + +inline constexpr detail::as_code_unit_impl as_char32_t; + +/* PAPER: inline constexpr @*unspecified*@ as_char8_t; */ +/* PAPER: */ +/* PAPER: inline constexpr @*unspecified*@ as_char16_t; */ +/* PAPER: */ +/* PAPER: inline constexpr @*unspecified*@ as_char32_t; */ +/* PAPER: */ +/* PAPER: } */ + +} // namespace utfview + +template +inline constexpr bool std::ranges::enable_borrowed_range> = + std::ranges::enable_borrowed_range; + +template +inline constexpr bool std::ranges::enable_borrowed_range> = + std::ranges::enable_borrowed_range; + +template +inline constexpr bool std::ranges::enable_borrowed_range> = + std::ranges::enable_borrowed_range; + +/* PAPER: namespace std::ranges { */ +/* PAPER: */ +/* PAPER: template */ +/* PAPER: inline constexpr bool enable_borrowed_range> = enable_borrowed_range; */ +/* PAPER: */ +/* PAPER: template */ +/* PAPER: inline constexpr bool enable_borrowed_range> = enable_borrowed_range; */ +/* PAPER: */ +/* PAPER: template */ +/* PAPER: inline constexpr bool enable_borrowed_range> = enable_borrowed_range; */ +/* PAPER: */ +/* PAPER: } */ + +#endif // UTFVIEW_CODE_UNIT_VIEW_HPP diff --git a/include/UtfView/detail/concepts.hpp b/include/UtfView/detail/concepts.hpp new file mode 100644 index 0000000..6cafed9 --- /dev/null +++ b/include/UtfView/detail/concepts.hpp @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-3.0-only + +#ifndef UTFVIEW_DETAIL_CONCEPTS_HPP +#define UTFVIEW_DETAIL_CONCEPTS_HPP + +#include +#include +#include +#include + +namespace utfview { + +/* PAPER: namespace std::uc { */ + +template +using exposition_only_with_reference = T&; // exposition only +template +concept exposition_only_can_reference // exposition only + = requires { typename exposition_only_with_reference; }; + +template +using exposition_only_maybe_const = + std::conditional_t; // exposition only + +/* PAPER */ + +template +constexpr bool exposition_only_is_empty_view = false; +template +constexpr bool exposition_only_is_empty_view> = true; + +template +concept exposition_only_code_unit_to = std::same_as, char8_t> || + std::same_as, char16_t> || + std::same_as, char32_t>; + +template +concept exposition_only_code_unit_from = std::same_as, char> || + std::same_as, wchar_t> || exposition_only_code_unit_to; + +template +concept exposition_only_utf_range = std::ranges::input_range && + exposition_only_code_unit_from>; + +/* !PAPER */ + +} // namespace utfview + +/* PAPER: } */ + +#endif // UTFVIEW_DETAIL_CONCEPTS_HPP diff --git a/include/UtfView/detail/constexpr_unless_msvc.hpp b/include/UtfView/detail/constexpr_unless_msvc.hpp new file mode 100644 index 0000000..3f76e3f --- /dev/null +++ b/include/UtfView/detail/constexpr_unless_msvc.hpp @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-3.0-only + +#ifndef UTFVIEW_DETAIL_CONSTEXPR_UNLESS_MSVC_HPP +#define UTFVIEW_DETAIL_CONSTEXPR_UNLESS_MSVC_HPP + +// msvc constexpr bugs can be induced by a light breeze +// https://developercommunity.visualstudio.com/t/std::initializer_list-data-member-of-cla/10622889 +// https://developercommunity.visualstudio.com/t/MSVC-complains-about-uninvoked-implicitl/10585513 +// https://developercommunity.visualstudio.com/t/Constraint-not-applied-to-defaulted-cons/10715859 +#ifdef _MSC_VER +#define CONSTEXPR_UNLESS_MSVC +#else +#define CONSTEXPR_UNLESS_MSVC constexpr +#endif + +#endif // UTFVIEW_DETAIL_CONSTEXPR_UNLESS_MSVC_HPP diff --git a/include/UtfView/detail/erroneous_behavior_global.hpp b/include/UtfView/detail/erroneous_behavior_global.hpp new file mode 100644 index 0000000..431374c --- /dev/null +++ b/include/UtfView/detail/erroneous_behavior_global.hpp @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-3.0-only + +#ifndef UTFVIEW_DETAIL_ERRONEOUS_BEHAVIOR_GLOBAL_HPP +#define UTFVIEW_DETAIL_ERRONEOUS_BEHAVIOR_GLOBAL_HPP + +namespace utfview::detail { + +inline bool& erroneous_behavior_global() { + static bool global{}; + return global; +} + +} // namespace utfview::detail + +#endif // UTFVIEW_DETAIL_ERRONEOUS_BEHAVIOR_GLOBAL_HPP diff --git a/include/UtfView/null_term.hpp b/include/UtfView/null_term.hpp new file mode 100644 index 0000000..9898c40 --- /dev/null +++ b/include/UtfView/null_term.hpp @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-3.0-only + +#ifndef UTFVIEW_NULL_TERM_HPP +#define UTFVIEW_NULL_TERM_HPP + +#include +#include +#include + +namespace utfview { + +/* PAPER: namespace std { */ + +/* PAPER */ + +template +concept exposition_only_default_initializable_and_equality_comparable_iter_value = + std::default_initializable> && + std::equality_comparable_with, + std::iter_value_t>; // @*exposition only*@ + +struct null_sentinel_t { + template + requires(not std::forward_iterator) && + exposition_only_default_initializable_and_equality_comparable_iter_value + friend constexpr bool operator==(I const& it, null_sentinel_t) { + return *it == std::iter_value_t{}; + } + template + requires exposition_only_default_initializable_and_equality_comparable_iter_value + friend constexpr bool operator==(I it, null_sentinel_t) { + return *it == std::iter_value_t{}; + } +}; + +inline constexpr null_sentinel_t null_sentinel; + +/* !PAPER */ + +namespace detail { + + struct null_term_impl { + template + requires exposition_only_default_initializable_and_equality_comparable_iter_value + constexpr auto operator()(I it) const { + return std::ranges::subrange(std::move(it), null_sentinel); + } + }; + +} // namespace detail + +inline constexpr detail::null_term_impl null_term; + +/* PAPER: inline constexpr @*unspecified*@ null_term; */ +/* PAPER: */ + +} // namespace utfview + +/* PAPER: } */ + +#endif // UTFVIEW_NULL_TERM_HPP diff --git a/include/UtfView/to_utf_view.hpp b/include/UtfView/to_utf_view.hpp new file mode 100644 index 0000000..29ece7c --- /dev/null +++ b/include/UtfView/to_utf_view.hpp @@ -0,0 +1,1210 @@ +// SPDX-License-Identifier: GPL-3.0-only + +#ifndef UTFVIEW_TO_UTF_VIEW_HPP +#define UTFVIEW_TO_UTF_VIEW_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace utfview { + +namespace detail { + + constexpr bool in(unsigned char lo, unsigned char c, unsigned char hi) { + return lo <= c && c <= hi; + } + + constexpr bool lead_code_unit(char8_t c) { + return static_cast(c - 0xc2) <= 0x32; + } + + constexpr bool is_ascii(char8_t c) { + return static_cast(c) < 0x80; + } + + constexpr bool continuation(char8_t c) { + return static_cast(c) < -0x40; + } + + constexpr int utf8_code_units(char8_t first_unit) { + return first_unit <= 0x7f ? 1 + : lead_code_unit(first_unit) + ? static_cast(0xe0 <= first_unit) + static_cast(0xf0 <= first_unit) + 2 + : -1; + } + + constexpr bool high_surrogate(char16_t c) { + return 0xD800 <= c && c <= 0xDBFF; + } + + constexpr bool low_surrogate(char16_t c) { + return 0xDC00 <= c && c <= 0xDFFF; + } + + inline CONSTEXPR_UNLESS_MSVC void erroneous() { +#ifndef _MSC_VER + if !consteval { +#endif +#ifndef NDEBUG + erroneous_behavior_global() = true; +#endif +#ifndef _MSC_VER + } +#endif + } + +} // namespace detail + +/* PAPER: namespace std::uc { */ + +/* PAPER */ + +template +consteval auto exposition_only_bidirectional_at_most() { // @*exposition only*@ + if constexpr (std::bidirectional_iterator) { + return std::bidirectional_iterator_tag{}; + } else if constexpr (std::forward_iterator) { + return std::forward_iterator_tag{}; + } else if constexpr (std::input_iterator) { + return std::input_iterator_tag{}; + } +} + +template +using exposition_only_bidirectional_at_most_t = + decltype(exposition_only_bidirectional_at_most()); // @*exposition only*@ + +enum class transcoding_error { + truncated_utf8_sequence, + unpaired_high_surrogate, + unpaired_low_surrogate, + unexpected_utf8_continuation_byte, + overlong, + encoded_surrogate, + out_of_range, + invalid_utf8_leading_byte +}; + +/* !PAPER */ + +template +concept exposition_only_to_utf_view_iterator_optimizable = + std::bidirectional_iterator && + requires { typename T::reserved_to_utf_view_iterator; }; + +/* PAPER */ + +/* PAPER: template */ +/* PAPER: concept exposition_only_to_utf_view_iterator_optimizable = @*unspecified*@ // @*exposition only*@ */ + +template +concept exposition_only_from_utf_view = + exposition_only_utf_range && std::ranges::view && + (!exposition_only_to_utf_view_iterator_optimizable> || + exposition_only_to_utf_view_iterator_optimizable>); + +template +class exposition_only_to_utf_view_impl + : public std::ranges::view_interface> { +public: + template + class exposition_only_utf_iterator + : public boost::stl_interfaces::iterator_interface< + exposition_only_bidirectional_at_most_t>, ToType, + ToType> { + + /* !PAPER */ + public: + using reserved_to_utf_view_iterator = void; + + /* PAPER */ + private: + using exposition_only_iter = + std::ranges::iterator_t>; + using exposition_only_sent = + std::ranges::sentinel_t>; + + template + friend class exposition_only_to_utf_view_impl; // @*exposition only*@ + + template + struct exposition_only_first_and_curr { // @*exposition only*@ + exposition_only_first_and_curr() = default; + constexpr exposition_only_first_and_curr(I curr) + : curr(std::move(curr)) { } + + I curr; + }; + template + struct exposition_only_first_and_curr { // @*exposition only*@ + exposition_only_first_and_curr() = default; + constexpr exposition_only_first_and_curr(I first, I curr) + : first(first), + curr(curr) { } + + I first; + I curr; + }; + + /* PAPER: using @*innermost-iter*@ = @*unspecified*@; // @*exposition only*@ */ + + /* !PAPER */ + template + struct innermost_iter_trait { + using type = Iter; + }; + + template + struct innermost_iter_trait { + using type = Iter::exposition_only_innermost_iter; + }; + + template + struct innermost_sent_trait { + using type = Sent; + }; + + template + struct innermost_sent_trait { + using type = Sent::exposition_only_innermost_sent; + }; + + using exposition_only_innermost_iter = + innermost_iter_trait::type; + + using exposition_only_innermost_sent = + innermost_sent_trait::type; + + /* PAPER */ + using exposition_only_from_type = decltype([] { + if constexpr (std::is_same_v>) { + return char8_t{}; + } else if constexpr (std::is_same_v< + wchar_t, + std::iter_value_t>) { + if constexpr (sizeof(wchar_t) == 2) { + return char16_t{}; + } else if constexpr (sizeof(wchar_t) == 4) { + return char32_t{}; + } + } else { + return std::iter_value_t{}; + } + }()); // @*exposition only *@ + + /* PAPER: using @*innermost-iter*@ = @*unspecified*@; // @*exposition only*@ */ + /* PAPER: using @*innermost-sent*@ = @*unspecified*@; // @*exposition only*@ */ + + public: + using value_type = ToType; + using reference_type = ToType&; + using difference_type = ptrdiff_t; + using iterator_concept = + exposition_only_bidirectional_at_most_t; + + CONSTEXPR_UNLESS_MSVC exposition_only_utf_iterator() + requires std::default_initializable + = default; + + private: + constexpr exposition_only_utf_iterator( + exposition_only_innermost_iter first, exposition_only_innermost_iter it, + exposition_only_innermost_sent last) // @*exposition only*@ + requires std::bidirectional_iterator + : first_and_curr_(first, it), + last_(last) { + if (curr() != last_) + read(); + } + constexpr exposition_only_utf_iterator( + exposition_only_innermost_iter it, + exposition_only_innermost_sent last) // @*exposition only*@ + requires(!std::bidirectional_iterator) + : first_and_curr_(std::move(it)), + last_(last) { + if (curr() != last_) + read(); + } + + public: + CONSTEXPR_UNLESS_MSVC exposition_only_utf_iterator() = default; + CONSTEXPR_UNLESS_MSVC exposition_only_utf_iterator( + exposition_only_utf_iterator const&) + requires std::copyable + = default; + + CONSTEXPR_UNLESS_MSVC exposition_only_utf_iterator& operator=( + exposition_only_utf_iterator const&) + requires std::copyable + = default; + + constexpr exposition_only_utf_iterator(exposition_only_utf_iterator&&) = default; + + constexpr exposition_only_utf_iterator& operator=(exposition_only_utf_iterator&&) = + default; + + constexpr exposition_only_iter base() const + requires std::forward_iterator + { + if constexpr (exposition_only_to_utf_view_iterator_optimizable< + exposition_only_iter>) { + if constexpr (std::bidirectional_iterator) { + return exposition_only_iter(begin(), curr(), last_); + } else { + return exposition_only_iter(curr(), last_); + } + } else { + return curr(); + } + } + + constexpr exposition_only_iter base() && + requires(!std::forward_iterator) { + return std::move(*this).curr(); + } + + /* PAPER: constexpr expected success() const; */ + + /* !PAPER */ + + constexpr std::expected success() const { + return success_; + } + + /* PAPER */ + + /* PAPER: constexpr value_type operator*() const; */ + /* !PAPER */ + constexpr value_type operator*() const { +#ifndef NDEBUG + if (*this == last_) { + detail::erroneous(); + } +#endif + if constexpr (std::forward_iterator) { + return buf_[buf_index_]; + } else { + return buf_[buf_index_ & 3]; + } + } + /* PAPER */ + + constexpr exposition_only_utf_iterator& operator++() { + if constexpr (std::forward_iterator) { + if (buf_index_ + 1 < buf_last_) { + ++buf_index_; + } else if (buf_index_ + 1 == buf_last_) { +/* !PAPER */ +#ifndef NDEBUG + if (curr() == last_) { + detail::erroneous(); + } +#endif + /* PAPER */ + std::advance(curr(), to_increment_); + to_increment_ = 0; + if (curr() != last_) { + read(); + } else { + buf_index_ = 0; + } + } + } else { + if (buf_index_ + 1 == buf_last_ && curr() != last_) { + read(); + } else if (buf_index_ + 1 <= buf_last_) { + ++buf_index_; + } +/* !PAPER */ +#ifndef NDEBUG + else if (curr() == last_) { + detail::erroneous(); + } +#endif + /* PAPER */ + } + return *this; + } + + constexpr auto operator++(int) { + if constexpr (std::is_same_v) { + ++*this; + } else { + auto retval = *this; + ++*this; + return retval; + } + } + + constexpr exposition_only_utf_iterator& operator--() + requires std::bidirectional_iterator + { + if (!buf_index_) + read_reverse(); + else if (buf_index_) + --buf_index_; + return *this; + } + + constexpr exposition_only_utf_iterator operator--(int) + requires std::bidirectional_iterator + { + auto retval = *this; + --*this; + return retval; + } + + friend constexpr bool operator==(exposition_only_utf_iterator const& lhs, + exposition_only_utf_iterator const& rhs) + requires std::forward_iterator || + requires(exposition_only_innermost_iter i) { i != i; } + { + if constexpr (std::forward_iterator) { + return lhs.curr() == rhs.curr() && lhs.buf_index_ == rhs.buf_index_; + } else { + if (lhs.curr() != rhs.curr()) + return false; + + if (lhs.buf_index_ == rhs.buf_index_ && lhs.buf_last_ == rhs.buf_last_) { + return true; + } + + return lhs.buf_index_ == lhs.buf_last_ && rhs.buf_index_ == rhs.buf_last_; + } + } + + friend constexpr bool operator==(exposition_only_utf_iterator const& lhs, + exposition_only_innermost_sent rhs) + requires std::copyable + { + if constexpr (std::forward_iterator) { + return lhs.curr() == rhs; + } else { + return lhs.curr() == rhs && lhs.buf_index_ == lhs.buf_last_; + } + } + + friend constexpr bool operator==(exposition_only_utf_iterator const& lhs, + exposition_only_innermost_sent rhs) + requires(!std::copyable) + { + return lhs.curr() == rhs && lhs.buf_index_ == lhs.buf_last_; + } + + /* !PAPER */ + + private: + struct decode_code_point_result { + char32_t c; + std::uint8_t to_incr; + std::expected success; + }; + + template + struct guard { + constexpr guard(exposition_only_innermost_iter&, exposition_only_innermost_iter&) { + } + }; + + template + requires std::forward_iterator + struct guard { + constexpr ~guard() { + curr = std::move(orig); + } + It& curr; + It orig; + }; + + /* PAPER */ + + constexpr exposition_only_innermost_iter begin() const // @*exposition only*@ + requires std::bidirectional_iterator + { + return first_and_curr_.first; + } + constexpr exposition_only_innermost_sent end() const { // @*exposition only*@ + return last_; + } + + /* !PAPER */ + + static constexpr decode_code_point_result decode_code_point_utf8_impl( + exposition_only_innermost_iter& it, exposition_only_innermost_sent const& last) { + char32_t c{}; + std::uint8_t u = *it; + ++it; + const std::uint8_t lo_bound = 0x80, hi_bound = 0xBF; + std::uint8_t to_incr = 1; + std::expected success{}; + + auto const error{[&](transcoding_error const error_enum_in) { + success = std::unexpected{error_enum_in}; + c = U'\uFFFD'; + }}; + + if (u <= 0x7F) [[likely]] // 0x00 to 0x7F + c = u; + else if (u < 0xC0) [[unlikely]] { + error(transcoding_error::unexpected_utf8_continuation_byte); + } else if (u < 0xC2 || u > 0xF4) [[unlikely]] { + error(transcoding_error::invalid_utf8_leading_byte); + } else if (it == last) [[unlikely]] { + error(transcoding_error::truncated_utf8_sequence); + } else if (u <= 0xDF) // 0xC2 to 0xDF + { + c = u & 0x1F; + u = *it; + + if (u < lo_bound || u > hi_bound) [[unlikely]] + error(transcoding_error::truncated_utf8_sequence); + else { + c = (c << 6) | (u & 0x3F); + ++it; + ++to_incr; + } + } else if (u <= 0xEF) // 0xE0 to 0xEF + { + std::uint8_t orig = u; + c = u & 0x0F; + u = *it; + + if (orig == 0xE0 && 0x80 <= u && u < 0xA0) [[unlikely]] + error(transcoding_error::overlong); + else if (orig == 0xED && 0xA0 <= u && u < 0xC0) [[unlikely]] + error(transcoding_error::encoded_surrogate); + else if (u < lo_bound || u > hi_bound) [[unlikely]] + error(transcoding_error::truncated_utf8_sequence); + else if (++it == last) { + [[unlikely]]++ to_incr; + error(transcoding_error::truncated_utf8_sequence); + } else { + ++to_incr; + c = (c << 6) | (u & 0x3F); + u = *it; + + if (u < lo_bound || u > hi_bound) [[unlikely]] + error(transcoding_error::truncated_utf8_sequence); + else { + c = (c << 6) | (u & 0x3F); + ++it; + ++to_incr; + } + } + } else if (u <= 0xF4) // 0xF0 to 0xF4 + { + std::uint8_t orig = u; + c = u & 0x07; + u = *it; + + if (orig == 0xF0 && 0x80 <= u && u < 0x90) [[unlikely]] + error(transcoding_error::overlong); + else if (orig == 0xF4 && 0x90 <= u && u < 0xC0) [[unlikely]] + error(transcoding_error::out_of_range); + else if (u < lo_bound || u > hi_bound) [[unlikely]] + error(transcoding_error::truncated_utf8_sequence); + else if (++it == last) { + [[unlikely]]++ to_incr; + error(transcoding_error::truncated_utf8_sequence); + } else { + ++to_incr; + c = (c << 6) | (u & 0x3F); + u = *it; + + if (u < lo_bound || u > hi_bound) [[unlikely]] + error(transcoding_error::truncated_utf8_sequence); + else if (++it == last) { + [[unlikely]]++ to_incr; + error(transcoding_error::truncated_utf8_sequence); + } else { + ++to_incr; + c = (c << 6) | (u & 0x3F); + u = *it; + + if (u < lo_bound || u > hi_bound) [[unlikely]] + error(transcoding_error::truncated_utf8_sequence); + else { + c = (c << 6) | (u & 0x3F); + ++it; + ++to_incr; + } + } + } + } + + return {.c{c}, .to_incr{to_incr}, .success{success}}; + } + + constexpr decode_code_point_result decode_code_point_utf8() { + guard g{curr(), curr()}; + return decode_code_point_utf8_impl(curr(), last_); + } + + static constexpr decode_code_point_result decode_code_point_utf16_impl( + exposition_only_innermost_iter& it, exposition_only_innermost_sent const& last) { + char32_t c{}; + std::uint16_t u = *it; + ++it; + std::uint8_t to_incr = 1; + std::expected success{}; + + auto const error{[&](transcoding_error const error_enum_in) { + success = std::unexpected{error_enum_in}; + c = U'\uFFFD'; + }}; + + if (u < 0xD800 || u > 0xDFFF) [[likely]] + c = u; + else if (u < 0xDC00) { + if (it == last) [[unlikely]] { + error(transcoding_error::unpaired_high_surrogate); + } else { + std::uint16_t u2 = *it; + if (u2 < 0xDC00 || u2 > 0xDFFF) [[unlikely]] + error(transcoding_error::unpaired_high_surrogate); + else { + ++it; + to_incr = 2; + std::uint32_t x = (u & 0x3F) << 10 | (u2 & 0x3FF); + std::uint32_t w = (u >> 6) & 0x1F; + c = (w + 1) << 16 | x; + } + } + } else + error(transcoding_error::unpaired_low_surrogate); + + return {.c{c}, .to_incr{to_incr}, .success{success}}; + } + + constexpr decode_code_point_result decode_code_point_utf16() { + guard g{curr(), curr()}; + return decode_code_point_utf16_impl(curr(), last_); + } + + static constexpr decode_code_point_result decode_code_point_utf32_impl( + exposition_only_innermost_iter& it) { + char32_t c = *it; + std::expected success{}; + ++it; + auto const error{[&](transcoding_error const error_enum_in) { + success = std::unexpected{error_enum_in}; + c = U'\uFFFD'; + }}; + if (c >= 0xD800) { + if (c < 0xE000) { + error(transcoding_error::encoded_surrogate); + } + if (c > 0x10FFFF) { + error(transcoding_error::out_of_range); + } + } + return {.c{c}, .to_incr{1}, .success{success}}; + } + + constexpr decode_code_point_result decode_code_point_utf32() { + guard g{curr(), curr()}; + return decode_code_point_utf32_impl(curr()); + } + + // Encode the code point c as one or more code units in buf. + constexpr void update(char32_t c, std::uint8_t to_incr) { + to_increment_ = to_incr; + buf_index_ = 0; + if constexpr (std::is_same_v) { + buf_[0] = c; + buf_last_ = 1; + } else if constexpr (std::is_same_v) { + if (c <= std::numeric_limits::max()) { + buf_[0] = c; + buf_[1] = 0; + buf_last_ = 1; + } else { + // From http://www.unicode.org/faq/utf_bom.html#utf16-4 + const char32_t lead_offset = 0xD800 - (0x10000 >> 10); + char16_t lead = lead_offset + (c >> 10); + char16_t trail = 0xDC00 + (c & 0x3FF); + buf_[0] = lead; + buf_[1] = trail; + buf_last_ = 2; + } + } else if constexpr (std::is_same_v) { + int bits = std::bit_width(static_cast(c)); + if (bits <= 7) [[likely]] { + buf_[0] = c; + buf_[1] = buf_[2] = buf_[3] = 0; + buf_last_ = 1; + } else if (bits <= 11) { + buf_[0] = 0xC0 | (c >> 6); + buf_[1] = 0x80 | (c & 0x3F); + buf_[2] = buf_[3] = 0; + buf_last_ = 2; + } else if (bits <= 16) { + buf_[0] = 0xE0 | (c >> 12); + buf_[1] = 0x80 | ((c >> 6) & 0x3F); + buf_[2] = 0x80 | (c & 0x3F); + buf_[3] = 0; + buf_last_ = 3; + } else { + buf_[0] = 0xF0 | ((c >> 18) & 0x07); + buf_[1] = 0x80 | ((c >> 12) & 0x3F); + buf_[2] = 0x80 | ((c >> 6) & 0x3F); + buf_[3] = 0x80 | (c & 0x3F); + buf_last_ = 4; + } + } else { + static_assert(false); + } + } + + /* PAPER: constexpr void read(); // @*exposition only*@ */ + /* PAPER: */ + + constexpr void read() { // @*exposition only*@ + success_.emplace(); + decode_code_point_result decode_result{}; + if constexpr (std::is_same_v) + decode_result = decode_code_point_utf8(); + else if constexpr (std::is_same_v) + decode_result = decode_code_point_utf16(); + else if constexpr (std::is_same_v) { + decode_result = decode_code_point_utf32(); + } else { + static_assert(false); + } + update(decode_result.c, decode_result.to_incr); + success_ = decode_result.success; + } + + struct read_reverse_impl_result { + decode_code_point_result decode_result; + exposition_only_innermost_iter new_curr; + }; + + constexpr read_reverse_impl_result read_reverse_utf8() const { + assert(curr() != begin()); + auto it{curr()}; + auto const orig{it}; + unsigned reversed{}; + do { + --it; + ++reversed; + } while (it != begin() && detail::continuation(*it) && reversed < 4); + if (detail::continuation(*it)) { + auto new_curr{orig}; + --new_curr; + return { + .decode_result{.c{U'\uFFFD'}, + .to_incr{1}, + .success{std::unexpected{ + transcoding_error::unexpected_utf8_continuation_byte}}}, + .new_curr{new_curr}}; + } else if (detail::is_ascii(*it) || detail::lead_code_unit(*it)) { + int const expected_reversed{detail::utf8_code_units(*it)}; + assert(expected_reversed > 0); + if (reversed > static_cast(expected_reversed)) { + auto new_curr{orig}; + --new_curr; + return { + .decode_result{.c{U'\uFFFD'}, + .to_incr{1}, + .success{std::unexpected{ + transcoding_error::unexpected_utf8_continuation_byte}}}, + .new_curr{new_curr}}; + } else { + auto lead{it}; + decode_code_point_result const decode_result{ + decode_code_point_utf8_impl(it, end())}; + if (decode_result.success || + decode_result.success == + std::unexpected{transcoding_error::truncated_utf8_sequence}) { + assert(decode_result.to_incr == reversed); + return {.decode_result{decode_result}, .new_curr{lead}}; + } else { + auto new_curr{orig}; + --new_curr; + return { + .decode_result{ + .c{U'\uFFFD'}, + .to_incr{1}, + .success{ + reversed == 1 + ? decode_result.success + : std::unexpected{transcoding_error:: + unexpected_utf8_continuation_byte}}}, + .new_curr{new_curr}}; + } + } + } else { + assert(detail::in(0xC0, *it, 0xC2) || detail::in(0xF5, *it, 0xFF)); + it = orig; + --it; + return { + .decode_result{ + .c{U'\uFFFD'}, + .to_incr{1}, + .success{ + reversed == 1 + ? std::unexpected{transcoding_error::invalid_utf8_leading_byte} + : std::unexpected{transcoding_error:: + unexpected_utf8_continuation_byte}}}, + .new_curr{it}}; + } + } + + constexpr read_reverse_impl_result read_reverse_utf16() const { + assert(curr() != begin()); + auto it{curr()}; + auto const orig{it}; + --it; + if (detail::high_surrogate(*it)) { + return {.decode_result{.c{U'\uFFFD'}, + .to_incr{1}, + .success{std::unexpected{ + transcoding_error::unpaired_high_surrogate}}}, + .new_curr{it}}; + } else if (detail::low_surrogate(*it)) { + if (it == begin()) { + return {.decode_result{.c{U'\uFFFD'}, + .to_incr{1}, + .success{std::unexpected{ + transcoding_error::unpaired_low_surrogate}}}, + .new_curr{it}}; + } else { + --it; + if (detail::high_surrogate(*it)) { + auto lead{it}; + return {.decode_result{decode_code_point_utf16_impl(it, end())}, + .new_curr{lead}}; + } else { + auto new_curr{orig}; + --new_curr; + return {.decode_result{.c{U'\uFFFD'}, + .to_incr{1}, + .success{std::unexpected{ + transcoding_error::unpaired_low_surrogate}}}, + .new_curr{new_curr}}; + } + } + } else { + return {.decode_result{.c{*it}, .to_incr{1}, .success{}}, .new_curr{it}}; + } + } + + constexpr read_reverse_impl_result read_reverse_utf32() const { + assert(curr() != begin()); + auto it{curr()}; + auto const orig{it}; + --it; + auto new_curr{orig}; + --new_curr; + return {.decode_result{decode_code_point_utf32_impl(it)}, .new_curr{new_curr}}; + } + + /* PAPER: constexpr void read_reverse(); // @*exposition only*@ */ + + constexpr void read_reverse() { // @*exposition only*@ + if (curr() == begin()) { + detail::erroneous(); + return; + } + success_.emplace(); + auto const read_reverse_impl_result{[&] { + if constexpr (std::is_same_v) { + return read_reverse_utf8(); + } else if constexpr (std::is_same_v) { + return read_reverse_utf16(); + } else if constexpr (std::is_same_v) { + return read_reverse_utf32(); + } + }()}; + update(read_reverse_impl_result.decode_result.c, + read_reverse_impl_result.decode_result.to_incr); + success_ = read_reverse_impl_result.decode_result.success; + curr() = read_reverse_impl_result.new_curr; + assert(buf_last_); + buf_index_ = buf_last_ - 1; + } + + /* PAPER */ + + constexpr exposition_only_innermost_iter& curr() & { + return first_and_curr_.curr; + } // @*exposition only*@ + + constexpr exposition_only_innermost_iter const& curr() const& { + return first_and_curr_.curr; + } // @*exposition only*@ + + constexpr exposition_only_innermost_iter curr() && { + return std::move(first_and_curr_.curr); + } // @*exposition only*@ + + std::array buf_{}; // @*exposition only*@ + + exposition_only_first_and_curr + first_and_curr_; // @*exposition only*@ + + [[no_unique_address]] exposition_only_innermost_sent last_; // @*exposition only*@ + + std::uint8_t buf_index_ = 0; // @*exposition only*@ + std::uint8_t buf_last_ = 0; // @*exposition only*@ + std::uint8_t to_increment_ = 0; // @*exposition only*@ + + /* !PAPER */ + std::expected success_{}; // @*exposition only*@ + /* PAPER */ + }; + +private: + template + static constexpr auto make_begin(auto first, auto last) { // @*exposition only*@ + if constexpr (std::bidirectional_iterator>) { + if constexpr (exposition_only_to_utf_view_iterator_optimizable< + std::ranges::iterator_t>) { + return exposition_only_utf_iterator(first.begin(), first.curr(), + first.last_); + } else { + return exposition_only_utf_iterator(first, first, last); + } + } else { + return exposition_only_utf_iterator(std::move(first), last); + } + } + template + static constexpr auto make_end(auto first, auto last) { // @*exposition only*@ + if constexpr (std::bidirectional_iterator>) { + if constexpr (exposition_only_to_utf_view_iterator_optimizable< + std::ranges::sentinel_t>) { + return exposition_only_utf_iterator(last.begin(), last.curr(), last.last_); + } else { + return exposition_only_utf_iterator(first, last, last); + } + } else { + return last; + } + } + + V base_ = V(); // @*exposition only*@ + +public: + constexpr exposition_only_to_utf_view_impl() + requires std::default_initializable + = default; + constexpr exposition_only_to_utf_view_impl(V base) + : base_(std::move(base)) { } + + constexpr V base() const& + requires std::copy_constructible + { + return base_; + } + constexpr V base() && { + return std::move(base_); + } + + constexpr auto begin() + requires(!std::copyable>) + { + return make_begin(std::ranges::begin(base_), std::ranges::end(base_)); + } + constexpr auto begin() const + requires std::copyable> + { + return make_begin(std::ranges::begin(base_), std::ranges::end(base_)); + } + + constexpr auto end() + requires(!std::copyable>) + { + return make_end(std::ranges::begin(base_), std::ranges::end(base_)); + } + constexpr auto end() const + requires std::copyable> + { + return make_end(std::ranges::begin(base_), std::ranges::end(base_)); + } + + constexpr bool empty() const { + return std::ranges::empty(base_); + } +}; + +template +class to_utf8_view { +private: + using exposition_only_iterator = + std::ranges::iterator_t>; + using exposition_only_sentinel = + std::ranges::sentinel_t>; + +public: + constexpr to_utf8_view() + requires std::default_initializable + = default; + constexpr to_utf8_view(V base) + : impl_(std::move(base)) { } + + constexpr V base() const& + requires std::copy_constructible + { + return impl_.base(); + } + constexpr V base() && { + return std::move(impl_).base(); + } + + constexpr auto begin() + requires(!std::copyable) + { + return impl_.begin(); + } + constexpr auto begin() const + requires std::copyable + { + return impl_.begin(); + } + + constexpr auto end() + requires(!std::copyable) + { + return impl_.end(); + } + constexpr auto end() const + requires std::copyable + { + return impl_.end(); + } + + constexpr bool empty() const { + return impl_.empty(); + } + +private: + exposition_only_to_utf_view_impl impl_; +}; + +template +to_utf8_view(R&&) -> to_utf8_view>; + +template +class to_utf16_view { +private: + using exposition_only_iterator = + std::ranges::iterator_t>; + using exposition_only_sentinel = + std::ranges::sentinel_t>; + +public: + constexpr to_utf16_view() + requires std::default_initializable + = default; + constexpr to_utf16_view(V base) + : impl_(std::move(base)) { } + + constexpr V base() const& + requires std::copy_constructible + { + return impl_.base(); + } + constexpr V base() && { + return std::move(impl_).base(); + } + + constexpr auto begin() + requires(!std::copyable) + { + return impl_.begin(); + } + constexpr auto begin() const + requires std::copyable + { + return impl_.begin(); + } + + constexpr auto end() + requires(!std::copyable) + { + return impl_.end(); + } + constexpr auto end() const + requires std::copyable + { + return impl_.end(); + } + + constexpr bool empty() const { + return impl_.empty(); + } + +private: + exposition_only_to_utf_view_impl impl_; +}; + +template +to_utf16_view(R&&) -> to_utf16_view>; + +template +class to_utf32_view { +private: + using exposition_only_iterator = + std::ranges::iterator_t>; + using exposition_only_sentinel = + std::ranges::sentinel_t>; + +public: + constexpr to_utf32_view() + requires std::default_initializable + = default; + constexpr to_utf32_view(V base) + : impl_(std::move(base)) { } + + constexpr V base() const& + requires std::copy_constructible + { + return impl_.base(); + } + constexpr V base() && { + return std::move(impl_).base(); + } + + constexpr auto begin() + requires(!std::copyable) + { + return impl_.begin(); + } + constexpr auto begin() const + requires std::copyable + { + return impl_.begin(); + } + + constexpr auto end() + requires(!std::copyable) + { + return impl_.end(); + } + constexpr auto end() const + requires std::copyable + { + return impl_.end(); + } + + constexpr bool empty() const { + return impl_.empty(); + } + +private: + exposition_only_to_utf_view_impl impl_; +}; + +template +to_utf32_view(R&&) -> to_utf32_view>; + +/* !PAPER */ + +namespace detail { + + template + using to_utf_view = std::conditional_t< + std::is_same_v, to_utf8_view, + std::conditional_t< + std::is_same_v, to_utf16_view, + std::conditional_t, to_utf32_view, void>>>; + + template + struct to_utf_impl : std::ranges::range_adaptor_closure> { + template + constexpr auto operator()(R&& r) const { + using T = std::remove_cvref_t; + if constexpr (exposition_only_is_empty_view) { + return std::ranges::empty_view{}; + } else if constexpr (std::is_bounded_array_v) { + constexpr auto n = std::extent_v; + auto first{std::ranges::begin(r)}; + auto last{std::ranges::end(r)}; + if (n && !r[n - 1]) { + --last; + } + std::ranges::subrange subrange(first, last); + return to_utf_view(std::move(subrange)); + } else { + auto view = std::views::all(std::forward(r)); + return to_utf_view(std::move(view)); + } + } + }; + +} // namespace detail + +template +inline constexpr detail::to_utf_impl to_utf; + +inline constexpr detail::to_utf_impl to_utf8; + +inline constexpr detail::to_utf_impl to_utf16; + +inline constexpr detail::to_utf_impl to_utf32; + +/* PAPER: template<@*code-unit-to*@ ToType> */ +/* PAPER: inline constexpr @*unspecified*@ to_utf; */ +/* PAPER: */ +/* PAPER: inline constexpr @*unspecified*@ to_utf8; */ +/* PAPER: */ +/* PAPER: inline constexpr @*unspecified*@ to_utf16; */ +/* PAPER: */ +/* PAPER: inline constexpr @*unspecified*@ to_utf32; */ + +} // namespace utfview + +/* PAPER: } */ + +template +inline constexpr bool std::ranges::enable_borrowed_range< + utfview::exposition_only_to_utf_view_impl> = + std::ranges::enable_borrowed_range; + +template +inline constexpr bool std::ranges::enable_borrowed_range> = + std::ranges::enable_borrowed_range; + +template +inline constexpr bool std::ranges::enable_borrowed_range> = + std::ranges::enable_borrowed_range; + +template +inline constexpr bool std::ranges::enable_borrowed_range> = + std::ranges::enable_borrowed_range; + +/* PAPER: namespace std::ranges { */ +/* PAPER: */ +/* PAPER: template */ +/* PAPER: inline constexpr bool enable_borrowed_range< */ +/* PAPER: std::uc::exposition_only_to_utf_view_impl> = enable_borrowed_range; */ +/* PAPER: */ +/* PAPER: template */ +/* PAPER: inline constexpr bool enable_borrowed_range> = enable_borrowed_range; */ +/* PAPER: */ +/* PAPER: template */ +/* PAPER: inline constexpr bool enable_borrowed_range> = enable_borrowed_range; */ +/* PAPER: */ +/* PAPER: template */ +/* PAPER: inline constexpr bool enable_borrowed_range> = enable_borrowed_range; */ +/* PAPER: */ +/* PAPER: } */ + +#endif // UTFVIEW_TO_UTF_VIEW_HPP diff --git a/include/UtfView/utfview.hpp b/include/UtfView/utfview.hpp new file mode 100644 index 0000000..67186e7 --- /dev/null +++ b/include/UtfView/utfview.hpp @@ -0,0 +1,8 @@ +#ifndef UTFVIEW_UTFVIEW_HPP +#define UTFVIEW_UTFVIEW_HPP + +#include +#include +#include + +#endif UTFVIEW_UTFVIEW_HPP diff --git a/paper/CMakeLists.txt b/paper/CMakeLists.txt new file mode 100644 index 0000000..f518625 --- /dev/null +++ b/paper/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-3.0-only + +add_custom_command( + OUTPUT P2728.html + COMMAND SRCDIR=${CMAKE_CURRENT_SOURCE_DIR} OUTDIR=${CMAKE_CURRENT_BINARY_DIR} make -C ${CMAKE_CURRENT_SOURCE_DIR}/../deps/wg21 html + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/P2728.md + VERBATIM) +add_custom_target(p2728 DEPENDS P2728.html) diff --git a/paper/P2728.md b/paper/P2728.md new file mode 100644 index 0000000..e8e1947 --- /dev/null +++ b/paper/P2728.md @@ -0,0 +1,6449 @@ +--- +title: "Unicode in the Library, Part 1: UTF Transcoding" +document: P2728R7 +date: 2024-10-06 +audience: + - SG-16 Unicode + - SG-9 Ranges + - LEWG +author: + - name: Eddie Nolan + email: +toc: true +monofont: "DejaVu Sans Mono" + +--- + +# Changelog + +## Changes since R0 + +- When naming code points in interfaces, use `char32_t`. +- When naming code units in interfaces, use `charN_t`. +- Remove each eager algorithm, leaving in its corresponding view. +- Remove all the output iterators. +- Change template parameters to `utfN_view` to the types of the from-range, + instead of the types of the transcoding iterators used to implement the view. +- Remove all make-functions. +- Replace the misbegotten `as_utfN()` functions with the `as_utfN` view + adaptors that should have been there all along. +- Add missing `transcoding_error_handler` concept. +- Turn `unpack_iterator_and_sentinel` into a CPO. +- Lower the UTF iterator concepts from bidirectional to input. + +## Changes since R1 + +- Reintroduce the transcoding-from-a-buffer example. +- Generalize `null_sentinel_t` to a non-Unicode-specific facility. +- In utility functions that search for ill-formed encoding, take a range + argument instead of a pair of iterator arguments. +- Replace `utf{8,16,32}_view` with a single `utf_view`. + +## Changes since R2 + +- Add `noexcept` where appropriate. +- Remove non-essential constants and utility functions, and elaborate on the + usage of the ones that remain. +- Note differences from similar elements proposed in [@P1629R1]. +- Extend the examples slightly. +- Correct an error in the description of the view adaptors' semantics, and + provide several examples of their use. + +## Changes since R3 + +- Changed the definition of the `code_unit` concept, and added `as_charN_t` + adaptors. +- Removed the utility functions and Unicode-related constants, except + `replacement_character`. +- Changed the constraint on `utf_iterator` slightly. +- Change `null_sentinel_t` back to being Unicode-specific. + +## Changes since R4 + +- Replace `unpacking_owning_view` with `unpacking_view`, and use it to do + unpacking, rather than sometimes doing the unpacking in the adaptor. +- Ensure `const` and non-`const` overloads for `begin` and `end` in all views. +- Move `null_sentinel_t` to `std`, remove its `base` member function, and make + it useful for more than just pointers, based on SG-9 guidance. + +## Changes since R5 + +- Simplify the complicated constraint on the comparison operator for + `null_sentinel_t`. +- Introduce `ranges::project_view`, and implement `charN_view`s in terms of + that. +- Convert the `utfN_view`s to aliases, rather than individual classes. + +## Changes since R6 + +- Fix a bug in `null_sentinel_t` causing it not to satisfy `sentinel_for` by + changing its `operator==` to return `bool`. +- Fix a bug in `null_sentinel_t` where it did not support non-copyable input + iterators by having operator== take input iterators by reference. +- Rename `as_utfN` to `to_utfN` to emphasize that a conversion is taking place + and to contrast with the code unit views, which remain named `as_charN_t`. +- Refactor `utf_view` into an exposition-only `@*utf-view-impl*@` class used + as an implementation detail of separate `to_utf8_view`, `to_utf16_view`, and + `to_utf32_view` classes, addressing broken deduction guides in the previous + revision. +- Remove `project_view` and copy most of its implementation into separate + `char8_view`, `char16_view`, and `char32_view` classes, addressing broken + deduction guides in the previous revision. +- Change `utf_iterator` to an exposition-only member class of + `@*utf-view-impl*@`. +- Eliminate iterator unpacking mechanism and replace it with an alternative + solution to the problem of transcoding ranges wrapping other transcoding + ranges. This simplifies the API at the expense of removing the transcoding + iterator's `begin()` and `end()` member functions and losing the ability to + implement unpacking for user-defined UTF iterators. +- Remove `std::uc::format`. +- Make all concepts exposition-only. +- Remove `transcoding_error_handler` mechanism. +- Introduce new error handling mechanism based on a new `transcoding_error` + enumeration which is returned by an `success()` member function of the + transcoding view's iterator. +- Remove ability to pass pointers to range adaptor closure objects, which + violated the restriction that only ranges may be passed to range adaptor + closure objects. +- Remove `std::format` and `std::ostream` functionality. It doesn't make sense + for this mechanism to be the only way we have to format/output `char8_t`; we + can revisit this functionality when we have already figured out how to + support e.g. `std::u8string`. +- Replace code examples with new ones reflecting API changes. +- Provide a reference implementation. + +# Motivation + +Unicode is important to many, many users in everyday software. It is not +exotic or weird. Well, it's weird, but it's not weird to see it used. C and +C++ are the only major production languages with essentially no support for +Unicode. + +Let's fix. + +To fix, first we start with the most basic representations of strings in +Unicode: UTF. You might get a UTF string from anywhere; on Windows you often +get them from the OS, in UTF-16. In web-adjacent applications, strings are +most commonly in UTF-8. In ASCII-only applications, everything is in UTF-8, +by its definition as a superset of ASCII. + +Often, an application needs to switch between UTFs: 8 -> 16, 32 -> 16, etc. +In SG-16 we've taken to calling such UTF-N -> UTF-M operations "transcoding". + +This paper provides interfaces to do UTF transcoding based on the ranges API. + +A particular reason for urgency in adding transcoding operations to the +standard library is that the standard library has previously contained +problematic-to-broken UTF transcoding facilities in the form of `std::codecvt` +facets which are currently slated for removal without replacement as +[P2871](https://wg21.link/P2871) and [P2873](https://wg21.link/P2873) make +their way through the committee. GitHub searches show that these facilities +are widely used; the functionality contained in this paper can serve as a +proper replacement. + +# The shortest Unicode primer imaginable + +There are multiple encoding types defined in Unicode: UTF-8, UTF-16, and +UTF-32. + +A *code unit* is the lowest-level datum-type in your Unicode data. Examples +are a `char8_t` in UTF-8 and a `char32_t` in UTF-32. + +A *code point* is a 32-bit integral value that represents a single Unicode +value. Examples are U+0041 "A" "LATIN CAPITAL LETTER A" and U+0308 "ยจ" +"COMBINING DIAERESIS". + +A code point may be consist of multiple code units. For instance, 3 UTF-8 +code units in sequence may encode a particular code point. + +# Basic examples + +## Transcoding a UTF-8 string literal to a `std::u32string` + +```cpp +std::u32string hello_world = + u8"ใ“ใ‚“ใซใกใฏไธ–็•Œ" | std::uc::to_utf32 | std::ranges::to(); +``` + +## Sanitizing potentially invalid Unicode + +Here, we sanitize potentially invalid Unicode C strings by replacing invalid +code units with replacement characters according to Unicode's recommended +Substitution of Maximal Subparts: + +```cpp +template +std::basic_string sanitize(CharT const* str) { + return std::uc::null_term(str) | std::uc::to_utf | std::ranges::to>(); +} +``` + +## Returning the final non-ASCII code point in a string, transcoding backwards lazily: + +```cpp +std::optional last_nonascii(std::ranges::view auto str) { + for (auto c : str | std::uc::to_utf32 | std::views::reverse + | std::views::filter([](char32_t c) { return c > 0x7f; }) + | std::views::take(1)) { + return c; + } + return std::nullopt; +} +``` + +## Transcoding strings and throwing a descriptive exception on invalid UTF + +(This example assumes the existence of the `enum_to_string` function from +[P2996](https://isocpp.org/files/papers/P2996R6.html#enum-to-string)) + +```cpp +template +std::basic_string transcode_or_throw(std::basic_string_view input) { + std::basic_string result; + auto view = input | to_utf; + for (auto it = view.begin(), end = view.end(); it != end; ++it) { + if (it.success()) { + result.push_back(*it); + } else { + throw std::runtime_error("error at position " + + std::to_string(it.base() - input.begin()) + ": " + + enum_to_string(it.success().error())); + } + } + return result; +} +``` + +## Adapting a range of non-character-type values + +Let's say that we want to take code points that we got from ICU, and transcode +them to UTF-8. The problem is that ICU's code point type is `int`. Since `int` +is not a character type, it's not deduced by `to_utf8` to be UTF-32 data. We +can address this by using the `std::uc::as_char32_t` to cast the `int`s to +`char32_t`: + +```cpp +std::vector input = get_icu_code_points(); +// This is ill-formed without the as_char32_t adaptation. +auto input_utf8 = + input | std::uc::as_char32_t | std::uc::to_utf8 | std::ranges::to(); +``` + +# Proposed design + +## Dependencies + +This proposal depends on the existence of +[P2727](https://isocpp.org/files/papers/P2727R0.html) +"std::iterator_interface". + +## Discussion of whether transcoding views should accept ranges of `char` and `wchar_t` + +Here are some examples of the differences between having the transcoding views +accept ranges of `char` and `wchar_t` or reject them. The `to_utfN` and +`as_charN` adaptors are discussed later in this paper. + +The `to_utfN` adaptors produce `to_utfN_view`s, which do transcoding. + +The `as_charN_t` adaptors produce `as_charN_view`s that are each very similar +to a `transform_view` that casts each element of the adapted range to a +`charN_t` value. An `as_charN_view` differs from the equivalent transform in +that it may be a borrowed range. + +Note the use of the shorthand "`charN_t`" below with `std::wstring`. That's +there because whether you write `as_char16_t` or `as_char32_t` is +implementation-dependent. + +::: tonytable + +### Rejecting ranges of `char` and `wchar_t` +```c++ +using namespace std::uc; + +auto v1 = u8"text" | to_utf32; // Ok. +auto v2 = u"text" | to_utf8; // Ok. +auto v3 = U"text" | to_utf16; // Ok. + +auto v4 = std::u8string(u8"text") | to_utf32; // Ok. +auto v5 = std::u16string(u"text") | to_utf8; // Ok. +auto v6 = std::u32string(U"text") | to_utf16; // Ok. + +auto v7 = std::string | to_utf32; // Error; ill-formed. +auto v8 = std::wstring | to_utf8; // Error; ill-formed. + +auto v9 = std::string | as_char8_t | to_utf32; // Ok. +auto v10 = std::wstring | as_charN_t | to_utf8; // Ok. +``` + +### Accepting ranges of `char` and `wchar_t` +```c++ +using namespace std::uc; + +auto v1 = u8"text" | to_utf32; // Ok. +auto v2 = u"text" | to_utf8; // Ok. +auto v3 = U"text" | to_utf16; // Ok. + +auto v4 = std::u8string(u8"text") | to_utf32; // Ok. +auto v5 = std::u16string(u"text") | to_utf8; // Ok. +auto v6 = std::u32string(U"text") | to_utf16; // Ok. + +auto v7 = std::string | to_utf32; // Ok. +auto v8 = std::wstring | to_utf8; // Ok. + +auto v9 = std::string | as_char8_t | to_utf32; // Ok. +auto v10 = std::wstring | as_charN_t | to_utf8; // Ok. +``` + +::: + +In short, rejecting `char` and `wchar_t` forces you to write "`| as_char8_t`" +everywhere you want to use a `std::string` with the interfaces proposed in +this paper. + +SG-16 has previously expressed strong support for rejecting `char` and +`wchar_t`, as can be observed in the polling history section. + +The feeling in SG-16 was that the `charN_t` types are designed to represent +UTF encodings, and `char` is not. A `char const *` string could be in any one +of dozens (hundreds?) of encodings. The addition of "`| as_char8_t`" to adapt +ranges of `char` is meant to act as a lexical indicator of user intent. + +The authors believe this decision is a mistake. Our argument for accepting +ranges of `char` and `wchar_t` is as follows. + +First, note that none of the `charN_t` types imposes any invariant that a +range of its contents contains valid Unicode. As a result, they cannot enforce +preconditions for APIs that require valid Unicode input at the level of the +type system. + +Therefore, we claim that the main use case of the `charN_t` types in APIs is +to facilitate a coding style that allows APIs to advertise to users whether +they expect Unicode-encoded strings (whether with a wide or a narrow +contract). + +For example, users of this coding style may write an API like the following: + +```cpp +// Expect input to be in Windows-1252 +std::size_t word_count(std::string_view); + +// Expect input to be in Unicode +std::size_t word_count(std::u8string_view); +``` + +If `to_utfN` rejects ranges of `char` and `wchar_t`, it would bring this +standard library API into alignment with this style. + +However, there are a number of reasons why we consider this approach +undesirable for our use case. + +First of all, for any large C++ API surface dealing with Unicode that was not +designed very recently, there will be APIs that expect UTF-8 in the form of +`std::string` parameters. This means that the semantic value of `char8_t` is +one-sided; in such an ecosystem, while the presence of `char8_t` certainly +indicates that the API expects UTF-8, the absence of `char8_t` may still +indicate a `char`-based API that also expects UTF-8. + +Furthermore, because `char8_t` is such a recent addition to the standard, and +because it's so poorly supported by other standard library facilities such as +`` and `std::format`, its penetration has been extremely low; a +Github Code Search showed 15.3M references to `std::string` and 6.7k +references to `std::u8string`. + +Finally, due to the particular history of implementation choices by compiler +writers, the proportion of C++ users who have the ability to properly benefit +from the use of `char8_t` is unfortunately smaller than intended. + +For the vast majority of users of Unix-like operating systems, both the basic +literal encoding and the execution encoding are UTF-8, and so `char8_t` is +mostly redundant, since it has approximately the same meaning as `char`. This +leaves Windows developers as the remaining large pool of users who could +potentially take advantage of `char8_t`. + +The issue is that Windows users are divided into two categories: those who use +MSVC's `/utf8` compiler flag, and those who do not. + +Users of `/utf8` are in the future: `/utf8` switches the basic literal +encoding and execution encoding to UTF-8. These users have less need for +`char8_t` because their `char`s are UTF-8. + +Non-users of `/utf8` are dealing with non-Unicode basic literal and execution +encodings, so theoretically they're the target audience for `char8_t`. But +unfortunately, without the `/utf8` flag, MSVC breaks compliance with the +standard, in that it violates the requirement that `u8""` string literals are +encoded in Unicode. Attempting to create such a string literal on MSVC without +specifying `/utf8` results in Windows-1252 code units inside of `char8_t` +bytes. For these users, `char8_t` is theoretically useful but broken in +practice. + +Rejecting `char` and `wchar_t` for UTF transcoding will therefore have +limited benefits. On the other hand, rejecting these types will send users +over to Stack Overflow to discover they need to copy boilerplate called +`| std::uc::as_char8_t` for reasons that will seem academic to most of them. + +## Error handling mechanism + +When invalid code units are encountered, the UTF transcoding views replace +those code units with U+FFFD replacement characters according to the Unicode +standard's recommended "Substitution of Maximal Subparts" algorithm. + +However, users of the transcoding views may want to know when invalid code +units have been encountered, and to implement custom behaviors if this is the +case. Simply checking whether the transcoded code points contain U+FFFD +replacement characters is not sufficient because these characters are an +in-band signal that can also appear in valid UTF. + +What's called for is a basis operation with which arbitrary error handling +approaches may be implemented. + +The UTF transcoding views in this paper provide such a basis operation by +adding an `success()` member function to the iterator of the transcoding view, +which informs users whether the current code point is a U+FFFD that was +inserted in response to an invalid code unit sequence. The `success()` member +function returns a `std::expected`, where +`std::uc::transcoding_error` is a new enum class containing enumerators for +every category of transcoding error. + +Users who choose not to implement error handling will simply sanitize any +invalid code unit sequences using U+FFFD replacement. Users who want to +implement error handling can implement any of the following approaches, either +by wrapping the iterator or by iterating with a traditional for loop: + +- Throwing an exception +- Using an character other than U+FFFD for replacing invalid code units +- Dropping illegal code units +- Producing an error log message +- Collecting statistics on transcoding errors +- Implementing a custom transcoding view whose `value_type` is + `std::expected` + +### Why `std::expected`? + +The main alternative to consider here would be to specify that +default-constructed `std::uc::transcoding_error` values represent success, or +add a `success` enumerator whose value is zero. There is precedent for doing +this in the standard in the error handling approach of `std::from_chars`, +which returns a `std::from_chars_result` containing a `std::errc` that has an +`operator bool()` that returns `true` if the `std::errc` is +default-constructed. + +However, that design decision was made before `std::expected` was added to the +standard library in C++23. Now that we have this facility, we should take the +opportunity to use the type system to structurally separate the error cases +from the success cases, instead of lumping them all together in the same type +as in the case of `std::errc`. + +### Existing practice + +- [`iconv()`](https://www.gnu.org/savannah-checkouts/gnu/libiconv/documentation/libiconv-1.17/iconv.3.html) + - Uses two possible `errno` error codes: + - `EINVAL` (the initial subsequence of a valid sequence was at the end of the + input sequence) + - `EILSEQ` (any other invalid sequence in the input) + - Uses an out-parameter to point to the beginning of the invalid sequence +- ICU + - [`u_strFromUTF8WithSub()`](https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/ustring_8h.html#a8fd0b27d2f87358cb5730ce6952af9a6) + - Either replaces invalid input sequences with a user-provided `int32_t` + (documentation recommends U+FFFD) or sets an error code using an + out-param +- [MultiByteToWideChar()](https://learn.microsoft.com/en-us/windows/win32/api/stringapiset/nf-stringapiset-multibytetowidechar) + - User specifies a flag to decide whether to fail on invalid input + - If set, any invalid input results in the error code + `ERROR_NO_UNICODE_TRANSLATION` + - If unset, uses U+FFFD replacement (unless pre-Vista in which case illegal + sequences are dropped) +- Python [`decode()`](https://docs.python.org/3/howto/unicode.html) + - Invalid sequences result in exceptions containing verbose descriptions of + the offending sequence + - Example: + ``` + >>> b'\x80abc'.decode("utf-8", "strict") + Traceback (most recent call last): + ... + UnicodeDecodeError: 'utf-8' codec can't decode byte 0x80 in position 0: + invalid start byte + ``` + - List of error messages: + - `unexpected end of data` + - `invalid start byte` + - `invalid continuation byte` + - `code point in surrogate code point range(0xd800, 0xe000)` + - `truncated data` + - `code point not in range(0x110000)` + - `illegal encoding` + - `illegal UTF-16 surrogate` + +The claim that `to_utfN_view`'s `success()` API is a basis operation is +supported by the fact that each of the above APIs can be implemented using it, +but not vice versa. See [Appendix: Implementing Existing Practice for Error +Handling](#appendix-implementing-existing-practice-for-error-handling) for +code examples which demonstrate this. + +### `std::uc::transcoding_error` enumerators + +- `truncated_utf8_sequence` + - An ill-formed subsequence that matches the beginning of some well-formed + sequence. + - Example invalid code unit sequence: UTF-8 `0xE1 0x80`. +- `unpaired_high_surrogate` + - Example invalid code unit sequence: UTF-16 `0xD800`. +- `unpaired_low_surrogate` + - Example invalid code unit sequence: UTF-16 `0xDC00`. +- `unexpected_utf8_continuation_byte` + - Example invalid code unit sequence: UTF-8 `0x80`. +- `overlong` + - An overlong UTF-8 encoding. + - Example invalid code unit sequence: UTF-8 `0xE0 0x80`. +- `encoded_surrogate` + - Applies to both UTF-8 and UTF-32. + - Example invalid code unit sequence: UTF-8 `0xED 0xA0`, UTF-32 + `0x0000D800`. +- `out_of_range` + - Applies to both UTF-8 and UTF-32 + - In UTF-8, this applies to `0xF4` if it is followed by a continuation + byte greater than `0x8F` + - In UTF-32, this is any code unit greater than `0x10FFFF` + - Example invalid code unit sequence: UTF-8 `0xF4 0x90`, UTF-32 + `0x110000`. +- `invalid_utf8_leading_byte` + - In UTF-8, this applies to `0xC0`-`0xC1` and `0xF5`-`0xFF`. + - Example invalid code unit sequence: UTF-8 `0xC0`. + +An alternative approach to minimize the number of enumerators could merge +`truncated_utf8_sequence` with `unpaired_high_surrogate` and merge +`unexpected_utf8_continuation_byte` with `unpaired_low_surrogate`, but based +on feedback, splitting these up seems to be preferred. + +### Examples + +The first two rows of each of the following tables are taken directly from the +"U+FFFD Substitution of Maximal Subparts" section of the Unicode standard, and +augmented to show the associated `success()` for each resulting code point. + +![](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABTQAAANhCAYAAADZhDRwAAABdWlDQ1BrQ0dDb2xvclNwYWNlRGlz +cGxheVAzAAAokXWQvUvDUBTFT6tS0DqIDh0cMolD1NIKdnFoKxRFMFQFq1OafgltfCQpUnETVyn4 +H1jBWXCwiFRwcXAQRAcR3Zw6KbhoeN6XVNoi3sfl/Ticc7lcwBtQGSv2AijplpFMxKS11Lrke4OH +nlOqZrKooiwK/v276/PR9d5PiFlNu3YQ2U9cl84ul3aeAlN//V3Vn8maGv3f1EGNGRbgkYmVbYsJ +3iUeMWgp4qrgvMvHgtMunzuelWSc+JZY0gpqhrhJLKc79HwHl4plrbWD2N6f1VeXxRzqUcxhEyYY +ilBRgQQF4X/8044/ji1yV2BQLo8CLMpESRETssTz0KFhEjJxCEHqkLhz634PrfvJbW3vFZhtcM4v +2tpCAzidoZPV29p4BBgaAG7qTDVUR+qh9uZywPsJMJgChu8os2HmwiF3e38M6Hvh/GMM8B0CdpXz +ryPO7RqFn4Er/QcXKWq8UwZBywAAAERlWElmTU0AKgAAAAgAAgESAAMAAAABAAEAAIdpAAQAAAAB +AAAAJgAAAAAAAqACAAQAAAABAAAFNKADAAQAAAABAAADYQAAAAAFUitfAAACBmlUWHRYTUw6Y29t +LmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0 +az0iWE1QIENvcmUgNi4wLjAiPgogICA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMu +b3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJk +ZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczp0aWZmPSJodHRwOi8vbnMuYWRvYmUuY29tL3Rp +ZmYvMS4wLyIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlm +LzEuMC8iPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgog +ICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+MTU4NDwvZXhpZjpQaXhlbFhEaW1lbnNpb24+ +CiAgICAgICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj4xMjI0PC9leGlmOlBpeGVsWURpbWVuc2lv +bj4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+Ct8q +BYkAAEAASURBVHgB7J0HuCRF1YZrCQu45JwWlpyUILDkHCUIkoOCAgoIroBkyRnBBKhITj8iElRA +FJAkOYhkQTISV5a4ZLb/8x6ptqfvhO65M/fOzP3qee6d7urqCm9VV3edOnVqWGIuyImACIiACIiA +CIiACIiACIiACIiACIiACIiACIhAFxCYqAvyqCyKgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiI +gBOQQFMNQQREQAREQAREQAREQAREQAREQAREQAREQAREoGsISKDZNVWljIqACIiACIiACIiACIiA +CIiACIiACIiACIiACEigqTYgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiLQNQQk0OyaqlJGRUAE +REAEREAEREAEREAEREAEREAEREAEREAEJNBUGxABERABERABERABERABERABERABERABERABEega +AhJodk1VKaMiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAISaKoNiIAIiIAIiIAIiIAIiIAIiIAI +iIAIiIAIiIAIdA0BCTS7pqqUUREQAREQAREQAREQAREQAREQAREQAREQAREQAQk01QZEQAREQARE +QAREQAREQAREQAREQAREQAREQAS6hoAEml1TVcqoCIiACIiACIiACIiACIiACIiACIiACIiACIiA +BJpqAyIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAl1DYJKuyakyKgIdROCNN94IEyZMCDPNNFMH +5ar7sjJ27Njw1FNPhVdffTXMOuusYZ555vHf7iuJcjyYBD755JPw9NNPh2effdazMWrUqDDvvPOG +ySabbDCzpbRFQAREQAREQAREQAREQAREQATaRKCQhuZ//vOf8IUvfKHU3xZbbFE4yzvvvLPHffLJ +Jxe+57vf/a7fc+SRRxa+p0zAf//732G//fYL6667bvjiF78YNtxww3D00UeHt956q0w0FWHfeeed +cMwxx4T1118/LLLIImGttdYKe++9d3juuecqwjVzcuyxxzqP5ZdfvuHtM8wwg4e99NJLG4atF+Dc +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 +bCYzukcEREAEREAEuolAPYFmN5VDeRUBERABERABERABERABERCBbiJQXy2jm0qivIqACIiACIiA +CIiACIiACIiACIiACIiACIiACPQ8AQk0e76KVUAREAEREAEREAEREAEREAEREAEREAEREAER6B0C +WnLeO3WpkoiACIiACAwwgaeeeio88MADbrfTdlkf4NSVnAiIgAiIgAiIgAiIgAiIgAgMTQISaA7N +elepRUAEREAEREAEREAEREAEREAEREAEREAERKArCWjJeVdWmzItAiIgAiIgAiIgAiIgAiIgAiIg +AiIgAiIgAkOTwCRFiz1s2LCiQRVOBERABERABERABERABERABERABERABERABERgCBM49NBDw1FH +HdUWAtLQbAtWRSoCIiACIiACIiACIiACIiACIiACIiACIiACItAOAhJotoOq4hQBERABERABERAB +ERABERABERABERABERABEWgLAQk024JVkYqACIiACIiACIiACIiACIiACIiACIiACIiACLSDQGEb +mvnEkyTJe+l8iBC45ZZbwmqrrTZESqtiViPw8ssvh/Hjx4cFFlig2mX5DREC6guGSEXXKebYsWMD +f4suumidULrU6wTUF/R6DTcu31tvvRWee+65sOSSSzYOrBA9S+DOO+8MSy+9dBg+fHjPllEFq0/g +/fffD48++mhYdtll6wfU1Z4mcN9994VFFlkkjBgxoqfLqcJVJ7DxxhuHq6++Or04evTo9LjVB9LQ +bDVRxScCIiACIiACIiACIiACIiACIiACIiACIiACItA2AhJotg2tIhYBERABERABERABERABERAB +ERABERABERABEWg1AQk0W01U8YmACIiACIiACIiACIiACIiACIiACIiACIiACLSNgASabUOriEVA +BERABERABERABERABERABERABERABERABFpNQALNVhNVfCIgAiIgAiIgAiIgAiIgAiIgAiIgAiIg +AiIgAm0jIIFm29AqYhEQAREQAREQAREQAREQAREQAREQAREQAREQgVYTkECz1UQVnwiIgAiIgAiI +gAiIgAiIgAiIgAiIgAiIgAiIQNsISKDZNrSKWAREQAREQAREQAREQAREQAREQAREQAREQAREoNUE +JNBsNVHFJwIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIi0DYCEmi2Da0iFgEREAEREAEREAEREAER +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 +AuoDeqcuY0mYnCo6QcUkpCZOIjn9isDQJqD3QW/Wf5l3Qm8SUKkQgKPsIicCIiACZQl0nEDzkksu +CZdddllgl0s0JzH+W02rsmxBFV4EREAEREAEREAEREAEREAEREAEREAEREAERKD7CXScQJOl3ywz +x7EpwB577NH9lFUCERABERABERABERABERABERABERABERABERCBlhDoOIGmGYwPW265ZWBZydRT +T92SQioSERABERABERABERABERABERABERABERABERCB3iDQcQLNiSaayO1m9gZelUIEREAEREAE +REAEREAEREAEREAEREAEREAERKCVBCZqZWSKSwREQAREQAREQAREQAREQAREQAREQAREQAREQATa +SUACzXbSVdwiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAItJSCBZktxKjIREAEREAEREAEREAER +EAEREAEREAEREAEREIF2EpBAs510FbcIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiEBLCUig2VKc +ikwEREAEREAEREAEREAEREAEREAEREAEREAERKCdBJre5fzvf/97O/OluDuYwNtvvx1U/x1cQQOQ +tffeey988skn4d133x2A1JREpxJQX9CpNTNw+Xr//ffDBx98ED788MOBS1QpdRwB9QUdVyUDnqGP +PvoovPPOO/o+HHDynZXguHHjwoMPPhgmnnjizsqYcjNgBBgfvPHGG+oLBox4ZyY0duzY8Nlnn4VJ +J520MzOoXLWVAN+FWTd+/PjsaUuPmxZoLrDAAi3NiCLrHgJvvvlmUP13T321I6evv/56QJAxatSo +dkSvOLuEgPqCLqmoNmaTwSt/888/fxtTUdSdTkB9QafXUPvzhzDzpZde0vdh+1F3dApMeM8333wS +YnR0LbU3c0xwIsjSWLG9nDs9dtrBPPPME6aYYopOz6ry1wYCI0aMqIh18sknrzhv5UnTAs2pppqq +lflQXF1EYJJJJgmq/y6qsDZkFc3MCRMmqB20gW03Ram+oJtqqz155YOVWVe9E9rDt1tiVV/QLTXV +vnwiwBg+fLj6gvYh7oqY0caacsopvS10RYaVyZYTQDuXdqDvgpaj7aoIeR8g1MoLtrqqEMps0wT4 +Lsy6dmrty4ZmlrSORUAEREAEREAEREAEREAEREAEREAEREAEREAEOpqABJodXT3KnAiIgAiIgAiI +gAiIgAiIgAiIgAiIgAiIgAiIQJaABJpZGjoWAREQAREQAREQAREQAREQAREQAREQAREQARHoaAIS +aHZ09ShzIiACIiACIiACIiACIiACIiACIiACIiACIiACWQISaGZp6FgEREAEREAEREAEREAEREAE +REAEREAEREAERKCjCUig2dHVo8yJgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAiIgAhkCUigmaWhYxEQ +AREQAREQAREQAREQAREQAREQAREQAREQgY4mIIFmR1ePMicCIiACIiACIiACIiACIiACIiACIiAC +IiACIpAlIIFmloaORUAEREAEREAEREAEREAEREAEREAEREAEREAEOpqABJodXT3KnAiIgAiIgAiI +gAiIgAiIgAiIgAiIgAiIgAiIQJaABJpZGjoWAREQAREQAREQAREQAREQAREQAREQAREQARHoaAKT +DFTuHnnkkXDDDTeEe++9N3A8zzzzhGWXXTasvPLKYbXVVhuobCidASLw6aefhqOOOiokSVI3xVVX +XTWss8464frrrw+33npr3bDDhg0Lhx12mIfpb9yTTDJJmGuuucICCywQFl100TD99NPXTVsXmyMw +0PWaz2WjNjPttNN6G6AdLLzwwoHwcq0loL6gtTy7NTb1Bd1ac63Nd5l2cNNNN+m7oLX4OyK2dr4T +WtFm9F0wMM2kTF9Ajvr73Z8vlb4P80QG/rydfQGl6W+b0VhxYNvEW2+9Ff7xj3+EZ555JowcOTIs +scQSYeaZZ66aiTJhsxG88sor4fe//73LoJZZZpnspYrjJ554Itx4441h6623loyggkyHnpjAqZCz +7COZSv8K3fR5oJNOOimxTiG9NxsPx7vsskvywQcflImyIuzzzz+fbL755smhhx5a4d/uE8pFug8/ +/HC7k+qo+G+++eaG+Xn77bdr1ne2/vfee2+Pi9+sf61j4m113JNPPnligtJk/PjxDculAP8l8NJL +LyVPPvlkQxyDWa+xDRVtMzbBktx5550Ny6QA/yOgvuB/LIbq0euvv548+uijDYuvvqAhoq4OUKQv +oIBl2kGZsPouGPzm8+abbyYPPPBAw4y0uq6y7/pWtxl9FzSszj4B7rjjjuSjjz7q45/3aHVd0Q6I +E9fquNUO8rVX/5zx1D333FM/kF1tZ1/Q6rg1VmxYnX0CmBJb8t577/Xxr+ZxzjnnJFNPPXWFLGCy +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 +1eLrNT+EuMyeyA1dAi+//LLbk9HmOUO3DVBy9QVDu/4p/dixY/1v0UUXFYwhTEB9wRCu/M+Ljs17 +VjywCktu6BJg34Kll146DB8+fOhCGOIlZ7zNWB87hnJDl8B9993nK1hHjBhRGALvkWeffdblPiis +1XNlwtaLR9faQ2DjjTd2s5IxdlZtb7TRRvG0pb9t19DM5xbjr/wVdWhxsky9FY4l8EU+tFqZZivy +rThEQAREQAREQAREQAREQAREQAREQAREoBcJoHS21FJLFSpambCFIlSgriVQXz2ya4uljIuACIiA +CIiACIiACIiACIiACIiACIiACIiACPQigZ4WaKLiPM000/jmRL1YeSqTCIiACIiACIiACIiACIiA +CIiACIiACIiACAw1AgO+5HwgAbNbHfYV5ERABERABERABERABERABERABERABERABERABHqDQE9r +aPZGFakUIiACIiACIiACIiACIiACIiACIiACIiACIiACkYAEmpGEfkVABERABERABERABERABERA +BERABERABERABDqegASaHV9FyqAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIiEAkIIFmJKFfERAB +ERABERABERABERABERABERABERABERCBjicggWbHV5EyKAIiIAIiIAIiIAIiIAIiIAIiIAIiIAIi +IAIiEAlIoBlJ6FcEREAEREAEREAEREAEREAEREAEREAEREAERKDjCUzSbA6ffPLJZm/VfV1OYPz4 +8UH13+WV2M/sv/322+Hjjz8OSZL0Mybd3s0E1Bd0c+21Ju/vvfde4E/vhNbw7NZY1Bd0a821Lt8f +fPBBGDdunPqC1iHtypjeeeed8PTTT4eJJ564K/OvTPefAOODt956S31B/1F2dQy0gWeffTYMHz68 +q8uhzDdHgLFB1n344YfZ05YeNy3QnGqqqVqaEUXWPQT4SFH9d099tSOnfKwMGzZM7aAdcLsoTvUF +XVRZbcrqhAkTfHJD74Q2Ae6SaNUXdElFtTGbfBO8++67+i5oI+NuiHrSSScNI0aMCPzKDU0CH330 +kde/vguGZv3HUse+YPLJJ49e+h1CBCaZpFLMONFE7VsYXplSCcizzTZbidAK2ksE0MRR/fdSjZYv +C5qZaOSoHZRn10t3qC/opdpsrix8sCDUVF/QHL9euUt9Qa/UZPPlQBtH3wXN8+uVO5977rkw66yz +SiurVyq0iXK8//77YezYsfouaIJdL93y0ksvhZlnntknOHqpXCpLMQJ5QXY7NXXbJyotVlaFEgER +EAEREAEREAEREAEREAEREAEREAEREAEREIHCBCTQLIxKAUVABERABERABERABERABERABERABERA +BERABAabgASag10DSl8EREAEREAEREAEREAEREAEREAEREAEREAERKAwAQk0C6NSQBEQAREQAREQ +AREQAREQAREQAREQAREQAREQgcEmIIHmYNeA0hcBERABERABERABERABERABERABERABERABEShM +QALNwqgUUAREQAREQAREQAREQAREQAREQAREQAREQAREYLAJSKA52DWg9EVABERABERABERABERA +BERABERABERABERABAoTkECzMCoFFAEREAEREAEREAEREAEREAEREAEREAEREAERGGwCEmgOdg0o +fREQAREQAREQAREQAREQAREQAREQAREQAREQgcIEJNAsjEoBRUAEREAEREAEREAEREAEREAEREAE +REAEREAEBpuABJqDXQNKXwRyBMaNGxfGjh2b89WpCIiACIiACIiACIiACIiACIiACIiACIgABCTQ +zLSD7bffPiy//PJhwQUXDGeeeWbmig7LErjooovCsGHDwnnnnVf21paFv/jiiyvyUCZPW221ld+L +cLHV7vXXXw+33npreO211yqifuyxx8Iqq6wSZppppjDvvPOm1+66666w2Wabhfnnn9/b5hZbbBHu +vffe9HrRA9r1qFGjigZXuDYRqFX//U2unW22v3nrlPvzfUKn5Ev5GJoE1BcMzXrPl7od7YDvCb7B +xowZk09O5xkCeidkYOhw0AmoLxj0KuiIDDDGu/vuu1uaF40RWopTkXUYAQk0P6+QW265JfBh8+1v +fztMNdVU4cADDwxvvPFGh1VX92VnookGr4lNmDChKrDBzBMZuv7668Nqq60W/vSnP1Xk7/jjjw+3 +3XZb2GmnncLRRx/t16699tqw8sorh6uuuiqMHDkyTDnllOGKK65wwft1111XcX+jk1o8Gt2n660l +UKv+W5uKYqtGQM9ANSryGywC6gsGi3xnpat2MHj1oXfC4LFXyn0JqC/oy2Qo+my33XYBAaScCIhA +MQKDJ20qlr8BC3XQQQeFhRZaKHzzm98Me+21V0Az75hjjhmw9HstIbRdP/nkk/CNb3yjY4rWiXnK +wnnwwQfDtNNO69rBtEHcEUccET777LNw++23h5tuuin8/e9/D5dcckngI/yoo47K3q5jERABERAB +ERABERABERABERABERABERgSBCTQtGpG++3OO+8MO++8c5h44onD1ltvHWabbbZw9tlnh3feeWdI +NIRWF/KGG27w5dNRC/G3v/1tWGGFFcIDDzwQ9thjDxcejxgxwjUN0UrEcY0w+++/f5/snHzyyX4t +quA/8sgjgaXXc8wxR5hiiil8mTbnL730Up97o0c+T/i///77Ye+99w5LLLFE+MIXvhAWXnjh8POf +/zwkSRJvK/y7/vrrexvK34DW7xprrOHea6+9tgspOUFgTnlPOeUU/33qqafCe++958fkCffuu++G +SSaZJCy99NJ+zj/MIuA++OAD/+3kf0WYkP911lkn7LfffgGNVI4R7M4333w+ufDhhx9WFJG633TT +Tb3u55prrvD1r3893H///WmYX//6187we9/7XurHAYJgeEdhMXFsu+224dJLL/W2SprUPxqy//nP +fyru5aRRuoT5+OOPw8EHHxyWWWYZ16ade+65w7e+9a3wwgsvcDlUq/+HHnrIr/GvSBqtbLNpwm0+ +QCh/7LHHOv9pppkmLLLIImGHHXaoeF7pF6ifJ598siI3b775pvvzHEXXiBMmQ4jr3//+dzjxxBPD +csstF/bcc894e8VvkbxxQ5k2euONN7qZiNlnn93NPOy6667hmmuu8TxhQmIoOvUF6gto9wPdDsaP +H+/vX/oDJg2j472y0UYb+TNJf4Ir806g3zjuuOO8r6dPw1wMfVxe449vy4033jjMOeec/l7j3XD+ ++efHbNR9JxRNg28buM4888xhuummC1/72tfCv/71rzSNTjxo1O+W+R4swqnV74Qi37SRO23tgAMO +CKNHjw60lVVXXTX8+c9/Dmhh7bLLLjHYkPtVX6C+4LLLLvM+mH4y6xjr0WdjKgxX5nlr1B8UHSNc +ffXVnoff/e53ruy0wAILeP+65ppr+orObH45bvRdSphGY4Q4TnnxxRfDq6++6ulnzYYUSaMbxwiw +kROBfhEwwU0hZ4kg4Un/Ct30eSB7QBMTEiQmiElMaJhccMEFyUcffZRGYdpniQkfkr/97W+JPcDJ +j3/84+QrX/lKcscddySHHHJIYgICD2vCjsQGvR5XvPn5559PTIst2WSTTZIVV1wx2W233RLr+OLl +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 +QAIkQALxCFCgGY8TQ5EACZAACZAACZAACZAACZAACZAACZAACZAACZQBAQo0y6ASmAUSIAESIAES +IAESIAESIAESIAESIAESIAESIIF4BCjQjMeJoUiABEiABEiABEiABEiABEiABEiABEiABEiABMqA +AAWaZVAJzAIJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkEA8AhRoxuPEUCRAAiRAAiRAAiRAAiRA +AiRAAiRAAiRAAiRAAmVAgALNMqgEZoEESIAESIAESIAESIAESIAESIAESIAESIAESCAeAQo043Fi +KBIgARIgARIgARIgARIgARIgARIgARIgARIggTIgQIFmGVQCs0ACJEACJEACJEACJEACJEACJEAC +JEACJEACJBCPAAWa8TgxFAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQQBkQoECzDCqBWSABEiAB +EiABEiABEiABEiABEiABEiABEiABEohHgALNeJwYigRIgARIgARIgARIgARIgARIgARIgARIgARI +oAwIUKBZBpXALJAACZAACZAACZAACZAACZAACZAACZAACZAACcQjQIFmPE4MRQIkQAIkQAIkQAIk +QAIkQAIkQAIkQAIkQAIkUAYEKNAsg0pgFkiABEiABEiABEiABEiABEiABEiABEiABEiABOIRWDZe +sOxQPXv2zPakT00Q+OWXX0yzZs1qoqwsZDCBRYsWmaVLl5pGjRoFB6BvTRBgX1AT1RxZyMWLFxv8 +NWnSJDIcL1Y3AfYF1V2/cUq3ZMkSs3DhQtO0adM4wRmmSgnMmzdP28Ayy1BnpkqrOGex/vjjD7Ng +wQKz/PLL5wzLANVL4NdffzWNGzc29evXr95CsmShBGbMmJFx7b333jN9+/bN8EvrJG+B5uuvv55W +HpgOCZAACZAACZAACZAACZAACZAACZAACZAACZBAFRGAgLtQjp/PCkWW6ZIACZAACZAACZAACZAA +CZAACZAACZAACZAACaROgALN1JEyQRIgARIgARIgARIgARIgARIgARIgARIgARIggUIRiL3kfPTo +0Rl56Ny5c8Y5T2qHwPz582kjqXaqO7CksJkHG5oNGzYMvE7P2iDAvqA26jmqlLCbhz/a042iVP3X +2BdUfx3nKiH6AYwNYDONrnYJoC9AG6ANzdptA7ChCXu6tK1du20AJYcd1QYNGtCGZo02gy+++MLA +vrp1vXr1soep/9ZzxKWeKhMkARIgARIgARIgARIgARIgARIgARIgARIgARIggQIQ4JLzAkBlkiRA +AiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAoUhQIFmYbgyVRIgARIgARIgARIgARIgARIgARIgARIg +ARIggQIQiG1DswD3ZpIkULEEfvzxR7UhufLKK1dsGZjx4hCYPXu2+fjjj823335rVlttNbPWWmvp +b3HuzrukTaDUzz5s1H3yySfm008/1aK1b9/erL322rRnm3ZFMz0SIAESIAESIAESIAESIIGyJhBL +Q/OHH35Qw74w7hv3b7/99otd8KOOOkrTHTFiROw4xx9/vMYZOnRo7DhJAn711VfmjDPOMH369DHY +AGn33Xc3l1xyiZk7d26SZDLCfvPNN+acc84xu+66q9loo43MXnvtZS6//HLz+++/Z4TL52TYsGHK +o2fPnjmjr7TSShr2gQceyBk2KsBtt92m6cRpEzNmzNCkMPmOE/6QQw7R8PncIywOhI/gg7RvuOEG +s2jRoqjiBV67/fbbzZZbbmlWWWUV/fvggw8CwxXC89///rfLDkINuO+++871gxHuMD+9kONfGLeg ++rL1mSPJqrn8r3/9SzkffPDBscv02muvmd12203bCdrMPvvso22ndevWBoaRJ06cGDstBiw9gVI+ ++yg9jKujn2/btq3ZYIMNtG2hfXXq1MmgTeH9hM0Y6DIJ/PbbbwZ/NBeeyYVnJEACJEACJEACJEAC +JFDpBGJpaGIigMlUEvfzzz/HDo7JBtLHDolxHYRRiGMFO3HjxQn3n//8x0Ag6xVevvvuu+aJJ54w +1157rYGgokOHDnGScsM8/PDD5sgjjzReLtOnTzcQUt111136u+6667rhkx6AHXh48xyWBsLh79df +fw0LEssfglikE8dhR2w4e+9ccaywMZ97hMXBvSGcf/3115X59ddfr/UJYXUcB027gQMHqgAawtFW +rVoVdRdHCCz9vNH+rZ+dsAf5xSlfGLeguLY+g65Vo59l731+o8r50ksvmZ133lnbSv369U3Xrl11 +p79JkyapIB19zH//+1/zwgsvmC222CIqKV4rAwLl8OwfcMABZvz48UoDAkwINaH5i10E58yZYy68 +8ELz5ptvmkcffdTUq1evDKiVRxaWX355FWbOnDlTtaPLI1fMBQmQAAmQAAmQAAmQAAmQQF0JxNLQ +hOAG2677/9ZZZx29P7QO/dcee+yxuuatJPEh1Dn66KNVMNitWzfz/PPPm6lTp6omJTQbf/rpJ3P4 +4YcnyhsmnIgDYcjWW2+taX700Udm9OjRpnnz5ua9995TbdBEiZZR4BVXXDGr/v3tYf3118/I8ZVX +XhkZZ+zYsRnh87mHPw60bp955hmtyxVWWEGFAXvssYcKODNuFnLy0EMPqYAKS4ahGYl6W2+99UJC +V663n5u/LnHur8/KLW1hct6/f39tKxBkfvbZZ+aNN94wL7/8ssFyZQic2rRpo4JNCKmsILowOWGq +aRAo9bM/ZswYFWZCUAlt4S+//NJAKP75558bfGzDigU4vHdvvfXWNIrMNEiABEiABEiABEiABEiA +BEigrAnE0tDEJAoCIL+D5hFcw4YNA6/7w1fCOTRgIIBo0aKFThibNWum2cYScWgNXnTRRSoAg1Yp +luLGcf/4xz/MvHnzzBprrKECtUaNGmk0aGRCKLzDDjuokOOtt95STa44aZZbmKD2EZXHfNpM0nvg +/t44OIYgCct9oYGL5ZoQLB977LFm8uTJZtllox8H1Dlcly5dql4DystNC81/sQl8+OGHZtasWRr+ +n//8pz73NjK0xfbcc0/9kIHnHoIpLN/v2LGjDcLfMiRQ6mcfmrxw0Pr9+9//rsf2H5ac33TTTfqB +BeHw0QZmXOhIgARIgARIgARIgARIgARIoJoJxNLQzAcABHjXXXedCo8wWcemBZtvvrk577zzDJbv +hTlMxrA0e9NNNzWbbLKJOeaYY1TrJCy83x9Cx2uuucbsvffeBgJDCK2uuuoq1WTxhw06f+edd9Qb +9i2tMNOGs3ZBsfwU2n5x3dtvv61BYbvRCjNt3O23317LifMnn3zSepf8d8KECQY246rVoW1ceuml +Wjxo4EZpFEPQfNhhhxnYmITDsk6cn3baaXpu/0ELb/DgwWbbbbfVtoc2hHv4zQDgfogPQTfc/fff +rxq8aO+V6BYuXKhlgbYhnnU851ia//TTT2cVJ6rs0DYDFzCDAAm/u+yyi5p3+Nvf/mbQJuEQ7qyz +zlJ7qNCQhZAnzB5s0v4A7QAa2qgLmJXAM//cc89llSPKA0Jy68I+eqCNbLzxxirshKav1yXNM/pT +fGiBbV5oD/fo0cMMGTJENcJPP/10ZYqPNHBff/21trWTTz5Zz/3/brzxRg3/1FNPZVyKmydvHcIU +whVXXKH2h/HhBh8SYDM4zLQIOJ9wwgnafvB87rTTThofGsF+Fzc/iAetWNie3GabbZSPtYkMUx/W +7qw/fXteLs++bVNh7Qn5PfTQQ7U9oY6tS1rfUc8n0rz44ovd9oRNiXCOtjxy5Eh7S9VGjtMP2gho +v8OHD3ff2dCahxYq8o7+4Oyzz7ZB9Tfu2AL9M+JbDWj7LLzyyisZ6aE/t+0OHy6h7QoTMX5Xl3bk +T4vnJEACJEACJEACJEACJEACKRCQwX7eToQJjmTBkclzRhpiz8uRSaNew3X/nwg9HLHf6MaR5Zka +Ria9zjLLLJMVHvFlguTIRNiNIxooGk4EpK6fTLCczTbbLDC+2BxzZAMXN2zYgUzkHRE0OTLpyQoi +WjCadrt27bKuRXmIYETjibZWYDARuup10RQMvB7HE3UATrIUOGfwxo0ba1hZxhgaVuz6OQ0aNAi9 +jgsoD+4pS5Qjw3kvymY6GkdskXq9Q4/zuUfcOCLMcERrVvMjwrPQPNxxxx0axt+O11xzTTfOZZdd +5oiGZ2g4sdvphhVbrBqud+/ejgjf3ThNmzZ1wwQdjBs3zg0rAh0NIhp+rp/Yzgz1C0rP7xeXmzee +aCM68vHBzYOf0aBBgxybL8SLKvurr76q6aAfkE10stJEe5TltG6d+e8lQhBv1pwk/QH6lhNPPDHr +nvYeImDTa3379s24R9CJaGe66aCOZTOwoGCBfknyjAREGOPIJjHu/Wx+8Wv7HRwjHJxlLLut67n/ +37777qtpyQZt7qUkebLpo/9H2b35sccisHLTxoHYY3UuuOACR1YCBIZH+US45cZJkh/UhZeDzYP9 +lY9nbrpBB+Xy7B933HHKRjTbHRHEBmU10M/WR9z6jno+cQMRlms+xPazI8Jzt75EIKn3T9IPIgL6 +Dzzvtj68vyLQVn+MM6xLMraQVRaB6d5yyy02Oefqq692lltuucBwp556qhuuru3ITYgHJEACJEAC +JEACJEACJEACqRGA9kLeLkygKbuD6wRh1VVXdUTLzxHtEkc2Y1EBmBX6iPaWe18r0MRkpmXLls6d +d97piKaPIxpvjmg1upMNCDOsCxJoiqaIhsVk+tlnn3XEzqEjNjBdIefqq6/uiI1Mm0SsXwiMMCmU +DRccTCYx6ZYdsmPFtYFkp3TNF4SyQQ4CXpRdtNGCLsfyK6VAExNC1FXYn2hquWWwAk1MFsPCf/LJ +J254K2RLcg8bJ46g1U6aRZPHvaf/AAIptFcInFFPYgdVz2XjFw0qZgrUH9dES07LhTiieelAkAB/ +CE5F61DDW6EB8idmG7TNQ5gmWk7+W2ecF0ugGZc1BFFiZ1bLJ0vUHQgKxF6sI1rOjtiMdZnI5ktu +OaLKboUv4AXhJYS9EF4hPdGcctNDHyF2e51p06Y5olHmPt+i8ejeBwdJ+gP0Lbgv/kRDUwWAotWo +wiOxIexeiyPQxL1lR3M3jmhla7tAeVBGK4xGOL9LkmcIiq0wCO3swQcfdGx/NWDAAPf+KFNdBJpJ +8uStQ/T1Q4cOdWRJvSOajs4RRxzh5mnKlClu0cU+pesvWobKSDa70X5W7BbrNTxX1iXJDz5UoPzg +Ixrwjmh76rtFtPXce4qGrE0667dcnn3ZiM4R7Uw3z6j3k046SevcK+z1F8DWR1KBZljfZAWa9plA +/4k6xrOYtB/EByXbfiG0FtuyKrh+8cUXnZ49e7pl9Qo0k4wtRONX+2n7XGMsgn4czwic2CDVe6AP +hkAdbU42DnLQZtD/IJ5919e1HfnrheckQAIkQAIkQAIkQAIkQAJ1J1AQgWb37t11MjBq1KisHNqJ +CrQgrbMCTQgLvRNde91Oztu3b+9qafoFmnZSLLtPO7KEzUbVX0xioVWJCcrdd9+dcS3XyYYbbqjx +7KQIE+Gkzk7CxH6eAyGJ1yE/Nm0IYvN1pRRo2vyH/UKgYZ0VaIaFhf+BBx5og7taoFHhcc17jyQC +TQhQEB9CklwOWmsICy02r7MCaVlSq9pm3muYJEMQjniy3FYvWaEe/FDnUQIJb1rFEmgiX1F/lvV9 +993nhpMdu71Z1WMIBpEOhFKyTDRn2a3wBXFuvvnmjPTs841r0ALzOgiq4A/O1tnwcfoDCFbQtyAN +9DV+B4GX/RATV6Apy/AdaKdabWikbf8g/BU7mipc8d4rSZ4RzwphIZB5//33vUnp8UEHHeTeM1+B +ZtI8eetQlnln5AkfNiAoAwdoPsJBKC42INUP7wG/gzAc4SFkl03VnKT5EVMFGr9fv37+pB0x96Ef +E/DhIZcr9bOP/Il9TEdMIWh5bFuyv3hP4aMbPhx6na2PpAJNpBvUN1mBJq57P1Tgnkn7QQjgkQ6E +h/73IlZwWO15r0Az6dgC+bKavxBWeh3Kh/v7V5ggjJjL0Wv23mm1I+/9eUwCJEACJEACJEACJEAC +JFA3AgWxoSkTFTN9+nQjE2qZL/zpYPMMNiKtvTiZyNpL7i9swMF2pt+df/756gU7cKK957+s56KJ +qb8ibDLYeAO7lds/mQyrfTEEuPfeezVc3H+wgygTbdfOpSxRM7L8T238IQ3Bb7ARQ9CftXsm2oi6 +OY1M0tQ+HOzUwR4gbHrB7pl1IvywhxX1i82hsFFO2J/fbigKhw2SwsKLcCmr/PncIyuRAA/RclNf +bAKVj8PmL2LKQKNecsklWZsFiQaS2ixEgCBbjLApKJrD+dw6URzRdAxso2i3loFNMC5rWx7YsBSt +VRvd/QUPONieg20+vwsruwgm1Y6uNzxs8MKJSQoDW7ReB7uRcF7bjEn6A9HYMuhb4PCs+t0GG2yg +9v38/lHnIqQxIvDRTX/Gjh2rzznaAhxsAMqSXbX9CXuBln+SPCMd0RDGj9oJFmGSHnv/wV5xXV3S +PHnvBzuqXod+YLvttlMva0f522+/dd8Jfpu0CIgNcGDPE/0l+sek+bH3Q3zYZsZO87adIC20Tdhn +zccV+9lHWWCPeeLEiWozFefWpiZ2Ooc9S/SdsEOdhgt7PpG2mHYxIrB3b5MPC2zAByfazEbMd7hp +4UDMbwRubJTv2CIjcTlB+8MYBQ52uu1Ywf6KhrnBM4wNvrBhXCHbkWaC/0iABEiABEiABEiABEiA +BBITiN7WOXFyf0bA5AQTHGwUIBoiBpMtCPfsxD0sWdG+CLyEyTqElBAIIh3RmsgKh3vAiWaX/mUF ++J+HLIkNuxToL0vNXH9sPCLag0aW1hps5oNjCGqxW3GQw+YC2H1WtGPMPffcY2TJpZFl8BkTQdEc +NdhMBZsiyBL9oGQK7ieaf65wxN4MAjBM/P2bh0B4hA0fvA47YmPzjCQOwlx/2lHx87lHVHr2mm0P +QUJUGybqV7QV9TIEbUHCeFzE5B8Ok2Ovg+AQQvxiOLRZbNAS5L7//nsjmozupbisbdlt+dwE/neA +dg9hrSzb1bKLXUw3SFTZIVzGRwivQ3g4CDogDPc60Z70nupxkv5AtGg1Du4RtjET+iYIU5I60U5V +Yab9cAEBHjYegrATeYRQBxscYSOzJHlGPmy+w/hj92sIvOwO3UnzjvBJ82TvgToM+khg6wofguBs +GcAeHzj8Du0AAnPrkuYHH6Ow6RaEv9jUC38QjIqNYH32sAGUaI3a5BP92vZf7GcfeccfHPpovGNF +W1rft3hH4qMePhz6n5MkhYt6PpGOaCpnJJcPC7xj4LART5AL8s93bOFP335YhX+bNm38lzPO8Y4o +ZDvKuBlPSIAESIAESIAESIAESIAEYhPIlgTEjhoeUGxgqtYDdj+W5V4qgMRuxbLESyfwVjPCn0KU +hqIVcATteIt0MJGDw+Q0aoIadQ/ER/qYJDZv3txYIQr84aDJAwEEdseFtikEmpjMBmmnIbwsA8SP +OkwAUW4ID7GTOjRBsIsvdmGH1idcXQSatlyyaYKmFfYPdYI/OFs+sVlmxFZYYBQIXrwOQim/QNN7 +vZKOsQuzFZDkK9BEGnBoB9AsDHIQEMJBM8/rZKMqtw68/oU4RvmC2ikETLbtJL0v2jBckAauTatU +ZU/SH9g6xPNgnwmbf/trNeHsedQvBGjQAIPQyS9shJBXbLGqkBPCbGjIQsAJgWaSPOP+Nt/QJAtz +SQWaVtBo00uaJxsv7Fmw1+3vTz/9pIdog2HsbVj8Js2P2FtVrU4Io8FZ7CbqRyVoF+NPzBeoX5Aw +1XvfoGPLv9DPPgR/jz/+uPLxa73i+cXu7fiTZfUqpEU/g3Z18MEHB2U7w89f3/Zirr5JbF7aoPqb +Dwtbl1bInZGgnASt4sh3bOFP294b/rn6frwvC9mO/HnjOQmQAAmQAAmQAAmQAAmQQDwCqQs0586d +q0vFoI0JrSSxPZah/SW23tylXv4shi0nxwQN6cLZ5aX+uNDiFDtxqv2IpXf5OqQD7VJMnIImhFZI +aZfQQtAq9gMjb4eJGf7EfqSB1qbfyY7q6mWX1fqvxzm3WqvQtgOrMKEuGNuJouz+q0mfffbZBppK +XgfhrdgcU6Zef2jIVYvDUmDbrrbaaqu8imXbI4TgX331lfFP9JGo1UKTnbIz7mGFfRmeBTqBmQT8 +pekgCJDd293l2v60xTalsVpYxS57kv7AmgyAtjU0KCF09Ds8C3EdhGf4cIH+D20syEEIjA8iEDzh +mYRAKEmekSaYYjmsbKAWdAv9OCM2FQOvhXlCm9brkubJGzfOsRUmQcCEjzF+rU70VWKLWfsssTua +mBHyAIEjtODxBwct/9tvv121ZHHPU045RetBLyb4V6xnf/78+a5WPz4M2vv6s4prEETi/SWb9Pgv +B57769sGytU3+a/bPCXpB/G+E5vZbv9o721//R8+6zK2sGnaX7RrOLQNaM7bD6b2etBvodpR0L3o +RwIkQAIkQAIkQAIkQAIkkJvAMrmDJAsBoSKEmRj8Y7m1dykrBBxWEBiUKgQBXs0JGwZ2L6FJAg0e +K7iz1+yv7HCsh7BNZwV29hp+sawTNuzwG+Ws4EU26wkMJjtzqz+0TeO6K6+8UidMWM7qzxuEEbDr +Bmcn3HHT9YazEzT4wUZnmBs9erReguasZYZlwTj2/kEjxYbx+ls7gGHpV4o/bNGde+65ml3YMQwz +d5CrPOBhtfcgePE7CMmsUCtoCaU/fCWd2/I8/PDDaovQn3eUG+VHO0ryvPjTyefctu04/QEEK1ZQ +P2bMmKzboQwwGRHX2bYELe4wgRHS8gp7oaGYJM+Ib/nDFEZQv2nbHcJaB9MdcBB0WjuW9hrMYfj7 +56R5smnF/cVHFauZGcRYNgFSO5onnniiakAnzQ+EfLCBCi1063BP2bBIbRjDDxrz+bhiPfvIv22f +tv8Oyi/agBVgW05J6zso3Th++bCweYTw32p42nthDAGhs9fVZWzhTQfHEMBCKIv3MTR3/Q7v5fXX +X1/HDLJpmylkO/Lfm+ckQAIkQAIkQAIkQAIkQALxCKQu0LSaDpgo2E1xkBVomWCDB6vpZJererMJ +DYz9998/Y2nupEmTzDnnnKPBDjvsMF365Y1jj2XXc9VKxIT8pJNOUkGKvYbJLDRFce+uXbta78Bf +2ala/bGxwtNPP+2GgTAWy0IfeeQR9cNy8bhue7G3CQetGdk91SAtOCxvR3khrMVSbq+w8MwzzzQQ +tMHuZhyHyZfduACT9X/9618ZwlPUh+z+7S4t32+//dQuaZy0KzkMWNs/tDm0jwsuuECXaEI7C8sd +wStfh/ZuNzOBHVQsN7YOtguh+QoNTdxHdru3l6riF88zNIHx3GIDMCtMQeGw4Yr9eCA7hwdqrhYS +QpL+AEu20WfAYSMUu1kJzrHcFPmH5mZch43EIICCwBDLymHj0OvwvENQd+2116p3nz599DdJnhEB +/CGUQTvGxxCvUBOan3YzNU38f/+gQQwBMzTp8MHJfmBBHWLTHL+9zaR58t4rzjE+Btg+TnbpNq+9 +9pobDXYZ7bMJcwmwR5o0P6gHaOAOHTo0gw/qwG4Ela+wvVjPPgS+0OaFwxJ5rEDwm69AW0OfDkEg +wu+4444aPml9a6Q8/uXDAsvnIXCF2QHY/UQbhLPjAGvf2GYn37GFXdIOzVXr8MEVmrlwsOUMTXPr +8AygP4DmJvoG2NgsZDuy9+UvCZAACZAACZAACZAACZBAQgIyscvbibYkdnZwhgwZ4qYhQjpHtPvU +X5ZVOqLZ4IhAz5GlhOrXqlUr/ZXl144I9zSeGNxXP6SFP5k8ONtuu60jGhyOTDzUTyYVjmhNuPeR +ia36y06+rp9sQuSGl8mvI5M6RzQx3LRxLtpWbvigAxF6ObKZhhtHbKs5YufSkc17XD9Z+uiIICAo +eqAfwu69995ufOQN5ZPJnPrhXJaOZsQVwateE+3JDP+oE9H4cpo1a+beR5bOOrJhkdO7d28H/Cxf +sdXpyNL0qKQcsf/nyGQuMowISDVNEWpFhvNeRL0jHyLM8XqHHudzDxvHljfsVwQZWdxDMyIXRCiu +eZfJd0YwES44on3r8hWNKkcE4w7q1d5bhBBunCeeeEL9ES6JE00mNz3bjmWHbtdPhBmaXJBfnPtY +bknqUzZZcURgoHkQ4Zq2N9kcyX0OZRMPB/mxLqrsIvjTdNBu/U606Nx7+K+JwFiviSAn41KS/kCE +Ko6Yk9B0UGfygUDLYp8nEbzpNbGFm3GPsBPUlQgOM9JDPyICTkc2a3H9e/To4YgAx00mSZ4RST5c +uKzBH30t+i/c23t/0W5z7+Hti9AvoI9AnaOvFW1VzRvaunVJ8hRVh0gPzw74etMXLVZHlkqrP+oQ +7QfPpn12RHvVkeXHNjtOkvyInUxHBGGaFvjgfYTyy1J3N33RBHTTDjso9bMvGozO5ptv7uYZZREz +GY4Izx35GOY+g6hDsfGcUYwk9R31fCJRtFfUi3y4ybgHTpL2g4gjWu0O6hxpIu94X9t3Pt698Ed7 +hstnbIF4tk2jn8L7R8zJwFvTQx+MeyAPovGs72Wx/6p+CP/UU09p2LTakSbGfyRAAiRAAiRAAiRA +AiRAAqkQgHZg3s4KALwCTSQmGpEqEMBEwf5BSCHLOR1ZXu1OvkR7Te9tBZpIRzbMcOyEAnExmRVN +RUeWQ2bkU7STNG3/vWXTBxVM2EkR0kB6gwYNyhAcZCTmOxGNJ0eWODoQyNr841eWzzuihedgcpnU +ifaUIzt7O1YwgvQgMOzZs6cjWoNZyVmBJgSpSZwsj1OGVsjkzT8mbaIV44gmXc4kZZMJzWtUwHwE +YBDQIk+iHRaVtHstn3vYON6y4xgC5G7dujli21CF6RBeJ3FhQg2kgbRE48exAnvcDwIlCMZk2XPG +bf7v//5PGSQVaCIdpIu27Rdeom5F607vYwWaXr+MDIScWG5JBJpIauLEiQ7aq7fNQRAoNmgdPEte +F1V2KwyDwM/v8hFoIo0k/QEEMmgbsiGY+9yjDxDNcEc27lK/uAJN3FvMU2jf5RUs2jaJjwpi8iCw +T0qSZ9wHQii0Je990G9MmDDBFap7BZqibaofaWxe8AvmEOyJtrGW0//BIW6eouoQeRVN0sD0RcPQ +EW31jP4R+YKwTrT0ETXDxc0PIsmGOo5szuTWqS23mOlwZFl+RrphJ6V+9pEvvEOQDyv8teXAL+oe +H65kZUFWEZLUd9TziYRRH7hfkEAT15P0gwgPJ9rcKoiHkBZpQ9gsG885YrJBzyFEtS7p2ALxxCSG +pmnHBLfccotNzpGVI/q+9D7zyAM+plphpg2cRjuyafGXBEiABEiABEiABEiABEig7gTqIQkZwKfu +kCyW9MEuG+xVeXfwxtJU2KXCBjsiBMm6N5Z8YfMg7JQrE3XXxlpWwAgPLHFHGljShvsjraQOyzFh +SwtlkElW4GYhSdPEkkBw+fnnn9UGXj75inNPmVjqfbDMHstLYRsUtgKxGQldYQlgcyAsb0TbRfur +FYc299577+kydDxzImQpm6In6Q/Qd2G5M54b2KYN6qOSFAxLaPEc4rmHrUwRNqotYLuENiytJHlG +GuhTkG885yJY12Tx++OPP+rmXv4d19EPY1mtCDM1T2H58PonzZM3bpxj9LkwVYLl87B1KYLxyGhJ +8oN+HM8m6heb52ApcdquGM8+TGhgOTbaFMwNwAYyzJV437FB5cqnvoPSieuXlAXqHuURzXa9xVVX +XaVmK+SDp4EdbevqMrawaQT94vnEpnp412MDvzBXjHYUdm/6kwAJkAAJkAAJkAAJkAAJ/EWgYALN +v27BIxIgARIggVIQiBJoliI/vCcJWALYsAv2ZiFcxodDr4AfwnlsGgTB7RVXXOHa47Vx+UsCJEAC +JEACJEACJEACJEACqW8KRKQkQAIkQAIkQAIkEEUAG/BBgx3a7GJT2jz44INGzDQYMQNgxBSLCjOh +KXn88cdHJcNrJEACJEACJEACJEACJEACNUoge713jYJgsUmABEiABEiABIpDADuHi51M1dLE7vZ/ ++9vfMm4MMymy6ZgR25oZ/jwhARIgARIgARIgARIgARIgARDgknO2AxIgARKoUgJY1rto0SIDbbgW +LVpUaSlZrEomANu748ePN9OmTTM//fSTa2NWdqSnzedKrljmnQRIgARIgARIgARIgAQKTLDEEvgA +AEAASURBVIACzQIDZvIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQALpEaANzfRYMiUSIAESIAES +IAESIAESIAESIAESIAESIAESIIECE4htQxPG+72uc+fO3lMe1xCB+fPnG9g/o6tdAosXLzZLly41 +DRs2rF0ILLlhX8BGsGTJEoO/Ro0aEUYNE2BfUMOV/7+i//HHHwZjA/YFtd0WfvvtN9O4cWNTr169 +2gZRw6XH/ADmZJo0aVLDFFj0BQsW6DxxmWWoP1eLreHzzz838+bNc4s+fPhwM3DgQPc8zYPYAk0M +Vr3u9ddf957ymARIgARIgARIgARIgARIgARIgARIgARIgARIgASUwKxZswpGgiLzgqFlwiRAAiRA +AiRAAiRAAiRAAiRAAiRAAiRAAiRAAmkToEAzbaJMjwRIgARIgARIgARIgARIgARIgARIgARIgARI +oGAEYi859+fgtdde83vxvEYIvPXWW6Zr1641UloWM4jA7NmzDWyjtGvXLugy/WqEAPuCGqnoiGLO +mTPHzJ0716y11loRoXip2gmwL6j2Gs5dPtjKwpKy9dZbL3dghqhaAtOmTTMdO3Y0yy23XNWWkQWL +JgD7mTNnzjSdOnWKDsirVU3g/fffN+3bt1ebulVdUBYukMBpp51mXnnlFfdaIfuDvAWam2++uZtB +HtQWAbyoWP+1Vef+0n7zzTe6IUyHDh38l3heQwTYF9RQZYcUFR838FfIgUrIreldRgTYF5RRZZQo +K/iw8dlnn5lNN920RDngbcuBADaE2WyzzUyDBg3KITvMQwkIYGMobAjUvXv3EtydtywXAvXr1zcb +bLABNxIulwopcj5atGiRcUf/BuMZF+t4wiXndQTI6CRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRA +AsUjQIFm8VjzTiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAnUkQIFmHQEyOgmQAAmQAAmQAAmQ +AAmQAAmQAAmQAAmQAAmQQPEIUKBZPNa8EwmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQQB0JUKBZ +R4CMTgIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkUDwCFGgWjzXvRAIkQAIkQAIkQAIkQAIkQAIk +QAIkQAIkQAIkUEcCFGjWESCjkwAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJFI8ABZrFY807kQAJ +kAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJ1JEABZp1BMjoJEACJEACJEACJEACJEACJEACJEACJEAC +JEACxSNAgWbxWPNOJEACJEACJEACJEACJEACJEACJEACJEACJEACdSRAgWYdATI6CZAACZAACZAA +CZAACZAACZAACZAACZAACZBA8QgsW8hbPfPMM+all17KusUyyyxjmjZtatq1a2f69OljWrZsmRWG +HpVNYMmSJebiiy82juPkLMhFF11kll32r6Y4d+5c8/bbb5uZM2eatm3bmk022cSsssoqOdNhgPIn +MGrUKPPFF1+Y9u3bm6OOOioyw2wHkXgq8uKUKVPMe++9Z5YuXWo23HBDfbbr168fWBbWfyCWivUM +Gw/4C7TNNtvouCDsHbLiiiuaDh066F/Hjh1NvXr1/EnwvIwJhLWDqHFhWFvwF3Pbbbc1vXv39nvz +vMwIhNUnnuXllltO5wRdu3Y1W2yxRUbOw9qONxDSuPDCCzPGlN7rPC4fAnHqE7m174Sg8Jg7YC6J +d0KnTp04nyyf6s0rJx9//LEZO3asxj3yyCPNWmutlZVOWP/hD8j3gZ9IZZ3PmjXLPProo6Z79+6m +W7duoZmfMWOGee6558wBBxzA5z+UUg1cEIFTLCcoIJly/+JEOuWUU9zw3rje4xYtWjhvvPFGnOSy +wgwfPtzZd999nWnTpmVdo0fhCLzwwgs5E//5559z1r1tB7/99pub3q233uo0a9YsI27Dhg2dyy+/ +3A3Dg9IT+Prrr50PP/wwUUa+/fZbRyYrWrcNGjRwZs+eHRqf7SAUTVldiNMXIMOff/65s/XWW2c8 +13j+5WOF884772SVifWfhaRsPb7//nvn3XffzZm/OOMBtIkzzzxT04rzDpGBrvPqq6/mvDcDFJ5A +3L4gTjvwjwvjtAW0HaRNVzoCc+bMceSjVc4MxK3PQw891Pnjjz/c9OK0HbQDpE9XOgITJ050Fi5c +mDMDcevTvhNyhW/UqJEjwmxn/vz5Oe/NAIUlgDrIZ24/aNAgd5x46qmnBmYybv/B90EgvqJ6Tpo0 +yfn1118T31OUHpxevXppWxgyZEhkfBFkarj//ve/keF4sfgE+vbt6z7PeDePHz++YJn4Sy1O7lQo +t+OOO5oTTzzRTX7RokVGJrgG2lr4GrPnnnsaEZAk1rSQiYx5+OGHzQknnOCmzYPyIzBmzBgjE5TA +jOHrauPGjfWadEaqtSetXb+0bL/99gYaXWgn55xzjn6FPeiggwLToWf5E7jjjjvM4sWL9TlHH3Dn +nXcaGXBkZZztIAtJRXvged5rr730WV5//fXN8ccfb6B9ed999xkRZhr5KGXko5SRyYiWk/Vf0dWd +M/P+8YA/QufOnf1exvsO+eGHH4wIUM1TTz1lZLBsttxyS3PXXXcZvhuysJW1h78dxB0XetuCv4Dr +rruu34vnZU7AW594V/zyyy9GhOOqpYUxA57v4447LqMU/raTcVFOmjRp4vfieRkTyFWf/neCNzzG +lJhHYiwxbtw4XRmGeeHkyZONfDgv41Iza34Cv//+u7n77rtdbzz/oswSWY/e/sON+L8Dvg/8RCrn +/PrrrzfPPvtsZIbnzZtnRowYYe6///7IcLxYIwTiikoFR4aUNU48+zVNhJmBwb/55htHlhlpurLE +ODBMlOc+++yjcUXVOCoYr6VMII4mhvcLmkxAY+Vg55131voUAXVG+CuvvFL9N9hggwx/npSOQD4a +miLM0nqUF5X+ypLjwAKwHQRiKUvPOH2BLDHX+m7evHmGVq5XY9ebDuu/LKs6NFNJNTTDxgP+G+R6 +h0Cz/4gjjtC21apVKyfue8Z/H56nQ8D7DEelmM+4MFdbiLofrxWPQD4ammHP7cCBA/XZlo9hbgFy +tR03IA9KSiCphmbcd0Ku+n/xxRcdMU+l7Wbo0KElZVDrN89HQ/Oee+7Ruttvv/0cWS6uxw888EAW +Sr4PspCUrUc+GprTp093oG29/PLLaxvwa2g+8cQTzkYbbaRhvLIpamiWXzMopoZmSTcFWnXVVQ3s +YcGJSrJ5+eWXzUknnaQSd/X0/ZNliHr95ptv1l98kYO79tpr9Ry22bwOUnvY6YMdnqOPPlo1wqAF +4HWffvqpkeUMZqeddjI9evQw/fr10/TwlZiueARkeYqRCZHeEPXhdbIEQbU433//fdXs9V7jcWUQ +gNYd7Jx06dJFNarbtGmjWlbQsvY6tgMvjeo4/u6777QgsIUkgie3UOj/YfMKDlp3cKx/xcB/MQhA +sx9jAfQlaD833HBDjFgMUu4E/OPCcs8v81cYAuutt54mjLkBHQnEIQCbibCfCnfZZZcZaPzRVQ6B +0aNHa2YPOeQQM2DAAD22fpVTCua0LgQgozn44IPNCiusYK644orApERsp6v9sBcD7KjD7jIdCZRU +oPnkk0+an376yYjNRLP55pvrxOSmm24yZ599trGTYFtFWFYAQdeNN96oy9Mxefnkk0/08mOPPaaT +GbHpp+d4ickXHtO/f38DISiWpUEtXezxGNHq1EkzAmLjGRgeF1ucKkzDMrYJEyboMlgYll+wYIGm +x3+FJ/DZZ59pvbRu3VqXlnvviIkrNgaCs3Xsvc7j8ieA5w8OAxVs/mCXh/oHK2wH5V+XSXPYs2dP +XQIIgTaWhln30UcfmalTpxpsCoQlZHCsf0uHv3EIYEmhXY6K9zdd5RPwjwsrv0QsQT4E7NJTbBxK +RwJxCUCJBZvO4uOonSPGjctwpSOATWCff/55s9JKK5ldd93V7L///rrUHMuOYaKOrjYIXHDBBSqb +GTlypFl55ZUDC73bbrsZKDjZv1122SUwHD1ri0BRbGh+8MEH7q5lwAtBod3JDDYUsRs2fqHBA0Hi +008/rfbVTj75ZLc20Kn9+OOPBnYVxVCwfr2BNid2vbvtttsMJs1rrLGGhpclympLBRqXEKRACwja +nNgx7fHHHzfnnXeeaoFCOApbbvgaAEEqBKuw2QihpxgzVhtde++9t5sHHuRHALbyRHU8MPKmm26q +wkorwIa2TZBbffXV1duGCwpDv/IkAG3nBx98UAVXBx54oGYSX1/xIQFa1NCwxtc4OFu/bAeKoyr+ +wTYm6hr9OT5cob+VpYm6eyEKCE0Ka2OX9V8VVR5ZCP94wBsYOxTjw2MSB7uscPzYlYRa6cP620HY +uNCf07DxxDrrrGNk4zF/cJ6XOQFvfULzRjYL1HH9m2++aTbeeGN9X/iL4G873usYv9vxhNefx+VL +IKo+k74TMN7ArucQduCdIKaNyrfgzJlLAMpHeP6hiASNO4wJIbjCLte4JiYE3LDeA2//4fXn+8BL +ozKOxWSEymYwR4DsRcwNVEbGmcuyIFAUgSaEkWHGXSGghNaWdccee6wKNPF11ivQRKcFB6EkOjr8 +2UHLmmuuqWrHuA4jsRBoQoD273//26y22mrw1qWu0OTE5AcC0GHDhplZs2bpNcSHMNOGu+aaa2hk +Vmmk88+7IZQ/RbGNoQJN2clSL4WpjtuNg/DVla6yCIhdHCP27gy+otnnERq3GGhCqwrP9jHHHKOF +YjuorLqNm1toYOKDFbQyYezburZt2+rAxZ6z/i2J6v2NGg+g1EkFmtDqh7Pvcz3hv7InENUO/ONC +b2HCxhMYR1Kg6SVVGcdh9YncX3TRRcY+397SRLWdbbbZxp0beOPwuHwJRNUncp3POwECTb4TyrfO +vTnDuO/2229XL688AIoPEGhizo6+AKu7/C6s/+D7wE+qvM/FLqo+5+jvaT6ovOuqXHNXFIEmdinE +LrfW4SsMbF5hl1LYTYStHLzQoK0HG5YQemCZOL6u4RqEWOjUIHTEUvIoBzua+NKPrzNYPu53sNmJ +l9zrr7+u9xLjsircfOmll8wee+yhA2LkgZqZfnL5n+NFhCUgQW6rrbZS76VLlwZddv2WLFmix/ha +S1dZBOxyc0w0YLPWOkxaIdDEsnMr0GQ7sHSq5xdCTNhOhSkQaNLjoxQ08u+9917VxEG/j354u+22 +M6z/6qn3sJL4xwNh4eL6w2wNnNXijxuP4UpLwN8OosaF3pyGjSeoieWlVDnH/vrEewIaexjz77vv +vmoH32+axt92vKVt2bKl95THFUAgqj7zyT7fCflQK10cyAJko1EjGzrpMmM7T0CfjrHil19+qYpO +WIrud/7+w17n+8CSqIxfCKa/+OILA5Mzdm+Vysg5c1kuBIoi0ISdyjPOOCOrzNCkhIDy4Ycf1g17 +MLGFhp7sXGouv/xyAy1NqJmjgWPZKmxlWU29rMT+52GXncF2ihWSBIVF5wltUGh04l7YtAR/cLIb +r24idMkll+S8X1Da9MskgE19YBclyjVs2FAvy854gcGg4QeH5SR0lUMAph6wdAwOph7w53cw7zBt +2jQju9YZtgM/nco/HzdunAozYQsNA1f7UQL9PDQv7rzzTnPXXXepQJP1X/n1nasEYeOBXPHCrsPu +KhwMxNNVDoGwdhA0LvSWKs54whuex+VNIKw+J0+erB/Axo4dqyZLrFkSlCas7ZR3SZm7MAJp16e1 +uch3Qhjx8vK3Hyy+//57VUYKyh3CBAk0w/qPoDToV54EMEfAHAAmyaDkBLkMnN3UCxsFwQ/z/7BV +nOVZMuaqmASy9beLeHdMbO3mILBtaR12JMc1axTcu9zchgn7tUZkIRxFvLA/aApBfR2CVtjsgTAT +y9DxpRCqz1dffbW72UDYveifHgGrXQPbqtDU8DsrqLbh/Nd5Xp4ErHYmTD307ds36w+2juDsgMbW +L9tBedZnPrmCTWQ4GOu3wkybDuwgw/3nP//RX9a/YuC/BATs+KBDhw4JYjFouRIIGxeWa36Zr8IQ +2GyzzdSUFFbn2HdIYe7EVKuJANoKbHRjs8G11167mopWlWWB3XSspkS/HzRH6NWrl5Z7/PjxBgJP +uuoj8Morr2ihsGoLK3Ht32GHHab+sLMPv1GjRlVf4Vmi1AgURUMzKrcTJ07Uy02aNHGD4SWETgwb +/mCii44M6uPY5CeX22CDDTQIhJLQ/sRLzeuuu+46Xe4Om24jRozQLwDnnnuuLjWH/SUc33LLLSrM +xJIXCNf8k3BvejxOhwAEW7CJiq8w+DLfrVs3N+Fvv/1WN5FCPdj6dS/yoGwJ4OsavrrBQWAZZN8M +2nnQ0kO4q666So25sx2UbZXmlTG7IZg1G+FNxGpeW3vI7Ae8dHiciwA2G3vttdf0q/3f//73XMF5 +vUIIBI0LKyTrzGZKBLAJqP2Q7Z0fpJQ8k6lCAljhhV2S4TCuhBCErrwJQAMbY8OddtpJ5/pBuV13 +3XV1x3qEDVrtGRSHfpVDoHv37oFm/rDzPVb5Yd7fsWNHfqConCotSU5LpqFp7WJCoAGHzszrsBwc +Di8lTHphd83vrKDRqiXjOjb4geAENjguvfTSjCgQjA4ePNjcfPPNuqkQNEDx8sPmQV6HDUvgYMfB +3sN7ncfpE4CdFGwaA3f66adn2NLDOYxGQ6C96qqrpn9zplgQAjAlgS/lUbsNwlYt7KvC5hHCsx0U +pCpKmqj9OAHTHnYXc2QI/fqFF16oecPu53Csf8XAfzkI4IPlFVdcYbBpABxWdaCfoatsArnGhZVd +OuY+LgGs0IDgAksNIczEiio6EggjAMUTfASBIgz2X4DpmrBdscPSoH9pCNhVXFYbLygX2PUazoYN +CkO/yiWApeaY//n/oGAGd8ABB+g1KyOo3JIy54UkUBQNTexy/Nxzz2WU46uvvlK7mPCERqb9qmYD +7bnnniq8+uabb1T7wrvzmQ1jd0zGUkZI8KGWjInx8OHDzQ477GCGDBlisJQd0n8YGX/55Zc1Ku6F +ifPhhx+uAk48LFB1xxcAqLTjoYLLtQGRBuK/nARgE8OvKWsjwR/L/WG3FDZLIXR+8cUXzRprrKE2 +9WBfEV9pIFiGbS26yiFgBx/4KBHmoL0HoSY0NKHFiRcb20EYrcr0x0ekO+64w0yfPt20adNGn2ts +9gZ7mrB/CDMh6KutY/1bEtX5GzQe8JYU7/qzzz7b66V2lew7BB8w0W7sBlIDBw7Ud35GBJ6UPYGg +dpBrXFj2hWIGExPwjw8hxIRA0zqM+7BZCF31EgjqC7yl9b8TvOEhzMQqLnw8h4NSC3bFbtu2rTcJ +HpchAcz9oIWNecA+++wTmkMINCGgnjFjhs4XrdJRaAReIAESqDkCRRFoQvvK7jpnCUOg2LlzZ9XM +vPjii7OWBsDwKzox2LLEruPWNqaNj19MZCD8ev/993XncuxeDoevudjFHFobb731ln6xgz8GRRBm +YjctuJNPPll3UL/mmmvMI488on74B+Pj+DoMjSK6uhPASyjKYVd6CDRhZxG73WPpIIQf1jYaBijX +X3+9CkKi0uG18iGAienzzz+vgugogSZyjOccAk2ERzy2g/KpxzRygmcbpkPOP/98fabxcQt/+EiB +D0kw/WFtZ+J+rP80qJdvGkHjAW9uIaz0O+87BO/nLbbYQj9i9u/fP2t1hz8uz8uTQFA7yDUuREms +YLs8S8VcJSXgfbZt3FatWhnYwcfqnJ133tl6u79sAy6KqjgI6gu8BfO/E7zh0Ragnb/tttvqZlGn +nHKKmq/yxudxeRLAh244KA9hpVaYw5JzzOthXgZxIBewjn2BJVF9vxgPwNnfsBLmuh4Wj/7VRaCe +fN3K3oEloIz+pdcxowWkFN8LnRx2v4LB4N133z1+RE9ICMswYMIkCFp/QZ0f7Hdg13NsDtSyZUv9 +ssedtDwQfYcQIm+33XY+33RP586dq2YDUGdBwux078bUkhKA5jTsFRV6Iw62g6Q1U9zwSfsCaN9g +coJfTEIaN24cmWHWfySesriI9yb+OnXqVBb5YSZKQyBpX1CaXPKuhSSA/hr9O4SRdLVL4NVXXzXY +1KlBgwa1C6HGSw6TQu+++66ukKxxFDVd/DfffFM/PkcJrGsaUJUXHgqJkOFZh1W4UGQphCuKhmY+ +GYcaOmxbYpOIuthNwIQ51+AK0n1oAeKPrjwIwH5ply5dyiMzzEXJCLAdlAx9QW6MCQ6Wm8d1rP+4 +pBiOBEiABEiABEiABEiABEiABGqLQNkJNLHM+KGHHlIDz9CcxNLvIK3K2qomlpYESIAESIAESIAE +SIAESIAESIAESIAESIAESAAEyk6giaXfWGYOh017TjjhBD3mPxIgARIgARIgARIgARIgARIgARIg +ARIgARIgARIoO4EmDDrvv//+BksNmzVrxhoiARIgARIgARIgARIgARIgARIgARIgARIgARIgAZdA +2Qk0l1lmGbWb6eaQByRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiTwPwLLkAQJkAAJkAAJkAAJ +kAAJkAAJkAAJkAAJkAAJkAAJVAoBCjQrpaaYTxIgARIgARIgARIgARIgARIgARIgARIgARIgAUOB +JhsBCZAACZAACZAACZAACZAACZAACZAACZAACZBAxRCgQLNiqooZJQESIAESIAESIAESIAESIAES +IAESIAESIAESoECTbYAESIAESIAESIAESIAESIAESIAESIAESIAESKBiCOS9y/nnn39eMYVkRtMl +sGDBAsP6T5dppaU2Z84cs3DhQraDSqu4lPPLviBloBWY3C+//GLwx3dCBVZeillmX5AizApN6rff +fmNfUKF1l2a258+fb7788kuz7LJ5TzHTzA7TKgGBRYsWmXnz5nFcUAL25XRLtIGvv/7aNGzYsJyy +xbwUiQDGBF4HuUGhXN5vG8dxCpUnplvmBFD3rP8yr6QCZ8+2AbaDAoMu8+RtOyjzbDJ7BSRg+wD7 +W8BbMekyJsC+oIwrp0hZW7p0qY4N2RcUCXiZ3sb2BWwHZVpBRcgW+gI4toEiwC7jW7AvKOPKKUHW +Ctkf5C3QbN++fQlQ8JblQACaOKz/cqiJ0uWhQYMGBl/h2Q5KVwflcGf2BeVQC6XNw+zZs1UTh31B +aeuh1HdnX1DqGij9/efOnWsWL17McUHpq6KkOZg1a5Zp166dwTiRrjYJWG1tjgtqs/5tqX/44Qez +xhprmKZNm1ov/tYQgSZNmmSUtlGjRhnnaZ7QhmaaNJkWCZAACZAACZAACZAACZAACZAACZAACZAA +CZBAQQlQoFlQvEycBEiABEiABEiABEiABEiABEiABEiABEiABEggTQIUaKZJk2mRAAmQAAmQAAmQ +AAmQAAmQAAmQAAmQAAmQAAkUlAAFmgXFy8RJgARIgARIgARIgARIgARIgARIgARIgARIgATSJECB +Zpo0mRYJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkEBBCVCgWVC8TJwESIAESIAESIAESIAESIAE +SIAESIAESIAESCBNAhRopkmTaZEACZAACZAACZAACZAACZAACZAACZAACZAACRSUAAWaBcXLxEmA +BEiABEiABEiABEiABEiABEiABEiABEiABNIkQIFmmjSZFgmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQ +AAmQQEEJUKBZULxMnARIgARIgARIgARIgARIgARIgARIgARIgARIIE0CFGimSZNpkQAJkAAJkAAJ +kAAJkAAJkAAJkAAJkAAJkAAJFJTAsgVN3ZP49OnTzbPPPmsmTZpkcLzWWmuZ7t27m6233tpst912 +npA8rAYCS5YsMRdffLFxHCeyONtuu63p3bu3eeaZZ8xLL70UGbZevXrmwgsv1DB1TXvZZZc17dq1 +Mx06dDCdOnUyLVu2jLw3L+ZHoNj16s9lrjaz4oorahtAO+jYsaNBeLp0CbAvSJdnpabGvqBSay7d +fCdpB88//zzHBeniL4vUCvlOSKPNcFxQnGaSpC9Ajuo67veXiuNDP5HinxeyL0Bp6tpmOFcsbpuY +O3euefvtt83MmTNN27ZtzSabbGJWWWWVwEwkCetNYNasWebRRx9VGVS3bt28lzKOZ8yYYZ577jlz +wAEHUEaQQaZMT0TgFMtJ9iGZcv9iRfpfoOHDhzvSKbhxveng+Oijj3YWLFiQJMmMsJ9//rmz7777 +OhdccEGGf6FPUC7cd9q0aYW+VVml/8ILL+TMz88//xxa3976P+WUUzQt/Hr9w46RbtppN2rUyBFB +qTN//vyc5WKAPwl8/fXXzocffpgTRynr1bahuG1GPrA4r776as4yMcBfBNgX/MWiVo++//575913 +381ZfPYFORFVdIA4fQEKmKQdJAnLcUHpm8+cOXOcKVOm5MxI2nXlfden3WY4LshZnVkBJk6c6Cxc +uDDL3++Rdl2hHSBNuLTTZjvw1170OeZTb7zxRnQguVrIviDttDlXzFmdWQFEic359ddfs/yDPG69 +9VanWbNmGbKAhg0bOpdffnlW8CRhvZGXLl3q9OrVS+8xZMgQ76WsYxFkarj//ve/WdfoEY9A3759 +M+pz/Pjx8SLmEargGprHHHOMGT16tGo+yQvG9OvXz3Tp0sWIMMTIANgMHTpUr0+dOtW88sorBl9D +kjrptMy4cePM7Nmzk0atU3gRfpiHH37YnHDCCXVKp9ojjxkzxrRo0SKwmOuuu26G/4477mhOPPHE +DD/vSZMmTcxvv/3meuWb9uLFi83HH39s3nnnHW07+IqHupw8ebJp0KCBmz4P0iFQrHoNym1Um/nh +hx+MCGPMU089pdrjW265pbnrrrvMQQcdFJQU/epIIN/nNei2UfXqDx/Vz7Av8NMq7Dn7gsLyrZTU +47QDW5Y4YTkusLQq6zftd4ItfV3aDMcFlmJxfutSV/4cRr3r/WFxHjWOYDsIIlY4v7T7Ar4TCldX +aacsQkNz1FFH6apOaERuv/32Rj6OmVGjRplzzjlHV1TaeVmSsP58Xn/99bpa2O/vPZ83b54ZMWKE +uf/++73ePC5zAsmlhwkK9Prrr6uwEkLKO+64wxx44IFu7B49ehj8odHuvvvuRr7kmFtuucUcf/zx +bhgeVAeBPffc06y00kqxCoPl33vvvXessAiURtpY6r7//vurKYQrrrjCXdYeOxMMmJNAKeo1LFNB +bUY0xPXDxG233WZOPvlks/POO8dus2H3oX82gSD22aH+9ClFm2FfEFYb6fmXol7Dch/UHtkXhNFK +1z9JO0gSFrkMqtew3Ielzb4gjFi6/mnUVVCOwuo1KCz8gvLBviCMVrr+adRVWI7SSJvtIIxuuv5B +z2DYHdKo16Rp850QRqzu/sOGDVNhJhTEbrzxRjfBddZZx5x11lnm0ksvdRVNkoR1E5IDKK+cffbZ +ZvnllzeiNeq9pMdPPvmk3uujjz4yv//+e9Z1epQ3gYJuCoSGAzdgwIAMYaYXCYSaXruI9ovKZZdd +Zk466STzyy+/eIPr8amnnmpOP/10PUZDhxAKDhp3iAPJOtwHH3yg59C4evPNN83gwYPVXqeowKpd +jS+++ELD2X9x7/niiy9qutDug7v22mv1/L333rNJ8beCCMCOp22DaAPsyCqo8lLKauPGjc3NN99s +2rRpY/BV/oYbbkgpZSZTSQTYF1RSbRUmr+wLCsO10lJlX1BpNZZ+ftkXpM+0ElNkO6jEWks/z3wn +pM8UKYp5Cl2xi+MzzzwTP64bNGiQwfP3/vvvGzEvmCism4gcLFq0yBx88MFmhRVWcGVG3us4llXO +Biu22rdvr3sqLLfccv4gPC9jAgUTaOKLFgR/cFb4GMYBasYwwv3dd9+pMViEgxASQgUr4PTGvemm +m1T4AD9odd5zzz16+ZtvvtE4iAsHgSXSwP2x+dB1111nXn75ZfP444+biy66yGy22WYGqsvWxb0n +DNYi3U8++USjPvbYY3qOZfR0lUkAbbBp06baWdp6rcySMNf5EoCpgeOOO06j40seXW0SYF9Qm/Xu +LTX7Ai+N2j1mX1C7dW9Lzr7AkqjtX7aD2q5/W3q+EyyJ9H4/++wznXu3bt1al5Z7U4YwExsDwUHG +kiSsNx3ZY0XlSyNHjjQrr7yy95J7vNtuu6ngFMJT/O2yyy7uNR6UP4GCLTmHyi6k3VDt7dy5cyQJ +2DDZeOONdTdLaFXCjl1ch2XtiANVdaQBmwdiRDYjOgSla665prnzzjtNz549VdAJe55inFRVmKHZ +6Y+TkYDv5NBDD9UlqdAGxS59WKaKdNdYYw1fSJ6CwH333aftwE8DquQQNHsd6nLs2LFeL/d4n332 +0a8rroccJEnbG89/LMaetSNFJ4ZOc8MNN/QH4XkdCBSyXpOmHVWM9ddfXy/z40QUpfyvJXlek9Zr +krSjSsC+IIpO3a8Vsl6Tph1VGvYFUXTqfi1JXSUJi5yxL6h7/RQrhSR1laQdJAmbq6zsC3IRqtv1 +pHVVqDaTqxRsB7kI1e16Ies1SdpRpeD4MIpOftcgo4HDCrkgt/rqq6s3wllZTZywNi0o12HlLjQ0 +YdLugQcesJf4W0UECibQ/PTTTxVTWKPzM4TAEQ7CxSRuvfXWU8k+4kDLs2PHjoHRJ0yY4ApWIUh7 +5JFHDGxwQHABQafstB4YL8gTG9zgD6rLcMh72H2D4teaX9gmP4ccckiWQPPZZ58NNdi7zTbbuMwt +wyRp2zhhv/g6BIHmrFmzwoLQP08ChazXpGlHFQFtAI5tIIpS/teSPK9J6zVJ2rlKwL4gF6H8rxey +XpOmHVUK9gVRdOp+LUldJQmLnLEvqHv9FCuFJHWVpB0kCZurrOwLchGq2/WkdVWoNpOrFGwHuQjV +7Xoh6zVJ2rlKwfFhLkLJrv/xxx8aIWyJN7Q04bA0PUlYxMGm0VBCQ53RlBiIVK8rmEDTCvuCDK8G +4bS2MsN2ww6KE9cP2pN+LdH69evrjlqwwYmdrZMINOPel+H+JIDl/VjO7XdBWpDQzt1rr738QfW8 +ZcuWWf5J0s6K7PP46aef1Md+DfJd5mkdCBSyXpOmHVUMtoEoOnW/luR5TVqvSdLOVRK2g1yE8r9e +yHpNmnZUKdgGoujU/VqSukoSFjljX1D3+ilWCknqKkk7SBI2V1nZF+QiVLfrSeuqUG0mVynYDnIR +qtv1QtZrkrRzlYLtIBehZNeXLl0aGWHJkiV6vV69eiZJWESCIBvmB7HhD5Te6KqXQMEEmlZjEXYt +YQcTy8qjHJaow1mV/qiwSa+tvfbagVFg+BVu5syZ+st/hSEAo75xdznv2rWrOeOMM2JnJEnauRKF +wWE42y5yhef1+AQKWa9J047KNeyzwLENKIbU/yV5XpPWa5K0cxWMfUEuQvlfL2S9Jk07qhTsC6Lo +1P1akrpKEhY5Y19Q9/opVgpJ6ipJO0gSNldZ2RfkIlS360nrqlBtJlcp2A5yEarb9ULWa5K0c5WC +48NchJJdt8vI58+fHxjR7qWC5f5Jwo4bN073YznwwAPNVlttZebNm6fp241/sVEQ/JBumHZoYIbo +WZYECrYpELTcoFEHO5p2k54wAtCQtDuE+zUp/XHQAK203n8t7Hzu3LmBl6z2aPPmzQOvW8987mnj +8rcyCDz99NNmzpw5Bpq7YQLwyigJc1kXArCzA9ehQ4e6JMO4FUyAfUEFV16KWWdfkCLMCk2KfUGF +VlzK2WZfkDLQCk2O7aBCKy7FbPOdkCLM/yVlV0XC5CBkRn5n9zT4f/bOA+xqIuvjo2JFwI4Ne+8F +FStW7B3Lioro6ooFC5a1Y8Pee8VeWXTFtmD/7A0L6qKuXQGxgoqKmu/8z3qyuXmTeyf3ze3/eZ73 +vclk6m8mM8nJmTMIlyXsM888o0ndfvvtrnPnzuFf37591X/w4MHqd80118Sz5HkDEqiYQBMsBg4c +qEjOOeccZ8LDOCOoDw8aNEi9semLCZNMWh4XRo4ePbqkynE8j+eee84lSf4fe+wxDbrYYovpb555 +xsvA8/olgL6BHdDgYGsDAx9d6xG4++673fPPP69f6vbff//WA8Aa6zzBsYAdgWMB+wCfC9gHQIBj +AfsB+wH7AAhwTqhMP1hggQV0fwxoYkLBLerGjRune6tgufnSSy+tm/fCpKFP2NVWW003AcJGQNE/ +2zUd6cHf5E7RfHnceAQqKtA89NBDVZoOqft6663XZqMNqP3uvPPODhv2dOjQwUFabs6ML0d3o0L4 +Y445xoKEv+jocKZGHF748wCad0cccUSBIPSJJ55wQ4cOdYi76667asgseSJCqXz/zJ4/dUoAX4Ke +ffZZt/HGG7uXXnpJVdlPPvnkOi0ti1UpAjAafeaZZ7o+ffpoFrCni43D6FqHAMeC1mnrYjXlWFCM +Tmtc41jQGu1cqpYcC0oRao3r7Aet0c7Fask5oRid9l+D/GezzTbThOKyGpxjI6DVV1/dde3aVWVF +vmGx1HzYsGFt/o499ljNa5dddtFrll77a8IUakmgYjY0USnYzRw+fLjr3bu3GzVqlFt44YVd9+7d +3UorreRgMxPaUNgMCBpxQ4YMKbCfue222zqodkN7E8JH7Gb+6KOPOkjrzYaCgUMnh4NQas0113Sw +x3LZZZfZZf298sorHdSP11lnHff555+7ESNG6I5Ze++9t1thhRU0TJY8EWHuuefWePvss49+OYBA +do011lA//qs/ArfddpszrVxMUOhLEHbDYad69MFu3brVX8FZolwJwJYKTAvA4SMI7CKZoen+/fs7 +aJTTNTcBjgXN3b6+teNY4EuqecNxLGjets1SM44FWWg1b1j2g+ZtW9+acU7wJZVfuFNPPVXlRU8+ ++aSbf/75Xc+ePd2LL76oe5xAeeyss84KM8sSNozEg6YnUFGBJuhBuAgV4gEDBqgQEUJFs2sAteFe +vXq5Sy+9tI3NOggJsbz8iiuucI8//rj+QSD6wAMP6LJgE0QhjznnnNMdddRRGhZC0smTJ8M7dFjK +Du3La6+91r355pvqP8ccczhI6Y8//vgwXJY8EQnCD9x877zzjmqfjh07NkyLB/8jYMKj//mkH2UJ +i1SyhMfOdLY7HeJBCw+aw+ijhx12mKq8p5eMV9pDIEs7IZ8s4bOERdpjxozBj7pZZ51VP4Jg6QE0 +tTfaaCO7xN8KEMjSVlnCoqhZwnMsqEDjeiaZpZ2ytmvWtDkWeDZaBYJlaassYbP2GY4FFWjcDElm +adtKhUVxORZkaLScg2ZpV2SdJXyWsEib/QAUauOytFWWsKhNlvCcE6rf/tgQ+pFHHnEw9wXZj9mr +hbLRxRdfrAJOK1WWsBYn+guNUDj7jV6LHpe6Hg3L49oTmEo01dpaYE0oly2vtkue0Sx4+PvJJ5+4 +t956S7U1oXU59dTFV71jBypMMJDYm0ZkmFiJA2hhbrrppiqogFFY2FyAcdlZZpnFLfTnDudJSbQn +z6T0ms0PQlx8PaFrXQJffPGF2pPh5jmt2wdQc44Frd3+qP2ECRP0b5llliGMFibAsaCFG//PqsPm +PVY8YBUWXesSwL4Fq666qptuuulaF0KL1xzv23jXhx1DutYl8PLLL+sK1o4dO3pDwDzy4YcfqtwH +CmvFXJawxdLhtcoQ2HrrrdWspKWOVdtbbbWVneb6W3ENzXhpYfwVf74OWpxYpp6HwxJ4nwetPPPM +o9xMgwRIgARIgARIgARIgARIgARIgARIgASakQCUzlZeeWWvqmUJ65UgAzUsgeLqkQ1bLRacBEiA +BEiABEiABEiABEiABEiABEiABEiABEigGQk0tUATKs5dunTRzYmasfFYJxIgARIgARIgARIgARIg +ARIgARIgARIgARJoNQJVX3JeTcDYrQ72FehIgARIgARIgARIgARIgARIgARIgARIgARIgASag0BT +a2g2RxOxFiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAkaAAk0jwV8SIAESIAESIAESIAESIAES +IAESIAESIAESIIG6J0CBZt03EQtIAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRgBCjQNBL8JQES +IAESIAESIAESIAESIAESIAESIAESIAESqHsCFGjWfROxgCRAAiRAAiRAAiRAAiRAAiRAAiRAAiRA +AiRAAkaAAk0jwV8SIAESIAESIAESIAESIAESIAESIAESIAESIIG6J9Ch3BJ+/fXX5UZlvAYn8Ouv +vzq2f4M3YjuLP2nSJDd58mT2g3ZybPToHAsavQXbX/6JEye6n376iWNB+1E2dAocCxq6+XIp/A8/ +/MDnglxINnYiv/zyi/v2229dhw5lv2I2NgCW3v3888/6x3fF1u4M6Affffed9oXWJtGatcdzYdRN +mTIleprrcdmzzRdffJFrQZhY4xDAwwrbv3HaqxIlhUATA9M000xTieSZZoMQ4FjQIA1VwWJCmPnj +jz9yTqgg40ZImmNBI7RSZcuIl1cINfl8WFnO9Z46PnaPHTuWz4f13lAVLB/eD/BswLGggpAbIGk8 +G44fP95NO+20DVBaFjFvAngmiLq6FGguv/zy0TLyuIUIfPPNN47t30INnlBVPKRgolp88cUTrtKr +VQhwLGiVlk6v54QJExz+lllmmfRAvNL0BDgWNH0Tl6wgNHE++ugjPh+WJNXcASDUxnww3XTTNXdF +WbtUAhBm/v777xwLUgm1xgV86FxyySVdx44dW6PCrGUBgc6dOxeczzTTTAXneZ7QhmaeNJkWCZAA +CZAACZAACZAACZAACZAACZAACZAACZBARQlQoFlRvEycBEiABEiABEiABEiABEiABEiABEiABEiA +BEggTwIUaOZJk2mRAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAlUlAAFmhXFy8RJgARIgARIgARI +gARIgARIgARIgARIgARIgATyJECBZp40mRYJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkEBFCVCg +WVG8TJwESIAESIAESIAESIAESIAESIAESIAESIAESCBPAhRo5kmTaZEACZAACZAACZAACZAACZAA +CZAACZAACZAACVSUAAWaFcXLxEmABEiABEiABEiABEiABEiABEiABEiABEiABPIkQIFmnjSZFgmQ +AAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQQEUJUKBZUbxMnARIgARIgARIgARIgARIgARIgARIgARI +gARIIE8CFGjmSZNpkQAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJVJQABZoRvH369HE9evRwSyyx +hLvmmmsiV3hIAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRQDwQo0PyzFZ588kl32223uX333dd1 +6tTJ/f3vf3dff/11PbQRy1BlAjvvvLObaqqp3DfffJNLznmnl0uhmEjNCHz55ZfuqaeecuPHj8+1 +DOxnueKseGIvvfSSe+GFF3LN5+2339axa8CAAbmm28qJ5c007/RauW2ape6VmBPYzxqvd1RiTuBz +Qf79IG+mvFfzb6NGT5FjQaO3IMtfbQIUaP5J/JhjjnFLLrmk22uvvdyhhx6qwqzTTjut2u3B/EiA +BJqcwMiRI13Pnj3dgw8+2OQ1ZfWKEdhtt90cXozoSIAEWpsA54TWbn+rPecEI8FfEmhtAhwLWrv9 +WfvsBCjQFGbDhw93zz33nNtnn33cNNNM43bZZRc3zzzzuOuuu85NnDgxO1XGIAESIAESIAESIAES +IAESIAESIAESIAESIAESqAiBqgg077zzThUWrrnmmu6vf/2ru/nmm92vv/4aVujZZ591WCL39NNP +6zLM888/322xxRYqZDzhhBPccccdp2Effvhhd9BBB2laFvmTTz5xJ598sttuu+3c2muv7fr37+/u +uusuuxz+Fktn0KBBukwPX0TgpptuOnfAAQe4SZMmuSFDhoRp8CAbgd9//90NHjzYde/e3XXp0sWt +u+667vTTT3d//PFHmBD6BvrFqFGj3IEHHqhash07dlRbpugPUYc+c+yxx2p6M888s1twwQVdv379 +HPpA1L3xxhtuhx12cAsvvLCbffbZ3QYbbKDC6WgYHP/000/usMMOcyuuuKKbaaaZ3FJLLeUuuugi +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 +vv32227dddd1c845p1tkkUX0+o8//uhOP/10Ndw+//zzu7XXXtudeuqp7ueff24Tv149kup7yy23 +ONh0vuGGG+q12A1XriTODVeJFitw2hiZNBYATTPOCRwLnM7rSXNC0nNBs84Jrf5ckPfQlza25J0P +08uXQNo8zrEgX85MjQQakQAFmo3YaixzUQIjR450PXv2dA8++GDRcLxYPwTS2uzzzz93p512muvU +qZMbPHiwW2edddxDDz2kv8OHD3fdunVzM888sxs2bJjr0aOHGzFiRP1UqkhJ0uqLKFNP3brD8m67 +7eZ23nnnNuTOOOMM9/TTT7u9995bhZbQ1N1iiy3c8ccf78aNG+eWXXZZ984777gTTzzRbbrppg5f +6xvBpdUXZW/lfpB32xXjnHdeTC8fAmljZHwsQG6cE/JhXo+pJN27Sc8FzT4ncD7Ir3emjS355cCU +KkGAY8F/qXIsqETvYpqNToC7nDd6C7L8JNDEBKCZ8fvvv7sDDzzQHXrooVrTNdZYQ/1wbfXVV1e/ +u+66y+2yyy7ulFNOcb169WpYImPGjGnYsley4K+//rqbZZZZ3DXXXKPZQIABLeytt97a3XPPPW6a +aabRPrHyyiur/2OPPeY23njjShapYmn36dPH7brrrlqnimXChEmgQQnExwJUAxo6mCeabU7gWJDc +SZOeC5p5TuBzQXI/oC8JcCxgHyABEgCB1lUFYvtXnABeMLAkdM0113RdunRxSy+9tNtzzz0dvq7H +HQQQWEKMpcVYcvu3v/3NPfDAAxoXS8nMjR49WpcXzzfffG7GGWfUJahYbmxpQoiBlxs4aPYh7zfe +eEPPUR5o+XXv3l3LgyWsKF+jaHNpJRrs32abbeb22WefNqXed9993QYbbKD+aW227bbbuoEDB2qY +iy66SNvyrbfecpMmTXIdOnRwq666apgutDPhJk+eHPr5Hjz33HMqGMOyZQjN0D9uvPHGNtHRj9BH +F154YTf77LNr+a+77rqCcJtssok78sgjVWMIx0hv0UUXVWGsLYVOqy8Swhdo9GdzPukhrA9nhENf +P//8893yyy+v9wC0W5dbbjl39dVX43JF3NChQ7XtwDnq8CCK+xPLKu+44w49/vTTT1XjEv4DBgxw +0MLF8fvvv+9++OEHPT7ssMO0DyAt9AEIM+Hwa30iaz/49ddf3bHHHqttDyYLLrig69evn/vkk080 +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 +KjUWTJkyRbUz0R6m0VUNHrDfib6Afg0t3SQ3btw4161bN9XQhS3VrA73DubP+eabL2vUugw/YcIE +hz+YBKBrXQLNNhb4zAkcCwr7+3fffedgFzjr3FiYSvJZLZ4LUBKfOYHPBYVthlUsMLXCze4KubTS +GcZP2JvHipy8HceCvIlWLj3YvBfFEd2HoHK5MOV6JbD11lvrajQrnwg0deWbnef5yyXnedJkWiRA +Au0m0LVrV4e/chyWiYkGZ8momGRFYzAMhw2AREMvPI8fYInwp59+6uRLsj6glfPChk2BMLHTlSYA +gW97WB177LFqk7VYTn369AlttFo42MVLc9gsCkLOM844Q+2i7rfffmlBi/pXyg5o0Ux5kQQalEB7 +x4JKzAkcC6rfmdrzXIDSVmJO4HNB9fsBcyQBjgXsAyRAAnECFGjGifCcBEigYQnMNttsKsgqpUHe +uXNn7zp+//33bqGFFlLNPWgOwr4aXX0TwMZNcRun8RLPPffcca+i50cddZSTpbGqjbjWWmvpLvdF +I/AiCZBAzQlUYk7gWFDzZs1cgLznBD4XZG4CRiCBuiDAsaAumoGFIIFcCVCgmStOJkYCJFBLAmKr +00HYlKeDZiV2K4eQdNddd3WbbrppnskzrQoQwMZT8c2n2psNltBhQycsRz/uuOPamxzjkwAJVIFA +JeYEjgVVaLics8h7TuBzQc4NxORIoEoEOBZUCTSzIYEqEqBAs4qwmRUJkEDjEZhhhhnc0KFDG6/g +LHGuBHbbbTeHPzoSIIHWJsCxoLXbH7XncwH7AAmQAAhwLGA/IIHaE5i69kVgCUiABEiABEiABEiA +BEiABEiABEiABEiABEiABEjAjwAFmn6cGIoESIAESIAESIAESIAESIAESIAESIAESIAESKAOCFCg +WQeNwCKQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAn4EaBA048TQ5EACZAACZAACZAACZAACZAA +CZAACZAACZAACdQBAQo066ARWAQSIAESIAESIAESIAESIAESIAESIAESIAESIAE/AhRo+nFiKBIg +ARIgARIgARIgARIgARIgARIgARIgARIggTogQIFmHTQCi0ACJEACJEACJEACJEACJEACJEACJEAC +JEACJOBHgAJNP04MRQIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkUAcEKNCsg0ZgEUiABEiABEiA +BEiABEiABEiABEiABEiABEiABPwIUKDpx4mhSIAESIAESIAESIAESIAESIAESIAESIAESIAE6oAA +BZp10AgsAgmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQgB8BCjT9ODEUCZAACZAACZAACZAACZAA +CZAACZAACZAACZBAHRCgQLMOGoFFIAESIAESIAESIAESIAESIAESIAESIAESIAES8CNAgaYfJ4Yi +ARIgARIgARIgARIgARIgARIgARIgARIgARKoAwIUaNZBI7AIJEACJEACJEACJEACJEACJEACJEAC +JEACJEACfgQo0PTjxFAkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAJ1QIACzTpoBBaBBEiABEiA +BEiABEiABEiABEiABEiABEiABEjAjwAFmn6cGIoESIAESIAESIAESIAESIAESIAESIAESIAESKAO +CHQotwyHHHJIuVEZr8EJfPbZZ27YsGENXgsWvz0EfvjhB/fbb7+5WWaZpT3JMG6DE+BY0OANmEPx +f/rpJzd58mQ3++yz55Aak2hUAhwLGrXl8iv3L7/84iZOnOjmnHPO/BJlSg1HYOzYsW6uueZy00wz +TcOVnQXOh8CUKVPcN99847p27ZpPgkylIQmMHz/ezTbbbG7aaadtyPKz0O0jMHr06IIEPv7444Lz +PE/KFmhefPHFeZaDaZEACZAACZAACZAACZAACZAACZAACZAACZAACTQJAQi4K+W45LxSZJkuCZAA +CZAACZAACZAACZAACZAACZAACZAACZBA7gQo0MwdKRMkARIgARIgARIgARIgARIgARIgARIgARIg +ARKoFAHvJec77LBDQRl69uxZcM6T1iHw3Xff0XZi6zR3Yk1hK+v33393M800U+J1erYGAY4FrdHO +xWr566+/OtjL6tixY7FgvNbkBDgWNHkDe1QPdrV//vlnN/PMM3uEZpBmJfD999+7Tp06uamnps5M +s7ZxqXrh/eDHH390nTt3LhWU15uYwKRJk/Q9kfZ0m7iRi1QNNjS//vrrMESvXr3C47wPpgrE5Z0o +0yMBEiABEiABEiABEiABEiABEiABEiABEiABEiCBShDg57NKUGWaJEACJEACJEACJEACJEACJEAC +JEACJEACJEACFSFAgWZFsDJREiABEiABEiABEiABEiABEiABEiABEiABEiCBShCgQLMSVJkmCZAA +CZAACZAACZAACZAAshon9AAAQABJREFUCZAACZAACZAACZBARQh4bwpUkdyZKAm0CAEYxf3jjz/c +nHPOWfMaT5gwwb3yyitqtH2VVVZxM844Y83LxAK0NgH0yffff9+NGzfOzT333G7hhRfW39amwtqT +AAmQAAmQAAmQAAmQAAmQAAmkEfDS0Pzqq690lyrsaOz717t377Q82/jvs88+mu65557b5lqaxwEH +HKBxTj755LQg7fL/7LPP3JFHHumwI9Nyyy3nttxyS3fqqac67OSZh7vrrrvcEkss4a699trU5H76 +6Sd3xhlnuO23394tv/zybtNNN3VHHHGEQ9na604//XTl16NHj5JJzT777BoWZW6PGzJkiKbj04fG +jBmjWZUTZ6GFFvLKZ4899iiaB4SP4INwl1xyicNuvlndDTfc4NZaay0311xz6d+///3vrEnkEh67 +Tu67774qKEJZNt98c7fOOuvoDoQrrbSSw72Xtj8Y+iH+4td33HFH5VysD+dS+IyJgDf62KBBg8KY +SeNFkl8YochB1v5VJKmmuzT//PMr+3feecerbs8//7zbYost9N5Au+2www56v8wzzzxu4403ds8+ ++6xXOgxEAiRAAiRAAiRAAiRAAiRAAiTQWgS8NDQhyJg8eXImMhCg+DoIS5D+b7/95htFhUuIM2XK +FO84vgEfffRRB4FsVHj51ltvuQcffNBdeOGFDi/hiy++uG9ybcL98ssvKkB677333LffftvmOjw+ ++eQTt+GGG7r//Oc/4fXRo0e7ESNGuGuuucYNHTrUbbLJJuG1rAdgDX7ROqalgXD4++GHH9KCePn/ +/PPP3v0I2oxw5cSx8pYqlAko0/JAOhDmv/DCC+6WW25xF198sbY/hNs+Dlpn/fv31zpAODrHHHO4 +qaf2+obgk7x3mDfffFMFRdCAg5t22mndCius4CZOnOjQB19//XX9+7//+z930003uS5duhSkPfPM +M6sw84MPPlCBqF388ccftT1///1386qLX/RTtF10bEBb+/j5VCBr//JJs1nC2L2EMb2Ue+qpp/Qj +DeJMM800DtrC0003nXvppZd0fMc4jD75xBNPuDXXXLNUcrxOAiRAAiRAAiRAAiRAAiRAAiTQQgS8 +pCsQxED4Ef9bdNFFFdUxxxzT5tp9993XkBjxcv3Xv/5VBX3du3d3jz/+uHvjjTdUUxKait98843b +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 +BEiABEggKwIUaGZFlvGSAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmkToACzdSRMkISIAESIAES +IAESIAESIAESIAESIAESIAESIIGsCFCgmRVZxksCJEACJEACJEACJEACJEACJEACJEACJEACJJA6 +AQo0U0fKCEmABEiABEiABEiABEiABEiABEiABEiABEiABLIiQIFmVmQZLwmQAAmQAAmQAAmQAAmQ +AAmQAAmQAAmQAAmQQOoEKNBMHSkjJAESIAESIAESIAESIAESIAESIAESIAESIAESyIoABZpZkWW8 +JEACJEACJEACJEACJEACJEACJEACJEACJEACqROgQDN1pIyQBEiABEiABEiABEiABEiABEiABEiA +BEiABEggKwIUaGZFlvGSAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmkTqBZ6jEGIhwxYoR5/vnn +Az5/H84+++ymRYsWZumllzabb765ad26dZMw9KhtArNmzTJnnHGG8TyvYEE23HBDs9lmm0WGmTx5 +snnggQdM9+7dTbdu3SLD0LM2CHzzzTfmzTffNF999ZXp0KGD6dKli5l//vljM3/rrbeaRRddVPuJ +2MAMUNUE0Ce8++675p133tH+f+WVVzYrrLBC3jxPmzbNjB071nz66admmWWWMV27djULLrhg3vC8 +UBsEkvQFM2fONG+//ba2G4wZOnXqZFZaaaXaKChzGUkg37gwGHi22WYzp556qnn22Wcjx5BRYZs1 +y3Q4G0ySxxkReOihh3SM0L9//4IpcFxQEE/NXfzhhx/Ma6+9Zr744gvTtm1bs/rqq5vFFlssshwY +F2AsiXEBwq622mo6RowMTM+qJ5Bvroh3wJxzzqnygTXWWMOss846OWVJ8h7huyEHXc2cxMkAOEeo +maosT0ZF4OTkJDeQTPl/LjcNHDjQDx+8N3jcqlUrT15kLtE1CXPBBRd4O+64oycT5CbX6JEdgeee +ey428h9//DG27tEO0Eai3F9//eX17NlT4xg8eHBUEPpVkIAIJr0PP/wwNge//fabd8IJJ3gyoMhp +DzJY9R5++OGC97/33nt6z6abblowHC9WjoBLX4Dcvfrqq54IonLaAJ7/fv36eTIoySkAnv2LL77Y +m2uuuXLCt2zZ0rv00ktzwvKk8gS+/fZbb9y4cbEZSdoXyKTV69y5c04bQJvBe2HKlCmx6TFAeQm4 +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 +/qu8kjLO3qRJk/QLfIcOHTJOidFXMwH2BdVcO+XJ25QpUwz+OnfuXJ4EmUpVEmBfUJXVUtZMQYAx +ceJE06VLl7Kmy8Sqi8CoUaO0DTRv3ry6MsbclI0AtPLGjRvHuWLZiFdnQqNHjzadOnUyLVq0qM4M +MleZElhwwQVz4p9vvvlyztM8oQ3NNGkyLhIgARIgARIgARIgARIgARIgARIgARIgARIggUwJUKCZ +KV5GTgIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkkCYBCjTTpMm4SIAESIAESIAESIAESIAESIAE +SIAESIAESIAEMiVAgWameBk5CZAACZAACZAACZAACZAACZAACZAACZAACZBAmgQo0EyTJuMiARIg +ARIgARIgARIgARIgARIgARIgARIgARLIlAAFmpniZeQkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIk +QAJpEqBAM02ajIsESIAESIAESIAESIAESIAESIAESIAESIAESCBTAhRoZoqXkZMACZAACZAACZAA +CZAACZAACZAACZAACZAACaRJgALNNGkyLhIgARIgARIgARIgARIgARIgARIgARIgARIggUwJUKCZ +KV5GTgIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkkCYBCjTTpMm4SIAESIAESIAESIAESIAESIAE +SIAESIAESIAEMiXQLNPYA5G/++675qmnnjKvv/66wfGyyy5runfvbtZff33To0ePQEge1gOBWbNm +mTPOOMN4nlewOBtuuKHZbLPNzIgRI8zzzz9fMOxss81mTj31VA1TatzNmjUzSy+9tOnQoYPp3Lmz +ad26dcG0ebE4AuWu13Au49rMggsuqG0A7aBjx44G4enSJcC+IF2etRob+4Jarbl0852kHTz77LMc +F6SLvypiy/KdkEab4bigPM0kSV+AHJU67g+XiuPDMJHyn2fZF6A0pbYZzhXL2yamTZtm3nzzTfPp +p5+atm3bmtVWW80suuiikZlIEjYYweTJk80DDzygMqhu3boFL+Ucjx8/3jzzzDOmT58+lBHkkKnS +ExE4OTnJPiRT/p/TTf8EuuCCCzzpFPx7g/HgeP/99/dmzJiRJMqcsJ999pm34447eqecckqOf9Yn +KBfSfeedd7JOqqrif+6552Lz8+OPP+at72D9Dxw4UOPCb9A/3zHiTTvuueee2xNBqTd9+vTYcjHA +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 +sx2AQmVckrpKEhalSRKe74Ty1z82hH7qqacMzH1B9mPt1ULZ6PLLL1cBp81VkrD2nuAvNELh7G/w +WvA47nowLI8rT2A20VRraoE1Il92ebW95HibDe7/fv7552bcuHGqrQmty9lnL7zqHTtQ4QUDib3V +iPQjizmAFuYWW2yhggoYhYXNBRiXXXDBBc0y/+xwHhVFKWlGxVdvfhDi4usJXeMSmDRpktqT4eY5 +jdsGUHL2BY1d/yj9lClT9K9z586E0cAE2Bc0cOX/U3TYvMeKB6zComtcAti3oGvXrqZ58+aNC6HB +S475Nub6sGNI17gERo8erStYW7Ro4QwB75EJEyao3AcKa4VckrCF4uG1bAhss802albSxo5V21tv +vbU9TfU3cw3NcG5h/BV/rg5anFimnobDEniXgVaaaaaRb8ZBAiRAAiRAAiRAAiRAAiRAAiRAAiRA +AvVIAEpnq6++ulPRkoR1ipCBapZAYfXImi0WM04CJEACJEACJEACJEACJEACJEACJEACJEACJFCP +BOpaoAkV5wUWWEA3J6rHymOZSIAESIAESIAESIAESIAESIAESIAESIAESKDRCJR9yXk5AWO3OthX +oCMBEiABEiABEiABEiABEiABEiABEiABEiABEqgPAnWtoVkfVcRSkAAJkAAJkAAJkAAJkAAJkAAJ +kAAJkAAJkAAJWAIUaFoS/CUBEiABEiABEiABEiABEiABEiABEiABEiABEqh6AhRoVn0VMYMkQAIk +QAIkQAIkQAIkQAIkQAIkQAIkQAIkQAKWAAWalgR/SYAESIAESIAESIAESIAESIAESIAESIAESIAE +qp4ABZpVX0XMIAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQgCVAgaYlwV8SIAESIAESIAESIAES +IAESIAESIAESIAESIIGqJ0CBZtVXETNIAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRgCTSzB0l/ +R44cmfQWhq8TAt9//71h/ddJZRZZjN9++838+eefZtKkSUXGwNvqgQD7gnqoxdLK8Mcffxj8TZky +pbSIeHdNE2BfUNPVl0rmZ86caWbMmGF+/PHHVOJjJLVJYOrUqeall14ys89OnZnarMHSc435wc8/ +/8y5YukoazoGvAt++uknM8ccc9R0OZj54ghgXBh0aAtZuaIFmj169MgqT4y3yglAmMn6r/JKyjh7 +EGROnz7ddOjQIeOUGH01E2BfUM21U568QZCJv86dO5cnQaZSlQTYF1RltZQ1U9OmTTMTJ040Xbp0 +KWu6TKy6CIwaNcp07drVNG/evLoyxtyUjcCvv/5qxo0bZ7p37162NJlQ9REYPXq06dSpk2nRokX1 +ZY45ypzAQgstlJNGy5Ytc87TPOHnszRpMi4SIAESIAESIAESIAESIAESIAESIAESIAESIIFMCVCg +mSleRk4CJEACJEACJEACJEACJEACJEACJEACJEACJJAmAQo006TJuEiABEiABEiABEiABEiABEiA +BEiABEiABEiABDIlQIFmpngZOQmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQQJoEKNBMkybjIgES +IAESIAESIAESIAESIAESIAESIAESIAESyJQABZqZ4mXkJEACJEACJEACJEACJEACJEACJEACJEAC +JEACaRKgQDNNmoyLBEiABEiABEiABEiABEiABEiABEiABEiABEggUwIUaGaKl5GTAAmQAAmQAAmQ +AAmQAAmQAAmQAAmQAAmQAAmkSYACzTRpMi4SIAESIAESIAESIAESIAESIAESIAESIAESIIFMCVCg +mSleRk4CJEACJEACJEACJEACJEACJEACJEACJEACJJAmAQo006TJuEiABEiABEiABEiABEiABEiA +BEiABEiABEiABDIlQIFmAG+/fv3M2muvbVZYYQUzdOjQwBUeNhqBv/76y0ycONHMnDmz0YrO8pIA +CZAACZAACVQRAY5JqqgymBUSIAESIAESIIGqIUCB5j9VMXLkSHPbbbeZAw44wMw///zmhBNOMN9/ +/33VVBQzYsy3335rnn/+efPNN99kimPw4MFmySWXNMsuu6y5/PLLM02LkTcegaza8S677GJmm202 +88MPPzQe1Bos8euvv25effXVVHP+3nvvaRsYMGBAqvEysmwINGJf0L59e7PMMstkA9QhVozz0E/e +eOONGvrWW2/NOS8URZZ9bKG2EDUmeeWVV8wOO+xgwBMf4XfaaSeDPiWpw72VrI+k+WV4EqhnAoX6 +gWLLzXFBseQqd18W48Ms31+VI8WUSeBvAhRo/tMSBg0aZFZccUWz9957myOPPFKFAmeddRbbSRUR +GDFihOnRo4d59NFHM8vVV199ZVDvEGoPGTLErL/++pmlxYgbk0A52nFjkq2tUvft29dggEnXuAQa +tS+YffbKDT2h6RjlKpkn5CdfW4gakzz22GM6Nhk+fLhp27atmW+++cx9992nK4yefPLJqOLl9cvH +I+8NvEACJJAZgXz9QGYJMuKqJMDxYVVWCzNVxQQqN6qsIigYFI4aNcrst99+Zo455jB9+vQxSyyx +hLn++uvNTz/9VEU5ZVayJgCNqT///NMceuihBkLutdZaK+skGT8JkAAJkAAJNASB8ePHm48++qhq +ygpTQzAts8cee1RNnoIZiRqTQGMT45SXXnrJPPvss+aNN94wd9xxh4Fw8owzzgjezmMSIAESIAES +IAESqGsCZRFo3nnnnSosXGeddcz+++9vbrnlFvPHH3/4YF9++WWDJXIvvviiLie++OKLzZZbbqlC +xlNOOcWcdNJJGvbxxx83hx12mMZlb/7888/N6aefbrbbbjuz3nrrmf79+5u77rrLXvZ/C8WDwSGW +IOGLCFzz5s3NIYccYn7++WczbNgwPw4eJCOAAffZZ59tUO8LLLCA6dSpk9lzzz0NNA6CrlevXjl1 +aq9h+f/GG2+spz179jSoJzhoUCLOt99+W89d/rnkpXfv3uboo4/W6C677DJNY9y4cS7Rq81V5OnL +L7805513ngpC0Vbh3n33XV0OttRSS5l55pnHLLLIInoe5LDZZpuZY4891kDzAscLLrigWX755VVb ++LfffsvJwzPPPKNLzbAsHkvFDjroIPPII49ofrEMzTqUGVqm3bp1U/4bbLCB1kc5NTJc6hb5TVJ+ +8MTzDp5LL7202X333c2YMWNssc0111yjLA4//HDfDweY8KGOoIENhzh222037S/ABsw7duxo9t13 +X/Pdd99pmOC/uHQRFv3aiSeeqMyhNdOuXTuzzz77GPRTcHHt2CWNX3/91QwcONCsttpqZt5559U8 +o716nqdpVNu/e+65R7njo1HQYaKO+sCSTzi8J3A+duxY/aAAjfkWLVqo1hHeDUEX17anT5+ufQfi +e+utt/xb8SxtvfXWmg5YP/zww3p89913q3Z+hw4dTKtWrcwmm2yiJkj8G/85iEvXhkdZt9lmG9Om +TRttV3gGb7rpJr1s2+EXX3xhvv76a00/uETcNY2nnnrK4PladNFFNc/bb799VQmKLAv7y76AfQHa +AsZZWB4N5/rM4wMjnuUPP/xQ77P/pk6dqv4YK8Dh3Ybx4yqrrKLvPPTBK6+8srn22mvtLU1+8Ryh +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 +pZQ5Sxwflhk4kyOBEghQoPkPPCw5F+PwRmxyGiynld1ujeyiWQJa3koC2RDYaKONDP7oSiNwyimn +lBYB7655ArJhk8EfXWMTYF/Q2PXP0pMACZBAkADfCUEajXnM8WFj1jtLXZsEKND8p95gIxS2COlI +gARIgARIgARIgARIgARIgARIgARIgARIgASql8Ds1Zs15owESIAESIAESIAESIAESIAESIAESIAE +SIAESIAEcglQoJnLg2ckQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAJVTIACzSquHGaNBEjgbwJ/ +/fWXmThxopk5cyaRNDCBH374wUyZMqWBCbDo7AvYBkiABEiABCwBjgssicb95bigceueJScBEKBA +k+2ABEig4gS+/fZb8/zzz5tvvvmmSV4GDx5sllxySd3R/vLLL9frr7zyitlhhx1M+/btzQorrGB2 +2mkn8/rrrze5t1o98pUX5VlmmWWqNduZ5wt1+OqrrzZJ57333jMbbLCBWWSRRcxyyy2n16dPn27O +Pvts3dSnTZs2Zr311jNnnnmm+e2335rcX60eUeW99dZbDWw633jjjdWa7Uzzle/ZQKLsCzJFXzeR +o7/AMzRgwAC/TNXQt7Zt29Z06tTJz1OpB4WelVLj5v0kUC0E8rXzqHEB8lyP48NGHxegXqPGS/CP +GhfU6/iwGt5jYE5HAtVGgALNaqsR5ocEGpDAiBEjTI8ePcyjjz6aU/qvvvrKnHXWWWb++ec3Q4YM +Meuvv7557LHH9Hf48OEGE8T55pvP3HfffWbttdc2Tz75ZM791XqSr7zI7+yzN2633LdvX7PLLrs0 +qbZzzjnHvPjii2bfffdVoSU0dbfccktz8sknm6+//tqstNJK5v333zennnqq2WKLLQy+1teCy1de +5L1R20G+Z4N9QS206OrOY6WfqT///DNVQPmelVQTYWQkUGEC+dp5eFyAbHJ8WOHKyjD5qPFS1Lig +3seHlX6PZVjFjJoEiibAXc6LRscbSYAEsiYAbT1MAg899FBz5JFHanJrrbWW+uHammuuqX533XWX +6dOnjznjjDPM5ptvnnW2Mot//PjxmcVdyxG/9dZbZsEFFzRDhw7VYmDSAo3ebbbZxtx///1mjjnm +0Dax+uqrq/8zzzxjevbsWZNF7tevn9l11121TDVZgIwyzb4gI7ANEi371gapaBazYQiExwUoOLT1 +MGast/EhxwXRzTpqXFDP40O+x6LbAX1JoHFVgVj3JEACmRPo1auX2W+//Zqkc8ABB5iNN95Y/SF4 +wiAUDtqY66yzjnn77bdN7969zdFHH63+l112mfqPGzfO/Pzzz6ZZs2ama9eueg3/oJ0JN2PGDP1N +8m/UqFEqGMOyZQjNunXrZm666aYmUSBPWOa+7LLLmoUWWkjzf/311+eE22yzzcyxxx6rWgI4RnzL +L7+8CmPtUuh85UVE+AKN5fPWucSHsC6cEQ6aixdffLFZZZVVzAILLKDarSuvvLK59tprcTkTd889 +92jdgXPQYSCKusZSqjvuuEOPv/jiC9W4hD+Wi0ILF8cff/yx+eWXX/R44MCB2gYQF9oAhJlw+LVt +Imk7+OOPP8yJJ56odQ+N33bt2pl99tnHfP755xq3/YeJEpa5I0/gh+Wje+65p4GWgHV33nmnXh87 +dqwK4ldccUXTokULbaPQMoXLV15ce+qpp3R5vdVWdokP97lwRji4d999V9vZUkstZeaZZx5dyo92 +FyzH3yHT++/SRvM9G+wLjKmHvsC2JrS/7bbbzqD9Lb300mb33Xc3Y8aMsZf117WN4nlB21p00UVN +q1atzPbbb28++uijnLhwUmzfinvxgQR9P0yfwCTIQQcdZB555BF9zrG8NanDBziY0MD7oWPHjqp5 +/t133/nRQEsdfQyW2gYd+imsZAC7fM8KwqOfwooGvMvQTyEt9Fu1orkeLDOP65dAse8EmB6KGheA +VCXGhy7jAuTNpQ/P91zX67jAZdySb7xUaFwA3uUeH7rMEVzGc/nKizIV+x5zedYQfyXmCEiXjgRK +JuA5OknIC/453sZgdUjgueeeq8NSsUhJCIjgw/vwww9jbxHhkCdalE3CiQDSm3feedVfJlueTEa1 +f5EJoyfLh7033njDk8GfJ0vK1X+JJZZQf/ki7x111FHqJ/YSPXn5ej/99JPXv39/9TvllFOapFXI +46GHHvKaN2/uiTDME81PD3nBMfq6Sy65xL/18ccf9+aee271R95lubMnQio9F+1RPxzKK5N0b665 +5vJEUOjJIELjR3yDBg3ScPnKi4si/PREmKbh8M8lPhsujjPCnXDCCZrnli1berI02xMNRz9/Tz/9 +NIIkci59wYUXXqhpioAuJ24wBZfzzz/fu/3227V+cT7nnHPqsQjCvQceeECPRYCt9YK2IcIE7/vv +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 +CWAjjbDNuXBpZRl72IvndUSAfUEdVWYFigKtf0x8jz32WNVyxAZi0PiBbUpon1122WX6USzt982P +P/6oKwUgFIDmEmxu0pEACZROgO+E0hnWQwwcH9ZDLbIMJPAvAQo0/2XBIxIggToggEkoDI3TNTYB +mCGI2jigsak0VunZFzRWfWdRWmz60a1bN3P77bfr8m0sPRf7vroJETQ04dJ+34hNaIPdyvFRbtdd +d9VN9bIoG+MkgUYjwHdCo9V4dHk5PozmQl8SqFUCFGjWas0x3yRAAiRAAiRAAiRAApkS2GijjQz+ +yuVkoy7dSb1c6TEdEiABEiABEiABEqhVArPXasaZbxIgARIgARIgARIgARIgARIgARIgARIgARIg +gcYjQIFm49U5S0wCJEACJEACJEACJEACJEACJEACJEACJEACNUuAAs2arTpmnARIgARIgARIgARI +gARIgARIgARIgARIgAQajwAFmo1X5ywxCZAACZAACZAACZAACZAACZAACZAACZAACdQsAQo0a7bq +mHESqH4C3377rXn++efNN998k5PZ9u3bm2WWWSbHr9wnbdu2NZ06dUot2XxlTS2BGo7o9ddfN6++ ++mpOCW699VYz22yzmRtvvDHHv5wn119/vebhzjvvTC3ZqLKmFnkNR5Tv+WBfUMOVyqyTAAmQQJEE +ot4J1TAuQHHSHh9yXJC/kUSxqYZxQdrjw6j2np8Kr5AACSQhQIFmEloMSwIkkIjAiBEjTI8ePcyj +jz7a5L7ZZ69s9/Pnn382yVMpHoXKWkq89XBv3759zS677BJZlEq2g7TbAApYqKyRABrEs9DzUck2 +APxpt4NCZW2Q6mYxSYAESKAggUL9ZL29EzguyN8U8rGptzZQqL3np8MrJEACLgSauQRiGBIgARJI +k8D48ePTjI5x1SCBfv36mV133dXMMcccNZh7ZjktAuwL0iLJeEiABEigtglwXFDb9ZdW7jkuSIsk +4yGBxiBQWRWpxmDMUpJAQxLo2bOnGTx4sJb9rLPOMuuss455++239RxfZHfaaaccLri2ww47mGWX +XdYstNBCZuONNzZY8hF0m222mTn22GPNY489ZnC84IILmuWXX94ceeSR5rfffgsGdT6+6667zAYb +bKBxdezY0ey7777mu+++8++HZiHyjuUiQffHH3+o9ul2221nCpUV2l9Dhgwx3bp1MwsssICmdfbZ +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 +0hRYViJaOZSkvXv3Nttvv32a1bOuDAgg2Ew44Extd4MpdAjohOnoZ511Vm2rY/mMCXAsyBgwqycB +EiCBMiKQxT2BzwVldAL829S0nw/5jlB+5wBbXHkEqNCsvGPKHpEACaRIYJFFFjGPPvpoijWyqnIk +0LdvX4M/SvUS4FhQvceePScBEiCBMAE+F4SJVN86nwuq75izx6VHoGHpNYktIgESIAESIAESIAES +IAESIAESIAESIAESIAESIIFoAlRoRnNhKgmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQQAkSoEKz +BA8Km0QCJEACJEACJEACJEACJEACJEACJEACJEACJBBNgArNaC5MJQESIAESIAESIAESIAESIAES +IAESIAESIAESKEECVGiW4EFhk0iABEiABEiABEiABEiABEiABEiABEiABEiABKIJUKEZzYWpJEAC +JEACJEACJEACJEACJEACJEACJEACJEACJUiACs0SPChsEgmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQ +AAmQQDQBKjSjuTCVBEiABEiABEiABEiABEiABEiABEiABEiABEigBAlQoVmCB4VNIgESIAESIAES +IAESIAESIAESIAESIAESIAESiCZAhWY0F6aSAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmUIAEq +NEvwoLBJJEACJEACJEACJEACJEACJEACJEACJEACJEAC0QSo0IzmwlQSIAESIAESIAESIAESIAES +IAESIAESIAESIIESJECFZgkeFDaJBEiABEiABEiABEiABEiABEiABEiABEiABEggmgAVmtFcmEoC +JEACJEACJEACJEACJEACJEACJEACJEACJFCCBKjQLMGDwiaRAAmQAAmQAAmQAAmQAAmQAAmQAAmQ +AAmQAAlEE6BCM5oLU0mABEiABEiABEiABEiABEiABEiABEiABEiABEqQABWaJXhQ2CQSIAESIAES +IAESIAESIAESIAESIAESIAESIIFoAlRoRnNhKgmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQQAkS +aFxsmx544IFii7JcmRP45JNPzLRp08q8F2x+bQjMnDnT/PHHH6ZNmza1qYZly5wAx4IyP4ApNH/O +nDkGfx9++GEKtbGKciXAsaBcj1x67f7tt9/M9OnTzcSJE9OrlDWVHYHPPvvMTJ482TRuXPQrZtn1 +mQ3OJfDnn3+ab7/9Vs+D3C1cqyYCU6ZMMePHjzeLLLJINXWbff2XwHfffZfDYsaMGTnraa4Ufbfp +27dvmu1gXSRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAhVC4IsvvsisJ5xynhlaVkwCJEACJEAC +JEACJEACJEACJEACJEACJEACJJA2ASo00ybK+kiABEiABEiABEiABEiABEiABEiABEiABEiABDIj +4DzlfMUVV8xpRNeuXXPWuVI9BGbPnm2aN29ePR1mT2sQ+Ouvv8zff/9tFl100RrbmFA9BDgWVM+x +juvp/PnzDf4WW2yxuCxMrwICHAuq4CAX6OKCBQsMfOc1bdq0QE5urmQCv/76q54DDRvSZqaSj3O+ +vuH94PfffzdLLLFEvmzcVuEE5s6dq++JjRo1qvCesntRBOBPGzE3rHTo0MEupv7bwBNJvVZWSAIk +QAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIZEODnswygskoSIAESIAESIAESIAESIAESIAESIAES +IAESIIFsCFChmQ1X1koCJEACJEACJEACJEACJEACJEACJEACJEACJJABASo0M4DKKkmABEiABEiA +BEiABEiABEiABEiABEiABEiABLIh4BwUKJvds1YSqA4CM2bMMP/8849ZaqmlqqPD7GUiAgiq8sUX +X5gvv/xSy6200kpmlVVWMQsvvHCiepiZBEiABEiABEiABEiABEiABEiABKqBgJOF5s8//6wRTBHF +1PVvr732cuZ3yCGHaL1XXHGFc5mjjz5ay5x//vnOZZJk/Pbbb80pp5xievToYdZee22z0047mQsv +vNDMmjUrSTWxeR9++GGz+uqrm6FDh8bmCW5Imj9YNmr54osvVn6bbLJJ1OactNatW2tetKE2cscd +d2g9LufQpEmTdFfFlIEyyGUf++23X959QPkIPsh33XXXGUT2Tip33nmn6dq1q1l66aX179NPP01a +RVH5+/fv78QgyGncuHFF7ascCkFhiIiLxRzDJP276aablPu+++7rVGzevHkG12Lbtm0Nor/tuOOO ++texY0fTpk0bHXN+++03p7qYiQRIgARIgARIgARIgARIgARIgASqhYCThSYCoePFO4nMnj3bOTsU +Dah/wYIFzmWgmEAZKCrSlpdfftlAIRtUXk6YMME888wz5uqrrzZvv/22ad++fdG7/fPPPw2Ut59/ +/nlOOPu4CpPmj6snmA7W4BfsY3B7cBn58Dd37txgcuLlP/74Q+txKQhrRkgxZWx7C+3HKrfi9oF6 +oMx/5513zL333muuvfZaPf5QbrvI9OnTzVFHHaV9gHJ0ySWXNA0bOn1DcKk+b56///7bmbWtCNdh +pcoll1xizjvvPLP//vubu+66K7NuWu4u4x/y9urVywwfPlzbAwUmlJqTJ082X3/9tY4N5557rhkz +Zox54oknTIMGDTJrNysmARIgARIgARIgARIgARIgARIggXIi4KRdgSJmzpw5Nf5WXXVV7esZZ5xR +Y9tTTz1VThz8tkK5deihh6qib8MNNzSvvvqq+eijjwwUIrBU/OWXX8yBBx7o50+yAMXkiy++aLp3 +727ee++9gkWT5i9YYYlkaNGiRY3zJXx+rbHGGjmtLabMZZddlnc/YcVWeB+w0sXxwrFfYoklVNG0 +yy67qIIzp3ExK48++qgqM1deeWXz448/mk8++UStcmOyp5oMhXmYadAaOLwN6y7Wuqk2ssoru+22 +21SZCUUlLDu/+eYbg48pX331lcEHFFihQzCW3n777VVOi90nARIgARIgARIgARIgARIgARIggf8R +cLLQxAs3FDphadSokSbBz1vU9nD+cliHtdTUqVNNy5YtVbnQrFkzbfY666yj01Vh5QWLPVizYbqu +q+yxxx5m2LBhrtlN0vzOFZdIxmLOl6Rlijkvg/vA8vLLL68KaFjsYjowrGoPP/xwM3bsWNO4cf7L +x1o8brDBBnVuXdekSRODv6AEz9dgP4N5uFx3BF577TXd2fbbb2+OPPLInB1jyvkNN9ygSnDkg2Id +rjkoJEACJEACJEACJEACJEACJEACJEACxjhZaBYD6tdffzXXXHONKoPWXHNNDXCx8cYbm7POOstg +Km6c4MX94IMPNuuvv75Zb731zGGHHaYWSnH5w+mYRnzVVVeZ3Xff3ay22mqqhLr88svV6imcN2r9 +ww8/1OTddtvNWGWmzWf9gmKqKKz3kgj8OkIpav+aN2+et3jS/Hkrq4ON3333nYHFmeVXB7us013g +XLrooot0n7DYzWeB/P7775sDDjjAwP8nBFOGsT5gwABdt//effddc+KJJ5ott9xSz1Wcc9hHlBuA +Cy64QOuAsh2BY7COcjfffLOtrla/+eqHYg3th7VyWHAdYNsRRxzhb4KFIdLQF0zbv/TSS9UHLSy6 +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 +p5vwrf3bb7+Zli1b5snFTZVO4Oeff9ZzgH7zKv1Ix/cP/nThV7l169bxmbil4gnMmDFDnw0bNy5a +3VTxjCq5gyNHjjTTpk3zu5jleFD0GXb//ff7DeRCdRHACdqtW7fq6jR7m0MAAxReXNq3b5+TzpXq +IsCxoLqOd1Rvp0+fbvDXsWPHqM1MqxICHAuq5EDn6easWbPM1KlTzfrrr58nFzdVOoHRo0ebzp07 +myZNmlR6V9m/GAIwepgwYYLZaKONYnIwuRoIjBkzxnTo0ME0bdq0GrrLPoYI9OzZM0ehueqqq4Zy +pLfKKefpsWRNJEACJEACJEACJEACJEACJEACJEACJEACJEACGROgQjNjwKyeBEiABEiABEiABEiA +BEiABEiABEiABEiABEggPQJUaKbHkjWRAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAlkTIAKzYwB +s3oSIAESIAESIAESIAESIAESIAESIAESIAESIIH0CFChmR5L1kQCJEACJEACJEACJEACJEACJEAC +JEACJEACJJAxASo0MwbM6kmABEiABEiABEiABEiABEiABEiABEiABEiABNIjQIVmeixZEwmQAAmQ +AAmQAAmQAAmQAAmQAAmQAAmQAAmQQMYEqNDMGDCrJwESIAESIAESIAESIAESIAESIAESIAESIAES +SI8AFZrpsWRNJEACJEACJEACJEACJEACJEACJEACJEACJEACGROgQjNjwKyeBEiABEiABEiABEiA +BEiABEiABEiABEiABEggPQJUaKbHkjWRAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAlkTKBxlvW/ ++OKL5vXXX6+xi4YNG5qmTZuadu3amR49ephWrVrVyMOE8iawYMECc8EFFxjP8wp25LzzzjONG9c8 +FSdNmmReeeUV06tXL54jBSmWdoZffvnFvPvuu+abb74xbdu2NRtssIFZZpllYhv9ySefmI8//tjg +POrYsaNZZ511TKNGjWLzc0PpEqjNWDBr1iwzbtw4M2XKFLPSSiuZzp07mxYtWpRuZ9myWAJxzwPB +Ag0aNDDnnntuzv2AY0GQUOUs//jjj+aDDz4w3333nWnfvr1Zf/31zRJLLJG3g3wmyIun7Dbi3oD7 +/Pjx4/WdYO211zarr756ZD/++ecfg+P/4YcfGowT9rkgMjMTy4JAsfcE27l7773XLL300voeadP4 +W14E4p4PcY0vtNBC+u7XqVMns+mmm+Z0rLbnTk5lXClJAt9//7154oknzEYbbWQ23HDD2DbyuSAW +TXVtEIWTkwgVaKb8P5dC/fv39/MHywaXW7Zs6Ymiw6W6GnkGDx7s7bnnnp48DNXYxoTsCLz22msF +K589e3bBY2/Pg99//z2yPlFkah1vvPFG5HYm1h8BeQn1PvvsM6cGXH311Z68qOacD02aNPHOPvvs +GuWnTZvmyUeOnLw4T+Rm5slNq0Z+JtQvgazGAnl59a666ipv4YUXzjkXmjVr5uF8opQOgZ9++smb +MGFCwQa5PA/gWse9A8KxoCDSksrgMhagwX/88Yd3+umne/IRM+falg9c3tNPP523T3wmyIun3jfO +nDnTkw9QTu145513vLXWWivnHMD1369fP08+ZOXUMXnyZG/jjTeukXerrbby5GNXTl6u1D+Bt956 +y/vzzz8LNiTpPSFYoXzo0vNh2223DSZzuUQI/Pbbb07v9q7vivvvv7/3999/+72rzbnjV8KFzAm8 +99573ty5cxPvB+8A3bt312t84MCBecvzuSAvnnrduPPOO+fct4cPH55Ze2qaxckTRdqyzTbbmGOP +Pdav9q+//jJfffWVufXWW408qJhdd91Vv9Lji0wSGT16tHn88cfNMccck6QY89Yxgdtuu82I4jpy +r7DMXHTRRXO2/frrr+aKK64wDz30UE46V8qPAL6unXjiiWpdefjhh6uF3auvvmqGDRtmLrroIrOS +WN0dcsghfscOOOAAgy+vyy+/vF7Xovg0Q4cONWPGjDF77LGHef/99w3SKOVJwHUsuPnmm81JJ52k +X+hPOOEEIy++RhQm5oEHHtDzqU2bNmafffYpTwhV3urw80AYx2KLLaZJHAvCZCpjXT5k6f29efPm +5rjjjjPLLbeceeaZZ4woM80uu+xiRDlu1lxzzZzO8pkgB0fZr8AqF7OzRJmhv3gHmD59urnuuuvM +fffdpzN78AsRxZjBmPH111/r88O+++5r8A5x/fXX6z0BzwVvv/22kY9fZc+lWjvgek+wfPA82Ldv +X7vK3wohEHw+FK2HmTNnjl7jd911l7n77rtN165dzRFHHJHT26TnTk5hrpQsgWuvvda89NJLedvH +54K8eKpvo6uqMOtAeQAAQABJREFUVMjkaFldytkvKKLMjMwOCwyZfq71ytSjyDz5EuVBRsvKtOR8 +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 +1yxYsMC0aNEii+pZZ5kQ4FhQJgcqw2ZCkYm/jh07ZrgXVl3qBL799luzwgorlHoz2b4MCeDDBl5Y +llpqqQz3wqpLncDo0aNN586dTZMmTUq9qWxfRgTwcQPKjGWXXTajPbDaciAwZswY06FDB9O0adNy +aC7bmDKB1q1b59TYrFmznPU0V4pWaKbZCNZFAiRQXgQWX3zx8mowW0sCJEACJJAZASozM0NbNhUv +vPDCVGaWzdFiQ0kgOwILLbQQlZnZ4WXNJEACIQKcDxACwlUSIAESIAESIAESIAESIAESIAESIAES +IAESIIHSJUCFZukeG7aMBEiABEiABEiABEiABEiABEiABEiABEiABEggRIAKzRAQrpIACZAACZAA +CZAACZAACZAACZAACZAACZAACZQuASo0S/fYsGUkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAIh +AlRohoBwlQRIgARIgARIgARIgARIgARIgARIgARIgARIoHQJUKFZuseGLSMBEiABEiABEiABEiAB +EiABEiABEiABEiABEggRoEIzBISrJEACJEACJEACJEACJEACJEACJEACJEACJEACpUuACs3SPTZs +GQmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQQIgAFZohIFwlARIgARIgARIgARIgARIgARIgARIg +ARIgARIoXQJUaJbusWHLSIAESIAESIAESIAESIAESIAESIAESIAESIAEQgQah9YzW/3444/NSy+9 +ZN577z2D5ZVXXtlstNFGZvPNNzfdunXLbL+suH4ILFiwwFxwwQXG87y8Ddhyyy3NdtttZ1588UXz ++uuv583boEEDc+6552qe2tbduHFj065dO9O+fXvTsWNH06pVq7z75kYSIIHiCHAsKI5bpZWq6zE+ +zK/Q/aNFixZ6P8A9Yc011zTITyEBEiABEsiGAO8J2XBlrSRQrgRmzZplPvjgAzNlyhTTtm1bs956 +65mll146sjtJ8gYr+P77780TTzyhOqgNN9wwuClnedKkSeaVV14xvXr1oo4gh0yJrojCyUmk+dBM ++X9Ohf7NNHjwYE8USH7ZYD1YPvTQQ7158+YlqTIn71dffeXtueee3jnnnJOTnvUK+oX9jh8/Putd +lVT9r732WsH2zJ49O/Z4B49///79tS78BtPjllFv2nUvssginihKvd9++61gv5iBBEjgfwQ4FvyP +RbUu/fTTT96ECRMKdr8+x3h7P3G9f8jHVm/06NEF+8QMJEACJEACuQTeeust788//8xNjFjjPSEC +CpNIoIIIiBGbN3fuXKce3X777V6zZs1ydAELL7ywd8kll9QonyRvsPA///zjde/eXfcxcODA4KYa +y6LI1HxvvPFGjW1McCOw88475xzP4cOHuxUsIlfmFpqHHXaYGTp0qFo7yM3L9OzZ02ywwQbms88+ +M/IybM4//3zd/tFHH5lRo0YZWM4lFXlJMY899piZPn160qK1yi8vPObxxx83xxxzTK3qqfTCt912 +m2nZsmVkN1dbbbWc9G222cYce+yxOWnBlcUWW8z8/vvvflKxdc+fP99MnjzZfPjhh3ruwOITx3Ls +2LGmSZMmfv1cIAESSI9AsddrVAs4FkRRKf20uhrjo0jkO2d+/vlnI4pZ89xzz+lMkq5du5p7773X +9O3bN6oqppEACZAACaRAgPeEFCCyChIoYwKiNDSHHHKIzuqEReRWW21lxo0bZ2699VZzxhln6IxK ++yyWJG8YybXXXquzhcPpwfVff/3VXHHFFeahhx4KJnO5xAkk1x4m6NA777yjykooKe+++27Tp08f +v3SXLl0M/nDS7rTTTubdd981t9xyizn66KP9PFyoDAK77rqrad26tVNnMP179913d8qLTGnUjanu +e++9t7pCuPTSS/1p7c6NYEYSIAEnAmlcr3E7SqNujgVxdNNLr48xPq71UeeMzBbRj5R33HGHOeGE +E8z222/vfP+K2w/TSYAESIAEognwnhDNhakkUC0ELr74YlVmwkDs+uuv97u96qqrmtNOO81cdNFF +/sflJHn9imQBH6xPP/10s/jiixuxGg1u0uVnn31W9/X555+bP/74o8Z2JpQ2gUyDAuHEgfTr1y9H +mRlEAqVm0C+itb4bNGiQOf74482cOXOC2XX5pJNOMieffLIu40SHEgoCizuUgWYd8umnn+o6rCzG +jBljTjzxRPXXKSaw6t/x66+/1nz2n+s+R44cqfXCug9y9dVX6/onn3xiq+JvGRGAH097DuIc4EBW +RgePTSWBFAlwLEgRZplWteiii5ohQ4aY5Zdf3sBq87rrrivTnrDZJEACJEACtSXAe0JtCbI8CcQT +EPcUOmMXOU499dScjMcdd5zB9Tdx4kQj7gVNkrzBiv766y+z7777miWWWMLXGQW3Y1lmORvM3lxp +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 +lN0QRKrHOdi2bdvSazhbRAIkkCoBjgWp4izbyuBXCW5GIPggCh9p1un8UUcdZTC7hEICJEACJFAd +BHhPqI7jzF6WFoELL7xQ9UUjR440K6ywgunWrZt59913NcYJjMcuu+wyv8FJ8vqFuFDxBDJVaIIe +lIswIT7++ONViQilovVrALPhHj16mOuvv76GnyooCTG9/KabbjKvvvqq/kEhOmLECJ0WbBVR2MdS +Sy1lTj31VM0LJem8efOQ7AumssP6cujQoWb8+PGavuSSSxpo6c8++2w/X5J9ohBeeHDxTZw4Ua1P +v//+e78uLvyPgH1h/F9K/FKSvKglSX5EKLRRClEOljewHMY52r9/fzV5j28Zt5AACdSWQJLrNUle +tCtJfo4FtT2SxZdPcpySHtekdU+aNMnvSMuWLfWDKKYhYdbGtttu62/jAgmQAAmQQDYEko7bSfIn +yYve8Z6QzTFmrSSQjwACQr/00ksGLn6g+7H+amFsdO2116qC05ZPkteWCf7CIhRif4PbgsuFtgfz +crn+CTQQS7WaHlgj2mWnV9tNjsVsdv/366+/NhMmTFBrTVhdNmyYf9Y7IlDhBgONvbWI9CsrsAAr +zO23315fTuAUFj4X4Fy2RYsWZqV/I5xHVVGbfUbVV2lpUOLi6wmFBEiguglwLKju44/eT58+Xf86 +duxIGCRAAiRAAlVOAHELOnfubJo0aVLlJNh9EqhuAmPGjNEZrE2bNnUGgdgpX375pep9YLCWT5Lk +zVcPt2VDoGfPnupW0taOWds777yzXU31N3MLzXBr4fwVf64CK05MU09DMAUe090LSZr7LLQvbicB +EiABEiABEiABEiABEiABEiABEiCBaiUAo7MNNtjAqftJ8jpVyExlSyC/eWTZdosNJwESIAESIAES +IAESIAESIAESIAESIAESIAESqEQCFa3QhIlz8+bNNThRJR489okESIAESIAESIAESIAESIAESIAE +SIAESIAEqo1AnU85r0vAiFYH/woUEiABEiABEiABEiABEiABEiABEiABEiABEiCByiBQ0RaalXGI +2AsSIAESIAESIAESIAESIAESIAESIAESIAESIAFLgApNS4K/JEACJEACJEACJEACJEACJEACJEAC +JEACJEACJU+ACs2SP0RsIAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQgCVAhaYlwV8SIAESIAES +IAESIAESIAESIAESIAESIAESIIGSJ0CFZskfIjaQBEiABEiABEiABEiABEiABEiABEiABEiABEjA +EqBC05LgLwmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQAAmQQMkToEKz5A8RG0gCJEACJEACJEACJEAC +JEACJEACJEACJEACJGAJNLYLSX9HjhyZtAjzVwiBGTNmGB7/CjmY7AYJ1IIAx4JawKuQon/99ZfB +3/Tp0yukR+wGCZAACZBAsQRmzpxpRo0aZRo2pM1MsQxZjgQqgcDs2bPNnDlzTKNGjSqhO+xDQgJ4 +RwwKzoWspGiFZrdu3bJqE+stcQJQZvL4l/hBYvNIoA4IcCyoA8glvgsoMvHXsWPHEm8pm0cCJEAC +JJA1gdGjR5vOnTubJk2aZL0r1k8CJFDCBMaMGWM6dOhgmjZtWsKtZNOyItC6deucqps1a5aznuYK +P5+lSZN1kQAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJZEqACs1M8bJyEiABEiABEiABEiABEiAB +EiABEiABEiABEiCBNAlQoZkmTdZFAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiSQKQEqNDPFy8pJ +gARIgARIgARIgARIgARIgARIgARIgARIgATSJECFZpo0WRcJkAAJkAAJkAAJkAAJkAAJkAAJkAAJ +kAAJkECmBKjQzBQvKycBEiABEiABEiABEiABEiABEiABEiABEiABEkiTABWaadJkXSRAAiRAAiRA +AiRAAiRAAiRAAiRAAiRAAiRAApkSoEIzU7ysnARIgARIgARIgARIgARIgARIgARIgARIgARIIE0C +VGimSZN1kQAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJZEqACs1M8bJyEiABEiABEiABEiABEiAB +EiABEiABEiABEiCBNAlQoZkmTdZFAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiRAAiSQKQEqNDPFy8pJ +oHQJ/PLLL2b69Oml20C2jARIoE4IcCyoE8wlvZN//vnHTJ061cyfP7+k28nGkQAJkAAJZE+AzwXZ +M+YeSIAE0iFAhWaAY79+/cwmm2xiVl99dXPrrbcGtnCxGALvvfeeeeedd4opWnJlsujLJ598Yho0 +aGCOP/74TPob12bsd4sttjBLLbWUWWWVVXTfv/32m7n44ovNxhtvbFZYYQWz2WabmQsvvND88ccf +mbSNlVYXgbhzsRwpZNGXUhoLsjomP/30k3n99dfNjz/+mNUu6qzerPqyzz776D0BL5JZSNy5O3Dg +QLPccsuZlVde2Vx77bW667ffftvsscceZrXVVtNnor322sugPIUESIAE0iCQ1TiaRtuS1pFFX7J+ +Lohrc9Q7AnjwnpD0rGB+EiCBuiJAhea/pEeOHGnuv/9+c9hhh5kllljCnH766WbGjBl1dRwqcj99 ++/Y1eEGrBCnHvsS1+ZJLLjFvvvmmOfjgg1VpCYucHXfc0Zx99tnmhx9+MGuttZaZOHGiOffcc832 +229vYLlDIYHaEIg7F2tTZ32VLce+xLU5PBZkyfTFF1803bp1M88880yWu6mTusu1L1HnwXfffWcu +uugife4ZNGiQ2Xzzzc2zzz6rv8OHDzdt27Y1iy++uHn88cf1g+8LL7xQJ4y5ExIggcomUK7jaNRR +Kce+xLU56rmA94Soo840EiCBUiHQuFQaUt/tOOOMM8waa6xhDjzwQNOkSROz//7760P+//3f/9V3 +07h/EkiVwIcffmhatGjhWyHjQQWWUz179jTDhg0zjRo1Mn///bfZYIMNNP2VV14x3bt3T7UNrIwE +SKD+CYTHgvpvEVtQ1wQwiwLj/THHHGNOPPFE3T0s9ZGGbV26dNG0hx9+2PTq1ctccMEFpkePHnXd +TO6PBEiABEigDghEPRfAip/3hDqAz12QAAkURYAWmoINVgijR482hxxyiCpz8NDepk0bc9ttt5k5 +c+YUBbaaCz344INm0003Nd98841a/GHZTqvGVH6sf/vtt+ayyy7TKc7HHnusefTRRzUdxyEoeKFC +/nvvvVeTH3roIV0fN26cvoBBCd20aVO1HIHVYVD++usvc+aZZ5oNN9xQLUxWXHFFc9BBB5mvv/7a +zwbrw6uuusqss846pnnz5ppv7bXXNrfccovmydcXZMANHlYt2AfKYyo3pm6HrRpfeukls8MOO5il +l17atGzZ0uy+++7m888/99vhuuDCKa7NOM/BcvLkyWbu3Lm63L9/f/Prr7/q7jt37qznP1ag1MQ6 +ZN68efrr+u+aa65RK08cl9atWysTKE2D4srt999/N2jjeuutZxZbbDGz5pprGtSPhyv0xV6fYIvr +NyywuN56661zkj/++GOz2267meWXX960a9fO7Lvvvmbs2LF+nrTPMVTs2l+/ERWyEHcuonscC0pv +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 +wG8KhQRIgARIgARI4P/bu89Yq4q9D8ADCCKgFDWiEhCxN2wBEYwNu6AfkA8iMWL4YomaWNEYlCga +e+wau2Kv2BUrgoAVW2xgASwIRuko+N7/3HevnIMgWy47WefwTMI5a++91uyZZxIu/u4UAgQIECBA +gAABAgQIECiPgEDz/8ciNigeM2ZMeUZGSwgQIECAAAECBAgQIECAAAECBAgQ+JvA348O/9st3iBA +gAABAgQIECBAgAABAgQIECBAgEA5BASa5RgHrSBAgAABAgQIECBAgAABAgQIECBAoAoBgWYVSG4h +QIAAgVUXmDdvXj54rWfPnqlTp06pd+/eacSIEWnhwoWrXqknCRAgQIAAAQIECBAgQGCNFbCH5ho7 +9DpOgACB2gv88ccf6dBDD01vvPFG6ty5c9p+++3TpEmT0rhx49LLL7+cXn311dS0qf9vrfYj4RsI +ECBAgAABAgQIECDQeAT8V2TjGUs9IUCAQOkEIrSMMLNfv35pypQp6YUXXkgzZ85MO+64Y37/lVde +KV2bNYgAAQIECBAgQIAAAQIEyi0g0Cz3+GgdAQIEGrTAnDlzcvt322231KxZs3wdv+N1lAULFuTf +1f645ppr8izP1q1bp/XXXz/ttdde6bnnnqv3+JIlS9LFF1+cdt9999S2bdt8z0UXXZSWLl1a7775 +8+en0047LXXv3j21atUqbbPNNinqHz58eOrVq1f6/fff8/0HH3xwOv744+s9Gy+GDh2a9t1333rv +f/zxx+nII49Mm266aZ6Reswxx6R33323uOfBBx/Mdb///vvpxBNPTFtvvXWKvuyxxx5p7NixxX1x +sXjx4jRs2LDcjzZt2qQuXbqk4447Ln333Xf17qu2v/Ue8oIAAQIECBAgQIAAAQINWECg2YAHT9MJ +ECBQdoG+ffum5s2bpzvvvDN9++23ubnvvfdeeuyxx9I666yT9ttvv6q7cPnll6dTTz01/fLLL6l/ +//45FB0/fnw64ogj0jvvvFPUE5+de+65OZDcf//909SpU9N5552XhgwZUtyzaNGi1KdPn3T11Vfn ++g444IAceEb9EYa+/fbb6c8//8z3v/XWWymCymVLvDdx4sTi7ddeey316NEjPf/882mnnXZK3bp1 +S6NGjUphEAFmlGnTpuW6BwwYkO655558zyabbJImTJiQDjnkkDR79ux8X4SU0faRI0fmZ/bZZ58c +cIZjXFfui5ur6W+u1A8CBAgQIECAAAECBAg0EoGmjaQfukGAAAECJRTo0KFDeuaZZ9L333+fttxy +yzxzMWZnRqAYy89jdmK15dFHH823Roh5//33pxdffDHdcsstKfbpjIA0Srz/7LPPpsGDB6dPP/00 +v//555/nmZR33XVXevPNN/N9t99+ew4ZIzT8+uuv05NPPpnivgg0o75/WyL8jBmXTZo0SdG+mDUa ++4OOHj06/fbbb+n000+vV2UclPThhx/mtn755ZfpqKOOSnPnzs0mceO9996bZ2xGeBnte/rpp9P0 +6dNzeBsBbQSlUartb77ZDwIECBAgQIAAAQIECDQSAYFmIxlI3SBAgEAZBSLMi1mQMeMwytprr51n +bEagedttt6XKkvRq2h4zGaPETM0ffvghXw8aNCgfMBRLsaPErMcIFa+66qq01lr/PfcuQtMrrrgi +f3733Xfn37H0O8pll12WWrZsma/juUsuuSRtuOGG+fW/+RGzTiNAjaXpu+yyS/HoYYcdlvcPjXAz +ZmdWysknn5y6du1aeZkGDhyYryv9ikAzSvS1EvrG4UlXXnllXobesWPH/Hm1/c03+0GAAAECBAgQ +IECAAIFGIvDf/9prJJ3RDQIECBAol0CEljFjMvaajNmEG220Ufrpp59ygBczJrfaaqsc0FXT6pg9 +GcHgjTfemG666aa03Xbb5SXrsU9lzP6MEqHiX3/9lffFrFtnJVD94osv8tsx6zH2zawbPsYHEbj2 +7Nkzz4is+/zKruN7o9x6663FbNHKM7FEPtoUMzErJU57r1vWXXfd/LLSzkr7KnuNVu7dfPPNU+wH +WinV9rdyv98ECBAgQIAAAQIECBBoDAICzcYwivpAgACBkgpUDuyJYDPCzCjxO/aCjHDupZdeqjrQ +jAOAPvnkk/TAAw/kfSrHjRuXrr322vzn0ksvTWeeeWZauHBhngEap6gvr2y22Wb57ThwJ/b2XF6p +zNhc3md136t7yFB8b5SYdRmH9yyvtGjRong7gtN/KjGzNfYYXVmptr8rq8fnBAgQIECAAAECBAgQ +aEgCAs2GNFraSoAAgQYmMGPGjNziyvLvSvNj+Xgs8Y7ZmtWUCA8/+OCD1L59+3wyeZxOHsvWY0Zk +LN+Og3zOOOOMfGp4BJ1PPPFEnm1ZqTv2uIxl4XEyepQIU+Pgn9iXMk4kr1s++uijui/zdWXmZN0P +6p42HqeVR4nDfi688MK6t6Vvvvkm/fzzz3nWaHxnNSXaFwcdxezODTbYoHgkZnmeddZZac8998z7 +csb3VtPfogIXBAgQIECAAAECBAgQaAQC9tBsBIOoCwQIECirQPfu3XPTInisW+677768DHvnnXeu ++/YKryP8jJPI99577xxkxo0xy/Gkk05KG2+8cZ6ZGYf5xCE/EV7Gvp11y3XXXZeXksdhQFEOPPDA +/HvEiBH5d+VHHDwUhwPVLREoxgE+ES5WSgSmP/74Y+VlPnG9Xbt2eV/QX3/9tXg/Dv/p3bt3bnfM +Cq229OrVK99a2fuz8ly8fvzxx4v9Qavtb+V5vwkQIECAAAECBAgQINAYBMzQbAyjqA8ECBAoqUDs +e/nII4/kfR/Hjh2bDj/88PTVV1/lmZWxBHvZ079X1I0INPv375+XqkeoGftmxpLs2J8zDtI56KCD +UtQX33f99dens88+O02ePDntuuuu6bPPPsvL1GOfyiFDhuSviPtiL86bb745xSzSvn375j0u49T0 +ZUufPn3yqePxHUcffXSe1XnDDTfUmwG63nrr5e+M7419OeNwoJhVGqeTR/0nnHBCquyTuWz9y3t9 +zjnnpDvuuCMfUhQnxEedcar7mDFjcoAb/Y9SbX+X9x3eI0CAAAECBAgQIECAQEMVEGg21JHTbgIE +CDQAgR49eqSnnnoq728ZB/rEnyg77LBDPok8AsdqSwSVERLGHpoTJkzIj8VS9gg6KzMvI1icNGlS +Di4feuihNGrUqNS2bdsUp42fcsopqVu3bvm5WLo+ceLEdOyxx6bY53P06NF51mPUNXfu3BweVto1 +cuTIHMLGcvFYtt6mTZu87DtmbcYeoJUSS8HjswsuuCCdf/75+e2YgTp8+PCV7hParFmzSjX5d8w6 +jT5GABuHKcWM1ihxYFEciFRZhl5tf/PDfhAgQIAAAQIECBAgQKCRCDT5z8mrf1XTl5gdU7dU+Vjd +R1w3EoHXX389L59sJN3RDQIEVlHg3/5dEEuxY8/K2D+zQ4cOq/itKc2fPz/FrMX436HY/3JFMx9j +j80pU6akLbbYYoUHAEUjor7Y5zLCzljGPnDgwPTwww+nWbNm1WvntGnT0pw5c/LJ7MsGkMt2JmZl +Vtq37Gf/9nUsW586dWruawSxKyrV9ndFz6/K+zNnzkzxJ06cVwgQIEBgzRYYP3583oKl7iF4a7aI +3hNYMwViH/htt902tW7des0EWMN73a9fv7xKrcIQE0dilV4tihmatVBVJwECBAj8TSDCuOUFcsOG +DcszKf/2QJ03Bg0alJetx1utWrXKh//U+Xi5lxFOxj+mVlaivmoCuU6dOq2squLzCG1XV4l/DMaM +1pWVavu7snp8ToAAAQIECBAgQIAAgbILCDTLPkLaR4AAgUYuMHTo0Lwk/J+62bFjx3/62GcECBAg +QIAAAQIECBAgsAYJCDTXoMHWVQIECJRRoGvXrin+lKXEMokuXbpYJlOWAdEOAgQIECBAgAABAgQI +LCMg0FwGxEsCBAgQWLMFBg8evGYD6D0BAgQIECBAgAABAgRKLtC05O3TPAIECBAgQIAAAQIECBAg +QIAAAQIECBQCAs2CwgUBAgQIECBAgAABAgQIECBAgAABAmUXEGiWfYS0jwABAgQIECBAgAABAgQI +ECBAgACBQkCgWVC4IECAAAECBAgQIECAAAECBAgQIECg7AICzbKPkPYRIECAAAECBAgQIECAAAEC +BAgQIFAICDQLChcECBAgQIAAAQIECBAgQIAAAQIECJRdQKBZ9hHSPgIECBAgQIAAAQIECBAgQIAA +AQIECgGBZkHhggABAgQIECBAgAABAgQIECBAgACBsgsINMs+QtpHgAABAgQIECBAgAABAgQIECBA +gEAhINAsKFwQIECAAAECBAgQIECAAAECBAgQIFB2AYFm2UdI+wgQIECAAAECBAgQIECAAAECBAgQ +KAQEmgWFCwIECBAgQIAAAQIECBAgQIAAAQIEyi4g0Cz7CGkfAQIECBAgQIAAAQIECBAgQIAAAQKF +gECzoHBBgAABAgQIECBAgAABAgQIECBAgEDZBQSaZR8h7SNAgAABAgQIECBAgAABAgQIECBAoBAQ +aBYULggQIECAAAECBAgQIECAAAECBAgQKLuAQLPsI6R9BAgQIECAAAECBAgQIECAAAECBAgUAgLN +gsIFAQIECBAgQIAAAQIECBAgQIAAAQJlFxBoln2EtI8AAQIECBAgQIAAAQIECBAgQIAAgUJAoFlQ +uCBAgAABAgQIECBAgAABAgQIECBAoOwCAs2yj5D2ESBAgAABAgQIECBAgAABAgQIECBQCAg0CwoX +BAgQIECAAAECBAgQIECAAAECBAiUXUCgWfYR0j4CBAgQIECAAAECBAgQIECAAAECBAoBgWZB4YIA +AQIECBAgQIAAAQIECBAgQIAAgbILCDTLPkLaR4AAAQIECBAgQIAAAQIECBAgQIBAISDQLChcECBA +gAABAgQIECBAgAABAgQIECBQdgGBZtlHSPsIECBAgAABAgQIECBAgAABAgQIECgEBJoFhQsCBAgQ +IECAAAECBAgQIECAAAECBMouINAs+whpHwECBAgQIECAAAECBAgQIECAAAEChYBAs6BwQYAAAQIE +CBAgQIAAAQIECBAgQIBA2QUEmmUfIe0jQIAAAQIECBAgQIAAAQIECBAgQKAQEGgWFC4IECBAgAAB +AgQIECBAgAABAgQIECi7gECz7COkfQQIECBAgAABAgQIECBAgAABAgQIFAICzYLCBQECBAgQIECA +AAECBAgQIECAAAECZRcQaJZ9hLSPAAECBAgQIECAAAECBAgQIECAAIFCQKBZULggQIAAAQIECBAg +QIAAAQIECBAgQKDsAgLNso+Q9hEgQIAAAQIECBAgQIAAAQIECBAgUAgINAsKFwQIECBAgAABAgQI +ECBAgAABAgQIlF1AoFn2EdI+AgQIECBAgAABAgQIECBAgAABAgQKAYFmQeGCAAECBAgQIECAAAEC +BAgQIECAAIGyC6y1qg2cMmXKqj7quQYuMGPGjGT8G/ggaj6B1SDg74LVgNjAq5g1a1aaPXt2atmy +ZQPvieYTIECAwP8qMH369NS+ffvUokWL/7UqzxMg0IAFpk2blv9t2KpVqwbcC01fVYF58+bVe3Th +woX1Xq/OF6scaHbr1m11tkNdBAgQIECAAAECBAgQIECAAAECBAg0EoHJkyenAQMG1KQ3lpzXhFWl +BAgQIECAAAECBAgQIECAAAECBAjUQkCgWQtVdRIgQIAAAQIECBAgQIAAAQIECBAgUBOBqpecr7VW +/Vs7d+5ckwaptPwCsQeC/dLKP05aSKDWAv4uqLVw+etfsmRJWrp0aWrevHn5G6uFBAgQIFBTgUWL +FuX9M5s0aVLT71E5AQLlFli8eHGK/KhpU/Pnyj1StWndzJkz04IFC4rK27VrV1yv7osmf/2nrO5K +1UeAAAECBAgQIECAAAECBAgQIECAAIFaCIjMa6GqTgIECBAgQIAAAQIECBAgQIAAAQIEaiIg0KwJ +q0oJECBAgAABAgQIECBAgAABAgQIEKiFgECzFqrqJECAAAECBAgQIECAAAECBAgQIECgJgICzZqw +qpQAAQIECBAgQIAAAQIECBAgQIAAgVoICDRroapOAgQIECBAgAABAgQIECBAgAABAgRqIiDQrAmr +SgkQIECAAAECBAgQIECAAAECBAgQqIWAQLMWquokQIAAAQIECBAgQIAAAQIECBAgQKAmAgLNmrCq +lAABAgQIECBAgAABAgQIECBAgACBWggINGuhqk4CBAgQIECAAAECBAgQIECAAAECBGoiINCsCatK +CRAgQIAAAQIECBAgQIAAAQIECBCohYBAsxaq6iRAgAABAgQIECBAgAABAgQIECBAoCYCAs2asKqU +AAECBAgQIECAAAECBAgQIECAAIFaCAg0a6GqTgIECBAgQIAAAQIECBAgQIAAAQIEaiIg0KwJq0oJ +ECBAgAABAgQIECBAgAABAgQIEKiFwP8BZSt/txxIMNkAAAAASUVORK5CYII=){ width=750px } + +Note that outside of the truncation case, the leading code unit is associated +with a more specific error enumerator, and then all the continuation bytes in +the invalid sequence are `unexpected_utf8_continuation_byte`. This is aligned +with my interpretation of the underlying logic of Substitution of Maximal +Subparts; also, any other approach would require additional lookahead, which +would break some of the API's invariants. + +## Erroneous Behavior + +Iterators are constructed from more than one underlying iterator. In order to +perform iteration in many text-handling contexts, you need to know the +beginning and the end of the range you are iterating over, just to be able to +perform iteration correctly. Note that this is not a safety issue, but a +correctness one. For example, say we have a string `s` of UTF-8 code units +that we would like to iterate over to produce UTF-32 code points. If the last +code unit in `s` is `0xe0`, we should expect two more code units to +follow. They are not present, though, because `0xe0` is the last code +unit. Now consider how you would implement `operator++()` for an iterator +`iter` that transcodes from UTF-8 to UTF-32. If you advance far enough to get +the next UTF-32 code point in each call to `operator++()`, you may run off the +end of `s` when you find `0xe0` and try to read two more code units. Note that +it does not matter that `iter` probably comes from a range with an +end-iterator or sentinel as its mate; inside `iter`'s `operator++()` this is +no help. `iter` must therefore have the end-iterator or sentinel as a data +member. The same logic applies to the other end of the range if `iter` is +bidirectional โ€” it must also have the iterator to the start of the underlying +range as a data member. This unfortunate reality comes up over and over in the +proposed iterators, not just the ones that are UTF transcoding iterators. This +is why iterators in this proposal (and the ones to come) usually consist of +three underlying iterators. + +Because of this fact, it's almost free to specify these iterators so that +dereferencing a past-the-end iterator, incrementing a past-the-end iterator, +and decrementing an at-the-beginning iterator are all erroneous behavior +instead of undefined behavior. The only time an additional branch is required +to ensure safety is to check for a before-the-beginning decrement in +`operator--` (although actually producing diagnostics for the EB requires +further branching). + +As long as a transcoding view is constructed with proper arguments, all +subsequent operations on it and its iterators are memory safe. + +## Optimization for transcoding views wrapping other transcoding views + +In generic contexts, users will create `to_utfN_view`s wrapping iterators of +other `to_utfN_view`s. This presents a problem for a naive implementation +because when `to_utfN_view` is wrapping a bidirectional range, the number of +iterators in each successive `to_utfN_view` wrapper increases geometrically +unless we use workarounds. + +The workaround makes it so that when a `to_utfN_view` is constructed from +another `to_utfN_view`'s iterators, instead of storing those iterators in the +iterators of the outer `to_utfN_view`, the outer `to_utfN_view`'s iterators have +identical contents to the inner `to_utfN_view`'s iterators, the only difference +being the output encoding. This also allows the outer `to_utfN_view`'s +iterators to reconstruct the inner `to_utfN_view` iterator when its `base()` +member function is invoked, without actually storing it. + +This optimization is only needed when the underlying range is bidirectional +(or "better"), because input ranges and forward ranges increase in size +linearly rather than geometrically with each successive wrapper, due to the +fact that the sentinel is not wrapped by the transcoding iterator. + +Although it's not strictly necessary, we could also apply the optimization +when the underlying range is a forward range, preventing the iterator size +from growing at all (as opposed to linear growth), but that isn't done in this +paper because we judge the tradeoffs as not being justified. It is not +possible to apply the optimization when the underlying range is an input +range, because of the fact that the underlying iterator is past-the-end of the +current code point. + +The diagram below represents the outcome of the following process: + +- The user starts with a range of `char8_t`s from `0x100` to `0x300`. +- They create a `to_utf16_view` with this underlying range. +- They advance that view's `begin()` iterator until the underlying pointer is + at `0x150` and reverse the view's `end()` iterator until the underlying + pointer is at `0x250`. +- They create a subrange with these iterators and wrap it in a + `to_utf32_view`. +- They advance the `to_utf32_view`'s `begin()` iterator until the underlying + pointer (two levels down) is at `0x175` and similarly reverse `end()` to + `0x225`. + +![](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAx8AAAOmCAIAAAAFA79PAAAAAXNSR0IArs4c6QAAAJBlWElmTU0A +KgAAAAgABgEGAAMAAAABAAIAAAESAAMAAAABAAEAAAEaAAUAAAABAAAAVgEbAAUAAAABAAAAXgEo +AAMAAAABAAIAAIdpAAQAAAABAAAAZgAAAAAAAABIAAAAAQAAAEgAAAABAAOgAQADAAAAAQABAACg +AgAEAAAAAQAAAx+gAwAEAAAAAQAAA6YAAAAAuhjAeAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAgtp +VFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0 +YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDYuMC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRw +Oi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNj +cmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFk +b2JlLmNvbS90aWZmLzEuMC8iPgogICAgICAgICA8dGlmZjpSZXNvbHV0aW9uVW5pdD4yPC90aWZm +OlJlc29sdXRpb25Vbml0PgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVu +dGF0aW9uPgogICAgICAgICA8dGlmZjpDb21wcmVzc2lvbj41PC90aWZmOkNvbXByZXNzaW9uPgog +ICAgICAgICA8dGlmZjpQaG90b21ldHJpY0ludGVycHJldGF0aW9uPjI8L3RpZmY6UGhvdG9tZXRy +aWNJbnRlcnByZXRhdGlvbj4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4K +PC94OnhtcG1ldGE+CtQK6igAAEAASURBVHgB7J0HeFRF24ZJ7400Sui9lwBBkI8qCKJUC12KCiIW +QEFRFKQIH0WRLh1U2kf7QUroXZHeIUASQkgoIZ30/M9mwuGwu9ks2d1ky3MurmXOnJl3Zu4zm332 +nffMWmVnZxfjQQIkQAIkQAIkQAIkoCcC1nqyQzMkQAIkQAIkQAIkQAIKAlRXnAckQAIkQAIkQAIk +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 +ARIgARIgARIgAR0IcGVQB3isSgIkQAIkQAIkQAIqBKiuVJAwgwRIgARIgARIgAR0IEB1pQM8ViUB +EiABEiABEiABFQJUVypImEECJGCUBKKiooyyX+wUCZAACSgToLpSJsJzEiAB4ySwaNEi4+wYe0UC +JEACSgSorpSA8JQESIAESIAESIAEdCJAdaUTPlYmARIgARIgARIgASUCVFdKQHhKAiRAAiRAAiRA +AjoRoLrSCR8rkwAJkAAJkAAJkIASAaorJSA8JQESIAESIAESIAGdCFBd6YSPlUmABEiABEiABEhA +iQDVlRIQnpIACZAACZAACZCATgSornTCx8okQAIkQAIkQAIkoESA6koJCE9JgARIgARIgARIQCcC +VFc64WNlEiABEiABEiABElAiQHWlBISnJEACJEACJEACJKATAaornfCxMgmQAAmQAAmQAAkoEaC6 +UgLCUxIgARIgARIgARLQiQDVlU74WJkESIAESIAESIAElAhQXSkB4SkJkAAJkAAJkAAJ6ESA6kon +fKxMAiRAAiRAAiRAAkoEqK6UgPCUBEiABEiABEiABHQiQHWlEz5WJgESIAESIAESIAElAlRXSkB4 +SgIkQAIkQAIkQAI6EaC60gkfK5MACZAACZAACZCAEgGqKyUgPCUBEiABEiABEiABnQhQXemEj5VJ +gARIgARIgARIQIkA1ZUSEJ6SAAkYHYHQ0NCmTZuuW7cOr3fu3DG6/rFDJEACJPAiAaqrF3nwjARI +wPgIuLi4ZGRkXL16Fa+urq7G10H2iARIgAReIEB19QIOnpAACRghAV9f35YtW6JjeEXaCHvILpEA +CZCAnADVlZwG0yRAAkZK4N13361SpQpejbR/7BYJkAAJyAhQXclgMEkCJGCsBOrVq9e1a1e8GmsH +2S8SIAESeE7AKjs7+/kZUyRAAiRAAiRAAiRAAroRoO9KN36sTQIkQAIkQAIkQAIvEqC6epEHz0iA +BEiABEiABEhANwJUV7rxY20SMAIC8fHxRtALrbqQmJiYlZWlVdFnhdLS0lJSUp6d8X8SIAESMAEC +VFcmcJPYRRKQEwgPD58xY4bIuXDhQtmyZQMCAnD622+/1a5du1SpUm+//XZUVBRynj59+tlnn1Ws +WLFy5crffvut9rKmdOnSBw8eFE3o6xWtt23btnjx4n/99Zdmm7tyDlEGI/X29h42bJg4jYiIwKk0 +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 +0yohNMTK0cna1U33CPRrCHq0ON2zhJCa+q/pUqQI5QMbXAmxYBeLtGrY+6Cjni9pGa98IQ1yaXBV +L9tHvWBi2qouU+86tgIEo3Ulg5Fe5ZqA7q2ohKyrck2fhS9rApr6r+lS1nlk+iRgAAJFUmwdAyOY +xjyTAbLKKEiABEiABEiABEig/BKgdVV+654lJwESIAESIAESKAkCtK5KgirjJAESIAESIAESKL8E +aF2V37pnyUmABEiABEiABEqCAK2rkqDKOEmABEiABEiABMovAVpX5bfuWXISIAESIAESIIGSIEDr +qiSoMk4SIAESIAESIIHyS4DWVfmte5acBEiABEiABEigJAjQuioJqoyTBEiABEiABEig/BKgdVV+ +654lJwESIAESIAESKAkC+X+QTo80sOM7Dj1u5C0koGQCOmp1rvpT/5Vck8ybPgQ09Z+qrg9H3qN4 +ApqqbpAsG+B3Bg2SD0ZCAiRAAiRAAiRAAkomAFNMlx+WRTDODCq5Hpk3EiABEiABEiAB4yNA68r4 +6ow5JgESIAESIAESUDIBWldKrh3mjQRIgARIgARIwPgI0LoyvjpjjkmABEiABEiABJRMgNaVkmuH +eSMBEiABEiABEjA+ArSujK/OmGMSIAESIAESIAElE6B1peTaYd5IgARIgARIgASMjwCtK+OrM+aY +BEiABEiABEhAyQR03audu/QquRaZNxIgARIgARIggZImoPvG7rru1V7SOWb8JEACJEACJEACJGAC +BLhXuwlUIotAAiRAAiRAAiSgLAJcd6Ws+mBuSIAESIAESIAEjJ0ArStjr0HmnwRIgARIgARIQFkE +aF0pqz6YGxIgARIgARIgAWMnQOvK2GuQ+ScBEiABEiABElAWAVpXyqoP5oYESIAESIAESMDYCdC6 +MvYaZP5JgARIgARIgASURYDWlbLqg7khARIgARIgARIwdgK0roy9Bpl/EiABEiABEiABZRGgdaWs ++mBuSIAESIAESIAEjJ0ArStjr0HmnwRIgARIgARIQFkEaF0pqz6YGxIgARIgARIgAWMnQOvK2GuQ ++ScBEiABEiABElAWAVpXyqoP5oYESKCoBJ5//vmVK1cW9S6GJwESIIGSI0DrquTYMmYSIIHSIJCZ +mVkayTANEiABEtCZAK0rnVExIAmQQMkT8PPza9asmYuLS9++faOjo5EgLn/55Zd69eo5OjqOGzdO +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 +rtixY8czZ87MmTMH+ztg2vHTTz9FVrEjA74oxBQh7hKr7KVsUyABEiCBwgkUuu6dAUiABEigqASw +rwG2oXJ0dBTPIHweiP2u8Es4Ih6x9hxbSWEaUQTAfNyaNWsk365du8ImwwEXbPWOMPglHOyzAOGH +H36QMgOzCV8gSpeNGzeGMad+y6JFi0T86ufOnTsjTHR0NEworIWHl5eXF8w4/AKPiArfJ0ozhjCw +hg8fjjDYcEtKiAIJkAAJyBOoCG/15w5lEiABEjAUATxe8CvOGB+C3aO+Thw7VMGsmTx58owZM7CK +HMGqV69uqESLFA9yApsP67E0V8RjuRWWw8O6KlKEDEwCJEACIMCZQaoBCZBASRGAySINAmlLQ+wm +pc23pN0xPJbv00UpRfWvESVHCiRAAiSgCwGuateFEsOQAAmQAAmQAAmQgK4EOHalKymGIwESMBQB +jBhhl3b8vKChImQ8JEACJKAoAlx3pajqYGZIgARIgARIgASMngBnBo2+ClkAEiABEiABEiABRRGg +daWo6mBmSIAESIAESIAEjJ4ArSujr0IWgARIgARIgARIQFEEaF0pqjqYGRIgARIgARIgAaMnQOvK +6KuQBSABEiABEiABElAUAVpXiqoOZoYESIAESIAESMDoCdC6MvoqZAFIgARIgARIgAQURYDWlaKq +g5khARIgARIgARIwegK0roy+ClkAEiABEiABEiABRRGgdaWo6mBmSIAESIAESIAEjJ4ArSujr0IW +gARIgARIgARIQFEEaF0pqjqYGRIgARIgARIgAaMnQOvK6KuQBSABEiABEiABElAUAVpXiqoOZoYE +SIAESIAESMDoCdC6MvoqZAFIgARIgARIgAQURYDWlaKqg5khARIgARIgARIwegK0roy+ClkAEiAB +EiABEiABRRGgdaWo6mBmSIAESIAESIAEjJ4ArSujr0IWgARKk8DVq1crVaoUEREhJTpv3ryGDRtK +lzICQvbu3VsmgPD65JNPPv744wKDVatW7fDhwwV6yTsGBQUh29JRr169iRMnZmRkyN9FXxIgARLQ +j4C5frfxLhIggXJLICf3kIqf71Jy1xSysrIQWNM9nwvCZGdn53MUlwsWLGjUqFGBXvKOiBDRnjhx +olatWhAuXbo0ePDg+vXrjxgxQv5G+pIACZCAHgQ4dqUHNN5CAiRQAIFmzZr98ssvGBZydHQcN26c +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 +SIAESIAEjJEA1ZUx9gptIgESIAESIAESkC8Bqiv59h0tJwESIAESIAESMEYCVFfG2Cu0iQRIgARI +gARIQL4E+CvOcu077JTIvcrk2nm0mwRIgAR0TQBb+GKTNl2XyvLKSIDqqozgKjwbpBXVVYX3Ag0g +ARIgASMhoPwDCUZikjmbwZVBc+59tp0ESIAESIAESED3BKiudM+UJZIACZAACZAACZgzAaorc+59 +tp0ESIAESIAESED3BKiudM+UJZIACZAACZAACZgzAaorc+59tp0ESIAESIAESED3BKiudM+UJZIA +CZAACZAACZgzAaorc+59tp0ESIAESIAESED3BKiudM+UJZIACZAACZAACZgzAaorc+59tp0ESIAE +SIAESED3BKiudM+UJZIACZAACZAACZgzAaorc+59tp0ESIAESIAESED3BKiudM+UJcqXwKFDh6pX +r15m+6tVq3b06NEyZ2dGEpA7gc6dO69bt07uraD9JFB+AlRX5WfIEkyHQDl/G3vZsmUNGzY0HRxs +CQmUkkBubm4pczA5CZgmAaor0+xXtqrMBLKyssaPH+/h4VGnTp1Vq1aJcg4cONC0aVM3N7dBgwbF +xcUhMiIiolevXq6urh07dnz11VcXL16MyAULFty/f//IkSODBw+eMmWKp6cnZsL27NlTZmOYkQQq +kEDxYY9vwVdffVW3bl1nZ+epU6cK27Zu3dqgQQMHBwcM+5SUlAo0mFWTgPEQoLoynr6gJUZB4PHj +xzExMbt27Zo8efJrr712/PhxCKaBAwdOmjRp3759uHmMGzcOhkJmWVlZ7d27t0+fPhBhyIXIu3fv +pqWlpaam7tixAwEUEhQU9O677xpFw2gECZSGgNphf+fOnZUrV65evXru3Ll4orhx40ZwcPCoUaNG +jhyJhwonJyfElKYSpiUBkyVgbbItY8NIoEwEoJnWr1/v7e3drl27EydObNq0qUaNGi1bthw2bBjK +mzVrFjxLTp8+ffHixQcPHlStWhXJfv75Z5Wq8By/fPlyOzs7PN/36NFD5SpPScD4CWzevFll2ItH +iDlz5jxbeEBghYWFnT9/vlWrVjNmzECLmjdvjicK428aLSQBAxCgujIAZFYhJwI+Pj6QVsLiJk2a +nD17Fs5Yp06dgse61IzLly/jMR3SSsRgDVG6JAK+vr6QVgg7Ojrm5eWpXOUpCRg/gXv37qkM+8jI +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 +V60pXdIAAAAASUVORK5CYII=){ width=750px } + +The goal is for the optimized implementation to avoid having to store all the +iterators that the naive implementation does, while still outwardly appearing +to the user as though its API is the same as the naive one. + +The iterators of the optimized `to_utf32_view` can simulate the naive +version's `base()` by reconstructing a `to_utf16_view` iterator containing its +own `first`, `curr`, and `last` iterators. However, if we added accessors for +`first()` and `last()` to the iterator, then we wouldn't be able to return the +same results as the naive implementation because we've lost information about +those iterators-- so this optimization can only work properly if we leave +those out. + +Unlike with other range adaptor objects, `base()` cannot have any overloads +that simply return a reference to the underlying iterator as opposed to a new +copy or move-constructed instantiation of it, because of this optimization. + +Input iterators cannot benefit from this optimization because they are +necessarily past-the-end of the current code point within the range being +adapted, whereas other iterator types are at the beginning of the current code +point. + +There is an unavoidable inconsistency introduced by this optimization that +occurs when one of the iterators is in the middle of a code point in a +variable length encoding (UTF-8 or UTF-16). Consider what happens when a user +attempts to convert the UTF-32 code point `U+1F574 ๐Ÿ•ด MAN IN BUSINESS SUIT +LEVITATING` to UTF-8 and then to UTF-16, but increments the iterator of the +UTF-8 transcoding view by one code unit first. + +In the naive implementation, the result is simply three replacement characters +as the UTF-16 transcoder encounters three unexpected UTF-8 continuation bytes: + +``` +UTF-32: 0x1F574 +UTF-8: 0xF0 0x9F 0x95 0xB4 + ^ +UTF-16: 0xFFFD 0xFFFD 0xFFFD +``` + +However, in the optimized implementation, when the UTF-16 transcoding view +wraps the iterator from the UTF-8 transcoding view, it looks directly at the +underlying UTF-32 iterator and forgets the UTF-8 iterator's position within +the code point: + +``` +UTF-32: 0x1F574 +UTF-16: 0xD83D 0xDD74 +``` + +Furthermore, when you invoke `base()` on an iterator of the UTF-16 transcoding +view, it's lost the intra-code-point position, moving it back to the starting +code unit: + +``` +Original iterator: +UTF-8: 0xF0 0x9F 0x95 0xB4 + ^ + +Result of base(): +UTF-8: 0xF0 0x9F 0x95 0xB4 + ^ +``` + +These inconsistencies are somewhat unfortunate, but they only apply when the +input to the transcoding view starts in the middle of a code point, which is +definitionally invalid UTF anyway; and it does not affect the invariant that +the output is always valid UTF. This is an acceptable tradeoff for avoiding +quadratic growth of the iterator sizes. + +There is one more quirk introduced by this optimization. For ordinary, +non-special-cased iterators of transcoding views, dereferencing a past-the-end +iterator, incrementing past the end, and decrementing before the beginning are +all erroneous behavior. However, because of the information loss associated +with this optimization, the EB detection can't kick in until the user has +exceeded the bounds of the deepest underlying range, rather than one of its +intermediate layers. + +For example, in the scenario in the diagram from before, the naive +implementation would detect EB when the `to_utf32_view`'s `begin()` iterator +was decremented to the point where the underlying range iterator was less than +`0x150`, but the special-cased implementation would simply continue reading +through the underlying range until `0x100`. This is perhaps surprising, but +still achieves memory safety. + +It's a useful property of this approach that the type system remembers the +correct type to use for `base()` even in the case of transcoding views +wrapping other transcoding view. To illustrate, consider this algorithm (not +proposed) as an example. + +```c++ +template S, output_iterator O> +transcode_result transcode_to_utf32(I first, S last, O out); +``` + +Such a transcoding algorithm is pretty similar to `std::ranges::copy`, in that +you should return both the output iterator *and* the final position of the +input iterator (`transcode_result` is an alias for `in_out_result`). Because +we can always provide `base()`, we have no trouble returning a +`transcode_result` here in every case: + +``` +template S, output_iterator O> +transcode_result transcode_to_utf32(I first, S last, O out) { + auto r = ranges::subrange(first, last) | uc::as_utf32; + + auto copy_result = ranges::copy(r, out); + + return transcode_result{copy_result.in.base(), copy_result.out}; +} +``` + +## Other design notes + +None of the proposed interfaces is subject to change in future versions of +Unicode; each relates to the guaranteed-stable subset. Just sayin'. + +None of the proposed interfaces allocates or throws. + +All the transcoding iterators allow you access to the underlying iterator via +`.base()`, following the convention of the iterator adaptors already in the +standard. + +The transcoding views are lazy, as you'd expect. They also compose with the +standard view adaptors, so just transcoding at most 10 UTF-16 code units out +of some UTF can be done with `foo | std::uc::to_utf16 | +std::ranges::views::take(10)`. + +Error handling strategies of the user's choosing can be implemented by the +user due to the suitable basis operation `success()` provided by the transcoding +iterator. This gives control to those who want to do something other than the +default. The default, according to Unicode, is to produce a replacement +character (`0xfffd`) in the output when broken UTF encoding is seen in the +input. This is what all these interfaces do, unless you make use of the basis +operation. + +The production of replacement characters as error-handling strategy is good +for memory compactness and safety. It allows us to store all our text as +UTF-8 (or, less compactly, as UTF-16), and then process code points as +transcoding views. If an error occurs, the transcoding views will simply +produce a replacement character; there is no danger of UB. + +## Null-terminated sequence sentinel `null_sentinel` and associated CPO `null_term` + +```cpp +namespace std { + + template + concept @*default-initializable-and-equality-comparable-iter-value*@ = + default_initializable> && + equality_comparable_with, iter_value_t>; // @*exposition only*@ + + + struct null_sentinel_t { + template + requires (not forward_iterator) && @*default-initializable-and-equality-comparable-iter-value*@ + friend constexpr bool operator==(I const& it, null_sentinel_t) { + return *it == iter_value_t{}; + } + template + requires @*default-initializable-and-equality-comparable-iter-value*@ + friend constexpr bool operator==(I it, null_sentinel_t) { + return *it == iter_value_t{}; + } + }; + + inline constexpr null_sentinel_t null_sentinel; + + inline constexpr @*unspecified*@ null_term; + +} +``` + +The sentinel type matches any iterator position `it` at which `*it` is equal +to a default-constructed object of type `iter_value_t`. This works for +null-terminated strings, but can also serve as the sentinel for any +range terminated by a default-constructed value. + +Because this type is potentially useful for lots of ranges unrelated to +Unicode or text, it is in the `std` namespace, not `std::uc`. + +The `null_sentinel_t`'s `operator==` has a separate overload for input +iterators that takes the iterator by reference instead of by value. We want to +take input iterators by reference because they are not required to be +copyable. However, for forward iterators, we want to take by value because +otherwise we incur a double indirection (e.g. `int* const& it`) that compilers +may not optimize. + +The name `null_term` denotes a customization point object +([customization.point.object]). Given a subexpression `E`, the expression +`null_term(E)` is expression-equivalent to `ranges::subrange(move(E), +null_sentinel)`. + +## Exposition-only concepts and traits + +```c++ +namespace std::uc { + + template + constexpr bool @*is-empty-view*@ = false; + template + constexpr bool @*is-empty-view*@> = true; + + template + concept @*code-unit-to*@ = same_as, char8_t> || + same_as, char16_t> || same_as, char32_t>; + + template + concept @*code-unit-from*@ = + same_as, char> || same_as, wchar_t> || @*code-unit-to*@; + + template + concept @*utf-range*@ = + ranges::input_range && @*code-unit-from*@>; + + template + consteval auto @*bidirectional-at-most*@() { // @*exposition only*@ + if constexpr (bidirectional_iterator) { + return bidirectional_iterator_tag{}; + } else if constexpr (forward_iterator) { + return forward_iterator_tag{}; + } else if constexpr (input_iterator) { + return input_iterator_tag{}; + } + } + + template + using @*bidirectional-at-most-t*@ = decltype(@*bidirectional-at-most*@()); // @*exposition only*@ + + template + consteval auto @*iterator-to-tag*@() { // @*exposition only*@ + if constexpr (random_access_iterator) { + return random_access_iterator_tag{}; + } else if constexpr (bidirectional_iterator) { + return bidirectional_iterator_tag{}; + } else if constexpr (forward_iterator) { + return forward_iterator_tag{}; + } else if constexpr (input_iterator) { + return input_iterator_tag{}; + } + } + + template + using @*iterator-to-tag-t*@ = decltype(@*iterator-to-tag*@()); // @*exposition only*@ +} +``` + +## Transcoding views + +```c++ +namespace std::uc { + + enum class transcoding_error { + truncated_utf8_sequence, + unpaired_high_surrogate, + unpaired_low_surrogate, + unexpected_utf8_continuation_byte, + overlong, + encoded_surrogate, + out_of_range, + invalid_utf8_leading_byte + }; + + template + concept @*to-utf-view-iterator-optimizable*@ = @*unspecified*@ // @*exposition only*@ + + template<@*code-unit-to*@ ToType, @*from-utf-view*@ V> + class @*to-utf-view-impl*@ : public ranges::view_interface<@*to-utf-view-impl*@> { + public: + template + class @*utf-iterator*@ : public iterator_interface<@*bidirectional-at-most-t*@>, ToType, ToType> { + + private: + using @*iter*@ = ranges::iterator_t<@*maybe-const*@>; + using @*sent*@ = ranges::sentinel_t<@*maybe-const*@>; + + template<@*code-unit-to*@ ToType2, + @*from-utf-view*@ V2> + friend class @*to-utf-view-impl*@; // @*exposition only*@ + + template + struct @*first-and-curr*@ { // @*exposition only*@ + @*first-and-curr*@() = default; + constexpr @*first-and-curr*@(I curr) : curr(move(curr)) {} + + I curr; + }; + template + struct @*first-and-curr*@ { // @*exposition only*@ + @*first-and-curr*@() = default; + constexpr @*first-and-curr*@(I first, I curr) : first(first), curr(curr) {} + + I first; + I curr; + }; + + using @*innermost-iter*@ = @*unspecified*@; // @*exposition only*@ + + using @*from-type*@ = decltype([] { + if constexpr (is_same_v>) { + return char8_t{}; + } else if constexpr (is_same_v>) { + if constexpr (sizeof(wchar_t) == 2) { + return char16_t{}; + } else if constexpr (sizeof(wchar_t) == 4) { + return char32_t{}; + } + } else { + return iter_value_t<@*innermost-iter*@>{}; + } + }()); // @*exposition only *@ + + using @*innermost-iter*@ = @*unspecified*@; // @*exposition only*@ + using @*innermost-sent*@ = @*unspecified*@; // @*exposition only*@ + + public: + using value_type = ToType; + using reference_type = ToType&; + using difference_type = ptrdiff_t; + using iterator_concept = @*bidirectional-at-most-t*@<@*iter*@>; + + constexpr @*utf-iterator*@() requires default_initializable = default; + + private: + constexpr @*utf-iterator*@(@*innermost-iter*@ first, @*innermost-iter*@ it, @*innermost-sent*@ last) // @*exposition only*@ + requires bidirectional_iterator<@*innermost-iter*@> + : first_and_curr_(first, it), last_(last) { + if (curr() != last_) + read(); + } + constexpr @*utf-iterator*@(@*innermost-iter*@ it, @*innermost-sent*@ last) // @*exposition only*@ + requires (!bidirectional_iterator<@*innermost-iter*@>) + : first_and_curr_(move(it)), last_(last) { + if (curr() != last_) + read(); + } + + public: + constexpr @*utf-iterator*@() = default; + constexpr @*utf-iterator*@(@*utf-iterator*@ const&) requires copyable<@*innermost-iter*@> = default; + + constexpr @*utf-iterator*@& operator=(@*utf-iterator*@ const&) requires copyable<@*innermost-iter*@> = default; + + constexpr @*utf-iterator*@(@*utf-iterator*@&&) = default; + + constexpr @*utf-iterator*@& operator=(@*utf-iterator*@&&) = default; + + constexpr @*iter*@ base() const requires forward_iterator<@*innermost-iter*@> + { + if constexpr (@*to-utf-view-iterator-optimizable*@<@*iter*@>) { + if constexpr (bidirectional_iterator<@*innermost-iter*@>) { + return @*iter*@(begin(), curr(), last_); + } else { + return @*iter*@(curr(), last_); + } + } else { + return curr(); + } + } + + constexpr @*iter*@ base() && + requires (!forward_iterator<@*innermost-iter*@>) { return move(*this).curr(); } + + constexpr expected success() const; + + constexpr value_type operator*() const; + + constexpr @*utf-iterator*@& operator++() { + if constexpr (forward_iterator<@*innermost-iter*@>) { + if (buf_index_ + 1 < buf_last_) { + ++buf_index_; + } else if (buf_index_ + 1 == buf_last_) { + advance(curr(), to_increment_); + to_increment_ = 0; + if (curr() != last_) { + read(); + } else { + buf_index_ = 0; + } + } + } else { + if (buf_index_ + 1 == buf_last_ && curr() != last_) { + read(); + } else if (buf_index_ + 1 <= buf_last_) { + ++buf_index_; + } + } + return *this; + } + + constexpr auto operator++(int) { + if constexpr (is_same_v) { + ++*this; + } else { + auto retval = *this; + ++*this; + return retval; + } + } + + constexpr @*utf-iterator*@& operator--() requires bidirectional_iterator<@*innermost-iter*@> + { + if (!buf_index_) + read_reverse(); + else if (buf_index_) + --buf_index_; + return *this; + } + + constexpr @*utf-iterator*@ operator--(int) requires bidirectional_iterator<@*innermost-iter*@> + { + auto retval = *this; + --*this; + return retval; + } + + friend constexpr bool operator==(@*utf-iterator*@ const& lhs, @*utf-iterator*@ const& rhs) + requires forward_iterator<@*innermost-iter*@> || requires (@*innermost-iter*@ i) { i != i; } + { + if constexpr (forward_iterator<@*innermost-iter*@>) { + return lhs.curr() == rhs.curr() && lhs.buf_index_ == rhs.buf_index_; + } else { + if (lhs.curr() != rhs.curr()) + return false; + + if (lhs.buf_index_ == rhs.buf_index_ && lhs.buf_last_ == rhs.buf_last_) { + return true; + } + + return lhs.buf_index_ == lhs.buf_last_ && rhs.buf_index_ == rhs.buf_last_; + } + } + + friend constexpr bool operator==(@*utf-iterator*@ const& lhs, @*innermost-sent*@ rhs) requires copyable<@*innermost-iter*@> + { + if constexpr (forward_iterator<@*innermost-iter*@>) { + return lhs.curr() == rhs; + } else { + return lhs.curr() == rhs && lhs.buf_index_ == lhs.buf_last_; + } + } + + friend constexpr bool operator==(@*utf-iterator*@ const& lhs, @*innermost-sent*@ rhs) requires (!copyable<@*innermost-iter*@>) + { + return lhs.curr() == rhs && lhs.buf_index_ == lhs.buf_last_; + } + + + constexpr @*innermost-iter*@ begin() const // @*exposition only*@ + requires bidirectional_iterator<@*innermost-iter*@> + { + return first_and_curr_.first; + } + constexpr @*innermost-sent*@ end() const { // @*exposition only*@ + return last_; + } + + constexpr void read(); // @*exposition only*@ + + constexpr void read_reverse(); // @*exposition only*@ + + constexpr @*innermost-iter*@& curr() & { return first_and_curr_.curr; } // @*exposition only*@ + + constexpr @*innermost-iter*@ const& curr() const& { return first_and_curr_.curr; } // @*exposition only*@ + + constexpr @*innermost-iter*@ curr() && { return move(first_and_curr_.curr); } // @*exposition only*@ + + array buf_{}; // @*exposition only*@ + + @*first-and-curr*@<@*innermost-iter*@> first_and_curr_; // @*exposition only*@ + + [[no_unique_address]] @*innermost-sent*@ last_; // @*exposition only*@ + + uint8_t buf_index_ = 0; // @*exposition only*@ + uint8_t buf_last_ = 0; // @*exposition only*@ + uint8_t to_increment_ = 0; // @*exposition only*@ + }; + + private: + template + static constexpr auto make_begin(auto first, auto last) { // @*exposition only*@ + if constexpr (bidirectional_iterator>) { + if constexpr (@*to-utf-view-iterator-optimizable*@>) { + return @*utf-iterator*@(first.begin(), first.curr(), first.last_); + } else { + return @*utf-iterator*@(first, first, last); + } + } else { + return @*utf-iterator*@(move(first), last); + } + } + template + static constexpr auto make_end(auto first, auto last) { // @*exposition only*@ + if constexpr (bidirectional_iterator>) { + if constexpr (@*to-utf-view-iterator-optimizable*@>) { + return @*utf-iterator*@(last.begin(), last.curr(), last.last_); + } else { + return @*utf-iterator*@(first, last, last); + } + } else { + return last; + } + } + + V base_ = V(); // @*exposition only*@ + + public: + constexpr @*to-utf-view-impl*@() requires default_initializable = default; + constexpr @*to-utf-view-impl*@(V base) : base_(move(base)) {} + + constexpr V base() const& requires copy_constructible + { + return base_; + } + constexpr V base() && { return move(base_); } + + constexpr auto begin() requires (!copyable>) + { + return make_begin(ranges::begin(base_), ranges::end(base_)); + } + constexpr auto begin() const requires copyable> + { + return make_begin(ranges::begin(base_), ranges::end(base_)); + } + + constexpr auto end() requires (!copyable>) + { + return make_end(ranges::begin(base_), ranges::end(base_)); + } + constexpr auto end() const requires copyable> + { + return make_end(ranges::begin(base_), ranges::end(base_)); + } + + constexpr bool empty() const { return ranges::empty(base_); } + }; + + template<@*from-utf-view*@ V> + class to_utf8_view { + private: + using @*iterator*@ = ranges::iterator_t<@*to-utf-view-impl*@>; + using @*sentinel*@ = ranges::sentinel_t<@*to-utf-view-impl*@>; + + public: + constexpr to_utf8_view() requires default_initializable = default; + constexpr to_utf8_view(V base) : impl_(move(base)) {} + + constexpr V base() const& requires copy_constructible + { + return impl_.base(); + } + constexpr V base() && { return move(impl_).base(); } + + constexpr auto begin() requires (!copyable<@*iterator*@>) + { + return impl_.begin(); + } + constexpr auto begin() const requires copyable<@*iterator*@> + { + return impl_.begin(); + } + + constexpr auto end() requires (!copyable<@*iterator*@>) + { + return impl_.end(); + } + constexpr auto end() const requires copyable<@*iterator*@> + { + return impl_.end(); + } + + constexpr bool empty() const { return impl_.empty(); } + + private: + @*to-utf-view-impl*@ impl_; + }; + + template + to_utf8_view(R&&) -> to_utf8_view>; + + template<@*from-utf-view*@ V> + class to_utf16_view { + private: + using @*iterator*@ = ranges::iterator_t<@*to-utf-view-impl*@>; + using @*sentinel*@ = ranges::sentinel_t<@*to-utf-view-impl*@>; + + public: + constexpr to_utf16_view() requires default_initializable = default; + constexpr to_utf16_view(V base) : impl_(move(base)) {} + + constexpr V base() const& requires copy_constructible + { + return impl_.base(); + } + constexpr V base() && { return move(impl_).base(); } + + constexpr auto begin() requires (!copyable<@*iterator*@>) + { + return impl_.begin(); + } + constexpr auto begin() const requires copyable<@*iterator*@> + { + return impl_.begin(); + } + + constexpr auto end() requires (!copyable<@*iterator*@>) + { + return impl_.end(); + } + constexpr auto end() const requires copyable<@*iterator*@> + { + return impl_.end(); + } + + constexpr bool empty() const { return impl_.empty(); } + + private: + @*to-utf-view-impl*@ impl_; + }; + + template + to_utf16_view(R&&) -> to_utf16_view>; + + template<@*from-utf-view*@ V> + class to_utf32_view { + private: + using @*iterator*@ = ranges::iterator_t<@*to-utf-view-impl*@>; + using @*sentinel*@ = ranges::sentinel_t<@*to-utf-view-impl*@>; + + public: + constexpr to_utf32_view() requires default_initializable = default; + constexpr to_utf32_view(V base) : impl_(move(base)) {} + + constexpr V base() const& requires copy_constructible + { + return impl_.base(); + } + constexpr V base() && { return move(impl_).base(); } + + constexpr auto begin() requires (!copyable<@*iterator*@>) + { + return impl_.begin(); + } + constexpr auto begin() const requires copyable<@*iterator*@> + { + return impl_.begin(); + } + + constexpr auto end() requires (!copyable<@*iterator*@>) + { + return impl_.end(); + } + constexpr auto end() const requires copyable<@*iterator*@> + { + return impl_.end(); + } + + constexpr bool empty() const { return impl_.empty(); } + + private: + @*to-utf-view-impl*@ impl_; + }; + + template + to_utf32_view(R&&) -> to_utf32_view>; + + template<@*code-unit-to*@ ToType> + inline constexpr @*unspecified*@ to_utf; + + inline constexpr @*unspecified*@ to_utf8; + + inline constexpr @*unspecified*@ to_utf16; + + inline constexpr @*unspecified*@ to_utf32; +} + +namespace std::ranges { + + template + inline constexpr bool enable_borrowed_range< + std::uc::@*to-utf-view-impl*@> = enable_borrowed_range; + + template + inline constexpr bool enable_borrowed_range> = enable_borrowed_range; + + template + inline constexpr bool enable_borrowed_range> = enable_borrowed_range; + + template + inline constexpr bool enable_borrowed_range> = enable_borrowed_range; + +} +``` + +The exposition-only concept `@*to-utf-view-iterator-optimizable*@` is true if +its template parameter is a specialization of `@*utf-iterator*@` and it is a +`@*std::ranges::bidirectional_iterator*@`. + +`@*to-utf-view-impl*@` is an exposition-only class that provides +implementation details common to the three transcoding views, `to_utf8_view`, +`to_utf16_view`, and `to_utf32_view`, which are themselves described further +down. + +The iterator type of `@*to-utf-view-impl*@` is +`@*utf-iterator*@`. `@*utf-iterator*@` is an iterator that transcodes from +UTF-N to UTF-M, where N and M are each one of 8, 16, or 32. N may equal +M. + +`@*utf-iterator*@` uses a mapping between character types and UTF encodings, +which is that that `char` and `char8_t` correspond to UTF-8, `char16_t` +corresponds to UTF-16, `char32_t` corresponds to UTF-32, and `wchar_t` +corresponds to UTF-16 if its size is two or UTF-32 if its size is 4. + +`@*utf-iterator*@` does its work by adapting an underlying range of code +units. We use the term "input subsequence" to refer to a potentially +ill-formed code unit subsequence which is to be transcoded into a code point +`c`. Each input subsequence is decoded from the UTF encoding corresponding to +`@*from-type*@`. If the underlying range contains ill-formed UTF, the code +units are divided into input subsequences according to Substitution of Maximal +Subparts, and each ill-formed input subsequence is transcoded into a +`U+FFFD`. `c` is then encoded to `ToType`'s corresponding encoding, into an +internal code unit buffer. + +`@*utf-iterator*@` maintains certain invariants; the invariants differ based +on whether `@*utf-iterator*@` is an input iterator. + +For input iterators the invariant is: if `*this` is at the end of the range +being adapted, then `curr()` == `last_`; otherwise, the position of `curr()` +is always at the end of the input subsequence corresponding to the current +code point `c`, and `buf_` contains the code units that comprise `c`, in the +UTF encoding corresponding to `ToType`. + +For forward and bidirectional iterators, the invariant is: if `*this` is at +the end of the range being adapted, then `curr()` == `last_`; otherwise, the +position of `curr()` is always at the beginning of the input subsequence +corresponding to the current code point `c` within the underlying range, +and `buf_` contains the code units in `ToFormat` that comprise `c`. + +The exposition-only member function `read` decodes the input subsequence +starting at position `curr()` into a code point `c`, using the UTF encoding +corresponding to `@*from-type*@`, and setting `c` to U+FFFD if the input +subsequence is ill-formed. If `c` is set to U+FFFD as the result of an +ill-formed input subsequence, it sets the error as described below. It sets +`to_increment_` to the number of code units read while decoding `c`; encodes +`c` into `buf_` in the UTF encoding corresponding to `ToType`; sets +`buf_index_` to `0`; and sets `buf_last_` to the number of code units encoded +into `buf_`. If `forward_iterator` is `true`, `curr()` is set to the +position it had before `read` was called. + +The exposition-only member function `read_reverse` decodes the input +subsequence ending at position `curr()` into a code point `c`, using the UTF +encoding corresponding to `@*from-type*@`, and setting `c` to U+FFFD if the +input subsequence is ill-formed. If `c` is set to U+FFFD as the result of an +ill-formed input subsequence, it sets the error as described below. It sets +`to_increment_` to the number of code units read while decoding `c`; encodes +`c` into `buf_` in the UTF encoding corresponding to `ToType`; sets +`buf_last_` to the number of code units encoded into `buf_`; and sets +`buf_index_` to `buf_last_ - 1`. + +In the following paragraph, `@*utf-error(foo)*@` refers to the result of the +exposition-only function: + +```cpp +expected @*utf-error-func*@(transcoding_error err) { + return unexpected{err}; +} +``` + +When the `@*utf-iterator*@` is at the end of the underlying range, `success()` +returns a default-constructed `expected`. When the +`@*utf-iterator*@` has a code unit, derived from a code point `c`, which is +itself derived from a particular input subsequence (the "current input +subsequence"), the result of the `success()` method corresponds to the +underlying range's input subsequences as follows. (All ranges of numerical +values of code units below are inclusive.) + +- If the encoding corresponding to `@*from-type*@` is UTF-8: + + - If the current input subsequence is valid UTF-8, `success()` returns + `expected{}`. + - If the current input subsequence is a code unit between 0x80 and 0xBF, + `success()` returns + `@*utf-error*@(transcoding_error::unexpected_utf8_continuation_byte)`. + - If the current input subsequence is a code unit between 0xC0 and 0xC2, or + between 0xF5 and 0xFF, `success()` returns + `@*utf-error*@(transcoding_error::invalid_utf8_leading_byte)`. + - If the current input subsequence is 0xE0, and the subsequent input + subsequence is between 0x80 and 0x9F; or if the current input subsequence + is 0xF0, and the subsequent input subsequence is between 0x80 and 0x8F; + then `success()` returns `@*utf-error*@(transcoding_error::overlong)`. + - If the current input subsequence is 0xED, and the subsequent input + subsequence is between 0xA0 and 0xBF, then `success()` returns + `@*utf-error*@(transcoding_error::encoded_surrogate)`. + - If the the current input subsequence is 0xF4, and the subsequent input + subsequence is between 0x90 and 0xBF, then `success()` returns + `@*utf-error*@(transcoding_error::out_of_range)` + - Otherwise, if the current input subsequence is invalid UTF-8, begins with + a code unit between 0xC2 and 0xF4, and there exists some hypothetical + sequence of code units which would make the current input subsequence + well-formed if concatenated to the end of it, `success()` returns + `@*utf-error*@(transcoding_error::truncated_utf8_sequence)`. + +- If the encoding corresponding to `@*from-type*@` is UTF-16: + + - If the current input subsequence is valid UTF-16, `success()` returns + `expected{}`. + - If the current input subsequence is between 0xD800 and 0xDBFF, `success()` + returns `@*utf-error*@(transcoding_error::unpaired_high_surrogate)`. + - If the current input subsequence is between 0xDC00 and 0xDFFF, `success()` + returns `@*utf-error*@(transcoding_error::unpaired_low_surrogate)`. + +- If the encoding corresponding to `@*from-type*@` is UTF-32: + + - If the current input subsequence is valid UTF-32, `success()` returns + `expected{}`. + - If the current input subsequence is between 0xD800 and 0xDFFF, `success()` + returns `@*utf-error*@(transcoding_error::encoded_surrogate)`. + - If the current input subsequence is between 0x110000 and 0xFFFFFFFF, + `success()` returns `@*utf-error*@(transcoding_error::out_of_range)`. + +`@*utf-iterator*@`'s exposition-only type alias `@*innermost-iter*@` is +`@*iter*@::@*innermost-iter*@` if `@*iter*@` is +`@*to_utf_view_iterator_optimizable*@`, or `@*iter*@` otherwise. The +exposition-only type alias `@*innermost-sent*@` is +`@*sent*@::@*innermost-sent*@` if `@*sent*@` is +`@*to_utf_view_iterator_optimizable*@`, or `@*sent*@` otherwise. + +If `@*utf-iterator*@` is a `bidirectional_iterator`, it is defined to be at +the beginning of its underlying range if `buf_index_` is zero and +`curr() == begin()`. If it is a `forward_iterator`, it is defined to be at the +end of its underlying range if `buf_index_ + 1 == buf_last_` and +`curr() == last_`. Otherwise, it is defined to be at the end of its underlying +range if `buf_index_ == buf_last_` and `curr() == last_`. + +If `operator*` is invoked while `@*utf-iterator*@` is at the end of its +underlying range, the behavior is erroneous and the result is +unspecified. Otherwise, `operator*` returns `buf_[buf_index_]`. + +If `operator++` is invoked while `@*utf-iterator*@` is at the end of its +underlying range, the behavior is erroneous and the iterator's state does not +change. If `operator--` is invoked while `@*utf-iterator*@` is at the +beginning of its underlying range, the behavior is erroneous and the +iterator's state does not change. + +`to_utf8_view` produces a UTF-8 view of the elements from a +`@*utf-range*@`. `to_utf16_view` produces a UTF-16 view of the elements from a +`@*utf-range*@`. `to_utf32_view` produces a UTF-32 view of the elements from a +`@*utf-range*@`. + +The names `to_utf8`, `to_utf16`, and `to_utf32` denote range adaptor objects +([range.adaptor.object]). `to_utf` denotes a range adaptor object +template. `to_utf8` produces `to_utf8_view`s, `to_utf16` produces +`to_utf16_view`s, and `to_utf32` produces `utf32_view`s. `to_utf` is +equivalent to `to_utf8` if `ToType` is `char8_t`, `to_utf16` if `ToType` is +`char16_t`, and `to_utf32` if `ToType` is `char32_t`. Let `to_utfN` denote any +one of `to_utf8`, `to_utf16`, and `to_utf32`, and let `V` denote the +`to_utfN_view` associated with that object. Let `E` be an expression and let +`T` be `remove_cvref_t`. If `decltype((E))` does not model +`@*utf-range*@`, `to_utfN(E)` is ill-formed. The expression `to_utfN(E)` is +expression-equivalent to: + +- If `T` is a specialization of `empty_view` ([range.empty.view]), then + `empty_view{}`. + +- Otherwise, if `T` is an array type of known bound, then: + + - If the array extent is nonzero and the last element of the array is zero, + then + `V(std::ranges::subrange(std::ranges::begin(E), --std::ranges::end(E)))` + - Otherwise, + `V(std::ranges::subrange(std::ranges::begin(E), std::ranges::end(E)))` + +- Otherwise, `V(std::views::all(E))` + +`utf_view`'s implementation of the `empty()` member function is more efficient +than the one provided by `view_interface`, since `view_interface`'s +implementation will construct `utf_view::begin()` and `utf_view::end()` and +compare them, whereas we can simply use the underlying range's `empty()`, +since a `utf_view` is empty if and only if its underlying range is empty. + +## Add code unit views and adaptors + +```c++ +namespace std::uc { + + template + consteval auto @*iterator-to-tag*@() { // @*exposition only*@ + if constexpr (random_access_iterator) { + return random_access_iterator_tag{}; + } else if constexpr (bidirectional_iterator) { + return bidirectional_iterator_tag{}; + } else if constexpr (forward_iterator) { + return forward_iterator_tag{}; + } else if constexpr (input_iterator) { + return input_iterator_tag{}; + } + } + + template + using @*iterator-to-tag-t*@ = decltype(@*iterator-to-tag*@()); // @*exposition only*@ + + template + concept @*convertible-to-charN-t-view*@ = @*code-unit-to*@ && ranges::view && convertible_to, ToType>; + + template<@*convertible-to-charN-t-view*@ V> + class as_char8_t_view : public ranges::view_interface> { + V base_ = V(); // @*exposition only*@ + + template + class @*iterator*@; // @*exposition only*@ + template + class @*sentinel*@; // @*exposition only*@ + + public: + constexpr as_char8_t_view() requires default_initializable = default; + constexpr as_char8_t_view(V base) : base_(move(base)) {} + + constexpr V& base() & { return base_; } + constexpr const V& base() const& requires copy_constructible + { + return base_; + } + constexpr V base() && { return move(base_); } + + constexpr @*iterator*@ begin() { return @*iterator*@{ranges::begin(base_)}; } + constexpr @*iterator*@ begin() const requires ranges::range + { + return @*iterator*@{ranges::begin(base_)}; + } + + constexpr @*sentinel*@ end() { return @*sentinel*@{ranges::end(base_)}; } + constexpr @*iterator*@ end() requires ranges::common_range + { + return @*iterator*@{ranges::end(base_)}; + } + constexpr @*sentinel*@ end() const requires ranges::range + { + return @*sentinel*@{ranges::end(base_)}; + } + constexpr @*iterator*@ end() const requires ranges::common_range + { + return @*iterator*@{ranges::end(base_)}; + } + + constexpr auto size() requires ranges::sized_range + { + return ranges::size(base_); + } + constexpr auto size() const requires ranges::sized_range + { + return ranges::size(base_); + } + }; + + template<@*convertible-to-charN-t-view*@ V> + template + class as_char8_t_view::@*iterator*@ + : public proxy_iterator_interface<@*iterator-to-tag-t*@>>, char8_t> { + public: + using reference_type = char8_t; + + private: + using @*iterator-type*@ = ranges::iterator_t<@*maybe-const*@>; // @*exposition only*@ + + friend access; + + constexpr @*iterator-type*@& base_reference() noexcept { return it_; } // @*exposition only*@ + constexpr @*iterator-type*@ base_reference() const { return it_; } // @*exposition only*@ + + @*iterator-type*@ it_ = @*iterator-type*@(); // @*exposition only*@ + + public: + constexpr @*iterator*@() = default; + constexpr @*iterator*@(@*iterator-type*@ it) : it_(move(it)) {} + + constexpr reference_type operator*() const { return *it_; } + }; + + template<@*convertible-to-charN-t-view*@ V> + template + class as_char8_t_view::@*sentinel*@ { + using @*base*@ = @*maybe-const*@; // @*exposition only*@ + using @*sentinel-type*@ = ranges::sentinel_t<@*base*@>; // @*exposition only*@ + + @*sentinel-type*@ end_ = @*sentinel-type*@(); // @*exposition only*@ + + public: + constexpr @*sentinel*@() = default; + constexpr explicit @*sentinel*@(@*sentinel-type*@ end) : end_(move(end)) {} + constexpr @*sentinel*@(@*sentinel*@ i) requires Const && convertible_to, ranges::sentinel_t<@*base*@>>; + + constexpr @*sentinel-type*@ base() const { return end_; } + + template + requires sentinel_for<@*sentinel-type*@, ranges::iterator_t<@*maybe-const*@>> + friend constexpr bool operator==(const @*iterator*@& x, const @*sentinel*@& y) { + return x.it_ == y.end_; + } + + template + requires sized_sentinel_for<@*sentinel-type*@, ranges::iterator_t<@*maybe-const*@>> + friend constexpr ranges::range_difference_t<@*maybe-const*@> operator-(const @*iterator*@& x, const @*sentinel*@& y) { + return x.it_ - y.end_; + } + + template + requires sized_sentinel_for<@*sentinel-type*@, ranges::iterator_t<@*maybe-const*@>> + friend constexpr ranges::range_difference_t<@*maybe-const*@> operator-(const @*sentinel*@& y, const @*iterator*@& x) { + return y.end_ - x.it_; + } + }; + + template + as_char8_t_view(R&&) -> as_char8_t_view>; + + template<@*convertible-to-charN-t-view*@ V> + class as_char16_t_view : public ranges::view_interface> { + V base_ = V(); // @*exposition only*@ + + template + class @*iterator*@; // @*exposition only*@ + template + class @*sentinel*@; // @*exposition only*@ + + public: + constexpr as_char16_t_view() requires default_initializable = default; + constexpr as_char16_t_view(V base) : base_(move(base)) {} + + constexpr V& base() & { return base_; } + constexpr const V& base() const& requires copy_constructible + { + return base_; + } + constexpr V base() && { return move(base_); } + + constexpr @*iterator*@ begin() { return @*iterator*@{ranges::begin(base_)}; } + constexpr @*iterator*@ begin() const requires ranges::range + { + return @*iterator*@{ranges::begin(base_)}; + } + + constexpr @*sentinel*@ end() { return @*sentinel*@{ranges::end(base_)}; } + constexpr @*iterator*@ end() requires ranges::common_range + { + return @*iterator*@{ranges::end(base_)}; + } + constexpr @*sentinel*@ end() const requires ranges::range + { + return @*sentinel*@{ranges::end(base_)}; + } + constexpr @*iterator*@ end() const requires ranges::common_range + { + return @*iterator*@{ranges::end(base_)}; + } + + constexpr auto size() requires ranges::sized_range + { + return ranges::size(base_); + } + constexpr auto size() const requires ranges::sized_range + { + return ranges::size(base_); + } + }; + + template<@*convertible-to-charN-t-view*@ V> + template + class as_char16_t_view::@*iterator*@ + : public proxy_iterator_interface<@*iterator-to-tag-t*@>>, char16_t> { + public: + using reference_type = char16_t; + + private: + using @*iterator-type*@ = ranges::iterator_t<@*maybe-const*@>; // @*exposition only*@ + + friend access; + + constexpr @*iterator-type*@& base_reference() noexcept { return it_; } // @*exposition only*@ + constexpr @*iterator-type*@ base_reference() const { return it_; } // @*exposition only*@ + + @*iterator-type*@ it_ = @*iterator-type*@(); // @*exposition only*@ + + public: + constexpr @*iterator*@() = default; + constexpr @*iterator*@(@*iterator-type*@ it) : it_(move(it)) {} + + constexpr reference_type operator*() const { return *it_; } + }; + + template<@*convertible-to-charN-t-view*@ V> + template + class as_char16_t_view::@*sentinel*@ { + using @*base*@ = @*maybe-const*@; // @*exposition only*@ + using @*sentinel-type*@ = ranges::sentinel_t<@*base*@>; // @*exposition only*@ + + @*sentinel-type*@ end_ = @*sentinel-type*@(); // @*exposition only*@ + + public: + constexpr @*sentinel*@() = default; + constexpr explicit @*sentinel*@(@*sentinel-type*@ end) : end_(move(end)) {} + constexpr @*sentinel*@(@*sentinel*@ i) requires Const && convertible_to, ranges::sentinel_t<@*base*@>>; + + constexpr @*sentinel-type*@ base() const { return end_; } + + template + requires sentinel_for<@*sentinel-type*@, ranges::iterator_t<@*maybe-const*@>> + friend constexpr bool operator==(const @*iterator*@& x, const @*sentinel*@& y) { + return x.it_ == y.end_; + } + + template + requires sized_sentinel_for<@*sentinel-type*@, ranges::iterator_t<@*maybe-const*@>> + friend constexpr ranges::range_difference_t<@*maybe-const*@> operator-(const @*iterator*@& x, const @*sentinel*@& y) { + return x.it_ - y.end_; + } + + template + requires sized_sentinel_for<@*sentinel-type*@, ranges::iterator_t<@*maybe-const*@>> + friend constexpr ranges::range_difference_t<@*maybe-const*@> operator-(const @*sentinel*@& y, const @*iterator*@& x) { + return y.end_ - x.it_; + } + }; + + template + as_char16_t_view(R&&) -> as_char16_t_view>; + + template<@*convertible-to-charN-t-view*@ V> + class as_char32_t_view : public ranges::view_interface> { + V base_ = V(); // @*exposition only*@ + + template + class @*iterator*@; // @*exposition only*@ + template + class @*sentinel*@; // @*exposition only*@ + + public: + constexpr as_char32_t_view() requires default_initializable = default; + constexpr as_char32_t_view(V base) : base_(move(base)) {} + + constexpr V& base() & { return base_; } + constexpr const V& base() const& requires copy_constructible + { + return base_; + } + constexpr V base() && { return move(base_); } + + constexpr @*iterator*@ begin() { return @*iterator*@{ranges::begin(base_)}; } + constexpr @*iterator*@ begin() const requires ranges::range + { + return @*iterator*@{ranges::begin(base_)}; + } + + constexpr @*sentinel*@ end() { return @*sentinel*@{ranges::end(base_)}; } + constexpr @*iterator*@ end() requires ranges::common_range + { + return @*iterator*@{ranges::end(base_)}; + } + constexpr @*sentinel*@ end() const requires ranges::range + { + return @*sentinel*@{ranges::end(base_)}; + } + constexpr @*iterator*@ end() const requires ranges::common_range + { + return @*iterator*@{ranges::end(base_)}; + } + + constexpr auto size() requires ranges::sized_range + { + return ranges::size(base_); + } + constexpr auto size() const requires ranges::sized_range + { + return ranges::size(base_); + } + }; + + template<@*convertible-to-charN-t-view*@ V> + template + class as_char32_t_view::@*iterator*@ + : public proxy_iterator_interface<@*iterator-to-tag-t*@>>, char32_t> { + public: + using reference_type = char32_t; + + private: + using @*iterator-type*@ = ranges::iterator_t<@*maybe-const*@>; // @*exposition only*@ + + friend access; + + constexpr @*iterator-type*@& base_reference() noexcept { return it_; } // @*exposition only*@ + constexpr @*iterator-type*@ base_reference() const { return it_; } // @*exposition only*@ + + @*iterator-type*@ it_ = @*iterator-type*@(); // @*exposition only*@ + + public: + constexpr @*iterator*@() = default; + constexpr @*iterator*@(@*iterator-type*@ it) : it_(move(it)) {} + + constexpr reference_type operator*() const { return *it_; } + }; + + template<@*convertible-to-charN-t-view*@ V> + template + class as_char32_t_view::@*sentinel*@ { + using @*base*@ = @*maybe-const*@; // @*exposition only*@ + using @*sentinel-type*@ = ranges::sentinel_t<@*base*@>; // @*exposition only*@ + + @*sentinel-type*@ end_ = @*sentinel-type*@(); // @*exposition only*@ + + public: + constexpr @*sentinel*@() = default; + constexpr explicit @*sentinel*@(@*sentinel-type*@ end) : end_(move(end)) {} + constexpr @*sentinel*@(@*sentinel*@ i) requires Const && convertible_to, ranges::sentinel_t<@*base*@>>; + + constexpr @*sentinel-type*@ base() const { return end_; } + + template + requires sentinel_for<@*sentinel-type*@, ranges::iterator_t<@*maybe-const*@>> + friend constexpr bool operator==(const @*iterator*@& x, const @*sentinel*@& y) { + return x.it_ == y.end_; + } + + template + requires sized_sentinel_for<@*sentinel-type*@, ranges::iterator_t<@*maybe-const*@>> + friend constexpr ranges::range_difference_t<@*maybe-const*@> operator-(const @*iterator*@& x, const @*sentinel*@& y) { + return x.it_ - y.end_; + } + + template + requires sized_sentinel_for<@*sentinel-type*@, ranges::iterator_t<@*maybe-const*@>> + friend constexpr ranges::range_difference_t<@*maybe-const*@> operator-(const @*sentinel*@& y, const @*iterator*@& x) { + return y.end_ - x.it_; + } + }; + + template + as_char32_t_view(R&&) -> as_char32_t_view>; + + inline constexpr @*unspecified*@ as_char8_t; + + inline constexpr @*unspecified*@ as_char16_t; + + inline constexpr @*unspecified*@ as_char32_t; + +} + +namespace std::ranges { + + template + inline constexpr bool enable_borrowed_range> = enable_borrowed_range; + + template + inline constexpr bool enable_borrowed_range> = enable_borrowed_range; + + template + inline constexpr bool enable_borrowed_range> = enable_borrowed_range; + +} +``` + +`char8_view` produces a view of `char8_t` elements from another view. +`char16_view` produces a view of `char16_t` elements from another view. +`char32_view` produces a view of `char32_t` elements from another view. Let +`charN_view` denote any one of the views `char8_view`, `char16_view`, and +`char32_view`. + +The names `as_char8_t`, `as_char16_t`, and `as_char32_t` denote range adaptor +objects ([range.adaptor.object]). `as_char8_t` produces `char8_view`s, +`as_char16_t` produces `char16_view`s, and `as_char32_t` produces +`char32_view`s. Let `as_charN_t` denote any one of `as_char8_t`, +`as_char16_t`, and `as_char32_t`, and let `V` denote the `charN_view` +associated with that object. Let `E` be an expression and let `T` be +`remove_cvref_t`. Let `F` be the `format` enumerator +associated with `as_charN_t`. If `decltype((E))` does not model +`utf_pointer` and if `charN_view(E)` is ill-formed, `as_charN_t(E)` is +ill-formed. The expression `as_charN_t(E)` is expression-equivalent to: + +- If `T` is a specialization of `empty_view` ([range.empty.view]), then + `empty_view<@*format-to-type-t*@>{}`. + +- Otherwise, if `T` is an array type of known bound, then: + + - If the array extent is nonzero and the last element of the array is zero, + then + `V(std::ranges::subrange(std::ranges::begin(E), --std::ranges::end(E)))` + - Otherwise, + `V(std::ranges::subrange(std::ranges::begin(E), std::ranges::end(E)))` + +- Otherwise, `V(std::views::all(E))`. + +\[Example 1: +```c++ +std::vector path_as_ints = {U'C', U':', U'\x00010000'}; +std::filesystem::path path = path_as_ints | as_char32_t | std::ranges::to(); +auto const& native_path = path.native(); +if (native_path != std::wstring{L'C', L':', L'\xD800', L'\xDC00'}) { + return false; +} +``` +โ€” end example\] + +## Why there are three `to_utfN_view`s views plus `utf_view`, and three `as_charN_t_view`s + +The views in `std::ranges` are constrained to accept only `std::ranges::view` +template parameters. However, they accept `std::ranges::viewable_range`s in +practice, because they each have a deduction guide that looks like this: + +```c++ +template +to_utf8_view(R &&) -> to_utf8_view>; +``` + +It's not possible to make this work for any view that's a template class that +accepts a template parameter other than the underlying view, because of the +all-or-nothing nature of deduction guides. So we need separate `to_utfN_view`s +and separate `as_charN_t_view`s instead of having them simply be alias +templates for a hypothetical generic `to_utf_view` or +`as_charN_t_view`, respectively. + +## Why `as_charN_t_view` is not implemented in terms of `transform_view` + +Because `transform_view` [cannot](https://stackoverflow.com/a/76789448) be a +`borrowed_range`, whereas `as_charN_t_view` can. + +[P3117](https://wg21.link/P3117R0) attempted to extend `transform_view` to be +conditionally borrowed, but its authors are not pursuing it further following +[concerns](https://github.com/cplusplus/papers/issues/1779#issuecomment-2014160066) +raised by SG9 in Tokyo 2024. + +A previous revision of this paper proposed for standardization a +`project_view` view that would be like `transform_view` except that the +transformation function would be an NTTP, enabling `project_view` to be a +`borrowed_range`. However, this was removed because the NTTP template +parameter prevents us from providing a `views::all_t` deduction guide as +described in the previous section. + +## Why `utf_view` always transcodes, even in UTF-N to UTF-N cases + +You might expect that if `r` in `r | to_utfN` is already in UTF-N, `r | +to_utfN` might just be `r`. This is not what the `to_utfN` adaptors do, +though. + +The adaptors each produce a view `utfv` that stores a view of type +`V`. Further, `utfv.begin()` is always a specialization of +`@*utf-iterator*@`. `utfv.end()` is also a specialization of +`@*utf-iterator*@` (if `common_range`), or otherwise the sentinel value for +`V`. + +This gives `r | to_utfN` some nice, consistent properties. With the +exception of `empty_view{} | to_utfN`, the following are always true: + +- `r | to_utfN` produces well-formed UTF. This is true even when the input was + already UTF-N. Remember, the input could have been UTF-N but had ill-formed + UTF in it. + +- `r | to_utfN` has a consistent API. If `r | to_utfN` were sometimes `r`, + and since `r` may be a reference to an array, you'd have to use + `std::ranges::begin(r)` and `::end(r)` all the time. However, you'd + probably write `r.begin()` and `r.end()`, only to one day get bitten by an + array-reference `r`. + +## Add a feature test macro + +Add the feature test macro `__cpp_lib_unicode_transcoding`. + +## Relevant Polls/Minutes + +### SG16 review of P2728R7 on 2023-09-13 (Telecon) + +- [Minutes](https://github.com/sg16-unicode/sg16-meetings/blob/master/README-2023.md#september-13th-2023) + +No polls were taken during this review. + +### SG16 review of P2728R6 on 2023-08-23 (Telecon) + +- [Minutes](https://github.com/sg16-unicode/sg16-meetings/blob/master/README-2023.md#august-23rd-2023) + +No polls were taken during this review. + +### SG9 review of [D2728R4](https://isocpp.org/files/papers/D2728R4.html) on 2023-06-12 during Varna 2023 + +- [Minutes](https://wiki.edg.com/bin/view/Wg21varna/P2728#SG9-2023-06-12) + +__POLL:__ Move null_sentinel_t to std:: namespace + +|SF|F|N|A|SA| +|-|-|-|-|-| +|1|3|1|0|0| + +__# Of Authors:__ 1 + +__Author's Position:__ F + +__Attendance:__ 9 (4 abstentions) + +__Outcome:__ Consensus in favor + +
+ +__POLL:__ Remove null_sentinel_t::base member function from the proposal + +|SF|F|N|A|SA| +|-|-|-|-|-| +|0|4|1|0|0| + +__# Of Authors:__ 1 + +__Author's Position:__ F + +__Attendance:__ 8 (3 abstentions) + +__Outcome:__ Consensus in favor + +
+ +__POLL:__ utf_iterator should be a separate type and not nested within utf_view + +|SF|F|N|A|SA| +|-|-|-|-|-| +|1|2|1|0|1| + +__Attendance:__ 8 (3 abstentions) + +__# of Authors:__ 1 + +__Author Position:__ F + +__Outcome:__ Weak consensus in favor + +SA: Having a separate type complexifies the API + +### SG16 review of P2728R3 on 2023-05-10 (Telecon) + +- [Minutes](https://github.com/sg16-unicode/sg16-meetings/blob/master/README-2023.md#may-10th-2023) + +__POLL:__ Separate `std::null_sentinel_t` from P2728 into a separate paper for +SG9 and LEWG; SG16 does not need to see it again. + ++----+---+---+---+----+ +| SF | F | N | A | SA | ++====+===+===+===+====+ +| 1 |1 |4 |2 | 1 | ++----+---+---+---+----+ + +__Attendance:__ 12 (3 abstentions) + +__Outcome:__ No consensus; author's discretion for how to continue. + +### SG16 review of P2728R0 on 2023-04-12 (Telecon) + +- [Minutes](https://github.com/sg16-unicode/sg16-meetings/blob/master/README-2023.md#april-12th-2023) + +__POLL:__ SG16 would like to see a version of P2728 without eager algorithms. + ++----+---+---+---+----+ +| SF | F | N | A | SA | ++====+===+===+===+====+ +| 4 |2 |0 |1 | 0 | ++----+---+---+---+----+ + +__Attendance:__ 10 (3 abstentions) + +__Outcome:__ Consensus in favor + +
+ +__POLL:__ UTF transcoding interfaces provided by the C++ standard library should +operate on charN_t types, with support for other types provided by adapters, +possibly with a special case for char and wchar_t when their associated +literal encodings are UTF. + ++----+---+---+---+----+ +| SF | F | N | A | SA | ++====+===+===+===+====+ +| 5 |1 |0 |0 | 1 | ++----+---+---+---+----+ + +__Attendance:__ 9 (2 abstentions) + +__Outcome:__ Strong consensus in favor + +Author's note: More commentary on this poll is provided in the section "Discussion of +whether transcoding views should accept ranges of `char` and `wchar_t`". But +note here that the authors doubt the viability of "a special case for char and +wchar_t when their associated literal encodings are UTF", since making the +evaluation of a concept change based on the literal encoding seems like a +flaky move; the literal encoding can change TU to TU. + +### SG16 review of P2728R0 on 2023-03-22 (Telecon) + +- [Minutes](https://github.com/sg16-unicode/sg16-meetings/blob/master/README-2023.md#march-22nd-2023) + +No polls were taken during this review. + +
+ +__POLL:__ `char32_t` should be used as the Unicode code point type within the +C++ standard library implementations of Unicode algorithms. + ++----+---+---+---+----+ +| SF | F | N | A | SA | ++====+===+===+===+====+ +| 6 |0 |1 |0 | 0 | ++----+---+---+---+----+ + +__Attendance:__ 9 (2 abstentions) + +__Outcome:__ Strong consensus in favor + +# Implementation experience + +The most recent revision of this paper has a reference implementation called +[UtfView](https://github.com/ednolan/utfview) available on GitHub, which is a +fork of Jonathan Wakely's implementation of P2728R6 as an implementation +detail for libstdc++. + +Versions of the interfaces provided by previous revisions of this paper have +also been implemented, and re-implemented, several times over the last 5 years +or so, as part of a proposed (but not yet accepted!) Boost library, +[Boost.Text](https://github.com/tzlaine/text). Boost.Text has hundreds of +stars on GitHub. + +Both libraries have comprehensive tests. + +# Appendix: Implementing Existing Practice for Error Handling + +## `iconv` + +This function transcodes until it finds an invalid or truncated sequence, +erroring out if so and distinguishing those two cases using errno. It uses an +out-parameter to point to the beginning of the invalid sequence. + +``` +struct iconv_t {}; + +// For the sake of simplicity, this iconv only converts between UTF-8 and UTF-32. +size_t iconv(iconv_t cd, const char** inbuf, size_t* inbytesleft, char** outbuf, + size_t* outbytesleft) { + if (!inbuf) { + return 0; + } + if (inbuf && !*inbuf) { + return 0; + } + assert(inbytesleft); + assert(outbuf); + assert(*outbuf); + assert(outbytesleft); + auto view = std::ranges::subrange(*inbuf, *inbuf + *inbytesleft) | std::uc::to_utf32; + for (auto it = std::ranges::begin(view), end = std::ranges::end(view); it != end;) { + if (it.success()) { + if (*outbytesleft < sizeof(char32_t)) { + errno = E2BIG; + return static_cast(-1); + } + char32_t c = *it; + (*outbuf)[0] = static_cast((c >> 24) & 0xFF); + (*outbuf)[1] = static_cast((c >> 16) & 0xFF); + (*outbuf)[2] = static_cast((c >> 8) & 0xFF); + (*outbuf)[3] = static_cast(c & 0xFF); + *outbuf += sizeof(char32_t); + *outbytesleft -= sizeof(char32_t); + ++it; + std::size_t bytes_converted = it.base() - *inbuf; + *inbytesleft -= bytes_converted; + *inbuf = it.base(); + } else { + transcoding_error e = it.success().error(); + switch (e) { + case transcoding_error::truncated_utf8_sequence: { + errno = EINVAL; + } break; + case transcoding_error::unexpected_utf8_continuation_byte: + case transcoding_error::overlong: + case transcoding_error::encoded_surrogate: + case transcoding_error::out_of_range: + case transcoding_error::invalid_utf8_leading_byte: { + errno = EILSEQ; + } break; + case transcoding_error::unpaired_high_surrogate: + case transcoding_error::unpaired_low_surrogate: { + std::unreachable(); + } + } + return static_cast(-1); + } + } + return 0; +} +``` + +## ICU `u_strFromUTF8WithSub` + +This function transcodes until it finds an invalid sequence and if it does, it +supports either erroring out or producing a substitution character of the +user's choice. It also supports pre-flighting to determine the required output +buffer size, and relying on null termination if the user doesn't supply the +size of the input buffer. + +``` +constexpr char16_t* u_strFromUTF8WithSub( + char16_t* dest, int32_t destCapacity, int32_t* pDestLength, + const char* src, int32_t srcLength, char32_t subchar, + int32_t* pNumSubstitutions, UErrorCode* pErrorCode) { + if (*pErrorCode != U_ZERO_ERROR) { + return nullptr; + } + if ((src == nullptr && srcLength != 0) || srcLength < -1 || (destCapacity < 0) || + (dest == nullptr && destCapacity > 0) || subchar > 0x10ffff || + (0xD800 <= subchar && subchar <= 0xDFFF)) { + *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; + return nullptr; + } + + if (pNumSubstitutions != nullptr) { + *pNumSubstitutions = 0; + } + + auto impl = + [&](auto view) { + auto end = std::ranges::end(view); + if (pDestLength) { + *pDestLength = 0; + for (auto it = std::ranges::begin(view); it != end; ++it) { + *pDestLength += it.success() ? 1 : (subchar > 0xFFFF ? 2 : 1); + } + } + if (destCapacity == 0) { + return dest; + } + char16_t* out_ptr = dest; + for (auto it = std::ranges::begin(view); it != end; ++it) { + auto write = + [&](char16_t c) { + *out_ptr = c; + ++out_ptr; + --destCapacity; + }; + if (it.success()) { + if (destCapacity == 0) { + return dest; + } + write(*it); + } else { + if (subchar == -1) { + *pErrorCode = U_INVALID_CHAR_FOUND; + return dest; + } else { + ++*pNumSubstitutions; + if (subchar > 0xFFFF) { + std::array subchar_utf16{}; + std::ranges::copy(std::array{subchar} | std::uc::to_utf16, subchar_utf16.data()); + write(subchar_utf16[0]); + if (destCapacity == 0) { + return dest; + } + write(subchar_utf16[1]); + } else { + write(static_cast(subchar)); + } + } + } + } + if (destCapacity > 0) { + *out_ptr = char16_t{}; + } + return dest; + }; + + if (srcLength == -1) { + return impl(std::null_term(src) | std::uc::to_utf16); + } else { + return impl(std::ranges::subrange(src, src + srcLength) | std::uc::to_utf16); + } +} +``` + +## Windows `MultiByteToWideChar` + +This function transcodes until it finds an invalid sequence. If it does, it +will error out if the user provides a flag; if this flag is not provided, the +behavior depends on the OS. Before Windows Vista, it simply drops the invalid +sequences; afterwards, it substitutes with U+FFFD. It also supports +pre-flighting to determine the required output buffer size, and relying on +null termination if the user doesn't supply the size of the input buffer. + +``` +constexpr int MultiByteToWideChar(unsigned int CodePage, unsigned long dwFlags, + const char* lpMultiByteStr, int cbMultiByte, + wchar_t* lpWideCharStr, int cchWideChar) { + (void)CodePage; // For simplicity we only implement CP_UTF8 + auto impl = [&](auto view) { + auto end = std::ranges::end(view); + if (cchWideChar == 0) { +#ifdef WINDOWS_XP + int chars = 0; + for (auto it = std::ranges::begin(view); it != end; ++it) { + chars += it.success() ? 1 : 0; + } + return chars; +#else + return static_cast(std::ranges::distance(view)); +#endif + } else { + wchar_t* out_ptr = lpWideCharStr; + for (auto it = std::ranges::begin(view); it != end; ++it) { + auto write = + [&](auto c) { + *out_ptr = static_cast(c); + ++out_ptr; + --cchWideChar; + }; + if (it.success()) { + if (cchWideChar == 0) { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return 0; + } + write(*it); + } else { + if (dwFlags == MB_ERR_INVALID_CHARS) { + SetLastError(ERROR_NO_UNICODE_TRANSLATION); + return 0; + } +#ifndef WINDOWS_XP + if (cchWideChar == 0) { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return 0; + } + write(*it); +#endif + } + } + return static_cast(out_ptr - lpWideCharStr); + } + }; + if (cbMultiByte == -1) { + if constexpr (sizeof(wchar_t) == 2) { + return impl(std::null_term(lpMultiByteStr) | std::uc::to_utf16); + } else { + return impl(std::null_term(lpMultiByteStr) | std::uc::to_utf32); + } + } else { + if constexpr (sizeof(wchar_t) == 2) { + return impl(std::ranges::subrange(lpMultiByteStr, lpMultiByteStr + cbMultiByte) | + std::uc::to_utf16); + } else { + return impl(std::ranges::subrange(lpMultiByteStr, lpMultiByteStr + cbMultiByte) | + std::uc::to_utf32); + } + } +} +``` + +## Python `decode()` + +This is a C++ analog of Python's `decode` function. It accepts a +`std::basic_string_view`, transcodes it from UTF-8, returns a new transcoded +`std::basic_string`, and throws an exception if it encounters invalid UTF +which explains the problem and provides the position of the offending +sequence. + +``` +template +std::basic_string decode(std::basic_string_view input) { + std::basic_string result; + result.reserve(input.size()); // like what size_hint does + auto view = input | to_utf; + for (auto it = std::ranges::begin(view), end = std::ranges::end(view); it != end; + ++it) { + if (it.success()) { + result.push_back(*it); + } else { + auto pos_curr = it.base() - input.begin(); + auto it2 = it; + auto pos_next = (++it2).base() - input.begin(); + std::ostringstream ss; + ss << "can't decode "; + if (pos_next > pos_curr + 1) { + ss << "characters"; + } else { + ss << "character 0x" << std::hex + << static_cast(static_cast(*it.base())) + << std::dec; + } + ss << " in position " << pos_curr; + if (pos_next > pos_curr + 1) { + ss << "-" << pos_next - 1; + } + ss << ": "; + ss << [&] { + switch (it.success().error()) { + case transcoding_error::truncated_utf8_sequence: + return "unexpected end of data"; + case transcoding_error::unpaired_high_surrogate: + case transcoding_error::unpaired_low_surrogate: + return "illegal UTF-16 surrogate"; + case transcoding_error::unexpected_utf8_continuation_byte: + case transcoding_error::invalid_utf8_leading_byte: + return "invalid start byte"; + case transcoding_error::encoded_surrogate: + if constexpr (std::same_as) { + return "code point in surrogate code point range(0xd800, 0xe000)"; + } + case transcoding_error::overlong: + if constexpr (std::same_as) { + return "code point not in range(0x110000)"; + } + case transcoding_error::out_of_range: + return "invalid continuation byte"; + } + std::unreachable(); + }(); + throw std::runtime_error(std::move(ss).str()); + } + } + return result; +} +``` + +# Special Thanks + +Zach Laine, for writing revisions one through six of the paper and implementing Boost.Text. + +Jonathan Wakely, for implementing P2728R6, and design guidance. + +Robert Leahy, for extensive design guidance including suggesting the error handling approach introduced in R7. + +Gaลกper Aลพman, for suggesting the use of `std::expected`. diff --git a/paper/generator/.clang-format b/paper/generator/.clang-format new file mode 100644 index 0000000..85282fd --- /dev/null +++ b/paper/generator/.clang-format @@ -0,0 +1,28 @@ +BasedOnStyle: WebKit +ColumnLimit: 200 +AlwaysBreakTemplateDeclarations: Yes +AlignAfterOpenBracket: Align +AllowShortFunctionsOnASingleLine: All +BreakConstructorInitializers: AfterColon +Cpp11BracedListStyle: True +SpaceBeforeCpp11BracedList: False +BreakBeforeBraces: Attach +AllowShortEnumsOnASingleLine: False +BreakStringLiterals: False +AlwaysBreakAfterReturnType: None +PenaltyReturnTypeOnItsOwnLine: 200 +ContinuationIndentWidth: 2 +IndentWidth: 2 +BreakBeforeBinaryOperators: None +IndentAccessModifiers: False +AccessModifierOffset: -2 +NamespaceIndentation: All +SpaceAfterTemplateKeyword: False +PackConstructorInitializers: NextLine +AlignTrailingComments: Leave +RequiresClausePosition: WithPreceding +IndentRequiresClause: True +SpaceBeforeParens: Custom +SpaceBeforeParensOptions: + AfterRequiresInClause: True + AfterRequiresInExpression: True diff --git a/paper/generator/generator.sh b/paper/generator/generator.sh new file mode 100755 index 0000000..846888c --- /dev/null +++ b/paper/generator/generator.sh @@ -0,0 +1,33 @@ +#/usr/bin/env bash + +set -euo pipefail + +set -x + +declare generator_script_dir=$(dirname $BASH_SOURCE) + +function process_file() { + local file="$1"; shift + local build_dir="$1" ; shift + cp $generator_script_dir/../../$file $build_dir + local file_copy=$build_dir/${file##*/} + clang-format-19 -i -style=file $file_copy + $generator_script_dir/post_clang_format.py $file_copy > ${file_copy}.md + rm $file_copy +} + +function main() { + local files=( + include/UtfView/code_unit_view.hpp + include/UtfView/detail/concepts.hpp + include/UtfView/null_term.hpp + include/UtfView/to_utf_view.hpp) + local build_dir=$generator_script_dir/build + mkdir $build_dir + cp $generator_script_dir/.clang-format $build_dir + for file in ${files[@]} ; do + process_file "$file" "$build_dir" + done +} + +main "$@" diff --git a/paper/generator/post_clang_format.py b/paper/generator/post_clang_format.py new file mode 100755 index 0000000..d2c46a2 --- /dev/null +++ b/paper/generator/post_clang_format.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 + +import re +import sys + +def convert_snake_to_kebab(text): + def snake_to_kebab(match): + word = match.group(0) + word = word.replace('exposition_only_', '', 1) + kebab_case_word = word.replace('_', '-') + return f"@*{kebab_case_word}*@" + + pattern = r'\bexposition_only_[a-zA-Z_]+\b' + result = re.sub(pattern, snake_to_kebab, text) + return result + + +def process_file(file_path): + in_paper_section = False + result_lines = [] + + with open(file_path, 'r') as file: + for line in file: + line = convert_snake_to_kebab(line); + if "/* PAPER: " in line: + result_lines.append(line[line.find("/* PAPER:") + len("/* PAPER: "):-4]) + result_lines.append("\n") + continue + + line = line.replace("std::", "") + line = line.replace("detail::", "") + line = line.replace("boost::stl_interfaces::", "") + line = line.replace("CONSTEXPR_UNLESS_MSVC", "constexpr") + + if "/* !PAPER */" in line: + in_paper_section = False + continue + elif "/* PAPER */" in line: + in_paper_section = True + continue + + if in_paper_section: + result_lines.append(line) + + return result_lines + +if __name__ == "__main__": + if len(sys.argv) != 2: + print("Usage: python post_clang_format.py ") + sys.exit(1) + + file_path = sys.argv[1] + + processed_lines = process_file(file_path) + + for line in processed_lines: + print(line, end="") diff --git a/src/UtfView/CMakeLists.txt b/src/UtfView/CMakeLists.txt new file mode 100644 index 0000000..fcc213c --- /dev/null +++ b/src/UtfView/CMakeLists.txt @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: GPL-3.0-only + +add_library(utfview INTERFACE) + +include(GNUInstallDirs) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +target_include_directories( + utfview + INTERFACE + $ + $ # /include/utfview +) + +target_link_libraries(utfview INTERFACE boost_stl_interfaces) + +install( + TARGETS utfview + EXPORT ${TARGETS_EXPORT_NAME} + DESTINATION ${CMAKE_INSTALL_LIBDIR}) + +install( + DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${CMAKE_PROJECT_NAME} + FILES_MATCHING + PATTERN "*.hpp") + +# Tests +if(BUILD_TESTING) + add_subdirectory(tests) +endif() diff --git a/src/UtfView/tests/CMakeLists.txt b/src/UtfView/tests/CMakeLists.txt new file mode 100644 index 0000000..dff39c2 --- /dev/null +++ b/src/UtfView/tests/CMakeLists.txt @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-3.0-only + +add_library( + utfview_test_lib + STATIC + code_unit_view.t.cpp + detail/concepts.t.cpp + framework.cpp + null_term.t.cpp + readme_examples.t.cpp + std_archetypes/exposition_only.t.cpp + std_archetypes/iterator.t.cpp + to_utf_view.t.cpp) + +target_link_libraries(utfview_test_lib utfview) + +add_executable( + utfview_test + main.t.cpp) + +target_link_libraries(utfview_test "$") + +add_test(NAME utfview_test COMMAND utfview_test) diff --git a/src/UtfView/tests/code_unit_view.t.cpp b/src/UtfView/tests/code_unit_view.t.cpp new file mode 100644 index 0000000..54078fe --- /dev/null +++ b/src/UtfView/tests/code_unit_view.t.cpp @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-3.0-only + +#include +#include +#include +#include +#include + +namespace utfview::tests { + +// TODO: Comprehensive testing for `code_unit_view` + +constexpr bool smoke_test() { + std::string_view foo{"foo"}; + auto bar{foo | as_char8_t}; + static_assert(std::ranges::borrowed_range); + auto baz{bar | std::ranges::to()}; + if (baz != std::u8string_view{u8"foo"}) { + return false; + } + return true; +} + +CONSTEXPR_UNLESS_MSVC bool code_unit_view_test() { + if (!smoke_test()) { + return false; + } + return true; +} + +#ifndef _MSC_VER +static_assert(code_unit_view_test()); +#endif + +static auto const init{[] { + framework::tests().insert({"code_unit_view_test", &code_unit_view_test}); + struct { + } result{}; + return result; +}()}; + +} // namespace utfview::tests diff --git a/src/UtfView/tests/detail/concepts.t.cpp b/src/UtfView/tests/detail/concepts.t.cpp new file mode 100644 index 0000000..8256bb6 --- /dev/null +++ b/src/UtfView/tests/detail/concepts.t.cpp @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-3.0-only + +#include +#include + +namespace utfview::tests { + +static_assert(exposition_only_code_unit_to); +static_assert(exposition_only_code_unit_to); +static_assert(exposition_only_code_unit_to); +static_assert(!exposition_only_code_unit_to); +static_assert(!exposition_only_code_unit_to); +static_assert(!exposition_only_code_unit_to); + +static_assert(exposition_only_code_unit_from); +static_assert(exposition_only_code_unit_from); +static_assert(exposition_only_code_unit_from); +static_assert(exposition_only_code_unit_from); +static_assert(exposition_only_code_unit_from); +static_assert(!exposition_only_code_unit_from); + +// todo: utf_range + +} // namespace utfview::detail::tests diff --git a/src/UtfView/tests/framework.cpp b/src/UtfView/tests/framework.cpp new file mode 100644 index 0000000..82ed583 --- /dev/null +++ b/src/UtfView/tests/framework.cpp @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-3.0-only + +#include +#include +#include + +namespace utfview::tests { + +namespace framework { + + std::map>& tests() { + static std::map> result{}; + return result; + } + +} // namespace framework + +} // namespace utfview::tests diff --git a/src/UtfView/tests/framework.hpp b/src/UtfView/tests/framework.hpp new file mode 100644 index 0000000..bf3278f --- /dev/null +++ b/src/UtfView/tests/framework.hpp @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-3.0-only + +#ifndef UTFVIEW_TESTS_FRAMEWORK_HPP +#define UTFVIEW_TESTS_FRAMEWORK_HPP + +#include +#include +#include + +namespace utfview::tests { + +namespace framework { + + std::map>& tests(); + +} // namespace framework + +} // namespace utfview::tests + +#endif // UTFVIEW_TESTS_FRAMEWORK_HPP diff --git a/src/UtfView/tests/main.t.cpp b/src/UtfView/tests/main.t.cpp new file mode 100644 index 0000000..d68b77b --- /dev/null +++ b/src/UtfView/tests/main.t.cpp @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-3.0-only + +#include +#include +#include + +int main() { + for (auto& [test_name, test] : utfview::tests::framework::tests()) { + if (!test()) { + std::cerr << test_name << " failed"; + return EXIT_FAILURE; + } + } +} diff --git a/src/UtfView/tests/null_term.t.cpp b/src/UtfView/tests/null_term.t.cpp new file mode 100644 index 0000000..1a76815 --- /dev/null +++ b/src/UtfView/tests/null_term.t.cpp @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-3.0-only + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace utfview::tests { + +static_assert(std::default_initializable< + std::iter_value_t>); +static_assert(std::equality_comparable_with< + std::iter_reference_t, + std::iter_value_t>); +static_assert( + std::sentinel_for); +static_assert(std::default_initializable< + std::iter_value_t>); +static_assert(std::equality_comparable_with< + std::iter_reference_t, + std::iter_value_t>); +static_assert( + std::sentinel_for); + +constexpr bool null_sentinel_input_iterator_test() { + int total = 0; + std_archetypes::input_iterator_archetype it{254}; + for (auto x : null_term(std::move(it))) { + total += x.x; + } + return total == 254 + 255; +} + +constexpr bool null_sentinel_forward_iterator_test() { + int total = 0; + std_archetypes::forward_iterator_archetype it{254}; + for (auto x : null_term(it)) { + total += x.x; + } + return total == 254 + 255; +} + +static_assert(null_sentinel_input_iterator_test()); +static_assert(null_sentinel_forward_iterator_test()); + +} // namespace utfview::tests diff --git a/src/UtfView/tests/readme_examples.t.cpp b/src/UtfView/tests/readme_examples.t.cpp new file mode 100644 index 0000000..c9e89f9 --- /dev/null +++ b/src/UtfView/tests/readme_examples.t.cpp @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: GPL-3.0-only + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace utfview::tests { + +template +std::basic_string sanitize(CharT const* str) { + return null_term(str) | to_utf | std::ranges::to>(); +} + +std::optional last_nonascii(std::ranges::view auto str) { + for (auto c : str | to_utf32 | std::views::reverse | + std::views::filter([](char32_t c) { return c > 0x7f; }) | + std::views::take(1)) { + return c; + } + return std::nullopt; +} + +#ifdef _MSC_VER +bool windows_path() { + std::vector path_as_ints = {U'C', U':', U'\x00010000'}; + std::filesystem::path path = + path_as_ints | as_char32_t | std::ranges::to(); + auto const& native_path = path.native(); + if (native_path != std::wstring{L'C', L':', L'\xD800', L'\xDC00'}) { + return false; + } + return true; +} +#endif + +std::u8string as_char32_t_example() { + auto get_icu_code_points = [] { return std::vector{0x1F574, 0xFFFD}; }; + std::vector input = get_icu_code_points(); + // This is ill-formed without the as_char32_t adaptation. + auto input_utf8 = input | as_char32_t | to_utf8 | std::ranges::to(); + return input_utf8; +} + +std::string enum_to_string(transcoding_error ec) { + switch (ec) { + case transcoding_error::truncated_utf8_sequence: + return "truncated_utf8_sequence"; + case transcoding_error::unpaired_high_surrogate: + return "unpaired_high_surrogate"; + case transcoding_error::unpaired_low_surrogate: + return "unpaired_low_surrogate"; + case transcoding_error::unexpected_utf8_continuation_byte: + return "unexpected_utf8_continuation_byte"; + case transcoding_error::overlong: + return "overlong"; + case transcoding_error::encoded_surrogate: + return "encoded_surrogate"; + case transcoding_error::out_of_range: + return "out_of_range"; + case transcoding_error::invalid_utf8_leading_byte: + return "invalid_utf8_leading_byte"; + } + std::unreachable(); +} + +template +std::basic_string transcode_or_throw(std::basic_string_view input) { + std::basic_string result; + auto view = input | to_utf; + for (auto it = view.begin(), end = view.end(); it != end; ++it) { + if (it.success()) { + result.push_back(*it); + } else { + throw std::runtime_error("error at position " + + std::to_string(it.base() - input.begin()) + ": " + + enum_to_string(it.success().error())); + } + } + return result; +} + +template +using transcode_result = std::ranges::in_out_result; + +template S, std::output_iterator O> +transcode_result transcode_to_utf32(I first, S last, O out) { + auto r = std::ranges::subrange(first, last) | to_utf32; + + auto copy_result = std::ranges::copy(r, out); + + return transcode_result{copy_result.in.base(), copy_result.out}; +} + +bool transcode_to_utf32_test() { + std::u8string_view char8_string{u8"\xf0\x9f\x95\xb4\xef\xbf\xbd"}; + to_utf16_view utf16_transcoding_view{char8_string}; + std::u32string char32_string{}; + auto transcode_result{transcode_to_utf32(utf16_transcoding_view.begin(), + utf16_transcoding_view.end(), + std::back_insert_iterator{char32_string})}; + auto expected_in_it{utf16_transcoding_view.begin()}; + std::ranges::advance(expected_in_it, 3); + if (expected_in_it != transcode_result.in) { + return false; + } + return true; +} + +bool readme_examples() { + using namespace std::string_view_literals; +#ifndef _MSC_VER + std::u32string hello_world = + u8"ใ“ใ‚“ใซใกใฏไธ–็•Œ" | to_utf32 | std::ranges::to(); + if (hello_world != U"ใ“ใ‚“ใซใกใฏไธ–็•Œ") { + return false; + } + if (sanitize(u8"\xc2") != u8"\xef\xbf\xbd") { + return false; + } + if (last_nonascii("hรดtel"sv).value() != U'รด') { + return false; + } + if (as_char32_t_example() != u8"\xf0\x9f\x95\xb4\xef\xbf\xbd") { + return false; + } + auto foo = transcode_or_throw(u8"\xf0\x9f\x95\xb4\xef\xbf\xbd"); + auto bar = std::u32string{U"\x0001F574\uFFFD"}; + if (foo != bar) { + return false; + } + try { + transcode_or_throw(u8"\xc3\xa9\xff"); + return false; + } catch (std::exception const& e) { + if (e.what() != "error at position 2: invalid_utf8_leading_byte"sv) { + return false; + } + } + if (!transcode_to_utf32_test()) { + return false; + } +#else + if (!windows_path()) { + return false; + } +#endif + return true; +} + +static auto const init{[] { + framework::tests().insert({"readme_examples", &readme_examples}); + struct { + } result{}; + return result; +}()}; + +} // namespace utfview::tests diff --git a/src/UtfView/tests/std_archetypes/exposition_only.hpp b/src/UtfView/tests/std_archetypes/exposition_only.hpp new file mode 100644 index 0000000..ddfa0cb --- /dev/null +++ b/src/UtfView/tests/std_archetypes/exposition_only.hpp @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-3.0-only + +#ifndef UTFVIEW_TESTS_STD_ARCHETYPES_EXPOSITION_ONLY_HPP +#define UTFVIEW_TESTS_STD_ARCHETYPES_EXPOSITION_ONLY_HPP + +namespace utfview::tests::std_archetypes { + +class boolean_testable_archetype2; + +class boolean_testable_archetype1 { +public: + constexpr explicit boolean_testable_archetype1(bool inner_in) + : inner_{inner_in} { } + constexpr operator bool() const noexcept { + return inner_; + } + constexpr boolean_testable_archetype2 operator!() const noexcept; + +private: + bool inner_; +}; + +class boolean_testable_archetype2 { +public: + constexpr explicit boolean_testable_archetype2(bool inner_in) + : inner_{inner_in} { } + constexpr operator bool() const noexcept { + return inner_; + } + constexpr boolean_testable_archetype1 operator!() const noexcept { + return boolean_testable_archetype1{!inner_}; + } + +private: + bool inner_; +}; + +constexpr boolean_testable_archetype2 boolean_testable_archetype1::operator!() + const noexcept { + return boolean_testable_archetype2{inner_}; +} + +} // namespace utfview::tests::std_archetypes + +#endif // UTFVIEW_TESTS_STD_ARCHETYPES_EXPOSITION_ONLY_HPP diff --git a/src/UtfView/tests/std_archetypes/exposition_only.t.cpp b/src/UtfView/tests/std_archetypes/exposition_only.t.cpp new file mode 100644 index 0000000..7f805f0 --- /dev/null +++ b/src/UtfView/tests/std_archetypes/exposition_only.t.cpp @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-3.0-only + +#include + +namespace utfview::tests::std_archetypes { + +#if defined(_GLIBCXX_VERSION_INCLUDED) || defined(_LIBCPP_VERSION) +static_assert(__boolean_testable); +static_assert(__boolean_testable); +#endif + +} // namespace utfview::tests::std_archetypes diff --git a/src/UtfView/tests/std_archetypes/iterator.hpp b/src/UtfView/tests/std_archetypes/iterator.hpp new file mode 100644 index 0000000..f8946fa --- /dev/null +++ b/src/UtfView/tests/std_archetypes/iterator.hpp @@ -0,0 +1,203 @@ +// SPDX-License-Identifier: GPL-3.0-only + +#ifndef UTFVIEW_TESTS_STD_ARCHETYPES_ITERATOR_HPP +#define UTFVIEW_TESTS_STD_ARCHETYPES_ITERATOR_HPP + +#include +#include +#include +#include +#include + +namespace utfview::tests::std_archetypes { + +#ifdef _MSC_VER +// https://developercommunity.visualstudio.com/t/MSVC-fails-to-resolve-operator-overloa/10560905 +using boolean_testable_archetype = bool; +#else +using boolean_testable_archetype = boolean_testable_archetype1; +#endif + +namespace detail { + + template + struct reference_type_archetype; + + template + struct value_type_archetype { + constexpr value_type_archetype() + : x{} { } + constexpr value_type_archetype(reference_type_archetype const& ref); + value_type_archetype(value_type_archetype const&) = default; + value_type_archetype& operator=(value_type_archetype const&) = default; + value_type_archetype(value_type_archetype&&) = default; + value_type_archetype& operator=(value_type_archetype&&) = default; + constexpr boolean_testable_archetype operator==( + value_type_archetype const& other) const { + return boolean_testable_archetype{x == other.x}; + } + constexpr boolean_testable_archetype operator!=( + value_type_archetype const& other) const { + return boolean_testable_archetype{x != other.x}; + } + State x; + }; + + template + struct reference_type_archetype { + constexpr boolean_testable_archetype operator==( + value_type_archetype const& value) const { + return boolean_testable_archetype{x == value.x}; + } + constexpr boolean_testable_archetype operator!=( + value_type_archetype const& value) const { + return boolean_testable_archetype{x != value.x}; + } + State const& x; + }; + + template + constexpr value_type_archetype::value_type_archetype( + reference_type_archetype const& ref) + : x{ref.x} { } + +} // namespace detail + +template , + typename ReferenceType = detail::reference_type_archetype> +struct basic_input_iterator_archetype { + using value_type = ValueType; + using reference_type = ReferenceType; + using difference_type = std::ptrdiff_t; + using iterator_concept = std::input_iterator_tag; + constexpr explicit basic_input_iterator_archetype(State x_in) + : x{std::move(x_in)} { } + basic_input_iterator_archetype(basic_input_iterator_archetype const&) = delete; + basic_input_iterator_archetype& operator=(basic_input_iterator_archetype const&) = + delete; + basic_input_iterator_archetype(basic_input_iterator_archetype&&) = default; + basic_input_iterator_archetype& operator=(basic_input_iterator_archetype&&) = default; + constexpr reference_type operator*() const { + return reference_type{x}; + } + constexpr basic_input_iterator_archetype& operator++() { + ++x; + return *this; + } + constexpr void operator++(int) { + ++x; + } + State x; +}; + +using input_iterator_archetype = basic_input_iterator_archetype; + +template , + typename ReferenceType = detail::reference_type_archetype> +struct basic_forward_iterator_archetype { + using value_type = ValueType; + using reference_type = ReferenceType; + using difference_type = std::ptrdiff_t; + using iterator_concept = std::forward_iterator_tag; + constexpr basic_forward_iterator_archetype() + : x{} { } + constexpr explicit basic_forward_iterator_archetype(State x_in) + : x{std::move(x_in)} { } + basic_forward_iterator_archetype(basic_forward_iterator_archetype const&) = default; + basic_forward_iterator_archetype& operator=(basic_forward_iterator_archetype const&) = + default; + basic_forward_iterator_archetype(basic_forward_iterator_archetype&&) = default; + basic_forward_iterator_archetype& operator=(basic_forward_iterator_archetype&&) = + default; + + constexpr reference_type operator*() const { + return reference_type{x}; + } + constexpr basic_forward_iterator_archetype& operator++() { + ++x; + return *this; + } + constexpr basic_forward_iterator_archetype operator++(int) { + basic_forward_iterator_archetype result{*this}; + ++x; + return result; + } + + friend boolean_testable_archetype operator==( + basic_forward_iterator_archetype const& lhs, + basic_forward_iterator_archetype const& rhs) { + return boolean_testable_archetype{lhs.x == rhs.x}; + } + friend boolean_testable_archetype operator!=( + basic_forward_iterator_archetype const& lhs, + basic_forward_iterator_archetype const& rhs) { + return boolean_testable_archetype{lhs.x != rhs.x}; + } + + State x; +}; + +using forward_iterator_archetype = basic_forward_iterator_archetype; + +template , + typename ReferenceType = detail::reference_type_archetype> +struct basic_bidirectional_iterator_archetype { + using value_type = ValueType; + using reference_type = ReferenceType; + using difference_type = std::ptrdiff_t; + using iterator_concept = std::bidirectional_iterator_tag; + constexpr basic_bidirectional_iterator_archetype() + : x{} { } + constexpr explicit basic_bidirectional_iterator_archetype(State x_in) + : x{std::move(x_in)} { } + basic_bidirectional_iterator_archetype(basic_bidirectional_iterator_archetype const&) = + default; + basic_bidirectional_iterator_archetype& operator=( + basic_bidirectional_iterator_archetype const&) = default; + basic_bidirectional_iterator_archetype(basic_bidirectional_iterator_archetype&&) = + default; + basic_bidirectional_iterator_archetype& operator=( + basic_bidirectional_iterator_archetype&&) = default; + + constexpr reference_type operator*() const { + return reference_type{x}; + } + constexpr basic_bidirectional_iterator_archetype& operator++() { + ++x; + return *this; + } + constexpr basic_bidirectional_iterator_archetype operator++(int) { + basic_bidirectional_iterator_archetype result{*this}; + ++x; + return result; + } + constexpr basic_bidirectional_iterator_archetype& operator--() { + --x; + return *this; + } + constexpr basic_bidirectional_iterator_archetype operator--(int) { + basic_bidirectional_iterator_archetype result{*this}; + --x; + return result; + } + + friend boolean_testable_archetype operator==( + basic_bidirectional_iterator_archetype const& lhs, + basic_bidirectional_iterator_archetype const& rhs) { + return boolean_testable_archetype{lhs.x == rhs.x}; + } + friend boolean_testable_archetype operator!=( + basic_bidirectional_iterator_archetype const& lhs, + basic_bidirectional_iterator_archetype const& rhs) { + return boolean_testable_archetype{lhs.x != rhs.x}; + } + + State x; +}; + +using bidirectional_iterator_archetype = + basic_bidirectional_iterator_archetype; + +} // namespace utfview::tests::std_archetypes + +#endif // UTFVIEW_TESTS_STD_ARCHETYPES_ITERATOR_HPP diff --git a/src/UtfView/tests/std_archetypes/iterator.t.cpp b/src/UtfView/tests/std_archetypes/iterator.t.cpp new file mode 100644 index 0000000..e53f273 --- /dev/null +++ b/src/UtfView/tests/std_archetypes/iterator.t.cpp @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-3.0-only + +#include +#include + +namespace utfview::tests::std_archetypes { + +static_assert(std::input_iterator); +static_assert(std::input_iterator>); +static_assert(std::forward_iterator); +static_assert(std::forward_iterator>); +static_assert(std::bidirectional_iterator); +static_assert(std::bidirectional_iterator>); + +} // namespace utfview::tests::std_archetypes diff --git a/src/UtfView/tests/to_utf_view.t.cpp b/src/UtfView/tests/to_utf_view.t.cpp new file mode 100644 index 0000000..c35f456 --- /dev/null +++ b/src/UtfView/tests/to_utf_view.t.cpp @@ -0,0 +1,1901 @@ +// SPDX-License-Identifier: GPL-3.0-only + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace utfview::tests { + +template +struct test_input_iterator { + using value_type = CharT; + using reference_type = CharT const&; + using difference_type = std::ptrdiff_t; + using iterator_concept = std::input_iterator_tag; + constexpr explicit test_input_iterator(std::initializer_list const& list) + : begin{list.begin()}, + end{list.end()} { } + test_input_iterator(test_input_iterator const&) = delete; + test_input_iterator& operator=(test_input_iterator const&) = delete; + test_input_iterator(test_input_iterator&&) = default; + test_input_iterator& operator=(test_input_iterator&&) = default; + constexpr reference_type operator*() const { + return *begin; + } + constexpr test_input_iterator& operator++() { + ++begin; + return *this; + } + constexpr void operator++(int) { + ++begin; + } + + friend constexpr bool operator==(std::default_sentinel_t const&, + test_input_iterator const& rhs) { + return rhs.begin == rhs.end; + } + + std::initializer_list::iterator begin; + std::initializer_list::iterator end; +}; + +template +test_input_iterator(std::initializer_list) -> test_input_iterator; + +static_assert(std::input_iterator>); + +template +struct test_comparable_input_iterator { + using value_type = CharT; + using reference_type = CharT const&; + using difference_type = std::ptrdiff_t; + using iterator_concept = std::input_iterator_tag; + constexpr explicit test_comparable_input_iterator( + std::initializer_list const& list) + : begin{list.begin()}, + end{list.end()} { } + test_comparable_input_iterator(test_comparable_input_iterator const&) = delete; + test_comparable_input_iterator& operator=(test_comparable_input_iterator const&) = + delete; + test_comparable_input_iterator(test_comparable_input_iterator&&) = default; + test_comparable_input_iterator& operator=(test_comparable_input_iterator&&) = default; + constexpr reference_type operator*() const { + return *begin; + } + constexpr test_comparable_input_iterator& operator++() { + ++begin; + return *this; + } + constexpr void operator++(int) { + ++begin; + } + + friend constexpr bool operator==(std::default_sentinel_t const&, + test_comparable_input_iterator const& rhs) { + return rhs.begin == rhs.end; + } + + friend constexpr bool operator==(test_comparable_input_iterator const&, + test_comparable_input_iterator const&) = default; + + std::initializer_list::iterator begin; + std::initializer_list::iterator end; +}; + +template +test_comparable_input_iterator(std::initializer_list) + -> test_comparable_input_iterator; + +static_assert(std::input_iterator>); + +template +struct test_copyable_input_iterator { + static constexpr std::initializer_list empty{}; + + using value_type = CharT; + using reference_type = CharT const&; + using difference_type = std::ptrdiff_t; + using iterator_concept = std::input_iterator_tag; + constexpr test_copyable_input_iterator() + : begin{empty.begin()}, + end{empty.end()} { } + constexpr explicit test_copyable_input_iterator( + std::initializer_list const& list) + : begin{list.begin()}, + end{list.end()} { } + test_copyable_input_iterator(test_copyable_input_iterator const&) = default; + test_copyable_input_iterator& operator=(test_copyable_input_iterator const&) = default; + test_copyable_input_iterator(test_copyable_input_iterator&&) = default; + test_copyable_input_iterator& operator=(test_copyable_input_iterator&&) = default; + constexpr reference_type operator*() const { + return *begin; + } + constexpr test_copyable_input_iterator& operator++() { + ++begin; + return *this; + } + constexpr void operator++(int) { + ++begin; + } + + friend constexpr bool operator==(std::default_sentinel_t const&, + test_copyable_input_iterator const& rhs) { + return rhs.begin == rhs.end; + } + + friend constexpr bool operator==(test_copyable_input_iterator const&, + test_copyable_input_iterator const&) = default; + + std::initializer_list::iterator begin; + std::initializer_list::iterator end; +}; + +template +test_copyable_input_iterator(std::initializer_list) + -> test_copyable_input_iterator; + +static_assert(std::input_iterator>); +static_assert(!std::forward_iterator>); + +template +struct test_forward_iterator { + static constexpr std::initializer_list empty{}; + + using value_type = CharT; + using reference_type = CharT const&; + using difference_type = std::ptrdiff_t; + using iterator_concept = std::forward_iterator_tag; + constexpr test_forward_iterator() + : begin{empty.begin()}, + end{empty.end()} { } + constexpr explicit test_forward_iterator(std::initializer_list const& list) + : begin{list.begin()}, + end{list.end()} { } + test_forward_iterator(test_forward_iterator const&) = default; + test_forward_iterator& operator=(test_forward_iterator const&) = default; + test_forward_iterator(test_forward_iterator&&) = default; + test_forward_iterator& operator=(test_forward_iterator&&) = default; + constexpr reference_type operator*() const { + return *begin; + } + constexpr test_forward_iterator& operator++() { + ++begin; + return *this; + } + constexpr test_forward_iterator operator++(int) { + auto ret = *this; + ++begin; + return ret; + } + + friend constexpr bool operator==(std::default_sentinel_t const&, + test_forward_iterator const& rhs) { + return rhs.begin == rhs.end; + } + + friend constexpr bool operator==(test_forward_iterator const&, + test_forward_iterator const&) = default; + + std::initializer_list::iterator begin; + std::initializer_list::iterator end; +}; + +template +test_forward_iterator(std::initializer_list) -> test_forward_iterator; + +static_assert(std::forward_iterator>); + +template +struct test_bidi_iterator { + static constexpr std::initializer_list empty{}; + + using value_type = CharT; + using reference_type = CharT const&; + using difference_type = std::ptrdiff_t; + using iterator_concept = std::bidirectional_iterator_tag; + constexpr test_bidi_iterator() + : begin{empty.begin()}, + end{empty.end()} { } + constexpr explicit test_bidi_iterator(std::initializer_list const& list) + : begin{list.begin()}, + end{list.end()} { } + test_bidi_iterator(test_bidi_iterator const&) = default; + test_bidi_iterator& operator=(test_bidi_iterator const&) = default; + test_bidi_iterator(test_bidi_iterator&&) = default; + test_bidi_iterator& operator=(test_bidi_iterator&&) = default; + constexpr reference_type operator*() const { + return *begin; + } + constexpr test_bidi_iterator& operator++() { + ++begin; + return *this; + } + constexpr test_bidi_iterator operator++(int) { + auto ret = *this; + ++begin; + return ret; + } + constexpr test_bidi_iterator& operator--() { + --begin; + return *this; + } + constexpr test_bidi_iterator operator--(int) { + auto ret = *this; + --begin; + return ret; + } + + friend constexpr bool operator==(std::default_sentinel_t const&, + test_bidi_iterator const& rhs) { + return rhs.begin == rhs.end; + } + friend constexpr bool operator==(test_bidi_iterator const&, + test_bidi_iterator const&) = default; + + std::initializer_list::iterator begin; + std::initializer_list::iterator end; +}; + +template +test_bidi_iterator(std::initializer_list) -> test_bidi_iterator; + +static_assert(std::bidirectional_iterator>); + +template +struct test_case_code_unit_result { + CharT code_unit; + std::expected success; +}; + +template +struct test_case { + std::initializer_list input; + std::initializer_list> output; +}; + +CONSTEXPR_UNLESS_MSVC test_case table3_8{ + .input{static_cast('\xc0'), static_cast('\xaf'), + static_cast('\xe0'), static_cast('\x80'), + static_cast('\xbf'), static_cast('\xf0'), + static_cast('\x81'), static_cast('\x82'), + static_cast('A')}, + .output{{U'\uFFFD', std::unexpected{transcoding_error::invalid_utf8_leading_byte}}, + {U'\uFFFD', + std::unexpected{transcoding_error::unexpected_utf8_continuation_byte}}, + {U'\uFFFD', std::unexpected{transcoding_error::overlong}}, + {U'\uFFFD', + std::unexpected{transcoding_error::unexpected_utf8_continuation_byte}}, + {U'\uFFFD', + std::unexpected{transcoding_error::unexpected_utf8_continuation_byte}}, + {U'\uFFFD', std::unexpected{transcoding_error::overlong}}, + {U'\uFFFD', + std::unexpected{transcoding_error::unexpected_utf8_continuation_byte}}, + {U'\uFFFD', + std::unexpected{transcoding_error::unexpected_utf8_continuation_byte}}, + {U'A', {}}}}; + +CONSTEXPR_UNLESS_MSVC test_case table3_9{ + .input{static_cast('\xed'), static_cast('\xa0'), + static_cast('\x80'), static_cast('\xed'), + static_cast('\xbf'), static_cast('\xbf'), + static_cast('\xed'), static_cast('\xaf'), + static_cast('A')}, + .output{{U'\uFFFD', std::unexpected{transcoding_error::encoded_surrogate}}, + {U'\uFFFD', + std::unexpected{transcoding_error::unexpected_utf8_continuation_byte}}, + {U'\uFFFD', + std::unexpected{transcoding_error::unexpected_utf8_continuation_byte}}, + {U'\uFFFD', std::unexpected{transcoding_error::encoded_surrogate}}, + {U'\uFFFD', + std::unexpected{transcoding_error::unexpected_utf8_continuation_byte}}, + {U'\uFFFD', + std::unexpected{transcoding_error::unexpected_utf8_continuation_byte}}, + {U'\uFFFD', std::unexpected{transcoding_error::encoded_surrogate}}, + {U'\uFFFD', + std::unexpected{transcoding_error::unexpected_utf8_continuation_byte}}, + {U'A', {}}}}; + +CONSTEXPR_UNLESS_MSVC test_case table3_10{ + .input{static_cast('\xf4'), static_cast('\x91'), + static_cast('\x92'), static_cast('\x93'), + static_cast('\xff'), static_cast('\x41'), + static_cast('\x80'), static_cast('\xbf'), + static_cast('B')}, + .output{{U'\uFFFD', std::unexpected{transcoding_error::out_of_range}}, + {U'\uFFFD', + std::unexpected{transcoding_error::unexpected_utf8_continuation_byte}}, + {U'\uFFFD', + std::unexpected{transcoding_error::unexpected_utf8_continuation_byte}}, + {U'\uFFFD', + std::unexpected{transcoding_error::unexpected_utf8_continuation_byte}}, + {U'\uFFFD', std::unexpected{transcoding_error::invalid_utf8_leading_byte}}, + {U'A', {}}, + {U'\uFFFD', + std::unexpected{transcoding_error::unexpected_utf8_continuation_byte}}, + {U'\uFFFD', + std::unexpected{transcoding_error::unexpected_utf8_continuation_byte}}, + {U'B', {}}}}; + +CONSTEXPR_UNLESS_MSVC test_case table3_11{ + .input{static_cast('\xe1'), static_cast('\x80'), + static_cast('\xe2'), static_cast('\xf0'), + static_cast('\x91'), static_cast('\x92'), + static_cast('\xf1'), static_cast('\xbf'), + static_cast('A')}, + .output{{U'\uFFFD', std::unexpected{transcoding_error::truncated_utf8_sequence}}, + {U'\uFFFD', std::unexpected{transcoding_error::truncated_utf8_sequence}}, + {U'\uFFFD', std::unexpected{transcoding_error::truncated_utf8_sequence}}, + {U'\uFFFD', std::unexpected{transcoding_error::truncated_utf8_sequence}}, + {U'A', {}}}}; + +CONSTEXPR_UNLESS_MSVC test_case two_byte{ + .input{static_cast('\xc2'), static_cast('\xa0')}, + .output{{U'\u00A0', {}}}}; + +CONSTEXPR_UNLESS_MSVC test_case two_byte_truncated_by_end{ + .input{static_cast('\xc2')}, + .output{{U'\uFFFD', std::unexpected{transcoding_error::truncated_utf8_sequence}}}}; + +CONSTEXPR_UNLESS_MSVC test_case two_byte_truncated_by_non_continuation{ + .input{static_cast('\xc2'), static_cast('A')}, + .output{{U'\uFFFD', std::unexpected{transcoding_error::truncated_utf8_sequence}}, + {U'A', {}}}}; + +CONSTEXPR_UNLESS_MSVC test_case three_byte{ + .input{static_cast('\xe4'), static_cast('\xba'), + static_cast('\xba')}, + .output{{U'\u4EBA', {}}}}; + +CONSTEXPR_UNLESS_MSVC test_case three_byte_truncated_at_third_by_end{ + .input{static_cast('\xe4'), static_cast('\xba')}, + .output{{U'\uFFFD', std::unexpected{transcoding_error::truncated_utf8_sequence}}}}; + +CONSTEXPR_UNLESS_MSVC test_case + four_byte_truncated_at_second_by_non_continuation{ + .input{static_cast('\xf0'), static_cast('A')}, + .output{{U'\uFFFD', std::unexpected{transcoding_error::truncated_utf8_sequence}}, + {U'A', {}}}}; + +CONSTEXPR_UNLESS_MSVC test_case four_byte_truncated_at_third_by_end{ + .input{static_cast('\xf0'), static_cast('\x90')}, + .output{{U'\uFFFD', std::unexpected{transcoding_error::truncated_utf8_sequence}}}}; + +CONSTEXPR_UNLESS_MSVC test_case four_byte_truncated_at_fourth_by_end{ + .input{static_cast('\xf0'), static_cast('\x90'), + static_cast('\x80')}, + .output{{U'\uFFFD', std::unexpected{transcoding_error::truncated_utf8_sequence}}}}; + +CONSTEXPR_UNLESS_MSVC test_case single_high{ + .input{u'\xD800'}, + .output{{U'\uFFFD', std::unexpected{transcoding_error::unpaired_high_surrogate}}}}; + +CONSTEXPR_UNLESS_MSVC test_case + surrogate_pair_truncated_by_non_low_surrogate{ + .input{u'\xD800', u'A'}, + .output{{U'\uFFFD', std::unexpected{transcoding_error::unpaired_high_surrogate}}, + {U'A', {}}}}; + +CONSTEXPR_UNLESS_MSVC test_case single_low{ + .input{u'\xDC00'}, + .output{{U'\uFFFD', std::unexpected{transcoding_error::unpaired_low_surrogate}}}}; + +CONSTEXPR_UNLESS_MSVC test_case surrogates{ + .input{u'\xD800', u'\xDC00'}, .output{{U'\U00010000', {}}}}; + +CONSTEXPR_UNLESS_MSVC test_case nonsurrogates{ + .input{u'X', u'Y', u'Z'}, .output{{U'X', {}}, {U'Y', {}}, {U'Z', {}}}}; + +CONSTEXPR_UNLESS_MSVC test_case encoded_surrogate{ + .input{U'\x0000DC00'}, + .output{{U'\uFFFD', std::unexpected{transcoding_error::encoded_surrogate}}}}; + +CONSTEXPR_UNLESS_MSVC test_case out_of_range{ + .input{U'\x00110000'}, + .output{{U'\uFFFD', std::unexpected{transcoding_error::out_of_range}}}}; + +CONSTEXPR_UNLESS_MSVC test_case valid_utf8_identity{ + .input{static_cast('A'), static_cast('\xc2'), + static_cast('\xa0'), static_cast('\xe4'), + static_cast('\xba'), static_cast('\xba'), + static_cast('\xf0'), static_cast('\x90'), + static_cast('\x80'), static_cast('\x80')}, + .output{{static_cast('A'), {}}, + {static_cast('\xc2'), {}}, + {static_cast('\xa0'), {}}, + {static_cast('\xe4'), {}}, + {static_cast('\xba'), {}}, + {static_cast('\xba'), {}}, + {static_cast('\xf0'), {}}, + {static_cast('\x90'), {}}, + {static_cast('\x80'), {}}, + {static_cast('\x80'), {}}}}; + +CONSTEXPR_UNLESS_MSVC test_case valid_utf8_char_identity{ + .input{'A', '\xc2', '\xa0', '\xe4', '\xba', '\xba', '\xf0', '\x90', '\x80', '\x80'}, + .output{{static_cast('A'), {}}, + {static_cast('\xc2'), {}}, + {static_cast('\xa0'), {}}, + {static_cast('\xe4'), {}}, + {static_cast('\xba'), {}}, + {static_cast('\xba'), {}}, + {static_cast('\xf0'), {}}, + {static_cast('\x90'), {}}, + {static_cast('\x80'), {}}, + {static_cast('\x80'), {}}}}; + +CONSTEXPR_UNLESS_MSVC test_case valid_utf16_identity{ + .input{u'A', u'\xD800', u'\xDC00'}, + .output{{u'A', {}}, {u'\xD800', {}}, {u'\xDC00', {}}}}; + +CONSTEXPR_UNLESS_MSVC test_case valid_utf16_wchar_identity{ + .input{L'A', L'\x4EBA'}, .output{{u'A', {}}, {u'\x4EBA', {}}}}; + +CONSTEXPR_UNLESS_MSVC test_case valid_utf32_identity{ + .input{U'X', U'Y', U'Z'}, .output{{U'X', {}}, {U'Y', {}}, {U'Z', {}}}}; + +CONSTEXPR_UNLESS_MSVC test_case four_continuations{ + .input{static_cast('\xf0'), static_cast('\x90'), + static_cast('\x80'), static_cast('\x80'), + static_cast('\x80')}, + .output{{U'\x00010000', {}}, + {U'\uFFFD', + std::unexpected{transcoding_error::unexpected_utf8_continuation_byte}}}}; + +CONSTEXPR_UNLESS_MSVC test_case two_low_surrogates{ + .input{u'\xD800', u'\xDC00', u'\xDC00'}, + .output{{U'\x00010000', {}}, + {U'\uFFFD', std::unexpected{transcoding_error::unpaired_low_surrogate}}}}; + +CONSTEXPR_UNLESS_MSVC test_case ff_at_end{ + .input{static_cast('\xc3'), static_cast('\xa9'), + static_cast('\xff')}, + .output{{U'\u00E9', {}}, + {U'\uFFFD', std::unexpected{transcoding_error::invalid_utf8_leading_byte}}}}; + +template +constexpr bool run_test_case_impl(test_case test_case) { + auto view{[&] { + auto it{WrappingIterator(test_case.input)}; + if constexpr (!std::copyable) { + std::ranges::subrange subrange{std::move(it), std::default_sentinel}; + return std::move(subrange) | to_utf; + } else { + auto end{WrappingIterator(test_case.input)}; + while (end != std::default_sentinel) { + ++end; + } + std::ranges::subrange subrange{it, end}; + return subrange | to_utf; + } + }()}; + { + auto output_it{test_case.output.begin()}; + auto view_it{view.begin()}; + auto end{view.end()}; + do { + if (*view_it != output_it->code_unit) { + return false; + } + if (view_it.success() != output_it->success) { + return false; + } + ++output_it; + ++view_it; + } while (view_it != end); + } + if constexpr (std::copyable) { + auto output_it{test_case.output.begin()}; + auto view_it{view.begin()}; + auto end{view.begin()}; + while (end != view.end()) { + ++end; + } + do { + if (*view_it != output_it->code_unit) { + return false; + } + if (view_it.success() != output_it->success) { + return false; + } + ++output_it; + ++view_it; + } while (view_it != end); + } + if constexpr (std::bidirectional_iterator) { + auto it2{WrappingIterator(test_case.input)}; + auto end2{view.end().base()}; + std::ranges::subrange subrange2{it2, end2}; + auto view2{std::move(subrange2) | to_utf}; + { + auto view_it{view2.end()}; + auto output_it{test_case.output.end()}; + auto end{view2.begin()}; + do { + --view_it; + --output_it; + if (*view_it != output_it->code_unit) { + return false; + } + if (view_it.success() != output_it->success) { + return false; + } + } while (view_it != end); + } + } + return true; +} + +template +constexpr bool run_test_case(test_case test_case) { + return run_test_case_impl>(test_case) && + run_test_case_impl>(test_case) && + run_test_case_impl>(test_case) && + run_test_case_impl>(test_case); +} + +template +constexpr bool input_iterator_test(std::initializer_list const single_arr) { + test_input_iterator single_begin(single_arr); + std::ranges::subrange subrange{std::move(single_begin), std::default_sentinel}; + auto single_view{to_utf32_view(std::move(subrange))}; + std::u32string single_u32{single_view | std::ranges::to()}; + if (single_u32.size() != 1 || single_u32.at(0) != U'x') { + return false; + } + return true; +} + +template +constexpr bool forward_iterator_test(std::initializer_list const single_arr) { + test_forward_iterator single_begin(single_arr); + std::ranges::subrange subrange{std::move(single_begin), std::default_sentinel}; + auto single_view{to_utf32_view(std::move(subrange))}; + std::u32string single_u32{single_view | std::ranges::to()}; + if (single_u32.size() != 1 || single_u32.at(0) != U'x') { + return false; + } + return true; +} + +template +constexpr bool bidi_iterator_test(std::initializer_list const single_arr) { + test_bidi_iterator single_begin(single_arr); + std::ranges::subrange subrange{std::move(single_begin), std::default_sentinel}; + auto single_view{to_utf32_view(std::move(subrange))}; + using single_view_iter_type = decltype(single_view.begin()); + std::u32string single_u32{single_view | std::ranges::to()}; + if (single_u32.size() != 1 || single_u32.at(0) != U'x') { + return false; + } + return true; +} + +template +constexpr bool double_encode_test(std::initializer_list const single_arr) { + test_forward_iterator single_begin(single_arr); + std::ranges::subrange subrange{std::move(single_begin), std::default_sentinel}; + auto single_view{to_utf32_view(std::move(subrange))}; + auto double_encoded_view{to_utf8_view(std::move(single_view))}; + std::u8string single_u8{double_encoded_view | std::ranges::to()}; + if (single_u8.size() != 1 || single_u8.at(0) != U'x') { + return false; + } + return true; +} + +constexpr bool utf_iterator_base_test() { + std::initializer_list arr{u8'b', u8'a', u8'r'}; + { + test_forward_iterator it_begin(arr); + std::ranges::subrange subrange{std::move(it_begin), std::default_sentinel}; + auto single_encoded_view = subrange | to_utf16; + auto iter = single_encoded_view.begin(); + ++iter; + if (*iter.base() != u8'a') { + return false; + } + } + { + test_forward_iterator it_begin(arr); + std::ranges::subrange subrange{std::move(it_begin), std::default_sentinel}; + auto double_encoded_view = subrange | to_utf16 | to_utf32; + auto iter = double_encoded_view.begin(); + ++iter; + if (*iter != U'a') { + return false; + } + if (*iter.base() != u'a') { + return false; + } + } + { + test_bidi_iterator it_begin(arr); + std::ranges::subrange subrange{std::move(it_begin), std::default_sentinel}; + auto double_encoded_view = subrange | to_utf16 | to_utf32; + auto iter = double_encoded_view.begin(); + ++iter; + if (*iter != U'a') { + return false; + } + if (*iter.base() != u'a') { + return false; + } + } + return true; +} + +constexpr bool post_increment_decrement_test() { + std::initializer_list arr{u8'x'}; + { + test_input_iterator it_begin(arr); + std::ranges::subrange subrange{std::move(it_begin), std::default_sentinel}; + auto single_encoded_view = std::move(subrange) | to_utf16; + auto iter = single_encoded_view.begin(); + if (*iter != u'x') { + return false; + } + static_assert(std::is_same_v); + iter++; + if (iter != std::default_sentinel) { + return false; + } + } + { + test_bidi_iterator it_begin(arr); + std::ranges::subrange subrange{std::move(it_begin), std::default_sentinel}; + auto single_encoded_view = subrange | to_utf16; + auto iter = single_encoded_view.begin(); + if (*iter != u'x') { + return false; + } + auto inc_result = iter++; + if (inc_result != single_encoded_view.begin()) { + return false; + } + if (iter != std::default_sentinel) { + return false; + } + auto dec_result = iter--; + if (dec_result != std::default_sentinel) { + return false; + } + if (iter != single_encoded_view.begin()) { + return false; + } + } + return true; +} + +static bool past_the_end_increment_eb_test() { + std::initializer_list arr{u8'x'}; + { + test_input_iterator it_begin(arr); + std::ranges::subrange subrange{std::move(it_begin), std::default_sentinel}; + auto single_encoded_view = std::move(subrange) | to_utf16; + auto iter = single_encoded_view.begin(); + if (*iter != u'x') { + return false; + } + ++iter; + if (detail::erroneous_behavior_global()) { + return false; + } + ++iter; + if (!detail::erroneous_behavior_global()) { + return false; + } + detail::erroneous_behavior_global() = false; + } + { + test_forward_iterator it_begin(arr); + std::ranges::subrange subrange{std::move(it_begin), std::default_sentinel}; + auto single_encoded_view = subrange | to_utf16; + auto iter = single_encoded_view.begin(); + if (*iter != u'x') { + return false; + } + ++iter; + if (detail::erroneous_behavior_global()) { + return false; + } + ++iter; + if (!detail::erroneous_behavior_global()) { + return false; + } + detail::erroneous_behavior_global() = false; + } + return true; +} + +static bool past_the_end_dereference_eb_test() { + std::initializer_list arr{u8'x'}; + { + test_input_iterator it_begin(arr); + std::ranges::subrange subrange{std::move(it_begin), std::default_sentinel}; + auto single_encoded_view = std::move(subrange) | to_utf16; + auto iter = single_encoded_view.begin(); + if (*iter != u'x') { + return false; + } + ++iter; + if (detail::erroneous_behavior_global()) { + return false; + } + *iter; + if (!detail::erroneous_behavior_global()) { + return false; + } + detail::erroneous_behavior_global() = false; + } + { + test_forward_iterator it_begin(arr); + std::ranges::subrange subrange{std::move(it_begin), std::default_sentinel}; + auto single_encoded_view = subrange | to_utf16; + auto iter = single_encoded_view.begin(); + if (*iter != u'x') { + return false; + } + ++iter; + if (detail::erroneous_behavior_global()) { + return false; + } + *iter; + if (!detail::erroneous_behavior_global()) { + return false; + } + detail::erroneous_behavior_global() = false; + } + return true; +} + +static bool before_the_beginning_decrement_eb_test() { + std::initializer_list arr{u8'x'}; + test_bidi_iterator it_begin(arr); + std::ranges::subrange subrange{std::move(it_begin), std::default_sentinel}; + auto single_encoded_view = subrange | to_utf16; + auto iter = single_encoded_view.begin(); + if (*iter != u'x') { + return false; + } + if (detail::erroneous_behavior_global()) { + return false; + } + --iter; + if (!detail::erroneous_behavior_global()) { + return false; + } + detail::erroneous_behavior_global() = false; + return true; +} + +constexpr bool to_utf_test() { + std::ranges::empty_view empty_view{}; + auto empty_utf_view{empty_view | to_utf8}; + static_assert( + std::is_same_v>); + auto u8_string_literal_utf_view{u8"foo" | to_utf32}; + auto u8_string_literal_utf_view_it{u8_string_literal_utf_view.begin()}; + if (*u8_string_literal_utf_view_it != U'f') { + return false; + } + ++u8_string_literal_utf_view_it; + if (*u8_string_literal_utf_view_it != U'o') { + return false; + } + ++u8_string_literal_utf_view_it; + if (*u8_string_literal_utf_view_it != U'o') { + return false; + } + ++u8_string_literal_utf_view_it; + if (u8_string_literal_utf_view_it != u8_string_literal_utf_view.end()) { + return false; + } + char8_t const non_null_terminated_array[3]{u8'a', u8'b', u8'c'}; + auto non_null_terminated_array_utf_view{non_null_terminated_array | to_utf32}; + auto non_null_terminated_array_utf_view_it{non_null_terminated_array_utf_view.begin()}; + if (*non_null_terminated_array_utf_view_it != U'a') { + return false; + } + ++non_null_terminated_array_utf_view_it; + if (*non_null_terminated_array_utf_view_it != U'b') { + return false; + } + ++non_null_terminated_array_utf_view_it; + if (*non_null_terminated_array_utf_view_it != U'c') { + return false; + } + ++non_null_terminated_array_utf_view_it; + if (non_null_terminated_array_utf_view_it != non_null_terminated_array_utf_view.end()) { + return false; + } + std::initializer_list arr{u8'b', u8'a', u8'r'}; + test_input_iterator input_it(arr); + std::ranges::subrange subrange{std::move(input_it), std::default_sentinel}; + auto input_utf_view{std::move(subrange) | to_utf32}; + auto input_utf_view_it{std::ranges::begin(input_utf_view)}; + if (*input_utf_view_it != U'b') { + return false; + } + ++input_utf_view_it; + if (*input_utf_view_it != U'a') { + return false; + } + ++input_utf_view_it; + if (*input_utf_view_it != U'r') { + return false; + } + ++input_utf_view_it; + if (input_utf_view_it != input_utf_view.end()) { + return false; + } + char8_t const* u8_ptr{u8"foo"}; + auto u8_ptr_utf_view{null_term(u8_ptr) | to_utf32}; + auto u8_ptr_utf_view_it{u8_ptr_utf_view.begin()}; + if (*u8_ptr_utf_view_it != U'f') { + return false; + } + ++u8_ptr_utf_view_it; + if (*u8_ptr_utf_view_it != U'o') { + return false; + } + ++u8_ptr_utf_view_it; + if (*u8_ptr_utf_view_it != U'o') { + return false; + } + ++u8_ptr_utf_view_it; + if (u8_ptr_utf_view_it != u8_ptr_utf_view.end()) { + return false; + } + return true; +} + +template